Extract and analyze Sky Blazer shapes
authorNick Downing <nick@ndcode.org>
Fri, 1 Jul 2022 02:09:20 +0000 (12:09 +1000)
committerNick Downing <nick@ndcode.org>
Fri, 1 Jul 2022 02:22:24 +0000 (12:22 +1000)
.gitignore
Makefile
shape/Makefile
shape/shape_extract.py
shape/sky_blazer0_segments.txt [new file with mode: 0644]
shape/star_blazer0_segments.txt [new file with mode: 0644]
star_blazer/Makefile
star_blazer/sky_blazer.txt
star_blazer/sky_blazer_object_defs.inc

index aa9ed67..2db34cd 100644 (file)
@@ -30,6 +30,8 @@
 /orig/Galaxian_1980_Starcraft.do
 /orig/Sky Blazer (4am and san inc crack).zip
 /orig/Star_Blazer_1981_Star_Craft.do
+/shape/Sky Blazer (4am and san inc crack).dsk
+/shape/Sky Blazer (4am and san inc crack).nib
 /shape/dhgr_pixel_shape_data_aux.inc
 /shape/dhgr_pixel_shape_data_main.inc
 /shape/dhgr_pixel_shape_index.inc
@@ -47,6 +49,7 @@
 /shape/shape6.png
 /shape/shape_data.inc
 /shape/shape_index.inc
+/shape/sky_blazer_shape.png
 /star_blazer/Sky Blazer (4am and san inc crack).dsk
 /star_blazer/Sky Blazer (4am and san inc crack).nib
 /star_blazer/sky_blazer.asm
index 4c59110..cd0fd99 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -46,7 +46,7 @@ orig:
        ${MAKE} ${MAKEFLAGS} -C orig
 
 .PHONY: shape
-shape: loader
+shape:
        ${MAKE} ${MAKEFLAGS} -C shape
 
 .PHONY: star_blazer
index b654028..3d9909c 100644 (file)
@@ -1,3 +1,6 @@
+DOS33=../dos33fsprogs/utils/dos33fs-utils/dos33
+DSK2NIB=../dsk2nib/dsk2nib
+
 .PHONY: all
 all: \
 dhgr_pixel_shape_index.inc \
@@ -16,7 +19,8 @@ shape2.png \
 shape3.png \
 shape4.png \
 shape5.png \
-shape6.png
+shape6.png \
+sky_blazer_shape.png
 
 dhgr_pixel_shape_index.inc: pixel.txt dhgr_shape.txt shape0c.png
        cat pixel.txt dhgr_shape.txt \
@@ -44,7 +48,7 @@ shape_index.inc: shape.txt shape0.png
 shape_data.inc: shape.txt shape0.png
        ./shape_compile.py --data shape0.png <$< >$@
 
-shape0.png: ../loader/star_blazer_recrack.a2bin
+shape0.png: star_blazer0.ihx
        ./shape_extract.py $< $@
 
 shape1.png: shape0.png
@@ -74,6 +78,44 @@ shape0b.png: shape0.png shape0a.png
 shape0c.png: shape_dhgr.png
        ./shape_color_to_mono.py $< $@
 
