### Install Target and Files Source: https://github.com/snes9xgit/snes9x/blob/master/qt/CMakeLists.txt Installs the 'snes9x-qt' executable and the 'cheats.bml' data file to their designated locations in the installation directory. ```cmake install(TARGETS snes9x-qt) install(FILES ../data/cheats.bml DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/snes9x) ``` -------------------------------- ### Create and Manage Movie Recordings in C++ Source: https://context7.com/snes9xgit/snes9x/llms.txt Use S9xMovieCreate to start a new recording, specifying the file path, controllers to record, and options like starting from a reset. Other functions allow opening existing movies, retrieving movie information, checking active states (playing/recording), toggling states, controlling frame display, stopping recordings, and verifying read-only status. ```cpp #include "movie.h" // Create a new movie recording uint8 controllers = 0x01; // Bit mask for which controllers to record uint8 opts = MOVIE_OPT_FROM_RESET; // Start from reset (vs. snapshot) wchar_t metadata[MOVIE_MAX_METADATA] = L"My Speedrun Attempt"; int result = S9xMovieCreate( "/path/to/movie.smv", controllers, opts, metadata, wcslen(metadata) ); if (result != SUCCESS) { fprintf(stderr, "Failed to create movie\n"); } // Open existing movie for playback result = S9xMovieOpen("/path/to/movie.smv", FALSE); // read-only = FALSE // Get movie information without opening MovieInfo info; if (S9xMovieGetInfo("/path/to/movie.smv", &info) == SUCCESS) { printf("Movie length: %u frames\n", info.LengthFrames); printf("Rerecord count: %u\n", info.RerecordCount); printf("ROM CRC32: 0x%08X\n", info.ROMCRC32); printf("ROM Name: %s\n", info.ROMName); } // Check movie state if (S9xMovieActive()) { if (S9xMoviePlaying()) { printf("Playing movie, frame %u of %u\n", S9xMovieGetFrameCounter(), S9xMovieGetLength()); } else if (S9xMovieRecording()) { printf("Recording movie, frame %u\n", S9xMovieGetFrameCounter()); } } // Toggle between recording and playback S9xMovieToggleRecState(); // Show/hide frame counter on screen S9xMovieToggleFrameDisplay(); // Stop movie (optionally clear movie state completely) S9xMovieStop(TRUE); // TRUE = clear completely // Check if movie is read-only if (S9xMovieReadOnly()) { printf("Movie is read-only\n"); } // Get movie ID (for verification) uint32 movie_id = S9xMovieGetId(); ``` -------------------------------- ### SDL3 Integration (System or FetchContent) Source: https://github.com/snes9xgit/snes9x/blob/master/qt/CMakeLists.txt Configures the build to use SDL3, either by finding an installed version or by using FetchContent to download and build it. This is controlled by the USE_SYSTEM_SDL3 cache variable. ```cmake set(USE_SYSTEM_SDL3 CACHE BOOL OFF) if (USE_SYSTEM_SDL3) find_package(SDL3 QUIET) endif() if (SDL3_FOUND) message("Using system SDL3.") list(APPEND LIBS SDL3::SDL3) list(APPEND INCLUDES ${SDL3_INCLUDE_DIRS}) else() include(FetchContent) FetchContent_Declare( SDL3 ``` -------------------------------- ### Core Library Setup Source: https://github.com/snes9xgit/snes9x/blob/master/qt/CMakeLists.txt Defines the C++ standard, enables compile command export, and sets up automatic code generation for the core SNES9x library. It includes a comprehensive list of source files for the core. ```cmake cmake_minimum_required(VERSION 3.20) project(snes9x-qt VERSION 1.63) include(GNUInstallDirs) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) set(CMAKE_GLOBAL_AUTOGEN_TARGET ON) set(DEFINES SNES9X_QT) set(SNES9X_CORE_SOURCES ../fxinst.cpp ../fxemu.cpp ../fxdbg.cpp ../c4.cpp ../c4emu.cpp ../apu/apu.cpp ../apu/bapu/dsp/sdsp.cpp ../apu/bapu/smp/smp.cpp ../apu/bapu/smp/smp_state.cpp ../msu1.cpp ../msu1.h ../dsp.cpp ../dsp1.cpp ../dsp2.cpp ../dsp3.cpp ../dsp4.cpp ../spc7110.cpp ../obc1.cpp ../seta.cpp ../seta010.cpp ../seta011.cpp ../seta018.cpp ../controls.cpp ../crosshairs.cpp ../cpu.cpp ../sa1.cpp ../debug.cpp ../sdd1.cpp ../tile.cpp ../tileimpl-n1x1.cpp ../tileimpl-n2x1.cpp ../tileimpl-h2x1.cpp ../srtc.cpp ../gfx.cpp ../memmap.cpp ../clip.cpp ../ppu.cpp ../dma.cpp ../snes9x.cpp ../globals.cpp ../stream.cpp ../conffile.cpp ../bsx.cpp ../snapshot.cpp ../screenshot.cpp ../movie.cpp ../statemanager.cpp ../sha256.cpp ../bml.cpp ../cpuops.cpp ../cpuexec.cpp ../sa1cpu.cpp ../cheats.cpp ../cheats2.cpp ../sdd1emu.cpp ../netplay.cpp ../server.cpp ../loadzip.cpp ../fscompat.cpp) add_library(snes9x-core ${SNES9X_CORE_SOURCES}) target_include_directories(snes9x-core PRIVATE ../) target_compile_definitions(snes9x-core PRIVATE ${DEFINES} ZLIB HAVE_STDINT_H HAVE_LIBPNG ALLOW_CPU_OVERCLOCK) ``` -------------------------------- ### ButtonToPointer Command Example Source: https://github.com/snes9xgit/snes9x/blob/master/docs/controls.txt Moves a pointer based on button presses. The pointer moves at a specified speed per frame while the button is held down. ```text ButtonToPointer 1u Slow ``` -------------------------------- ### Initialize Git Submodules Source: https://github.com/snes9xgit/snes9x/wiki/Compiling Command to fetch and initialize project dependencies required for building Snes9x. ```bash git submodule update --init ``` ```bash snes9x$ git submodule update --init --recursive ``` ```bash snes9x$ git init && git submodule update --init --recursive ``` -------------------------------- ### Justifier Commands Source: https://github.com/snes9xgit/snes9x/blob/master/docs/controls.txt Commands for the Justifier accessory, including trigger and start actions. ```text Justifier# AimOffscreen ``` ```text Justifier# {Trigger, Start} ``` ```text Justifier# AimOffscreen "" ``` -------------------------------- ### Update Git Submodules Source: https://github.com/snes9xgit/snes9x/blob/master/win32/docs/how2compile.txt Use this command in the Snes9x git directory to automatically download required modules. This is the recommended method for installing dependencies. ```bash git submodule update --init ``` -------------------------------- ### Initialize Settings structure Source: https://github.com/snes9xgit/snes9x/blob/master/docs/porting.html Required initialization for the Settings structure to ensure proper emulation behavior. ```cpp memset(&Settings, 0, sizeof(Settings)); Settings.MouseMaster = true; Settings.SuperScopeMaster = true; Settings.JustifierMaster = true; Settings.MultiPlayer5Master = true; Settings.FrameTimePAL = 20000; Settings.FrameTimeNTSC = 16667; Settings.SoundPlaybackRate = 32040; Settings.SoundInputRate = 31947; Settings.SupportHiRes = true; Settings.Transparency = true; Settings.AutoDisplayMessages = true; Settings.InitialInfoStringTimeout = 120; Settings.HDMATimingHack = 100; Settings.BlockInvalidVRAMAccessMaster = true; ``` -------------------------------- ### Controllers Management Source: https://github.com/snes9xgit/snes9x/blob/master/docs/porting.html Guide to managing SNES controllers, including mapping buttons and pointers, reporting input states, and setting controller types. ```APIDOC ## Controllers Management Read `controls.h`, `crosshair.h`, `controls.txt` and `control-inputs.txt` for details. This section is the minimal explanation to get the SNES controls workable. The real SNES allows several different types of devices to be plugged into the game controller ports. The devices Snes9x emulates are a joypad, multi-player adaptor known as the Multi Player 5 or Multi Tap (allowing a further 4 joypads to be plugged in), a 2-button mouse, a light gun known as the Super Scope, and a light gun known as the Justifier. In your initialization code, call `S9xUnmapAllControl` function. Map any IDs to each SNES controller's buttons and pointers. (ID 249-255 are reserved). Typically, use `S9xMapPointer` function for the pointer of the SNES mouse, Super Scope and Justifier, `S9xMapButton` function for other buttons. Set `poll` to `false` for the joypad buttons, `true` for the other buttons and pointers. `S9xMapButton(k1P_A_Button, s9xcommand_t cmd = S9xGetCommandT("Joypad1 A"), false); ` In your main emulation loop, before `S9xMainLoop` function is called, check your system's keyboard/joypad, and call `S9xReportButton` function to report the states of the SNES joypad buttons to Snes9x. Checking and reporting input immediately before `S9xMainLoop` is preferred to minimize input latency. `void MyMainLoop (void) {     MyReportButttons();     S9xMainLoop(); } ` `void MyReportButtons (void) {     S9xReportButton(k1P_A_Button, (key_is_pressed ? true : false)); } ` Prepare your `S9xPollButton` and `S9xPollPointer` function to reply Snes9x's request for other buttons/cursors states. Call `S9xSetController` function. It connects each input device to each SNES input port. Here's typical controller settings that is used by the real SNES games: Joypad `S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0); ` Mouse (port 1) `S9xSetController(0, CTL_MOUSE, 0, 0, 0, 0); S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0); ` Mouse (port 2) `S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); S9xSetController(1, CTL_MOUSE, 1, 0, 0, 0); ` Super Scope `S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); S9xSetController(1, CTL_SUPERSCOPE, 0, 0, 0, 0); ` Multi Player 5 `S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); S9xSetController(1, CTL_MP5, 1, 2, 3, 4); ` Justifier `S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); S9xSetController(1, CTL_JUSTIFIER, 0, 0, 0, 0); ` Justifier (2 players) `S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); S9xSetController(1, CTL_JUSTIFIER, 1, 0, 0, 0); ` ``` -------------------------------- ### Sound Initialization and Playback Source: https://github.com/snes9xgit/snes9x/blob/master/docs/porting.html Functions for initializing the sound system, mixing samples, and managing the sample buffer. ```APIDOC ## `bool8 S9xInitSound (int buffer_ms)` ### Description Allocates memory for mixing and queueing SNES sound data, performs further sound code initialization, and opens the host system's sound device. Requires `Settings.SoundSync`, `Settings.SoundPlaybackRate`, and `Settings.SoundInputRate` to be set beforehand. `buffer_ms` specifies the memory buffer size in milliseconds; 0 uses the default. ### Method `S9xInitSound` ### Parameters - **buffer_ms** (int) - Required - The memory buffer size for queueing sound data in milliseconds. Use 0 for the suggested default. ### Returns `bool8` - Indicates success or failure of initialization. ``` ```APIDOC ## `void S9xMixSamples (uint8 *buffer, int sample_count)` ### Description Fills the provided `buffer` with `sample_count` mixed SNES sound samples. Samples are in `int16` format, interleaved for left and right channels. If insufficient samples are available, the buffer is filled with silence and the function returns `false`. ### Method `S9xMixSamples` ### Parameters - **buffer** (uint8 *) - Required - Pointer to the buffer to be filled with sound data. - **sample_count** (int) - Required - The number of samples to retrieve. ### Returns `bool8` - `false` if fewer samples than requested are available, `true` otherwise. ``` ```APIDOC ## `int S9xGetSampleCount (void)` ### Description Returns the number of sound samples currently available in the buffer for playback. ### Method `S9xGetSampleCount` ### Parameters None ### Returns `int` - The number of available sound samples. ``` ```APIDOC ## `void S9xSetSamplesAvailableCallback (void (*) samples_available (void *), void *data)` ### Description Sets up a callback function that is invoked when sound samples become available. The callback function `samples_available` should return `void` and accept a `void *` argument. `data` is a user-defined pointer passed to the callback. Pass `NULL` for both arguments to disable the callback. ### Method `S9xSetSamplesAvailableCallback` ### Parameters - **samples_available** (void (*) (void *)) - Optional - The callback function to be executed when samples are available. - **data** (void *) - Optional - A pointer to be passed to the callback function. ``` -------------------------------- ### Process Language PO Files Source: https://github.com/snes9xgit/snes9x/blob/master/gtk/CMakeLists.txt Iterates through a list of languages to process .po files and install generated .mo files. This is useful for managing internationalization. ```cmake foreach(lang de es fr_FR ja pl pt_BR ru sr@latin uk zh_CN) GETTEXT_PROCESS_PO_FILES(${lang} ALL PO_FILES po/${lang}.po) install(FILES ${CMAKE_BINARY_DIR}/${lang}.gmo DESTINATION ${LOCALEDIR}/${lang}/LC_MESSAGES RENAME ${CMAKE_PROJECT_NAME}.mo COMPONENT translations) endforeach() ``` -------------------------------- ### Configure and Build with CMake Source: https://github.com/snes9xgit/snes9x/wiki/Compiling Commands to configure the build environment using CMake and compile using Ninja. ```bash snes9x/gtk$ cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -S . -B build ``` ```bash snes9x/gtk$ cd build snes9x/gtk/build$ ninja ``` ```bash snes9x/gtk/build$ sudo ninja install ``` -------------------------------- ### AxisToButtons Command Example Source: https://github.com/snes9xgit/snes9x/blob/master/docs/controls.txt Translates axis data to button reports. Reports button states when axis deflection exceeds a threshold in either direction, and resets when deflection drops below the threshold. ```text AxisToButtons 0/255 T=50% ``` -------------------------------- ### Manage Memory and ROM Loading in C++ Source: https://context7.com/snes9xgit/snes9x/llms.txt Use the Memory subsystem to initialize the emulator, load ROMs from files or memory buffers, and manage SRAM persistence. ```cpp #include "memmap.h" #include "snes9x.h" // Initialize memory subsystem if (!Memory.Init()) { fprintf(stderr, "Failed to initialize memory\n"); return 1; } // Load a ROM file if (!Memory.LoadROM("/path/to/game.smc")) { fprintf(stderr, "Failed to load ROM: %s\n", Memory.ROMFilename.c_str()); return 1; } // Access ROM information after loading printf("ROM Name: %s\n", Memory.ROMName); printf("ROM ID: %s\n", Memory.ROMId); printf("ROM Size: %s\n", Memory.Size()); printf("ROM Type: %s (HiROM: %d, LoROM: %d)\n", Memory.MapType(), Memory.HiROM, Memory.LoROM); printf("SRAM Size: %s\n", Memory.StaticRAMSize()); printf("Region: %s\n", Memory.Country()); printf("CRC32: 0x%08X\n", Memory.ROMCRC32); // Load SRAM (battery-backed save data) if it exists Memory.LoadSRAM("/path/to/game.srm"); // After gameplay, save SRAM Memory.SaveSRAM("/path/to/game.srm"); // Load ROM from memory buffer (useful for embedded applications) const uint8 *rom_data = /* ROM data buffer */; uint32 rom_size = /* size of ROM data */; if (!Memory.LoadROMMem(rom_data, rom_size, "game.smc")) { fprintf(stderr, "Failed to load ROM from memory\n"); } // Cleanup when done Memory.Deinit(); ``` -------------------------------- ### Configure and Build with Meson Source: https://github.com/snes9xgit/snes9x/wiki/Compiling Commands for older versions of Snes9x that utilize the Meson build system. ```bash snes9x/gtk$ meson build --prefix=/usr --buildtype=release --strip ``` -------------------------------- ### Configure Graphics Rendering Source: https://context7.com/snes9xgit/snes9x/llms.txt Handles initialization of the graphics subsystem, frame update callbacks, and display settings for SNES PPU emulation. ```cpp #include "gfx.h" #include "display.h" // Initialize graphics subsystem if (!S9xGraphicsInit()) { fprintf(stderr, "Failed to initialize graphics\n"); return 1; } // Configure display settings Settings.Transparency = TRUE; Settings.DisableGraphicWindows = FALSE; Settings.DisplayFrameRate = TRUE; Settings.DisplayTime = FALSE; Settings.BilinearFilter = TRUE; Settings.ShowOverscan = FALSE; // Screen dimensions // SNES_WIDTH = 256, SNES_HEIGHT = 224 (or 239 for extended) // MAX_SNES_WIDTH = 512, MAX_SNES_HEIGHT = 478 (hi-res modes) // Port must implement these functions: // Called at start of each frame bool8 S9xInitUpdate(void) { // Prepare your framebuffer for rendering return TRUE; } // Called at end of each frame with rendered image bool8 S9xDeinitUpdate(int width, int height) { // GFX.Screen contains the rendered frame // width = actual width (256 or 512 for hi-res) // height = actual height (224, 239, 448, or 478) uint16 *screen = GFX.Screen; uint32 pitch = GFX.Pitch; // Bytes per row // Copy to your display buffer // Pixel format is RGB565 or RGB555 depending on build return TRUE; } // Continue update mid-frame (for hi-res mode changes) bool8 S9xContinueUpdate(int width, int height) { return TRUE; } // Control frame timing void S9xSyncSpeed(void) { // Implement frame rate limiting // Settings.FrameTime contains target frame time } // Display on-screen messages S9xSetInfoString("Game Loaded"); // Custom display string callback void MyDisplayString(const char *str, int linesFromBottom, int pixelsFromLeft, bool allowWrap, int type) { // Render text overlay } S9xCustomDisplayString = MyDisplayString; // Force background layers (for debugging) Settings.BG_Forced = 0; // 0 = normal, bit flags to force layers // Get current frame buffer pointer uint16 *framebuffer = GFX.Screen; // Cleanup S9xGraphicsDeinit(); ``` -------------------------------- ### Global Variables and Settings Source: https://github.com/snes9xgit/snes9x/blob/master/docs/porting.html Configuration of the GFX buffer and the Settings structure for emulation behavior. ```APIDOC ## GFX.Screen ### Description Pointer to the buffer where Snes9x renders the SNES screen. Requires at least 2*512*478 bytes (or 2*256*239 if hires is disabled). ## GFX.Pitch ### Description Bytes per line of the GFX.Screen buffer. Typically set to 1024. ## Settings Structure ### Description Global structure containing emulation switches. Required fields include: - **MouseMaster** (bool) - **SuperScopeMaster** (bool) - **JustifierMaster** (bool) - **MultiPlayer5Master** (bool) - **FrameTimePAL** (int) - **FrameTimeNTSC** (int) - **SoundPlaybackRate** (int) - **SoundInputRate** (int) - **SupportHiRes** (bool) - **Transparency** (bool) - **AutoDisplayMessages** (bool) - **InitialInfoStringTimeout** (int) - **HDMATimingHack** (int) - **BlockInvalidVRAMAccessMaster** (bool) ``` -------------------------------- ### Define Qt UI Files Source: https://github.com/snes9xgit/snes9x/blob/master/qt/CMakeLists.txt Lists the UI files used by the Qt interface for Snes9x. ```cmake set(QT_UI_FILES src/GeneralPanel.ui src/ControllerPanel.ui src/EmuSettingsWindow.ui src/DisplayPanel.ui src/SoundPanel.ui src/EmulationPanel.ui src/ShortcutsPanel.ui src/FoldersPanel.ui) ``` -------------------------------- ### Settings Structure Configuration Source: https://context7.com/snes9xgit/snes9x/llms.txt Global configuration options for the Snes9x emulator. ```APIDOC ## Settings Structure ### Description The Settings structure controls emulator behavior including timing, graphics, sound, and input. ### Configuration Fields - **PAL** (bool) - Video timing mode (FALSE=NTSC, TRUE=PAL) - **FrameTime** (int) - Frame time in microseconds - **SkipFrames** (int) - Number of frames to skip - **SoundPlaybackRate** (int) - Audio output sample rate - **Stereo** (bool) - Enable stereo sound - **Transparency** (bool) - Enable graphics transparency - **MouseMaster** (bool) - Enable mouse peripheral support - **Port** (int) - Netplay port number - **ServerName** (string) - Netplay server address ``` -------------------------------- ### Implement Main Emulation Loop Source: https://github.com/snes9xgit/snes9x/blob/master/docs/porting.html Report button states immediately before calling the main loop to minimize input latency. ```C++ void MyMainLoop (void) {     MyReportButttons();     S9xMainLoop(); } ``` ```C++ void MyReportButtons (void) {     S9xReportButton(k1P_A_Button, (key_is_pressed ? true : false)); } ``` -------------------------------- ### Build Options Source: https://github.com/snes9xgit/snes9x/blob/master/docs/porting.html Defines for enabling support for compressed ROM images and freeze-game files, and for using OpenGL for rendering. ```APIDOC ## Build Options ### `ZLIB / UNZIP_SUPPORT / JMA_SUPPORT` Define these if you want to support GZIP/ZIP/JMA compressed ROM images and GZIP compressed freeze-game files. ### `USE_OPENGL` Define this and set `Settings.OpenGLEnable` to `true`, then you'll get the rendered SNES image as one OpenGL texture. ### Typical Options Common for Most Platforms `ZLIB UNZIP_SUPPORT JMA_SUPPORT RIGHTSHIFT_IS_SAR ` ```