Add relocation stub disassembled from original binary

This commit is contained in:
J.B. Langston
2017-02-02 23:24:38 -05:00
parent 98189faa00
commit 8c788d7024
+121
View File
@@ -0,0 +1,121 @@
; Relocatable code stub for Supermon 64 by Jim Butterfield
; Jim Butterfield described the post-processing of Supermon 64 binaries
; in a posting to comp.sys.cbm on Dec 20, 2003:
; I should note that, since Supermon+64 is relocatable code, the source
; does not assemble into the final binary file. It may seem crude, but
; I follow this procedure: (1) The source is carefully structured so
; that there are no "dispersed addresses" such as might be created with
; something like LDA #>VECTOR .. LDY #<VECTOR - every relocatable
; address is two adjacent bytes; (2) I assemble the source TWICE, to
; two different page addresses; the only difference in the binaries will
; be the high-order bytes of the relocatable addresses; (3) a small
; post-processing program blends the two binaries into a relocatable
; package, adding a Basic driver to complete the bundle.
; Source: https://groups.google.com/forum/#!searchin/comp.sys.cbm/supermon$2064%7Csort:relevance/comp.sys.cbm/5owItyf5qjk/50_UQlwVnPcJ
; This code was disassembled from the original Supermon+64 V1.2 binary.
; The relocation stub starts at the Start of Variables pointer (VARTAB) and
; works backwards through the Supermon64 machine code, copying it to the top
; of basic memory pointer (MEMSIZ), and decrementing the pointer as it goes.
; Relative addresses that need to be adjusted are marked with a $36 byte
; immediately following them. Since we're working backwards, the marker is
; encountered first, then the high byte, then the low byte of the address
; needing to be adjusted. The relative addresses are calculated such that
; adding the top of memory to them will yield the absolute address of the
; jump target in the relocated code.
; The next step will be to build a Python script that will take Supermon64
; binaries assembled to two different addresses and output relocatable code
; with the relative addresses and $36 address markers.
; ----------------------------------------------------------------------------
; variables
SOURCE = $22 ; first temp variable
TOPMEM = $24 ; highest address available to BASIC
LASTBYT = $26 ; previous byte encountered
VARTAB = $2D ; pointer to start of BASIC variable storage area
FRETOP = $33 ; pointer to bottom of string text storage area
TARGET = $37 ; end of basic memory/start of machine code (aka MEMSIZ)
; ----------------------------------------------------------------------------
; basic header
* = $0801
; 100 PRINT "{DOWN}SUPERMON+64 JIM BUTTERFIELD"
; 110 SYS(PEEK(43)+256*PEEK(44)+71)
.BYTE $29,$08,$64,$00,$99,$20,$22,$11
.TEXT "SUPERMON+64 JIM BUTTERFIELD"
.BYTE $22,$00,$43,$08,$6E,$00,$9E,$28
.BYTE $C2,$28,$34,$33,$29,$AA,$32,$35
.BYTE $36,$AC,$C2,$28,$34,$34,$29,$AA
.BYTE $37,$31,$29,$00,$00,$00,$00,$00
.BYTE $00
; ----------------------------------------------------------------------------
; relocator stub
LDA VARTAB ; start copying from the start of basic variables
STA SOURCE
LDA VARTAB+1
STA SOURCE+1
LDA TARGET ; start copying to the end of BASIC memory
STA TOPMEM
LDA TARGET+1
STA TOPMEM+1
LOOP LDY #$00 ; no offset from pointers
LDA SOURCE ; decrement two-byte source address
BNE NB1
DEC SOURCE+1
NB1 DEC SOURCE
LDA (SOURCE),Y ; get byte currently pointed to by SOURCE
CMP #$36 ; check for address marker ($36)
BNE NOADJ ; skip address adjustment unless found
LDA SOURCE ; decrement two-byte source address
BNE NB2
DEC SOURCE+1
NB2 DEC SOURCE
LDA (SOURCE),Y ; get byte currently pointed to by SOURCE
CMP #$36 ; check for second consecutive marker ($36)
BEQ DONE ; if found, we're done with relocation
STA LASTBYT ; if not, save byte for later
LDA SOURCE ; decrement two-byte source address
BNE NB3
DEC SOURCE+1
NB3 DEC SOURCE
LDA (SOURCE),Y ; current byte is low byte of relative address
CLC
ADC TOPMEM ; calc absolute low byte by adding top of memory
TAX ; save absolute low byte in X
LDA LASTBYT ; previous byte is high byte of relative address
ADC TOPMEM+1 ; calc absolute high byte by adding top of memory
PHA ; save absolute high byte on stack
LDA TARGET ; decrement two-byte target address
BNE NB4
DEC TARGET+1
NB4 DEC TARGET
PLA ; retrieve absolute high byte from stack
STA (TARGET),Y ; save it to the target address
TXA ; retrieve absolute low byte from stack
NOADJ PHA ; save current byte on stack
LDA TARGET ; decrement two-byte target address
BNE NB5
DEC TARGET+1
NB5 DEC TARGET
PLA ; retrieve current byte from stack
STA (TARGET),Y ; save it in the target address
CLC ; clear carry for unconditional loop
BCC LOOP ; rinse, repeat
DONE LDA TARGET ; fix pointer to string storage
STA FRETOP
LDA TARGET+1
STA FRETOP+1
JMP (TARGET) ; jump to the beginning of the relocated code