+star_blazer0.ihx: star_blazer0.a2bin star_blazer0_segments.txt
+       ../utils/a2_load.py --segments=star_blazer0_segments.txt 0x17d1 $< $@
+
+star_blazer0.a2bin: ../orig/Star_Blazer_1981_Star_Craft.do
+       ${DOS33} $^ LOAD "STAR BLAZER" $@
+
+sky_blazer_shape.png: sky_blazer0.ihx
+       ./shape_extract.py $< $@
+
+sky_blazer0.ihx: \
+Sky\ Blazer\ (4am\ and\ san\ inc\ crack).nib \
+sky_blazer0_segments.txt \
+../orig/Apple\ Disk\ II\ 16\ Sector\ Interface\ Card\ ROM\ P5\ -\ 341-0027.bin \
+Apple\ II+\ -\ 341-0020\ -\ Applesoft\ BASIC\ Autostart\ Monitor\ F800\ -\ 2716.bin
+       ../utils/a2_load.py \
+--c6-rom=../orig/Apple\ Disk\ II\ 16\ Sector\ Interface\ Card\ ROM\ P5\ -\ 341-0027.bin \
+--f8-rom=Apple\ II+\ -\ 341-0020\ -\ Applesoft\ BASIC\ Autostart\ Monitor\ F800\ -\ 2716.bin \
+--trace=68 \
+0x17d1 \
+"$<" \
+$@
+
+Sky\ Blazer\ (4am\ and\ san\ inc\ crack).nib: \
+Sky\ Blazer\ (4am\ and\ san\ inc\ crack).dsk
+       ${DSK2NIB} "$^" "$@"
+
+Sky\ Blazer\ (4am\ and\ san\ inc\ crack).dsk: \
+../orig/Sky\ Blazer\ (4am\ and\ san\ inc\ crack).zip
+       rm -f "$@"
+       unzip -j "$<" "Sky Blazer (4am and san inc crack)/$@"
+       touch "$@"
+
+Apple\ II+\ -\ 341-0020\ -\ Applesoft\ BASIC\ Autostart\ Monitor\ F800\ -\ 2716.bin: \
+../orig/APPLE\ Computer\ and\ Peripheral\ Card\ Roms\ Collection.zip
+       rm -f "$@"
+       unzip "$<" "$@"
+       touch "$@"
+
 .PHONY: clean
 clean:
        rm -f \
@@ -85,4 +127,7 @@ pixel_shape_data.inc \
 shape_index.inc \
 shape_data.inc \
 shape0[abc].png \
-shape[0-6].png
+shape[0-6].png \
+sky_blazer_shape.png \
+Sky\ Blazer\ \(4am\ and\ san\ inc\ crack\).dsk \
+Sky\ Blazer\ \(4am\ and\ san\ inc\ crack\).nib
index 4dc0a13..b84f850 100755 (executable)
@@ -3,6 +3,7 @@
 import numpy
 import sys
 import PIL.Image
+from intelhex import IntelHex
 
 EXIT_SUCCESS = 0
 EXIT_FAILURE = 1
@@ -34,21 +35,12 @@ PALETTE = numpy.array(
 )
 
 if len(sys.argv) < 3:
-  print(f'usage: {sys.argv[0]:s} in.bin out.png')
+  print(f'usage: {sys.argv[0]:s} in.ihx out.png')
   sys.exit(EXIT_FAILURE)
-in_bin = sys.argv[1]
+in_ihx = sys.argv[1]
 out_png = sys.argv[2]
 
-with open(in_bin, 'rb') as fin:
-  data = list(fin.read())
-  hdr = data[:4]
-  bin = data[4:]
-load_addr = hdr[0] | (hdr[1] << 8)
-load_size = hdr[2] | (hdr[3] << 8)
-assert load_size == len(bin)
-
-mem = [0] * 0x10000
-mem[load_addr:load_addr + load_size] = bin
+intelhex = IntelHex(in_ihx)
 
 image_out = numpy.zeros((PITCH_Y * 32, PITCH_X * 8), numpy.uint8)
 
@@ -70,11 +62,11 @@ for i in range(0x100):
   bg = 0xa if (j ^ k) & 1 else 5
   image_out[y:y + PITCH_Y, x:x + PITCH_X] = bg
 
