# The main config file

# Note.
# Be aware that when this configuration is being overwritten
# by another configuration, any empty nested part
# in the further configurations will reset (empty out) all the values.
# For example:
# the main config              second config       result
# ...                          ...                 ...
# list:                        list:               list:
#   gba:                         gba:                gba:
#     lib: mgba_libretro                               lib: ""
#     roms: [ "gba", "gbc" ]                           roms: []
# ...                                              ...
#
# So do not leave empty nested keys.

# for the compatibility purposes
version: 3

# new decentralized library of games
library:
  # optional alias file for overriding game names from the basePath path
  aliasFile: alias.txt
  # root folder for the library (where games are stored)
  basePath: assets/games
  # a list of ignored words in the ROM filenames
  ignored:
    - neogeo
    - pgm
    # DOSBox filesystem state
    - .pure
  # an explicit list of supported file extensions
  # which overrides Libretro emulator ROMs configs
  supported:
  # print some additional info
  verbose: true
  # enable library directory live reload
  # (experimental)
  watchMode: false

coordinator:
  # debugging switch
  #   - shows debug logs
  #   - allows selecting worker instances
  debug: false
  # selects free workers:
  #   - empty value (default, any free)
  #   - ping (with the lowest ping)
  selector:
  monitoring:
    port: 6601
    # enable Go profiler HTTP server
    profilingEnabled: false
    metricEnabled: false
    urlPrefix: /coordinator
  # a custom Origins for incoming Websocket connections:
  # "" -- checks same origin policy
  # "*" -- allows all
  # "your address" -- checks for that address
  origin:
    userWs:
    workerWs:
  # max websocket message size in bytes
  maxWsSize: 32000000
  # HTTP(S) server config
  server:
    address: :8000
    cacheControl: "max-age=259200, must-revalidate"
    frameOptions: ""
    https: false
    # Letsencrypt or self cert config
    tls:
      address: :443
      # allowed host name
      domain:
      # if both are set then will use certs
      # and Letsencryt instead
      httpsCert:
      httpsKey:
  analytics:
    inject: false
    gtag:

worker:
  # show more logs
  debug: false
  library:
    # root folder for the library (where games are stored)
    basePath: assets/games
  network:
    # a coordinator address to connect to
    coordinatorAddress: localhost:8000
    # where to connect
    endpoint: /wso
    # ping endpoint
    pingEndpoint: /echo
    # set public ping address (IP or hostname)
    publicAddress:
    # make coordinator connection secure (wss)
    secure: false
    # ISO Alpha-2 country code to group workers by zones
    zone:
  monitoring:
    # monitoring server port
    port: 6602
    profilingEnabled: false
    # monitoring server URL prefix
    metricEnabled: false
    urlPrefix: /worker
  server:
    address: :9000
    https: false
    tls:
      address: :444
      # LetsEncrypt config
      # allowed host name
      domain:
      # Own certs config
      httpsCert:
      httpsKey:
  # optional server tag
  tag:

