Add little brick out
authorNick Downing <nick@ndcode.org>
Tue, 24 May 2022 07:42:53 +0000 (17:42 +1000)
committerNick Downing <nick@ndcode.org>
Tue, 24 May 2022 08:27:58 +0000 (18:27 +1000)
13 files changed:
.gitignore
Makefile
apple_io.py
little_brick_out/Makefile [new file with mode: 0644]
little_brick_out/bootable.txt [new file with mode: 0644]
little_brick_out/little_brick_out.bas.patch [new file with mode: 0644]
little_brick_out/little_brick_out_tone_asm.txt [new file with mode: 0644]
little_brick_out/little_brick_out_tone_disasm.sed [new file with mode: 0644]
little_brick_out/little_brick_out_tone_disasm.txt [new file with mode: 0644]
little_brick_out/tone.asm [new file with mode: 0644]
little_brick_out/tone_asm.txt [new file with mode: 0644]
orig/Makefile
test/little_brick_out_tone.py [new file with mode: 0755]

index ea6a99b..2922576 100644 (file)
@@ -10,10 +10,15 @@ __pycache__
 /lemonade/lemonade_flash.asm
 /lemonade/lemonade_flash_patched.asm
 /lemonade/lemonade_tone.asm
-/lemonade/lemonade_tone_patched.asm
 /lemonade/lemonade_patched.bas
 /lemonade/lemonade_patched.dsk
 /lex_yy.py
+/little_brick_out/bootable.dsk
+/little_brick_out/little_brick_out.bas
+/little_brick_out/little_brick_out_tone.asm
+/little_brick_out/little_brick_out_patched.bas
+/little_brick_out/little_brick_out_patched.dsk
+/orig/Apple_DOS_3.3_Master.dsk
 /orig/Apple_DOS_v3.3_1980_Apple.do
 /orig/DOS_Tool_Kit_v1.0_1980_Apple.do
 /orig/Lemonade_Stand_1979_Apple.do
index ca46f90..f2d3c18 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -9,6 +9,7 @@ all: \
 dos33fsprogs \
 lemonade \
 linapple-pie \
+little_brick_out \
 orig \
 element.py \
 lex_yy.py \
@@ -35,6 +36,16 @@ bas_to_tok.py
 linapple-pie:
        ${MAKE} ${MAKEFLAGS} -C linapple-pie/src
 
+.PHONY: little_brick_out
+little_brick_out: \
+dos33fsprogs \
+linapple-pie \
+tok_to_bin.py \
+bin_to_tok.py \
+tok_to_bas.py \
+bas_to_tok.py
+       ${MAKE} ${MAKEFLAGS} -C little_brick_out
+
 .PHONY: orig
 orig:
        ${MAKE} ${MAKEFLAGS} -C orig
