AS6500=../asxv5pxx/asxmak/linux/exe/as6500
ASLINK=../asxv5pxx/asxmak/linux/exe/aslink
+RLE_LOADER=0x800
+
.PHONY: all
all: \
star_blazer.dsk \
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 \
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
// 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
# 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" $@
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:
--- /dev/null
+#!/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))
--- /dev/null
+#!/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))
--- /dev/null
+; 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