diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | autorun.sys | bin | 1113 -> 1151 bytes | |||
-rwxr-xr-x | mkrelocxex.pl | 44 | ||||
-rw-r--r-- | reloc.s | 79 |
4 files changed, 67 insertions, 58 deletions
@@ -5,7 +5,7 @@ reloc.atr: reloc.xex hello40.xex hello41.xex mkrelocxex.pl autorun.sys autorun.sys: reloc.xex hello40.xex hello41.xex ./mkrelocxex.pl hello40.xex hello41.xex autorun.sys -reloc.xex: reloc.s +reloc.xex: reloc.s mkrelocxex.pl cl65 -t none -o reloc.xex reloc.s hello40.xex: hello.s diff --git a/autorun.sys b/autorun.sys Binary files differindex 8aedd8b..65b4c28 100644 --- a/autorun.sys +++ b/autorun.sys diff --git a/mkrelocxex.pl b/mkrelocxex.pl index a871cd5..a46360b 100755 --- a/mkrelocxex.pl +++ b/mkrelocxex.pl @@ -2,6 +2,7 @@ # mkrelocxex prototype in perl (will rewrite in C). # this version only supports init addresses, not run addresses. +# *very* ugly code, sorry about that. use bytes; @@ -45,17 +46,6 @@ sub read_seg { return @bytes; } -sub print_table { - my ($name, $t) = @_; - print "\n$name byte table:\n"; - my $i = 0; - for(@$t) { - printf "\$%04x ", $_; - print "\n" if $i && ($i & 10 == 0); - } - print "\n"; -} - ($start, $end) = read_header($lo); ($hi_start, $hi_end) = read_header($hi); @@ -77,20 +67,33 @@ if(($hi_start != ($start + 0x0100)) || ($hi_end != ($end + 0x0100))) { @bytes = read_seg($lo, $start, $end); @hi_bytes = read_seg($hi, $hi_start, $hi_end); +@bit_table = (); for($i = 0; $i < @bytes; $i++) { my ($a, $b) = ($bytes[$i], $hi_bytes[$i]); - next if $a == $b; - if($b == ($a + 1)) { - push @hi_table, ($i + $start); + my $bit; + + if($a == $b) { + $bit = 0; + } elsif($b == ($a + 1)) { + $bit = 1; } else { die "invalid difference (not 0 or 1)\n"; } + + my $table_idx = int($i / 8); + my $pos = 7 - $i % 8; + #warn "$i $table_idx $pos\n"; + $bit_table[$table_idx] |= ($bit * (1 << $pos)); } -push(@hi_table, 0); +$offset = $start; -print_table("hi", \@hi_table); -print "table size: " . @hi_table . " bytes\n\n"; +if(0) { + for(@bit_table) { + printf("\$%04x: %08b \$%04x\n", $offset, $_, $_); + $offset += 8; + } +} ($istart, $iend) = read_header($lo); @@ -127,9 +130,12 @@ $rcode .= chr(0); $rcode .= chr($init & 0xff); $rcode .= chr($init >> 8); -for(@hi_table) { +printf "bitmap table starts at \$%04x\n", ($rstart + length($rcode)); + +for(@bit_table) { + die "bad relocation" if $_ > 0xff; $rcode .= chr($_ & 0xff); - $rcode .= chr($_ >> 8); + #$rcode .= chr($_ >> 8); } $rend = $rstart + length($rcode) - 1; @@ -18,8 +18,10 @@ zp_addr = FR0 offset_pages = zp_addr ; 1 byte table_ptr = zp_addr+1 ; 2 bytes - dest_ptr = table_ptr ; alias - code_ptr = zp_addr+3 ; 2 bytes + dest_ptr = zp_addr+3 ; 2 bytes + code_ptr = zp_addr+5 ; 2 bytes + shfreg = zp_addr+7 ; 1 byte + pagecount = zp_addr+8 ; 1 byte .org start_addr - 6 .word $ffff @@ -41,7 +43,7 @@ memlo_00: sbc MEMLO+1 sta offset_pages - bcs memlo_ok + bcs relocate_code .ifdef verbose_memlo_check ; whoops, MEMLO is too high, print message and wait for keystroke @@ -72,74 +74,75 @@ exitwait: freeze: bne freeze ; wait for the user to press Reset. .endif -memlo_ok: - ; adjust addresses before moving the code. +relocate_code: + ; adjust addresses while 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 - - ; point to next table entry - inc table_ptr - bne tp1ok - inc table_ptr+1 -tp1ok: - inc table_ptr - bne tp2ok - inc table_ptr+1 -tp2ok: - - 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 - sbc offset_pages - sta (code_ptr),y - sec ; *should* already be set... - bcs fixup_addrs -fixup_done: - - ; absolute addresses are fixed up, now move the code. + ; ...and to the code we're moving... lda code_start sta code_ptr lda code_start+1 sta code_ptr+1 + + ; ...and to the destination we're moving to. lda MEMLO sta dest_ptr lda MEMLO+1 sta dest_ptr+1 - ; x = (code_end >> 8) - (code_start >> 8) + 2 + ; pagecount = (code_end >> 8) - (code_start >> 8) + 2 lda code_end+1 sec sbc code_start+1 tax inx inx - ldy #0 + stx pagecount + + ldx #0 + lda (table_ptr,x) + sta shfreg ; this moves a page at a time, meaning if code_end isn't ; on an even page boundary, we move a little more than ; needed. it won't hurt anything, and it follows the ; KISS principle. + ldy #0 move_loop: lda (code_ptr),y + pha + cpx #8 + bne shiftit + + ; bump bitmap pointer + inc table_ptr + bne tpok + inc table_ptr+1 + +tpok: + ; get next byte of bitmap + ldx #0 + lda (table_ptr,x) + sta shfreg + +shiftit: + inx + pla + asl shfreg + bcc dontadj + sbc offset_pages + +dontadj: sta (dest_ptr),y iny bne move_loop inc code_ptr+1 inc dest_ptr+1 - dex + dec pagecount bne move_loop ; bump MEMLO to point one byte past the end of the moved code. |