Add relocation stub disassembled from original binary
This commit is contained in:
+121
@@ -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
|
||||
Reference in New Issue
Block a user