-  data_ptr = mem[shape_data_ptr_lo + i] + (mem[shape_data_ptr_hi + i] << 8)
-  width_bytes = mem[shape_width_bytes + i]
-  height = mem[shape_height + i]
-  size_bytes = mem[shape_size_bytes + i]
-  width = mem[shape_width + i]
+  data_ptr = intelhex[shape_data_ptr_lo + i] + (intelhex[shape_data_ptr_hi + i] << 8)
+  width_bytes = intelhex[shape_width_bytes + i]
+  height = intelhex[shape_height + i]
+  size_bytes = intelhex[shape_size_bytes + i]
+  width = intelhex[shape_width + i]
   print(
     'i',
     f'{i:02x}',
@@ -114,8 +106,8 @@ for i in range(0x100):
     shape = numpy.array(
       [
         [
-          mem[pixel_data_table_left] & mem[pixel_mask_table_left + i],
-          mem[pixel_data_table_right] & mem[pixel_mask_table_right + i]
+          intelhex[pixel_data_table_left] & intelhex[pixel_mask_table_left + i],
+          intelhex[pixel_data_table_right] & intelhex[pixel_mask_table_right + i]
         ]
       ],
       numpy.uint8
@@ -130,7 +122,7 @@ for i in range(0x100):
     )
 
     shape = numpy.array(
-      mem[start:start + size_bytes1],
+      list(intelhex.tobinstr(start, start + size_bytes1 - 1)),
       numpy.uint8
     ).reshape((height, width_bytes))
 
@@ -165,24 +157,29 @@ for i in range(0x100):
         shape1 = numpy.array(
           [
             [
-              mem[pixel_data_table_left + j] &
-                mem[pixel_mask_table_left + i],
-              mem[pixel_data_table_right + j] &
-                mem[pixel_mask_table_right + i]
+              intelhex[pixel_data_table_left + j] &
+                intelhex[pixel_mask_table_left + i],
+              intelhex[pixel_data_table_right + j] &
+                intelhex[pixel_mask_table_right + i]
             ]
           if (j & 1) == 0 else
             [
-              mem[pixel_data_table_right + j] &
-                mem[pixel_mask_table_right + i],
-              mem[pixel_data_table_left + j] &
-                mem[pixel_mask_table_left + i],
+              intelhex[pixel_data_table_right + j] &
+                intelhex[pixel_mask_table_right + i],
+              intelhex[pixel_data_table_left + j] &
+                intelhex[pixel_mask_table_left + i],
             ]
           ],
           numpy.uint8
         )
       else:
         shape1 = numpy.array(
-          mem[start + j * size_bytes1:start + (j + 1) * size_bytes1],
+          list(
+            intelhex.tobinstr(
+              start + j * size_bytes1,
+              start + (j + 1) * size_bytes1 - 1
+            )
+          ),
           numpy.uint8
         ).reshape((height, width_bytes))
 
diff --git a/shape/sky_blazer0_segments.txt b/shape/sky_blazer0_segments.txt
new file mode 100644 (file)
index 0000000..f78f516
--- /dev/null
@@ -0,0 +1 @@
+[0x0000,0xc000)
diff --git a/shape/star_blazer0_segments.txt b/shape/star_blazer0_segments.txt
new file mode 100644 (file)
index 0000000..6b7d274
--- /dev/null
@@ -0,0 +1,36 @@
+# file was constructed from a memory dump after copy protected loader ran
+# after loading at 0x0300:
+#   [0x0300, 0x0303) is jump to crack loader
+#   [0x0303, 0x0a00) is junk
+#   [0x0a00, 0x2000) is program
+#   [0x2000, 0x4000) is hi-res screen 0 which is reused by the crack loader:
+#     [0x2000, 0x27ed) is end of program which is copied to 0x9600
+#     [0x27ed, 0x3200) is junk copied after end of program at 0x9ded
+#     [0x3200, 0x3c00) is junk copied to end of memory at 0xb600
+#     [0x3c00, 0x3f00) is junk copied to start of memory at 0x0000, except:
+#       [0x3c20, 0x3c22) is vec_start (duplicated in crack loader, not used)
+#       [0x3c22, 0x3c24) is vec_init_game
+#       [0x3c24, 0x3c26) is vec_start_game
+#       [0x3c28, 0x3c2a) is vec_calculate_object_shape
+#       [0x3c4e, 0x3c50) is vec_draw_misc_from_table
+#       [0x3e00, 0x3e02) is vec_restart
+#     [0x3f00, 0x3f79) is crack loader
+#     [0x3f79, 0x4000) is junk
+#   [0x4000, 0x8c08) is program
+#   [0x8c08, 0x8e00) is junk which I think is from the shape editor he used
+#   [0x8e00, 0x9600) is program
+[0x0022, 0x0024) # vec_init_game
+[0x0024, 0x0026) # vec_start_game
+[0x0028, 0x002a) # vec_calculate_object_shape
+[0x004e, 0x0050) # vec_draw_misc_from_table
+[0x0200, 0x0202) # vec_restart
+[0x0a00, 0x17f5)
+[0x1800, 0x1dc6)
+[0x1e00, 0x1f39)
+[0x1f80, 0x2000)
+[0x4000, 0x4a10)
+[0x4a80, 0x4a90)
+[0x4b00, 0x4dc0)
+[0x4ed0, 0x4f00)
+[0x4f40, 0x8c08)
+[0x8e00, 0x9ded)
index 668f23f..2249f20 100644 (file)
@@ -8,7 +8,12 @@ LOAD_ADDR=0x800
 
 .PHONY: all
 all: \
-star_blazer.dsk
+star_blazer.dsk \
+sky_blazer_shape_index.inc \
+sky_blazer_shape_data.inc \
+sky_blazer_object_index.inc \
+sky_blazer_object_data.inc \
+sky_blazer_draw_misc_table.inc
 
 star_blazer.dsk: ../util/bootable.dsk star_blazer_pack_rev.a2bin
        cp ../util/bootable.dsk $@
index a2fde44..fce37f4 100644 (file)
@@ -715,7 +715,7 @@ shapes
 0xc1,ships
 0xc2,ships
 0xc3,ships
-0xd0,text_star
+0xd0,text_sky
 0xd1,text_blazer
 0xd2,text_by
 0xd3,text_tony
@@ -728,12 +728,9 @@ shapes
 0xe1,text_copyright
 0xe2,text_star_craft
 0xe3,text_inc
-0xe4,text_thanks
-0xe5,text_lot_comma
-0xe6,text_raly
-0xe7,text_minus_20
-0xe8,text_20_40_60_80
-0xe9,text_100_120_300_1500
+0xe7,text_minus_200
+0xe8,text_20_40_60_80_100_120
+0xe9,text_targets
 0xf0,ground
 0xf1,ground
 0xf2,ground
index e4dd6f5..b13ef3e 100644 (file)
@@ -236,7 +236,7 @@ SHAPE_C0_SHIPS = 0xc0
 SHAPE_C1_SHIPS = 0xc1
 SHAPE_C2_SHIPS = 0xc2
 SHAPE_C3_SHIPS = 0xc3
-SHAPE_D0_TEXT_STAR = 0xd0
+SHAPE_D0_TEXT_SKY = 0xd0
 SHAPE_D1_TEXT_BLAZER = 0xd1
 SHAPE_D2_TEXT_BY = 0xd2
 SHAPE_D3_TEXT_TONY = 0xd3
@@ -249,12 +249,9 @@ SHAPE_DD_TEXT_PERFORMANCE = 0xdd
 SHAPE_E1_TEXT_COPYRIGHT = 0xe1
 SHAPE_E2_TEXT_STAR_CRAFT = 0xe2
 SHAPE_E3_TEXT_INC = 0xe3
-SHAPE_E4_TEXT_THANKS = 0xe4
-SHAPE_E5_TEXT_LOT_COMMA = 0xe5
-SHAPE_E6_TEXT_RALY = 0xe6
-SHAPE_E7_TEXT_MINUS_20 = 0xe7
-SHAPE_E8_TEXT_20_40_60_80 = 0xe8
-SHAPE_E9_TEXT_100_120_300_1500 = 0xe9
+SHAPE_E7_TEXT_MINUS_200 = 0xe7
+SHAPE_E8_TEXT_20_40_60_80_100_120 = 0xe8
+SHAPE_E9_TEXT_TARGETS = 0xe9
 SHAPE_F0_GROUND = 0xf0
 SHAPE_F1_GROUND = 0xf1
 SHAPE_F2_GROUND = 0xf2