Improve a2_load.py to load from nibble image or a2bin, add Alien Rain (can't disassem...
authorNick Downing <nick@ndcode.org>
Thu, 30 Jun 2022 08:47:01 +0000 (18:47 +1000)
committerNick Downing <nick@ndcode.org>
Thu, 30 Jun 2022 08:47:54 +0000 (18:47 +1000)
.gitignore
galaxian/Makefile
galaxian/alien_rain0_segments.txt [new file with mode: 0644]
orig/Makefile
star_blazer/Makefile
utils/a2_load.py

index 0b11135..7335cb5 100644 (file)
@@ -21,6 +21,7 @@
 /galaxian/galaxian_shape.json
 /galaxian/galaxian_shape.png
 /orig/APPLE Computer and Peripheral Card Roms Collection.zip
+/orig/Alien_Rain_1981_Broderbund_DOS.nib
 /orig/Alien_Typhoon_1981_Starcraft.do
 /orig/Apple_DOS_v3.3_1980_Apple.do
 /orig/Galaxian_1980_Starcraft.do
index 7b8ca48..d54375b 100644 (file)
@@ -7,6 +7,8 @@ ASLINK=../asxv5pxx/asxmak/linux/exe/aslink
 all: \
 galaxian_shape.png \
 galaxian.asm \
+alien_rain_shape.png \
+alien_rain.asm \
 alien_typhoon_shape.png \
 alien_typhoon.asm \
 
@@ -27,12 +29,43 @@ galaxian0.a2bin \
 galaxian0_segments.txt \
 Apple\ II+\ -\ 341-0020\ -\ Applesoft\ BASIC\ Autostart\ Monitor\ F800\ -\ 2716.bin
        ../utils/a2_load.py \
---f8_rom="Apple II+ - 341-0020 - Applesoft BASIC Autostart Monitor F800 - 2716.bin" \
-0x9707 $< $@ <galaxian0_segments.txt
+--f8-rom="Apple II+ - 341-0020 - Applesoft BASIC Autostart Monitor F800 - 2716.bin" \
+--segments=galaxian0_segments.txt \
+0x9707 \
+$< \
+$@
 
 galaxian0.a2bin: ../orig/Galaxian_1980_Starcraft.do
        ${DOS33} $< LOAD "GALAXIAN" $@
 
+alien_rain_shape.png: alien_rain_shape.json
+       ./shape_extract_png.py $^ $@
+
+alien_rain_shape.json: alien_rain.txt alien_rain0.ihx
+       ./shape_extract.py $^ $@
+
+alien_rain.asm: \
+alien_rain_trace.txt \
+alien_rain.txt \
+alien_rain0.ihx
+       ../utils/disasm.py --trace=$^ $@
+
+alien_rain0.ihx: \
+../orig/Alien_Rain_1981_Broderbund_DOS.nib \
+alien_rain0_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=../galaxian/Apple\ II+\ -\ 341-0020\ -\ Applesoft\ BASIC\ Autostart\ Monitor\ F800\ -\ 2716.bin \
+--trace=26 \
+0x9788 \
+$< \
+$@
+
+alien_rain0.a2bin: ../orig/Alien_Typhoon_1981_Starcraft.do
+       ${DOS33} $< LOAD "ALIEN TYPHOON" $@
+
 alien_typhoon_shape.png: alien_typhoon_shape.json
        ./shape_extract_png.py $^ $@
 
@@ -48,7 +81,11 @@ alien_typhoon0.ihx
 alien_typhoon0.ihx: \
 alien_typhoon0.a2bin \
 alien_typhoon0_segments.txt
-       ../utils/a2_load.py 0x8f98 $< $@ <alien_typhoon0_segments.txt
+       ../utils/a2_load.py \
+--segments=alien_typhoon0_segments.txt \
+0x8f98 \
+$< \
+$@
 
 alien_typhoon0.a2bin: ../orig/Alien_Typhoon_1981_Starcraft.do
        ${DOS33} $< LOAD "ALIEN TYPHOON" $@
@@ -74,6 +111,9 @@ clean:
 galaxian_shape.png \
 galaxian_shape.json \
 galaxian.asm \
+alien_rain_shape.png \
+alien_rain_shape.json \
+alien_rain.asm \
 alien_typhoon_shape.png \
 alien_typhoon_shape.json \
 alien_typhoon.asm
diff --git a/galaxian/alien_rain0_segments.txt b/galaxian/alien_rain0_segments.txt
new file mode 100644 (file)
index 0000000..6f30f54
--- /dev/null
@@ -0,0 +1 @@
+[0x0000, 0xc000)
index 5730fe2..26f0a71 100644 (file)
@@ -1,6 +1,8 @@
 .PHONY: all
 all: \
 APPLE\ Computer\ and\ Peripheral\ Card\ Roms\ Collection.zip \
+Apple\ Disk\ II\ 16\ Sector\ Interface\ Card\ ROM\ P5\ -\ 341-0027.bin \
+Alien_Rain_1981_Broderbund_DOS.nib \
 Alien_Typhoon_1981_Starcraft.do \
 Apple_DOS_v3.3_1980_Apple.do \
 Galaxian_1980_Starcraft.do \
@@ -20,6 +22,14 @@ APPLE\ Computer\ and\ Peripheral\ Card\ Roms\ Collection.zip:
        rm -f $@
        wget https://mirrors.apple2.org.za/ftp.apple.asimov.net/emulators/rom_images/APPLE%20Computer%20and%20Peripheral%20Card%20Roms%20Collection.zip
 
+Apple\ Disk\ II\ 16\ Sector\ Interface\ Card\ ROM\ P5\ -\ 341-0027.bin:
+       rm -f $@
+       wget https://mirrors.apple2.org.za/ftp.apple.asimov.net/emulators/rom_images/Apple%20Disk%20II%2016%20Sector%20Interface%20Card%20ROM%20P5%20-%20341-0027.bin
+
+Alien_Rain_1981_Broderbund_DOS.nib:
+       rm -f $@
+       wget https://archive.org/download/a2_Alien_Rain_1981_Broderbund_DOS/$@
+
 Alien_Typhoon_1981_Starcraft.do:
        rm -f $@
        wget https://archive.org/download/a2_Alien_Typhoon_1981_Starcraft/$@
@@ -43,6 +53,7 @@ clean:
 realclean:
        rm -f \
 APPLE\ Computer\ and\ Peripheral\ Card\ Roms\ Collection.zip \
+Alien_Rain_1981_Broderbund_DOS.nib \
 Alien_Typhoon_1981_Starcraft.do \
 Apple_DOS_v3.3_1980_Apple.do \
 Galaxian_1980_Starcraft.do \
index 4bcebce..29104f7 100644 (file)
@@ -95,7 +95,7 @@ star_blazer.asm.patch
        patch $@ <$@.patch
 
 star_blazer0.ihx: star_blazer0.a2bin star_blazer0_segments.txt
-       ../utils/a2_load.py 0x17d1 $< $@ <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" $@
index fc17817..4039b17 100755 (executable)
@@ -7,50 +7,123 @@ from intelhex import IntelHex
 EXIT_SUCCESS = 0
 EXIT_FAILURE = 1
 
+in_c6_rom = None
 in_f8_rom = None
-if len(sys.argv) >= 2 and sys.argv[1][:9] == '--f8_rom=':
-  in_f8_rom = sys.argv[1][9:]
+segments_txt = None
+trace = -1 # track to trace from
+while len(sys.argv) >= 2:
+  if sys.argv[1][:9] == '--c6-rom=':
+    in_c6_rom = sys.argv[1][9:]
+  elif sys.argv[1][:9] == '--f8-rom=':
+    in_f8_rom = sys.argv[1][9:]
+  elif sys.argv[1][:11] == '--segments=':
+    segments_txt = sys.argv[1][11:]
+  elif sys.argv[1] == '--trace':
+    trace = 0
+  elif sys.argv[1][:8] == '--trace=':
+    trace = int(sys.argv[1][8:], 0)
+  else:
+    break
   del sys.argv[1]
 if len(sys.argv) < 4:
-  print(f'usage: {sys.argv[0]:s} [--f8_rom=rom.bin] entry_point in.a2bin out.ihx <segments.txt')
+  print(f'usage: {sys.argv[0]:s} [--c6-rom=rom.bin] [--f8-rom=rom.bin] [--segments=segments.txt] [--trace[=disk2_track]] entry_point in.(a2bin|nib) out.ihx')
   sys.exit(EXIT_FAILURE)
 entry_point = int(sys.argv[1], 0)
-in_a2bin = sys.argv[2]
+in_a2bin_nib = sys.argv[2]
 out_ihx = sys.argv[3]
 
-segments0 = []
-for line in sys.stdin:
-  i = line.find('#')
-  if i != -1:
-    line = line[:i]
-  line = line.rstrip()
-  if len(line):
-    assert line[:1] == '[' and line[-1:] == ')'
-    fields = line[1:-1].split(',')
-    assert len(fields) == 2
-    segments0.extend([int(i, 0) for i in fields])
-if len(segments0) == 0:
-  segments0 = [0, 0x10000]
-
-with open(in_a2bin, 'rb') as fin:
-  a2bin = list(fin.read())
-  hdr = a2bin[:4]
-  bin = a2bin[4:]
-load_addr = hdr[0] | (hdr[1] << 8)
-load_size = hdr[2] | (hdr[3] << 8)
-assert len(bin) == load_size
+segments0 = [0, 0x10000]
+if segments_txt is not None:
+  with open(segments_txt) as fin:
+    segments0 = []
+    for line in fin:
+      i = line.find('#')
+      if i != -1:
+        line = line[:i]
+      line = line.rstrip()
+      if len(line):
+        assert line[:1] == '[' and line[-1:] == ')'
+        fields = line[1:-1].split(',')
+        assert len(fields) == 2
+        segments0.extend([int(i, 0) for i in fields])
 
 mem = [0] * 0x10000
 mem_used = [False] * 0x10000
 
+if in_c6_rom is not None:
+  with open(in_c6_rom, 'rb') as fin:
+    c6_rom = list(fin.read())
+  assert len(c6_rom) == 0x100
+  mem[0xc600:0xc700] = c6_rom
+
+start_addr = -1
 if in_f8_rom is not None:
   with open(in_f8_rom, 'rb') as fin:
     f8_rom = list(fin.read())
   assert len(f8_rom) == 0x800
   mem[0xf800:] = f8_rom
 
-mem[load_addr:load_addr + load_size] = bin
-mem_used[load_addr:load_addr + load_size] = [True] * load_size
+disk2_data = []
+if in_a2bin_nib[-6:] == '.a2bin':
+  with open(in_a2bin_nib, 'rb') as fin:
+    a2bin = list(fin.read())
+    hdr = a2bin[:4]
+    bin = a2bin[4:]
+  load_addr = hdr[0] | (hdr[1] << 8)
+  load_size = hdr[2] | (hdr[3] << 8)
+  assert len(bin) == load_size
+  mem[load_addr:load_addr + load_size] = bin
+  mem_used[load_addr:load_addr + load_size] = [True] * load_size
+elif in_a2bin_nib[-4:] == '.nib':
+  with open(in_a2bin_nib, 'rb') as fin:
+    nib = list(fin.read())
+  assert len(nib) % 6656 == 0
+  disk2_data = [
+    nib[i:i + 6656] + nib[i:i + 11]
+    for i in range(0, len(nib), 6656)
+  ]
+  load_addr = mem[0xfffc] | (mem[0xfffd] << 8) # boot autostart monitor
+else:
+  assert False
+
+disk2_phase = 0
+disk2_track = 0
+disk2_index = 0
+disk2_address = [0xd5, 0xaa, 0x96]
+def disk2(addr, data):
+  global disk2_phase, disk2_track, disk2_index
+
+  if (addr & 9) == 1:
+    phase = (addr >> 1) & 3
+    track = disk2_track + (((phase - disk2_phase) + 2) & 3) - 2
+    disk2_phase = phase
+    if track >= 0 and track < 80:
+      disk2_track = track
+      print('disk2_track', disk2_track)
+  elif addr == 0xc:
+    if (disk2_track & 1) or disk2_track >= 35:
+      data = 0
+    else:
+      i = disk2_track >> 1
+      if disk2_data[i][disk2_index:disk2_index + 3] == disk2_address:
+        address = [
+          (disk2_data[i][disk2_index + j] << 1) &
+            disk2_data[i][disk2_index + j + 1]
+          for j in range(3, 11, 2)
+        ]
+        print(
+          'volume',
+          address[0],
+          'track',
+          address[1],
+          'sector',
+          address[2],
+          'checksum',
+          address[3]
+        )
+      data = disk2_data[i][disk2_index]
+      disk2_index = (disk2_index + 1) % 6656
+  return data
 
 class Mem:
   def __init__(self, mem, mem_used):
@@ -58,15 +131,25 @@ class Mem:
     self.mem_used = mem_used
 
   def __getitem__(self, addr):
+    if (addr & 0xfff0) == 0xc0e0:
+      #print('rd', hex(addr), hex(self.mem[addr]))
+      return disk2(addr & 0xf, 0)
     #self.mem_used[addr] = False
     return self.mem[addr]
 
   def __setitem__(self, addr, data):
+    if (addr & 0xfff0) == 0xc0e0:
+      #print('wr', hex(addr), hex(data))
+      disk2(addr & 0xf, data)
     self.mem[addr] = data
     self.mem_used[addr] = True
 
 mpu = py65.devices.mpu65c02.MPU(Mem(mem, mem_used), load_addr)
 while mpu.pc != entry_point:
+  if disk2_track == trace and mem[mpu.pc] == 0x4c:
+    addr = mem[mpu.pc + 1] | (mem[mpu.pc + 2] << 8)
+    print(f'{mpu.pc:04x}: jmp {addr:04x}')
+  #print('pc', hex(mpu.pc))
   mpu.step()
 if mpu.p & 8:
   print('warning: d = 1')