index bf78760..8311318 100644 (file)
@@ -179,7 +179,11 @@ colors = [
 LEMONADE_TONE_PERIOD = 0x300
 LEMONADE_TONE_DUR = 0x301
 LEMONADE_TONE_TONE = 0x302
-LEMONADE_TONE_TONE1 = 0x310
+
+# see little_brick_out_tone.lst
+LITTLE_BRICK_OUT_TONE_PERIOD = 6
+LITTLE_BRICK_OUT_TONE_DUR = 7
+LITTLE_BRICK_OUT_TONE_TONE = 0x300
 
 # see tone.lst
 TONE_REST = 0x300
@@ -519,7 +523,18 @@ def call(addr):
   global flash_color0
 
   addr &= 0xffff
-  if addr == TONE_REST or addr == TONE_TONE:
+  if addr == LITTLE_BRICK_OUT_TONE_TONE:
+    # for little brick out, see test/little_brick_out_tone.py
+    period_count = ((low_mem[LITTLE_BRICK_OUT_TONE_PERIOD] - 1) & 0xff) + 1
+    duration_count = ((low_mem[LITTLE_BRICK_OUT_TONE_DUR] - 1) & 0xff) + 1
+    cycles = 1.37788799e-02 + duration_count * (
+      -4.21513128e-06 + 1.27999925e+02 / period_count
+    )
+    duration = 1.27091766e-05 + duration_count * (
+      2.50897802e-03 + 2.25279897e-03 / period_count
+    )
+    tone(cycles / duration, duration)
+  elif addr == TONE_REST or addr == TONE_TONE:
     pass
     ## for lemonade_patched, see test/tone.py
     #if addr == TONE_REST:
@@ -536,7 +551,7 @@ def call(addr):
     #  tone(1. / period, duration)
     #else:
     #  time.sleep(duration)
-  elif addr == LEMONADE_TONE_TONE or addr == LEMONADE_TONE_TONE1:
+  elif addr == LEMONADE_TONE_TONE:
     # for lemonade, see test/lemonade_tone.py
     period_count = ((low_mem[LEMONADE_TONE_PERIOD] - 1) & 0xff) + 1
     duration_count = ((low_mem[LEMONADE_TONE_DUR] - 1) & 0xff) + 1
diff --git a/little_brick_out/Makefile b/little_brick_out/Makefile
new file mode 100644 (file)
index 0000000..6a0f9ad
--- /dev/null
@@ -0,0 +1,132 @@
+DOS33=../dos33fsprogs/utils/dos33fs-utils/dos33
+MKDOS33FS=../dos33fsprogs/utils/dos33fs-utils/mkdos33fs
+TOK_TO_BIN=../tok_to_bin.py
+BIN_TO_TOK=../bin_to_tok.py
+TOK_TO_BAS=../tok_to_bas.py
+BAS_TO_TOK=../bas_to_tok.py
+
+.PHONY: all
+all: little_brick_out_patched.dsk little_brick_out_tone.obj
+
+little_brick_out_patched.dsk: little_brick_out_patched.bin tone.obj bootable.dsk
+       cp bootable.dsk $@
+       ${DOS33} $@ DELETE HELLO
+       ${DOS33} $@ SAVE A little_brick_out_patched.bin "LITTLE BRICK OUT PATCHED"
+       ${DOS33} $@ SAVE B tone.obj TONE.OBJ
+       ${DOS33} $@ HELLO "LITTLE BRICK OUT PATCHED"
+
+little_brick_out_patched.bin: little_brick_out_patched.tok
+       ${TOK_TO_BIN} <$< >$@
+
+little_brick_out_patched.tok: little_brick_out_patched.bas
+       ${BAS_TO_TOK} <$< >$@
+
+little_brick_out_patched.bas: little_brick_out.bas little_brick_out.bas.patch
+       cp little_brick_out.bas $@
+       patch $@ <little_brick_out.bas.patch
+
+little_brick_out.bas: little_brick_out.tok
+       ${TOK_TO_BAS} <$< >$@
+
+little_brick_out.tok: little_brick_out.bin
+       ${BIN_TO_TOK} <$< >$@
+
+little_brick_out.bin: ../orig/Apple_DOS_3.3_Master.dsk
+       ${DOS33} $< LOAD "LITTLE BRICK OUT" $@
+
+tone.obj: \
+tone.asm \
+tone_asm.txt \
+bootable.dsk \
+../orig/DOS_Tool_Kit_v1.0_1980_Apple.do
+       cp ../orig/DOS_Tool_Kit_v1.0_1980_Apple.do .
+       tr '\t\na-z' ' \rA-Z' <tone.asm |\
+LC_ALL=C tr '\000-\177' '\200-\377' >__temp__.asm
+       ${MKDOS33FS} __temp__.dsk
+       ${DOS33} __temp__.dsk SAVE T __temp__.asm TONE.ASM
+       rm -f ../linapple-pie/Printer.txt
+       tr '\n' '\r' <tone_asm.txt |\
+( \
+  cd ../linapple-pie && \
+  ./linapple -b -1 ../little_brick_out/DOS_Tool_Kit_v1.0_1980_Apple.do -2 ../little_brick_out/__temp__.dsk \
+)
+       tr -d '\r' <../linapple-pie/Printer.txt >tone.lst
+       ${DOS33} __temp__.dsk LOAD TONE.OBJ $@
+       rm DOS_Tool_Kit_v1.0_1980_Apple.do __temp__.asm __temp__.dsk
+
+little_brick_out_tone.obj: \
+little_brick_out_tone.asm \
+little_brick_out_tone_asm.txt \
+bootable.dsk \
+../orig/DOS_Tool_Kit_v1.0_1980_Apple.do
+       cp ../orig/DOS_Tool_Kit_v1.0_1980_Apple.do .
+       tr '\t\na-z' ' \rA-Z' <little_brick_out_tone.asm |\
+LC_ALL=C tr '\000-\177' '\200-\377' >__temp__.asm
+       ${MKDOS33FS} __temp__.dsk
+       ${DOS33} __temp__.dsk SAVE T __temp__.asm "LITTLE BRICK OUT TONE.ASM"
+       rm -f ../linapple-pie/Printer.txt
+       tr '\n' '\r' <little_brick_out_tone_asm.txt |\
+( \
+  cd ../linapple-pie && \
+  ./linapple -b -1 ../little_brick_out/DOS_Tool_Kit_v1.0_1980_Apple.do -2 ../little_brick_out/__temp__.dsk \
+)
+       tr -d '\r' <../linapple-pie/Printer.txt >little_brick_out_tone.lst
+       ${DOS33} __temp__.dsk LOAD "LITTLE BRICK OUT TONE.OBJ" $@
+       rm DOS_Tool_Kit_v1.0_1980_Apple.do __temp__.asm __temp__.dsk
+
+little_brick_out_tone.asm: \
+little_brick_out_tone_disasm.txt \
+little_brick_out_tone_disasm.sed \
+bootable.dsk \
+../orig/Apple_DOS_3.3_Master.dsk
+       rm -f ../linapple-pie/Printer.txt
+       tr '\n' '\r' <little_brick_out_tone_disasm.txt |\
+( \
+  cd ../linapple-pie && \
+  ./linapple -b -1 ../little_brick_out/bootable.dsk -2 ../orig/Apple_DOS_3.3_Master.dsk \
+)
+       tr -d '\r' <../linapple-pie/Printer.txt |\
+sed -nf little_brick_out_tone_disasm.sed >__temp__.asm
+       sed -ne 's/^\(l\.[0-9a-f]\+\).*/\1/p' <__temp__.asm >__defs__.txt
+       sed -ne 's/^.\+\(l\.[0-9a-f]\+\).*/\1/p' <__temp__.asm >__refs__.txt
+       for i in `cat __defs__.txt`; \
+do \
+  if ! grep -q $$i __refs__.txt; \
+  then \
+    sed -e "s/$$i//" -i __temp__.asm; \
+  fi; \
+done
+       ( \
+  for i in `LC_ALL=C sort <__refs__.txt |uniq`; \
+  do \
+    if ! grep -q $$i __defs__.txt; \
+    then \
+      echo $$i; \
+    fi; \
+  done |sed -e 's/^l.\(.*\)/&\tequ\t$$\1/'; \
+  cat __temp__.asm; \
+) >$@
+       rm __temp__.asm __defs__.txt __refs__.txt
+
+bootable.dsk: ../orig/Apple_DOS_v3.3_1980_Apple.do bootable.txt
+       dd if=/dev/zero of=$@ count=35 bs=4096
+       tr '\n' '\r' <../little_brick_out/bootable.txt |\
+( \
+  cd ../linapple-pie && \
+  ./linapple -b -1 ../orig/Apple_DOS_v3.3_1980_Apple.do -2 ../little_brick_out/$@ \
+)
+
+clean:
+       rm -f \
+little_brick_out_patched.dsk \
+little_brick_out_patched.bin \
+little_brick_out_patched.tok \
+little_brick_out_patched.bas \
+little_brick_out.bas \
+little_brick_out.tok \
+little_brick_out.bin \
+bootable.dsk \
+__temp__.asm \
+__temp__.dsk \
+__defs__.txt \
+__refs__.txt
diff --git a/little_brick_out/bootable.txt b/little_brick_out/bootable.txt
new file mode 100644 (file)
index 0000000..b027cda
--- /dev/null
@@ -0,0 +1,4 @@
+NEW
+10 HOME
+20 PRINT "HELLO"
+INIT HELLO,D2
diff --git a/little_brick_out/little_brick_out.bas.patch b/little_brick_out/little_brick_out.bas.patch
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/little_brick_out/little_brick_out_tone_asm.txt b/little_brick_out/little_brick_out_tone_asm.txt
new file mode 100644 (file)
index 0000000..4a04202
--- /dev/null
@@ -0,0 +1,5 @@
+BRUN EDASM.OBJ
+PR#1
+DR 2
+ASM LITTLE BRICK OUT TONE.ASM,LITTLE BRICK OUT TONE.OBJ
+
diff --git a/little_brick_out/little_brick_out_tone_disasm.sed b/little_brick_out/little_brick_out_tone_disasm.sed
new file mode 100644 (file)
index 0000000..3893a08
--- /dev/null
@@ -0,0 +1,9 @@
+/^0300-/,/^0312-/{
+  y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
+  s/^\([^ ]\{4\}\)-   \([^ ]\{2\}\( [^ ]\{2\}\)*\) \+\([^ ]\{3\}\)   \(.*\)/l.\1\t\4\t\5\t\t\t\2/
+  s/\$/l./
+  s/#l\./#$/
+  s/\(,[xy]\)\t/\1/
+  s/^l.0300/\torg\t$0300\n&/
+  p
+}
diff --git a/little_brick_out/little_brick_out_tone_disasm.txt b/little_brick_out/little_brick_out_tone_disasm.txt
new file mode 100644 (file)
index 0000000..c9980c5
--- /dev/null
@@ -0,0 +1,5 @@
+LOAD LITTLE BRICK OUT,D2
+GOSUB 7000
+PR#1
+CALL -151
+300L
diff --git a/little_brick_out/tone.asm b/little_brick_out/tone.asm
new file mode 100644 (file)
index 0000000..ee672e8
--- /dev/null
@@ -0,0 +1,26 @@
+spkr   equ     $c030
+       org     $300
+rest   lda     #0
+       sta     freql
+       sta     freqh
+tone   ldx     #0
+durl   equ     *-1
+       ldy     #0
+durh   equ     *-1
+loop   lda     #0
+freql  equ     *-1
+       adc     #0
+countl equ     *-1
+       sta     countl
+       lda     #0
+freqh  equ     *-1
+       adc     #0
+counth equ     *-1
+       sta     counth
+       bcc     nospkr
+       lda     spkr
+nospkr inx
+       bne     loop
+       iny
+       bne     loop
+       rts
diff --git a/little_brick_out/tone_asm.txt b/little_brick_out/tone_asm.txt
new file mode 100644 (file)
index 0000000..f51e61c
--- /dev/null
@@ -0,0 +1,5 @@
+BRUN EDASM.OBJ
+PR#1
+DR 2
+ASM TONE.ASM,TONE.OBJ
+
index 369525e..51275ce 100644 (file)
@@ -1,9 +1,16 @@
 .PHONY: all
 all: \
+Apple_DOS_3.3_Master.dsk \
 Apple_DOS_v3.3_1980_Apple.do \
 DOS_Tool_Kit_v1.0_1980_Apple.do \
 Lemonade_Stand_1979_Apple.do
 
+# little brick out
+Apple_DOS_3.3_Master.dsk:
+       rm -f $@
+       wget https://archive.org/download/Apple_DOS_3.3_Master/$@
+
+# really the 1983 release, which I use as DOS reference
 Apple_DOS_v3.3_1980_Apple.do:
        rm -f $@
        wget https://archive.org/download/a2_Apple_DOS_v3.3_1980_Apple/$@
@@ -20,6 +27,7 @@ clean:
        # avoid hitting archive.org every time
        # they can be deleted manually if needed
        #rm -f \
+#Apple_DOS_3.3_Master.dsk \
 #Apple_DOS_v3.3_1980_Apple.do \
 #DOS_Tool_Kit_v1.0_1980_Apple.do \
 #Lemonade_Stand_1979_Apple.do
diff --git a/test/little_brick_out_tone.py b/test/little_brick_out_tone.py
new file mode 100755 (executable)
index 0000000..0d63341
--- /dev/null
@@ -0,0 +1,76 @@
+#!/usr/bin/env python3
+
+import numpy
+import py65.devices.mpu6502
+
+CPU_HZ = 3579545 * 4 / 14 # 1.02272714 MHz (from NTSC clock)
+
+mem = [0] * 0x10000
+cpu = py65.devices.mpu6502.MPU(memory = mem, pc = 0x400)
+
+def bload(bin_in):
+  with open(bin_in, 'rb') as fin:
+    bin = list(fin.read())
+    load_addr = bin[0] + (bin[1] << 8)
+    load_size = bin[2] + (bin[3] << 8)
+    assert len(bin) == load_size + 4
+  mem[load_addr:load_addr + load_size] = bin[4:]
+
+bload('../little_brick_out/little_brick_out_tone.obj')
+
+# jsr 0x0300
+#mem[0x400:0x403] = [0x20, 0x00, 0x03]
+
+# jsr 0x030d
+# enter here to avoid period error due to entry x = 0
+mem[0x400:0x403] = [0x20, 0x0d, 0x03]
+# then run it another 15 times preserving returned x
+mem[0x403:0x430] = [0x20, 0x0a, 0x03] * 15
+
+x = []
+y = []
+for period_count in [1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff]:
+  for duration_count in [1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff]:
+    mem[6] = period_count
+    #mem[7] = duration_count
+    cpu.reset()
+    toggles = 0
+    while cpu.pc != 0x430: #0x403:
+      if cpu.pc >= 0x400:
+        mem[7] = duration_count
+      if cpu.pc == 0x300:
+       toggles += 1
+      cpu.step()
+    duration = cpu.processorCycles / CPU_HZ / 16
+    cycles = toggles / 2 / 16
+    print(f'period_count {period_count:02x} duration_count {duration_count:02x} cycles {cycles:10.3f} duration {duration:10.6f}')
+    x.append([1, duration_count, duration_count / period_count])
+    y.append([cycles, duration])
+x = numpy.array(x, numpy.double)
+y = numpy.array(y, numpy.double)
+
+p, _, _, _ = numpy.linalg.lstsq(x, y, rcond = None)
+print('p', p)
+
+print(numpy.concatenate([x @ p, y], 1))
+
+# example: generate 440 Hz for 0.125s (55 cycles)
+y = numpy.array([55., .125], numpy.double)
+x = numpy.linalg.solve(p[1:, :].transpose(), y - p[0, :])
+print('x', x)
+duration_count = round(x[0])
+period_count = round(x[0] / x[1])
+
+mem[6] = period_count
+#mem[7] = duration_count
+cpu.reset()
+toggles = 0
+while cpu.pc != 0x430: #0x403:
+  if cpu.pc >= 0x400:
+    mem[7] = duration_count
+  if cpu.pc == 0x300:
+   toggles += 1
+  cpu.step()
+duration = cpu.processorCycles / CPU_HZ / 16
+cycles = toggles / 2 / 16
+print(f'period_count {period_count:02x} duration_count {duration_count:02x} cycles {cycles:10.3f} duration {duration:10.6f}')