Modifications Used to Create the ASMPATCH Assembler/Linker/Patcher

I've enjoyed extending and using the Merlin32 assembler in order to make ASMPATCH. I don't like its expression syntax. But that goes back to the late 1980's when the Merlin8/16 product was written and is no fault of the Merlin32 author (who's only fault is in trying to create a work-alike tool.) It is also targeting Apple IIgs code development so it may seem a little strange from the perspective of a NES or SNES assembly writer or ROM hacker. But it does have some nice aspects. It's available in source code, the source code is quite readable, and the code is consistently written and relatively easy to read. What really clinched the deal for me is that the internal design approach treats every assembly line as though it were a separate assembly source code file all of its own. So each line has its own "address" and its own "little bit of generated data" and there are few assumptions made beyond that. It does not assume any particular memory system, for example. It just doesn't care, since each line almost "lives in its own lilttle world." This fact alone makes it really easy to adapt in almost any direction, since there are no specific, assumed memory models to interfere.

     Related Pages

  Discussion and example source code using ASMPATCH ASMPATCH: Patching SNES ROMs from Assembly  
  Linker concepts needed to understand ASMPATCH's approach to patching ROMs ASMPATCH: ROM Patching Concepts  

 

Modifications to Merlin32 in order to make ASMPATCH

The changes I made for assembly, linker file processing, and patching fit into the following categories:

    Support PC-Relative and PC-Relative-Long Branching

  Accept (don't reject) external symbol references, deferring pc-relative distance errors until link-time assembly phase  
  Generate relocation record when external symbols are referenced and accepted assembly phase  
  Extend relocation record to provide signal linking PC-relative values at link-time assembly phase  
  Extend relocation record to support appropriate link-time error messages assembly phase  
  Added support for linking external symbol pc-relative references; plus errors as appropriate link phase  
 

    Linker File Parsing Extensions

  Parse BSZ (was noted in the code, but wasn't parsed) to set patch segment end limitation assembly phase  
  Parse RMI to set the source ROM filename to be copied and then modified assembly phase  
  Parse RMO to set the destination ROM filename to be updated in place during patching
assembly phase  
  Parse MAP to set ROM mapping of CPU address space to ROM disk file address space assembly phase  
  Parse ROM to link a patch segment to a ROM section for updating during patching assembly phase  
 

    ROM Patching Extensions

  ORG now sets the lowest address that may be patched by a patch segment patch phase  
  BSZ sets the highest address that may be patched by a patch segment patch phase  
  RMI+RMO are used to either copy+modify, or directly modify, a ROM file (or default to prior behavior, if missing) patch phase  
  MAP sections named by patch segments (using ROM) are modified by generated code and data patch phase  
  CHK directive, for patching purposes, always generates a value of 0 patch phase  
  Direct use of assembled segments and associated generated bytes to patch ROM files patch phase  
  DS avoids patching the ROM when the default data value of 0 is implied or used patch phase  
  ORG avoids patching the ROM with 'filler' when skipping over memory addresses patch phase  
  Extensive patch warning messages and patch information added patch phase  
 

    Other

  Added -Q quiet mode assembly and link phase  

The assembly and linking of the assembly code source is unchanged, other than as indicated above. In fact, outside of the changes regarding the pc-relative and pc-relative-long addressing where an external label was involved, there were no changes. The linker file processing was changed quite a bit, however, in order to support direct ROM patching by ASMPATCH. Finally, of course, there was the block of changes required to actually patch the ROM and to report any related warnings or errors during that added process step. There were no substantial changes to the processing of source code, so all you need to do is follow the existing documentation for using Merlin32. There are a few minor changes for patchiong behavior. The DS directive normally allows you to generate blocks of data. The only change here is about interpretation, not syntax, in the context of ROM patching. If you use the default data value for DS (which is 0), then the patching program will skip over directly patching 0 values into the ROM file. In addition, the CHK directive (which supposedly generates checksums on the fly) uses an algorithm that isn't needed here. So I generate a 0 value for it.

 

Last updated 5/17/2016, 15:50 UT. You may contact me at jonk at infinitefactors dot org.