emulator:
  # set the total number of threads for the image processing
  # (removed)
  threads: 0

  # enable autosave for emulator states if set to a non-zero value of seconds
  autosaveSec: 0

  # save directory for emulator states
  # special tag {user} will be replaced with current user's home dir
  storage: "{user}/.cr/save"

  # path for storing emulator generated files
  localPath: "./libretro"

  # checks if the system supports running an emulator at startup
  failFast: true

  # do not send late video frames
  skipLateFrames: false

  # log dropped frames (temp)
  logDroppedFrames: false

  libretro:
    # use zip compression for emulator save states
    saveCompression: true
    # Sets a limiter function for some spammy core callbacks.
    # 0 - disabled, otherwise -- time in milliseconds for ignoring repeated calls except the last.
    debounceMs: 0
    # Allow duplicate frames
    dup: true
    # Libretro cores logging level: DEBUG = 0, INFO, WARN, ERROR, DUMMY = INT_MAX
    logLevel: 1
    cores:
      paths:
        libs: assets/cores
      # Config params for Libretro cores repository,
      # available types are:
      #   - buildbot (the default Libretro nightly repository)
      #   - github (GitHub raw repository with a similar structure to buildbot)
      #   - raw (just a link to a zip file extracted as is)
      repo:
        # enable auto-download for the list of cores (list->lib)
        sync: true
        # external cross-process mutex lock
        extLock: "{user}/.cr/cloud-game.lock"
        map:
          darwin:
            amd64:
              arch: x86_64
              ext: .dylib
              os: osx
              vendor: apple
            arm64:
              arch: arm64
              ext: .dylib
              os: osx
              vendor: apple
          linux:
            amd64:
              arch: x86_64
              ext: .so
              os: linux
            arm:
              arch: armv7-neon-hf
              ext: .so
              os: linux
          windows:
            amd64:
              arch: x86_64
              ext: .dll
              os: windows
        main:
          type: buildbot
          url: https://buildbot.libretro.com/nightly
          # if repo has file compression
          compression: zip
        # a secondary repo to use i.e. for not found in the main cores
        secondary:
          type: github
          url: https://github.com/sergystepanov/libretro-spiegel/raw/main
          compression: zip
      # Libretro core configuration
      #
      # The emulator selection will happen in this order:
      #   - based on the folder name in the folder param
      #   - based on the folder name (core name) in the list (i.e. nes, snes)
      #   - based on the rom names in the roms param
      #
      # Available config params:
      #   - altRepo (bool) prioritize secondary repo as the download source
      #   - lib (string)
      #   - roms ([]string)
      #   - scale (int) scales the output video frames by this factor.
      #   - folder (string)
      #       By default emulator selection is based on the folder named as cores
      #       in the list (i.e. nes, snes) but if you specify folder param,
      #       then it will try to load the ROM file from that folder first.
      #   - width (int) -- broken
      #   - height (int) -- broken
      #   - ratio (float)
      #   - isGlAllowed (bool)
      #   - usesLibCo (bool)
      #   - hasMultitap (bool) -- (removed)
      #   - coreAspectRatio (bool) -- (deprecated) correct the aspect ratio on the client with the info from the core.
      #   - hid (map[int][]int)
      #       A list of device IDs to bind to the input ports.
      #       Can be seen in human readable form in the console when worker.debug is enabled.
      #       Some cores allow binding multiple devices to a single port (DosBox), but typically,
      #       you should bind just one device to one port.
      #   - kbMouseSupport (bool) -- (temp) a flag if the core needs the keyboard and mouse on the client
      #   - nonBlockingSave (bool) -- write save file in a non-blocking way, needed for huge save files
      #   - vfr (bool)
      #    (experimental)
      #       Enable variable frame rate only for cores that can't produce a constant frame rate.
      #       By default, we assume that cores output frames at a constant rate which equals
      #       their tick rate (1/system FPS), but OpenGL cores like N64 may have significant
      #       frame rendering time inconsistencies. In general, VFR for CFR cores leads to
      #       noticeable video stutter (with the current frame rendering time calculations).
      #   - options ([]string) a list of Libretro core options for tweaking.
      #       All keys of the options should be in the double quotes in order to preserve upper-case symbols.
      #   - options4rom (rom[[]string])
      #       A list of core options to override for a specific core depending on the current ROM name.
      #   - hacks ([]string) a list of hacks.
      #       Available:
      #       - skip_hw_context_destroy -- don't destroy OpenGL context during Libretro core deinit.
      #                                    May help with crashes, for example, with PPSSPP.
      #       - skip_same_thread_save -- skip thread lock save (used with PPSSPP).
      #   - uniqueSaveDir (bool) -- needed only for cores (like DosBox) that persist their state into one shared file.
      #       This will allow for concurrent reading and saving of current states.
      #   - saveStateFs (string) -- the name of the file that will be initially copied into the save folder.
      #       All * symbols will be replaced to the name of the ROM.
      list:
        gba:
          lib: mgba_libretro
          roms: [ "gba", "gbc" ]
          options:
            mgba_audio_low_pass_filter: disabled
            mgba_audio_low_pass_range: 50
        pcsx:
          lib: pcsx_rearmed_libretro
          roms: [ "cue", "chd" ]
          # example of folder override
          folder: psx
          # see: https://github.com/libretro/pcsx_rearmed/blob/master/frontend/libretro_core_options.h
          options:
            "pcsx_rearmed_show_bios_bootlogo": enabled
            "pcsx_rearmed_drc": enabled
            "pcsx_rearmed_display_internal_fps": disabled
        # MAME core requires additional manual setup, please read:
        # https://docs.libretro.com/library/fbneo/
        mame:
          lib: fbneo_libretro
          folder: mame
          roms: [ "zip" ]
        nes:
          lib: nestopia_libretro
          roms: [ "nes" ]
          options:
            nestopia_aspect: "uncorrected"
        snes:
          lib: snes9x_libretro
          roms: [ "smc", "sfc", "swc", "fig", "bs" ]
          hid:
            # set the 2nd port to RETRO_DEVICE_JOYPAD_MULTITAP ((1<<8) | 1) as SNES9x requires it
            # in order to support up to 5-player games
            # see: https://nintendo.fandom.com/wiki/Super_Multitap
            1: 257
        n64:
          lib: mupen64plus_next_libretro
          roms: [ "n64", "v64", "z64" ]
          isGlAllowed: true
          usesLibCo: true
          vfr: true
          # see: https://github.com/libretro/mupen64plus-libretro-nx/blob/master/libretro/libretro_core_options.h
          options:
            "mupen64plus-169screensize": 640x360
            "mupen64plus-43screensize": 320x240
            "mupen64plus-EnableCopyColorToRDRAM": Off
            "mupen64plus-EnableCopyDepthToRDRAM": Off
            "mupen64plus-EnableEnhancedTextureStorage": True
            "mupen64plus-EnableFBEmulation": True
            "mupen64plus-EnableLegacyBlending": True
            "mupen64plus-FrameDuping": True
            "mupen64plus-MaxTxCacheSize": 8000
            "mupen64plus-ThreadedRenderer": False
            "mupen64plus-cpucore": dynamic_recompiler
            "mupen64plus-pak1": memory
            "mupen64plus-rdp-plugin": gliden64
            "mupen64plus-rsp-plugin": hle
            "mupen64plus-astick-sensitivity": 100
        dos:
          lib: dosbox_pure_libretro
          roms: [ "zip", "cue" ]
          folder: dos
          kbMouseSupport: true
          nonBlockingSave: true
          saveStateFs: "*.pure.zip"
          hid:
            0: [ 257, 513 ]
            1: [ 257, 513 ]
            2: [ 257, 513 ]
            3: [ 257, 513 ]
          options:
            "dosbox_pure_conf": "outside"
            "dosbox_pure_force60fps": "true"

