Files
yaze/docs/asar-integration.md
scawful a1429a8199 Update README and documentation for v0.3.0 release
- Revamped README.md to provide a clearer overview of the project, including updated platform support, key features, and installation instructions.
- Added a new asar-integration.md file detailing the Asar 65816 assembler integration, including usage examples and API references.
- Updated changelog.md to reflect new features and improvements in version 0.3.0, including Asar integration, ZSCustomOverworld v3, and enhanced message editing.
- Revised getting-started.md to indicate the completion of Asar patching features and updated CLI command statuses.
- Enhanced index.md to include new documentation links and a summary of major new features in the latest release.
- Improved infrastructure.md to reflect the transition to C++23 and modern CMake practices.
2025-09-25 09:28:46 -04:00

9.6 KiB

Asar 65816 Assembler Integration Guide

Yaze v0.3.0 includes complete integration with the Asar 65816 assembler, enabling cross-platform ROM patching, symbol extraction, and assembly validation for SNES development.

Overview

The Asar integration provides:

  • ROM Patching: Apply 65816 assembly patches directly to SNES ROMs
  • Symbol Extraction: Extract labels, addresses, and opcodes from assembly files
  • Assembly Validation: Comprehensive syntax checking and error reporting
  • Cross-Platform: Full support for Windows, macOS, and Linux
  • Modern APIs: Both CLI tools and C++ programming interface

Quick Examples

Command Line Usage

# Apply assembly patch to ROM
z3ed asar my_patch.asm --rom=zelda3.sfc
✅ Asar patch applied successfully!
📁 Output: zelda3_patched.sfc
🏷️  Extracted 6 symbols:
  main_routine @ $008000
  data_table @ $008020

# Extract symbols without patching
z3ed extract my_patch.asm

# Validate assembly syntax
z3ed validate my_patch.asm
✅ Assembly file is valid

# Launch interactive TUI
z3ed --tui

C++ API Usage

#include "app/core/asar_wrapper.h"

// Initialize Asar
yaze::app::core::AsarWrapper wrapper;
wrapper.Initialize();

// Apply patch to ROM
std::vector<uint8_t> rom_data = LoadRom("zelda3.sfc");
auto result = wrapper.ApplyPatch("patch.asm", rom_data);

if (result.ok() && result->success) {
    std::cout << "Found " << result->symbols.size() << " symbols:" << std::endl;
    for (const auto& symbol : result->symbols) {
        std::cout << "  " << symbol.name << " @ $" 
                  << std::hex << symbol.address << std::endl;
    }
}

// Extract symbols independently
auto symbols = wrapper.ExtractSymbols("source.asm");
auto main_symbol = wrapper.FindSymbol("main_routine");

Assembly Patch Examples

Basic Hook

; Simple code hook
org $008000
custom_hook:
    sei                 ; Disable interrupts
    rep #$30            ; 16-bit A and X/Y
    
    ; Your custom code
    lda #$1234
    sta $7E0000
    
    rts

; Data section
custom_data:
    db "YAZE", $00
    dw $1234, $5678

Advanced Features

; Constants and macros
!player_health = $7EF36C
!custom_ram = $7E2000

macro save_context()
    pha : phx : phy
endmacro

macro restore_context()
    ply : plx : pla
endmacro

; Main code
org $008000
advanced_hook:
    %save_context()
    
    ; Modify gameplay
    sep #$20
    lda #$A0            ; Full health
    sta !player_health
    
    %restore_context()
    rtl

Testing Infrastructure

ROM-Dependent Tests

Yaze includes comprehensive testing that handles ROM files properly:

// ROM tests are automatically skipped in CI
YAZE_ROM_TEST(AsarIntegration, RealRomPatching) {
    auto rom_data = TestRomManager::LoadTestRom();
    AsarWrapper wrapper;
    wrapper.Initialize();
    
    auto result = wrapper.ApplyPatch("test.asm", rom_data);
    EXPECT_TRUE(result.ok());
}

CI/CD Compatibility

  • ROM-dependent tests are labeled with ROM_DEPENDENT
  • CI automatically excludes these tests: --label-exclude ROM_DEPENDENT
  • Development builds can enable ROM testing with YAZE_ENABLE_ROM_TESTS=ON

Cross-Platform Support

Build Configuration

The Asar integration works across all supported platforms:

# Modern CMake target
target_link_libraries(my_target PRIVATE yaze::asar)

# Cross-platform definitions automatically handled
# Windows: _CRT_SECURE_NO_WARNINGS, strcasecmp=_stricmp
# Linux:   linux, stricmp=strcasecmp  
# macOS:   MACOS, stricmp=strcasecmp

Platform-Specific Notes

  • Windows: Uses static linking with proper MSVC runtime
  • macOS: Universal binaries support both Intel and Apple Silicon
  • Linux: Compatible with both GCC and Clang compilers

API Reference

AsarWrapper Class

namespace yaze::app::core {

class AsarWrapper {
public:
    // Initialization
    absl::Status Initialize();
    void Shutdown();
    bool IsInitialized() const;
    
    // Core functionality
    absl::StatusOr<AsarPatchResult> ApplyPatch(
        const std::string& patch_path,
        std::vector<uint8_t>& rom_data,
        const std::vector<std::string>& include_paths = {});
    
