aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2025-04-23 06:36:00 -0400
committerB. Watson <urchlay@slackware.uk>2025-04-23 06:36:00 -0400
commit8158e2e1b60484c8c12da62afbd439d810e96c3e (patch)
treef30742bcd6a57c63f0d1c26b0bbca3f3ccdd3b89
parent3a120e78480a3b43c5cf32d9e6efae5a698abd38 (diff)
downloadatari8-self-relocator-8158e2e1b60484c8c12da62afbd439d810e96c3e.tar.gz
reloc.s: optimize for size.
-rw-r--r--README.txt32
-rw-r--r--autorun.sysbin1206 -> 1117 bytes
-rw-r--r--reloc.s37
3 files changed, 45 insertions, 24 deletions
diff --git a/README.txt b/README.txt
index 07ee72b..5505d95 100644
--- a/README.txt
+++ b/README.txt
@@ -34,7 +34,7 @@ it'll actually run in its new location.
Unfortunately, the code can only be relocated by multiples of 256
bytes. The low bytes aren't adjusted. So unless MEMLO happens to
-contain $FF in its low byte, some memory will be wasted (up to 256
+contain $FF in its low byte, some memory will be wasted (up to 255
bytes).
The code from Insight: Atari is doesn't produce self-relocating
@@ -229,30 +229,32 @@ $09 $40 ; hi byte of LDA $4015 operand
$10 $40 ; hi byte of LDA $4016
$00 $00 ; terminator
-Low byte relocation table:
-
-$01 $40 ; lo byte of JSR $4007 operand
-$04 $40 ; lo byte of JSR $400E operand
-$08 $40 ; lo byte of LDA $4015 operand
-$0F $40 ; lo byte of LDA $4016
-$00 $00 ; terminator
-
Program loads from $4000 to $4016. If MEMLO was $1CFC, the relocator
-will move the program to $1CFC - $1D12 and set MEMLO to $1D13. The
+will move the program to $1D00 - $1D16 and set MEMLO to $1D17. The
operand of the first instruction (was JSR $4007) will be altered
-to $1D03 (aka $4007 - $4000 + $1CFC), which is the address that the
+to $1D07 (aka $4007 - $4000 + $1CFC), which is the address that the
subroutine got relocated to.
The original program assembled to a 32-byte file. The relocatable
-version will be around 200 bytes: 28 bytes for the original file
-(minus its INITAD segment), ~128 bytes for the relocator code, 8 bytes
-for the address table, and 20 bytes for the two relocation tables.
+version will be around 400 bytes: 28 bytes for the original file
+(minus its INITAD segment), ~300 bytes for the relocator code, 8
+bytes for the address table, and 10 bytes for the relocation table.
However, the relocator and tables are only used once, and can be
overwritten afterwards (so they count as free memory).
Relocation Table Format
-Bitmap.
+Current implementation:
+
+A list of addresses that need to be adjusted (high bytes of absolute
+addresses), 2 bytes each, terminated with $00 $00.
+
+Possible future implementation:
+
+Bitmap. One bit per byte in the file. 1 if the address needs
+adjusting, 0 if not. This *probably* will actually be smaller than
+the list of addresses. Also has the advantage of being a fixed size,
+easily calculated/predicted.
The relocator is 256 bytes long or less.
The GR.0 display list with a 16K cart in is at $7C20.
diff --git a/autorun.sys b/autorun.sys
index 41fc439..2ef3512 100644
--- a/autorun.sys
+++ b/autorun.sys
Binary files differ
diff --git a/reloc.s b/reloc.s
index 3702430..530e303 100644
--- a/reloc.s
+++ b/reloc.s
@@ -1,4 +1,8 @@
+; uncomment to enable user-friendly "MEMLO is too high" error.
+; adds ~80 bytes to the code size (40% larger).
+ ;verbose_memlo_check = 1
+
.export _main
.include "atari.inc"
@@ -39,6 +43,7 @@ memlo_00:
bcs memlo_ok
+ .ifdef verbose_memlo_check
; whoops, MEMLO is too high
whoops:
ldx #0
@@ -61,22 +66,31 @@ exitwait:
lda #0
sta COLOR2
rts
+ .else
+ lda #$40
+ sta COLOR2
+freeze: bne freeze
+ .endif
memlo_ok:
- ; adjust addresses before moving the code
+ ; adjust addresses before moving the code.
+ ; point to the relocation table...
lda #<table
sta table_ptr
lda #>table
sta table_ptr+1
fixup_addrs:
+ ; walk the reloc table
ldy #1
lda (table_ptr),y
sta code_ptr+1
dey
lda (table_ptr),y
sta code_ptr
- inc table_ptr ; point to next entry
+
+ ; point to next table entry
+ inc table_ptr
bne tp1ok
inc table_ptr+1
tp1ok:
@@ -84,7 +98,8 @@ tp1ok:
bne tp2ok
inc table_ptr+1
tp2ok:
- ora code_ptr+1 ; quit if we hit $0000 in the table
+
+ ora code_ptr+1 ; A still has code_ptr, quit if we hit $0000 in the table
beq fixup_done
lda (code_ptr),y ; Y still 0
sec
@@ -127,7 +142,6 @@ move_loop:
dex
bne move_loop
-
; bump MEMLO to point one byte past the end of the moved code.
lda code_end
sec
@@ -136,12 +150,13 @@ move_loop:
lda code_end+1
sbc code_start+1
sta code_end+1
- inc code_end
- bne ceok
- inc code_end+1 ; code_end is now the code length + 1 byte
-ceok:
+ ;inc code_end
+ ;bne ceok
+ ;inc code_end+1 ; code_end is now the code length + 1 byte
+;ceok:
lda code_end
- clc
+ ;clc
+ sec
adc MEMLO
sta MEMLO
lda code_end+1
@@ -175,11 +190,15 @@ do_init:
done:
rts
+ .ifdef verbose_memlo_check
whoops_msg: .byte "MEMLO is too high! Press any key to exit.", EOL
whoops_len = (*-whoops_msg)
+ .endif
end_addr:
+ .out .sprintf("reloc.s code size $%04x (%d)", (* - start_addr), (* - start_addr))
+
; this was for testing only. mkrelocxex.c adds the init address.
; .word INITAD
; .word INITAD+1