encoder:
  audio:
    # audio frame duration needed for WebRTC (Opus)
    # most of the emulators have ~1400 samples per a video frame,
    # so we keep the frame buffer roughly half of that size or 2 RTC packets per frame
    # (deprecated) due to frames
    frame: 10
    # dynamic frames for Opus encoder
    frames:
      - 10
      - 5
    # speex (2), linear (1) or nearest neighbour (0) audio resampler
    # linear should sound slightly better than 0
    resampler: 2
  video:
    # h264, vpx (vp8) or vp9
    codec: h264
    # Threaded encoder if supported, 0 - auto, 1 - nope, >1 - multi-threaded
    threads: 0
    # see: https://trac.ffmpeg.org/wiki/Encode/H.264
    h264:
      # crf, cbr
      mode: crf
      # Constant Rate Factor (CRF) 0-51 (default: 23)
      crf: 23
      # Rate control options
      # set the maximum bitrate
      maxRate: 0
      # set the expected client buffer size
      bufSize: 0
      # ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow, placebo
      preset: superfast
      # baseline, main, high, high10, high422, high444
      profile: baseline
      # film, animation, grain, stillimage, psnr, ssim, fastdecode, zerolatency
      tune: zerolatency
      # 0-3
      logLevel: 0
    # see: https://www.webmproject.org/docs/encoder-parameters
    vpx:
      # target bitrate (KBit/s)
      bitrate: 1200
      # force keyframe interval
      keyframeInterval: 5

# game recording
# (experimental)
# recording allows export RAW a/v streams of games
# by default, it will export audio as WAV files,
# video as a list of PNG-encoded images, and
# one additional FFMPEG concat demux file
recording:
  enabled: false
  # name contains the name of the recording dir (or zip)
  # format:
  # %date:go_time_format% -- refer: https://go.dev/src/time/format.go
  # %user% -- user name who started the recording
  # %game% -- game name (game ROM name)
  # %rand:len% -- a random string of given length
  # as example: 20210101101010_yeE_user1_badApple
  name: "%date:20060102150405%_%rand:3%_%user%_%game%"
  # zip and remove recording dir on completion
  zip: true
  # save directory
  folder: ./recording

# cloud storage options
# it is mandatory to use a cloud storage when running
# a distributed multi-server configuration in order to
# share save states between nodes (resume games on a different worker)
storage:
  # cloud storage provider:
  #   - empty (No op storage stub)
  #   - s3 (S3 API compatible object storage)
  provider:
  s3Endpoint:
  s3BucketName:
  s3AccessKeyId:
  s3SecretAccessKey:

webrtc:
  # turn off default Pion interceptors (see: https://github.com/pion/interceptor)
  # (performance)
  disableDefaultInterceptors: false
  # indicates the role of the DTLS transport (see: https://github.com/pion/webrtc/blob/master/dtlsrole.go)
  # (debug)
  #  - (default)
  #  - 1 (auto)
  #  - 2 (client)
  #  - 3 (server)
  dtlsRole:
  # a list of STUN/TURN servers to use
  iceServers:
    - urls: stun:stun.l.google.com:19302
  # configures whether the ice agent should be a lite agent (true/false)
  # (performance)
  # don't use iceServers when enabled
  iceLite: false
  # ICE configuration
  # by default, ICE ports are random and unlimited
  # alternatives:
  #   1. instead of random unlimited port range for
  #   WebRTC connections, these params limit port range of ICE connections
  icePorts:
    min:
    max:
  #  2. select a single port to forward all ICE connections there
  singlePort:
  # override ICE candidate IP, see: https://github.com/pion/webrtc/issues/835,
  # can be used for Docker bridged network internal IP override
  iceIpMap:
  # set additional log level for WebRTC separately
  # -1 - trace, 6 - nothing, ..., debug - 0
  logLevel: 6
