Rename my_loader to hires_loader, implement rle_loader (needed so as not to overwrite...
authorNick Downing <nick@ndcode.org>
Mon, 13 Jun 2022 06:23:02 +0000 (16:23 +1000)
committerNick Downing <nick@ndcode.org>
Tue, 14 Jun 2022 07:18:47 +0000 (17:18 +1000)
disasm/Makefile
emu_65c02/emu_65c02.c
loader/Makefile
loader/hires_loader.asm [moved from loader/my_loader.asm with 100% similarity]
loader/hires_loader.py [moved from loader/my_loader.py with 100% similarity]
loader/rle_decode.py [new file with mode: 0755]
loader/rle_encode.py [new file with mode: 0755]
loader/rle_loader.asm [new file with mode: 0644]

index 3b06093..2051142 100644 (file)
@@ -3,6 +3,8 @@ DOS33=../dos33fsprogs/utils/dos33fs-utils/dos33
 AS6500=../asxv5pxx/asxmak/linux/exe/as6500
 ASLINK=../asxv5pxx/asxmak/linux/exe/aslink
 
+RLE_LOADER=0x800
+
 .PHONY: all
 all: \
 star_blazer.dsk \
@@ -17,13 +19,22 @@ shape4.png \
 shape5.png \
 shape6.png
 
-star_blazer.dsk: ../util/bootable.dsk star_blazer.bin
+star_blazer.dsk: ../util/bootable.dsk star_blazer_rle_loader.bin
        cp ../util/bootable.dsk $@
-       ${DOS33} $@ SAVE B star_blazer.bin "STAR BLAZER"
-
-star_blazer.bin: star_blazer.ihx ../loader/star_blazer_my_loader.bin
+       ${DOS33} $@ SAVE B star_blazer_rle_loader.bin "STAR BLAZER RLE LOADER"
+
+star_blazer_rle_loader.bin: \
+star_blazer_hires_loader.bin \
+../loader/rle_loader.bin \
+../loader/star_blazer_rle_loader.bin
+       ../loader/rle_encode.py ${RLE_LOADER} ../loader/rle_loader.bin $< $@
+       -diff -q ../loader/star_blazer_rle_loader.bin $@
+
+star_blazer_hires_loader.bin: \
+star_blazer.ihx \
+../loader/star_blazer_hires_loader.bin
        ./pack.py $< $@
-       -diff -q ../loader/star_blazer_my_loader.bin $@
+       -diff -q ../loader/star_blazer_hires_loader.bin $@
 
 star_blazer.ihx: star_blazer.rel
        ${ASLINK} -n -m -u -i \
@@ -107,7 +118,7 @@ shape0b.png: shape0.png shape0a.png
 shape0c.png: shape_dhgr.png
        ./shape_color_to_mono.py $< $@
 
-mem.bin: ../loader/star_blazer_my_loader.bin
+mem.bin: ../loader/star_blazer_hires_loader.bin
        ./load.py $^ $@
 
 .PHONY: clean
index b53527e..017b1c9 100644 (file)
@@ -949,9 +949,13 @@ int main(int argc, char **argv) {
 
   // do this before creating the CPU
   if (load_address != -1) {
-    lc_state = LC_SELECT_RAM_WP | LC_BANK2;
-    mem[RESET_VECTOR] = (uint8_t)(load_address & 0xff);
-    mem[RESET_VECTOR + 1] = (uint8_t)(load_address >> 8);
+#if APPLE_IIE
+    ef_rom[RESET_VECTOR & 0x1fff] = (uint8_t)(load_address & 0xff);
+    ef_rom[(RESET_VECTOR + 1) & 0x1fff] = (uint8_t)(load_address >> 8);
+#else
+    f8_rom[RESET_VECTOR & 0x7ff] = (uint8_t)(load_address & 0xff);
+    f8_rom[(RESET_VECTOR + 1) & 0x7ff] = (uint8_t)(load_address >> 8);
+#endif
   }
 
   // open pty and child process if requested
index df63d32..abca368 100755 (executable)
@@ -7,17 +7,17 @@ ASLINK=../asxv5pxx/asxmak/linux/exe/aslink
 
 # need to install intelhex package in Python first:
 #   pip3 install --user intelhex
-HEX2BIN=python3 ${HOME}/.local/bin/hex2bin.py
+HEX2BIN=hex2bin.py
 
-# also address of the loader
-HIRES_SCREEN=0x2000
+RLE_LOADER=0x800
+HIRES_LOADER=0x2000
 
 .PHONY: all
 all: \
 star_blazer.bin \
 star_blazer_dejunked0.bin \
 star_blazer_dejunked1.bin \
-star_blazer_my_loader.bin
+star_blazer_rle_loader.bin
 
 star_blazer.bin: ../orig/Star_Blazer_1981_Star_Craft.do
        ${DOS33} ../orig/Star_Blazer_1981_Star_Craft.do LOAD "STAR BLAZER" $@
@@ -28,16 +28,28 @@ star_blazer_dejunked0.bin: star_blazer.bin
 star_blazer_dejunked1.bin: star_blazer.bin
        ./dejunk.py $< $@ 0xff
 
-star_blazer_my_loader.bin: my_loader.bin star_blazer_dejunked0.bin
-       ./my_loader.py $^ $@
+star_blazer_rle_loader.bin: rle_loader.bin star_blazer_hires_loader.bin
+       ./rle_encode.py ${RLE_LOADER} $^ $@
 
-my_loader.bin: my_loader.ihx
+rle_loader.bin: rle_loader.ihx
        ${HEX2BIN} $< $@
 
-my_loader.ihx: my_loader.rel
-       ${ASLINK} -n -m -u -i -b text=${HIRES_SCREEN} $@ $^
+rle_loader.ihx: rle_loader.rel
+       ${ASLINK} -n -m -u -i -b text=${RLE_LOADER} $@ $^
 
-my_loader.rel: my_loader.asm
+rle_loader.rel: rle_loader.asm
+       ${AS6500} -l -o $<
+
+star_blazer_hires_loader.bin: hires_loader.bin star_blazer_dejunked0.bin
+       ./hires_loader.py $^ $@
+
+hires_loader.bin: hires_loader.ihx
+       ${HEX2BIN} $< $@
+
+hires_loader.ihx: hires_loader.rel
+       ${ASLINK} -n -m -u -i -b text=${HIRES_LOADER} $@ $^
+
+hires_loader.rel: hires_loader.asm
        ${AS6500} -l -o $<
 
 clean:
similarity index 100%
rename from loader/my_loader.asm
rename to loader/hires_loader.asm
similarity index 100%
rename from loader/my_loader.py
rename to loader/hires_loader.py
diff --git a/loader/rle_decode.py b/loader/rle_decode.py
new file mode 100755 (executable)
index 0000000..eed82fb
--- /dev/null
@@ -0,0 +1,77 @@
+#!/usr/bin/env python3
+
+import sys
+
+EXIT_SUCCESS = 0
+EXIT_FAILURE = 1
+
+# key byte is partitioned as follows
+KEY_EOF = 0
+KEY_LIT = 1 # literal lengths 01..af
+KEY_RUN = 0xb0 # run lengths 02..51
+N_KEYS = 0x100
+
+if len(sys.argv) < 3:
+  print(f'usage: {sys.argv[0]:s} in.bin out.bin')
+  sys.exit(EXIT_FAILURE)
+in_bin = sys.argv[1]
+out_bin = sys.argv[2]
+
+with open(in_bin, 'rb') as fin:
+  data = list(fin.read())
+  hdr = data[:4]
+  rle = data[4:]
+load_addr = hdr[0] | (hdr[1] << 8)
+assert hdr[2] == len(rle) & 0xff
+assert hdr[3] == len(rle) >> 8
+
+assert rle[0] == 0xa9 # lda #NN
+assert rle[4] == 0xa9 # lda #NN
+src = rle[1] | (rle[5] << 8)
+assert src == load_addr + len(rle) - 1
+
+assert rle[8] == 0xa9 # lda #NN
+assert rle[0xc] == 0xa9 # lda #NN
+dest = rle[9] + (rle[0xd] << 8)
+
+assert rle[0x67] == 0x4c # jmp NNNN
+start = rle[0x68] | (rle[0x69] << 8)
+
+bin = [0] * (dest + 1 - start)
+print(f'rle {len(rle):04x} bin {len(bin):04x}')
+
+i = len(rle)
+j = len(bin)
+while True:
+  i -= 1
+  assert i >= 0x6a
+  count = rle[i]
+  if count == KEY_EOF:
+    break
+  if count < KEY_RUN:
+    i -= count
+    assert i >= 0x6a
+
+    j -= count
+    assert j >= 0
+
+    bin[j:j + count] = rle[i:i + count]
+  else:
+    count -= KEY_RUN - 2
+
+    i -= 1
+    assert i >= 0
+
+    j -= count
+    assert j >= 0
+
+    bin[j:j + count] = rle[i:i + 1] * count
+assert i == 0x6a
+assert j == 0
+
+load_addr = start
+load_size = len(bin)
+hdr = [load_addr & 0xff, load_addr >> 8, load_size & 0xff, load_size >> 8]
+
+with open(out_bin, 'wb') as fout:
+  fout.write(bytes(hdr + bin))
diff --git a/loader/rle_encode.py b/loader/rle_encode.py
new file mode 100755 (executable)
index 0000000..ac52e58
--- /dev/null
@@ -0,0 +1,120 @@
+#!/usr/bin/env python3
+
+import sys
+
+EXIT_SUCCESS = 0
+EXIT_FAILURE = 1
+
+# key byte is partitioned as follows
+KEY_EOF = 0
+KEY_LIT = 1 # literal lengths 01..af
+KEY_RUN = 0xb0 # run lengths 02..51
+N_KEYS = 0x100
+
+MAX_LIT = KEY_RUN - KEY_LIT # af
+MAX_RUN = N_KEYS - KEY_RUN + 1 # 51
+
+if len(sys.argv) < 5:
+  print(f'usage: {sys.argv[0]:s} load_addr rle_loader.bin in.bin out.bin')
+  sys.exit(EXIT_FAILURE)
+load_addr = int(sys.argv[1], 0)
+rle_loader_bin = sys.argv[2]
+in_bin = sys.argv[3]
+out_bin = sys.argv[4]
+
+with open(rle_loader_bin, 'rb') as fin:
+  rle_loader = list(fin.read())
+assert len(rle_loader) == 0x6a
+
+with open(in_bin, 'rb') as fin:
+  data = list(fin.read())
+  hdr = data[:4]
+  bin = data[4:]
+start = hdr[0] | (hdr[1] << 8)
+assert hdr[2] == len(bin) & 0xff
+assert hdr[3] == len(bin) >> 8
+
+rle = [0] * (len(bin) + (len(bin) >> 7) + 2)
+
+i = len(bin)
+j = len(rle)
+while i:
+  # look for a run
+  count = 1
+  while (
+    count < MAX_RUN and
+      i - count - 1 >= 0 and
+      bin[i - count - 1] == bin[i - 1]
+  ):
+    count += 1
+
+  # since we are in key mode we can output runs of at least 2
+  if count >= 2:
+    i -= count
+    assert i >= 0
+
+    j -= 1
+    assert j >= 0
+    rle[j] = KEY_RUN + count - 2
+
+    j -= 1
+    assert j >= 0
+    rle[j] = bin[i]
+  else:
+    # we will have to start literal mode, stop with a run of at least 3
+    count = 1
+    while (
+      count < MAX_LIT and count < i and (
+        i - count - 3 < 0 or
+          bin[i - count - 2] != bin[i - count - 1] or
+          bin[i - count - 3] != bin[i - count - 1]
+      )
+    ):
+      count += 1
+
+    # but do not stop in the middle of a pair
+    if (
+      count == MAX_LIT and
+        count + 1 <= i and
+        bin[i - count - 1] == bin[i - count]
+    ):
+      count -= 1
+
+    i -= count
+    assert i >= 0
+
+    j -= 1
+    assert j >= 0
+    rle[j] = KEY_LIT + count - 1
+
+    j -= count
+    assert j >= 0
+    rle[j:j + count] = bin[i:i + count]
+j -= 1
+assert j >= 0
+rle[j] = KEY_EOF
+
+rle = rle_loader + rle[j:]
+print(f'bin {len(bin):04x} rle {len(rle):04x}')
+
+src = load_addr + len(rle) - 1
+assert rle[0] == 0xa9 # lda #NN
+rle[1] = src & 0xff
+assert rle[4] == 0xa9 # lda #NN
+rle[5] = src >> 8
+
+dest = start + len(bin) - 1
+assert rle[8] == 0xa9 # lda #NN
+rle[9] = dest & 0xff
+assert rle[0xc] == 0xa9 # lda #NN
+rle[0xd] = dest >> 8
+
+assert rle[0x67] == 0x4c # jmp NNNN
+rle[0x68] = start & 0xff
+rle[0x69] = start >> 8
+
+load_size = len(rle)
+hdr = [load_addr & 0xff, load_addr >> 8, load_size & 0xff, load_size >> 8]
+
+with open(out_bin, 'wb') as fout:
+  fout.write(bytes(hdr + rle))
diff --git a/loader/rle_loader.asm b/loader/rle_loader.asm
new file mode 100644 (file)
index 0000000..54ee39b
--- /dev/null
@@ -0,0 +1,94 @@
+; key byte is partitioned as follows
+KEY_EOF = 0
+KEY_LIT = 1 ; literal lengths 01..af
+KEY_RUN = 0xb0 ; run lengths 02..51
+N_KEYS = 0x100
+
+       .r65c02
+
+       .area   zpage
+       .setdp
+
+       .ds     80
+src:   .ds     2                       ; address of next byte to read
+dest:  .ds     2                       ; address of next byte to write
+count: .ds     1
+
+       .area   text
+
+       lda     #0
+       sta     src
+       lda     #0
+       sta     src + 1
+
+       lda     #0
+       sta     dest
+       lda     #0
+       sta     dest + 1
+
+       ldy     #0
+loop:  lda     [src],y
+       beq     done
+       cmp     #KEY_RUN
+       bcs     run
+
+       ; lit
+       sta     count
+       tay
+
+       ; src -= count + 1
+       ;clc
+       lda     src
+       sbc     count
+       sta     src
+       lda     src + 1
+       sbc     #0
+       sta     src + 1
+
+       ; dest -= count
+       ;sec
+       lda     dest
+       sbc     count
+       sta     dest
+       lda     dest + 1
+       sbc     #0
+       sta     dest + 1
+
+0$:    lda     [src],y
+       sta     [dest],y
+       dey
+       bne     0$
+       beq     loop
+
+run:   sec
+       sbc     #KEY_RUN - 2
+       sta     count
+
+       ; src -= 2
+       ;sec
+       lda     src
+       sbc     #2
+       sta     src
+       lda     src + 1
+       sbc     #0
+       sta     src + 1
+
+       ; dest -= count
+       ;sec
+       lda     dest
+       sbc     count
+       sta     dest
+       lda     dest + 1
+       sbc     #0
+       sta     dest + 1
+
+       iny
+       lda     [src],y
+
+       ldy     count
+0$:    sta     [dest],y
+       dey
+       bne     0$
+       beq     loop
+
+done:  jmp     0