PVSneslib Documentation

repository·master·Indexed 22 days ago

https://github.com/alekmaul/pvsneslib

A development kit for coding Nintendo SNES games in C or assembly. It features the 816-tcc compiler/linker toolchain and a hardware abstraction library covering backgrounds, sprites, input, sound (SPC700), and memory support (HiROM/FastROM). Includes specialized tools such as 816-opt for assembly optimization, bin2txt for binary-to-text conversion, and fnt4snes for variable font width conversion.

Tokens
9.1K
Snippets
40
Records
55
Agent score
74%

What's inside PVSneslib

  1. Overview of PVSnesLib Features

    master

    PVSnesLib is a development kit for coding Nintendo SNES games in C or assembly. It includes a compiler/linker toolchain (816-tcc) and a library for hardware abstraction.

    Key capabilities include:

    • Backgrounds: Tile and map loading, support for multiple BG modes.
    • Sprites: OAM management helpers for animation.
    • Input: Reading controller/pad and mouse/superscope input.
    • Sound & Music: Integration with the SPC700 audio driver.
    • Memory Support: HiROM and FastROM support.
    • Flexibility: Write in C, use assembly for performance-critical sections, or use assembly exclusively.
  2. Optimize BRR encoding quality and size

    master

    When using snesbrr, follow these best practices to improve audio quality and file size:

    • Minimize File Size: Ensure both the loop start point and the loop size are multiples of 16. If they are not, the tool will automatically repeat samples until they reach a multiple of 16, which can increase file size.
    • Improve Audio Quality: Use a higher sampling rate than strictly necessary for the source. Gaussian filtering (used during SNES decoding) reduces high-frequency volume. Increasing the sampling rate offsets this effect.
      • Example: A 4000 Hz square wave requires 8000 Hz minimum. At 8000 Hz, the decoded volume is only ~27%. At 16000 Hz, it reaches ~89%. At 32000 Hz, it reaches ~99%.
    • Manual Encoding: For simple waves (Square, Triangle, Sawtooth), you can manually provide BRR block data for maximum quality and smallest size.
  3. How 816-opt optimizations work

    master

    816-opt performs several types of optimizations through iterative passes. It continues scanning the assembly source until no further changes can be made. Key optimization patterns include:

    • Prologue/epilogue simplification: Collapses stack-frame sequences and removes .define <name>_locals 0 markers for functions without local variables.
    • Redundant store elimination: Removes stores to registers that are immediately overwritten, unused before a function call, or only used as a pointer.
    • Pseudo-register (preg) optimizations: Simplifies store/push/load sequences for virtual 16/32-bit registers (e.g., converting a store+push into a single push).
    • Increment/decrement folding: Converts pseudo-register stores followed by inc/dec into direct hardware register operations.
    • Shift/rotate folding: Merges pseudo-register stores followed by shifts (like asl) into a single shift on the accumulator.
    • 32-bit value reordering: Reorders 32-bit value copies to enable further optimizations.
    • Comparison optimizations: Simplifies common compare/branch sequences.
    • Branch distance optimization: Converts long branch instructions to short forms when the target is close.
    • Dead code and local name cleanup: Removes unused local variable names and bookkeeping metadata.
  4. Quickstart with PVSnesLib

    master

    To get a project compiling quickly, follow these steps:

    1. Download the appropriate release for your operating system from the latest release page and unzip the archive.
    2. Set the environment variable PVSNESLIB_HOME to point to the directory where you unzipped the library. This is required for the toolchain to function.
    3. Write a Hello World program to verify your setup. For a detailed guide on the Hello World example, refer to the Compiling helloworld-example tutorial.

    For advanced details regarding Makefile setup, folder layouts, and flashing to real SNES hardware, consult the Project Wiki.

    export PVSNESLIB_HOME="/path/to/pvsneslib"
  5. Load maps into the mapbuffer[]

    master

    To initialize the extension, you must first load your map data into WRAM using mapbuffersLoad, and then point the standard map engine to the mapbuffer instead of the original map data using mapLoad.

    #include "mapbufferextension.h"
    
    // 1. Load map data into WRAM
    mapbuffersLoad((u8 *)&mapmario, (&mapmario_end - &mapmario));
    
    // 2. Point the map engine to the buffer instead of the original map
    mapLoad((u8 *)&mapbuffer, (u8 *)&tilesetdef, (u8 *)&tilesetatt);
    #include "mapbufferextension.h"
    ...
    //load map into wram 
    mapbuffersLoad((u8 *)&mapmario, (&mapmario_end- &mapmario));
    //map engine gets the buffer instead
    mapLoad((u8 *)&mapbuffer, (u8 *)&tilesetdef, (u8 *)&tilesetatt);
  6. Build the Capcom Logo demo using Visual Studio Code

    master

    To build the Capcom logo demo, ensure you have Visual Studio Code installed. Open the root directory of the project in VS Code and use the integrated build task to compile the source code.

    1. Open the project root directory in Visual Studio Code.
    2. Press Ctrl + Shift + B to trigger the build process.
    3. Once the build completes, open the resulting logo.sfc file using a Super Nintendo (SNES) emulator to view the demo.
    # Build command via VS Code shortcut
    Ctrl + Shift + B
  7. Build and Clean PVSneslib projects in VS Code

    master

    Once configured, you can manage your project using VS Code tasks:

    1. Open your project folder in VS Code (File -> Open Folder...).
    2. Press Ctrl + Shift + B to trigger the build tasks.
    3. Select from the following tasks:
      • PVSneslib - Build: Compiles the project.
      • PVSneslib - Clean: Removes all object files and temporary files.

    Alternatively, you can run build commands manually via the integrated terminal after navigating to your project directory.

  8. Update VRAM using the 'Fast' method (Dynamic Tile Buffer)

    master

    For high-performance tile manipulation (e.g., event-driven or time-based changes), use the Dynamic Tile Buffer (__dtb__) and Dynamic Tile Queue (__dtq__) workflow. This method avoids full-screen updates by queuing only necessary tiles to be updated during V-Blank.

    Workflow Steps:

    1. Prepare Metadata: Call __mapGetMetaTilesInfo__ to pre-store variables required for the dynamic buffer.
    2. Setup/Update Buffer: Call __GetDynamicTileID__ to setup or update the __dtb__. This returns an index used for subsequent calls.
    3. Manipulate Tiles: Use one of the following to modify tiles using the index from step 2:
      • __mapChangeTileByID__: Changes a tile by ID and attributes.
      • __ManipulateDynamicTile__: Example of event-driven manipulation (e.g., reacting to a player collision).
      • __DynamicTileAutoUpdate__: Example of time-based manipulation (call once before queuing).
    4. Queue Tiles: Call __maptileQueueUpdate__ once before WaitForVBlank to push tiles currently on screen from the __dtb__ into the __dtq__.
    5. Flush to VRAM: Call __maptileVRAMUpdate__ once after WaitForVBlank to update the queued tiles in VRAM and flush the queue. VRAM access is only permitted during V-Blank.