    absl::StatusOr<std::vector<AsarSymbol>> ExtractSymbols(
        const std::string& asm_path,
        const std::vector<std::string>& include_paths = {});
    
    // Symbol management
    std::optional<AsarSymbol> FindSymbol(const std::string& name);
    std::vector<AsarSymbol> GetSymbolsAtAddress(uint32_t address);
    std::map<std::string, AsarSymbol> GetSymbolTable();
    
    // Utility functions
    absl::Status ValidateAssembly(const std::string& asm_path);
    std::string GetVersion();
    void Reset();
};

}

Data Structures

struct AsarSymbol {
    std::string name;           // Symbol name
    uint32_t address;          // Memory address  
    std::string opcode;        // Associated opcode
    std::string file;          // Source file
    int line;                  // Line number
    std::string comment;       // Optional comment
};

struct AsarPatchResult {
    bool success;              // Whether patch succeeded
    std::vector<std::string> errors;     // Error messages
    std::vector<std::string> warnings;   // Warning messages  
    std::vector<AsarSymbol> symbols;     // Extracted symbols
    uint32_t rom_size;         // Final ROM size
    uint32_t crc32;            // CRC32 checksum
};

Error Handling

Common Errors and Solutions

Error Cause Solution
Unknown command Invalid opcode Check 65816 instruction reference
Label not found Undefined label Define the label or check spelling
Invalid hex value Bad hex format Use $1234 format, not $GOOD
Buffer too small ROM needs expansion Check if ROM needs to be larger

Error Handling Pattern

auto result = wrapper.ApplyPatch("patch.asm", rom_data);
if (!result.ok()) {
    std::cerr << "Patch failed: " << result.status().message() << std::endl;
    return;
}

if (!result->success) {
    std::cerr << "Assembly errors:" << std::endl;
    for (const auto& error : result->errors) {
        std::cerr << "  " << error << std::endl;
    }
}

Development Workflow

CMake Presets

# Development build with ROM testing
cmake --preset dev
cmake --build --preset dev
ctest --preset dev

# CI-compatible build (no ROM tests)
cmake --preset ci 
cmake --build --preset ci
ctest --preset ci

# Release build with packaging
cmake --preset macos-release
cmake --build --preset macos-release
cmake --build --preset macos-release --target package

Testing Workflow

  1. Write assembly patch
  2. Validate syntax: z3ed validate patch.asm
  3. Extract symbols: z3ed extract patch.asm
  4. Apply to test ROM: z3ed asar patch.asm --rom=test.sfc
  5. Test in emulator

Integration with Yaze Editor

The Asar integration is built into the main yaze editor:

  • Assembly Editor: Real-time syntax validation
  • Project System: Save/load assembly patches with projects
  • Symbol Browser: Navigate symbols with address lookup
  • Patch Management: Apply and manage multiple patches

Performance and Memory

  • Large ROM Support: Handles ROMs up to 16MB
  • Efficient Symbol Storage: Hash-based symbol lookup
  • Memory Safety: RAII and smart pointer usage
  • Cross-Platform Optimization: Platform-specific optimizations

Future Enhancements

Planned improvements for future versions:

  • Real-time Assembly: Live compilation and testing
  • Visual Debugging: Assembly debugging tools
  • Patch Management: GUI for managing multiple patches
  • Symbol Navigation: Enhanced symbol browser with search

Assembly Patch Templates

Basic Assembly Structure

; Header comment explaining the patch
; Author: Your Name
; Purpose: Brief description

; Constants section
!player_health = $7EF36C
!custom_ram = $7E2000

; Code section
org $008000
main_hook:
    ; Save context
    pha : phx : phy
    
    ; Your custom code here
    sep #$20            ; 8-bit A
    lda #$A0            ; Full health
    sta !player_health
    
    ; Restore context
    ply : plx : pla
    rts

; Data section
data_table:
    dw $1234, $5678, $9ABC

Advanced Features

; Macro definitions
macro save_registers()
    pha : phx : phy
endmacro

macro restore_registers()
    ply : plx : pla
endmacro

; Conditional assembly
if !version == 3
    ; ZSCustomOverworld v3 specific code
    org $C08000
else
    ; Vanilla ROM code
    org $008000
endif

advanced_routine:
    %save_registers()
    
    ; Complex logic here
    
    %restore_registers()
    rtl

Testing Your Patches

Development Workflow

  1. Write Assembly: Create your .asm patch file
  2. Validate: z3ed validate patch.asm
  3. Extract Symbols: z3ed extract patch.asm
  4. Apply Patch: z3ed asar patch.asm --rom=test.sfc
  5. Test in Emulator: Verify functionality

Best Practices

  • Always backup ROMs before patching
  • Use test ROMs for development
  • Validate assembly before applying
  • Start with simple patches and build complexity
  • Document your patches with clear comments

Troubleshooting

Common Issues

Issue Solution
"Unknown command" Check 65816 instruction reference
"Label not found" Define the label or check spelling
"Invalid hex value" Use $1234 format, not $GOOD
"Buffer too small" ROM may need expansion

Getting Help


For complete API reference and advanced usage, see the documentation index.