INDEX | ROMS | CODE MAP





WiLL-i-ROMS mods


Disassembly of Defender sound ROM code and use of Heathkit ET-3400 to play the SYNTHs and change a parameter via the PIA B input binary bit data switches. Audio is typically sent from the 8 bit accumulator A to the PIA port A output address 0x8000 (arcade: 0x0400). PIA port B is the sound select port on pinball and arcade games, but here it is assigned to parameter changes via an 8 bit binary data switch. The digital audio sent out from the PIA is then piggy-backed onto a modified sound board's 1408 DAC chip and then amplified with the TDA2002 8 watt amplifier.

Link to the WiLL-i-ROMS repo of functioning .asm files.

Below is the first mod hardware version of a Heathkit ET-3400 mpu system with added PIA and addressing logic and a modified system 7 sound board with RAM, ROM, MPU and PIA ICs removed:

Heathkit ET-4300 mpu and modified sound board

An updated hardware mod version now has a breakout board consisting of two PIAs and two 8 bit switches to allow for adjusting two parameters within the assembly code. PIA 2 port A is free for a possible future addition of an 8 bit rotary encoder. Experiments with extracted assembly code from various System 4-7 ROM SYNTH routines have their own repo, linked below.

Link to the DEF-ROM repo of experimental .asm files.

Below is the latest (2021) mod hardware version of a Heathkit ET-3400 mpu system with breakout board of two PIAs and necessary addressing logic jumpered to a modified system 7 sound board using only DAC to amplifier signal path with RAM, ROM, MPU and PIA ICs removed:

Heathkit ET-4300 mpu and modified sound board version 2









Williams Defender sound ROM code layout

The following table shows the current state of figuring out the assembly routines for the 2kb Sound Rom 15.
It has been updated to show the merged source file labels (work in progress).
Link to merged file here in the github repo.


Sound ROM 15 notes:
DEFENDER SOUNDS REV. 1.0 BY SAM D 10/80
COPYRIGHT WILLIAMS ELECTRONICS 1980
PROGRAM ORIGINATION DATE 10/24/80
PROGRAM RELEASE 10/31/80
PROGRAMMER: SAM DICKER


General Definitions:
PARAM : modifier or setter of parameters that affect the sound
SYNTH : looping code with output writes to generate sound via the PIA/DAC
UTIL : similar to PARAM
IRQ : routine handles the interrupt request vectors that select the sound
CALCOS : calculate offset routine for both sound select and PARAM modifiers
NMI : non-masking interrupt routine to handle the test/reset button press
VWTAB : vector table (fdb) addresses for PARAM/SYNTH routines as per IRQ
VVECT : table (fcb) parameters for SYNTHs (7x 8 bit params and 1x 16 bit counter)
WAVFCB : waveform data called by SYNTHs or PARAMs
MOTVCT : Motorola vector table for IRQ, SWI, NMI, RESET

Addr Label Source Label Notes ____ _____ ____________ _____ F800 ORG ORG F801 RESET SETUP F82A PARAM1 VARILD Vari Loader F83F SYNTH1 VARI Variable Duty Cycle Square Wave Routine F88C PARAM2 LITE Lightning F894 SYNTH2 APPEAR Appear F89E " " LITEN Lightning+Appear Routine F8CD SYNTH3 TURBO Turbo F8DC " " NOISE White Noise Routine F913 PARAM3 BG1 Background 1 Routine F91C PARAM4 THRUST Thrust F923 PARAM5 CANNON Cannon F930 SYNTH4 FNOISE Filtered Noise Routine F9A6 SYNTH5 RADIO Radio F9D4 SYNTH6 HYPER Hyper F9F3 SYNTH7 SCREAM Scream FA44 PARAM6 ORGANT Organ Tune FA48 PARAM7 ORGNT1 " " FA84 PARAM8 ORGANN Organ Note 4 BYTES(MODE,OSCILLATOR MASK HI+1,LO+1,NOTE#) FA89 PARAM9 ORGNN1 " " FA9A SYNTH8 ORGNN2 " " FAB3 " " ORGANL Organ Loader OSCIL=OSCILLATOR MASK, ACCA=DELAY, DUR=DURATION FADB " " ORGAN Organ Routine DUR=DURATION, OSCILLATOR MASK FB0A UTIL1 TRANS Parameter Transfer FB1E PARAM10 BGEND Background End Routine FB24 PARAM11 BG2INC Background Sound #2 Increment FB34 UTIL2 BG2 Background 2 Routine FB49 PARAM12 SP1 Spinner #1 Sound FB71 PARAM13 BON2 Laser Ball Bonus #2 FB81 " " GWLD GWAVE Loader FBE7 SYNTH9 GWAVE GWAVE Routine ACCA= FREQ PATTERN LENGTH, X= FREQ PAT ADDR FC21 PARAM14 " " " FC4B PARAM15 " " " FC56 PARAM16 " " " FC65 PARAM17 " " " FC75 PARAM18 WVTRAN Wave Transfer Routine FC87 PARAM19 WVDECA Wave Decay Routine DECAY AMOUNT IN ACCA(1/16 PER DECAY) FCB6 IRQ IRQ Interrupt Processing FD0E IRQ2 IRQ3 " " FD21 CALCOS ADDX Add A to X Register FD2F NMI NMI Diagnostic Processing FD58 VWTAB JMPTBL Special Routine Jump Table FD76 VVECT VVECT Vari Vectors FD9A WAVFCB1 RADSND Radio Sound Waveform FDAA " ORGTAB Organ Tune Table Phantom FDB7 " " " " " Taccata (JS Bach's Toccata and Fugue in D Minor) FE41 WAVFCB2 NOTTAB Organ Note Table FE4D WAVFCB3 GWVTAB Wave Table 1ST BYTE= WAVELENGTH FEEC WAVFCB4 SVTAB GWAVE Sound Vector Table FF55 WAVFCB5 GFRTAB GWAVE Freq Pattern Table FFF8 MOTVCT MOTVCT Motorola Vector Table





WiLL-i-ROMS mods code

Sample code for SYNTH1 / VARI (Variable Duty Cycle Square Wave Routine):

; SYNTH1/PARAM1 CODE - 24 Apr 2021 ; hack for Heathkit ET-3400 Audio Setup - 2x PIA input params ; user RAM = 197 + 256 bytes = 453 ; addr 0000 - 00C4 and 0100 - 01FF ; using PIA1 addr 8000-8003 (DAC, param1) ; and PIA2 addr 8004-8007 (param3) ; mpu clock speed is default/low (quoted as 0.5 MHz), expecting ~894750 cycles per second ; using edited subroutines RESET, NMI, PARAM1, CALCOS, UTIL1, SYNTH1 ; ; PIA Addressing changes for breakout board ; fix for PIA2 DDR/CR set using extended addressing ; PIA init code refactoring ; ;*************************************; ; USED RAM ADDR LOCATIONS (typical values) ;*************************************; 0000 : 00 24 ; CALCOS, UTIL1 0002 : 01 08 ; X, UTIL1 0004 : 00 18 ; X 0006 : nn 01 ; X, nn countdown, SAW params 000F to 0017 0008 : 00 08 ; A, A 000A : 81 02 ; A, X 000C : 00 FF ; X, A 000E : FF nn ; nn countdown 0010 : nn ; nn rapid ;*************************************; ;RESET INIT (POWER-ON) org 0011 ;*************************************; 0011 : 8E 01 FF lds #$01FF ; load SP with 01FFh 0014 : CE 80 00 ldx #$8000 ; load X with 8000h, PIA1 (DAC) addr 0017 : 6F 02 clr $02,x ; clear(00) addr X + 02h (set 8002 PIA1 PR/DDR port B in) 0019 : 86 FF ldaa #$FF ; load A with FFh (1111 1111) 001B : A7 00 staa $00,x ; store A in addr X + 00h (set 8000 PIA1 PR/DDR port A out) 001D : 86 3C ldaa #$3C ; load A with 3Ch(0011 1100) 001F : A7 01 staa $01,x ; store A in addr X + 01h (8001 PIA1 CR port A) 0021 : 86 37 ldaa #$37 ; load A with 37h(0011 0111) 0023 : A7 03 staa $03,x ; store A in addr X + 03h (8003 PIA1 CR port B) 0025 : 7F 40 02 clr $4002 ; clear(00) 4002h (set PIA2 PR/DDR port B in) 0028 : 86 04 ldaa #$04 ; set CR bit 2 high for PIA2 002A : B7 40 03 staa $4003 ; store A in addr 4003 (PIA2 CR port B) 002D : 01 nop ; ; ~ all nops here - SPARE 0030 : 01 nop ; ;*************************************; ;NMI - MAIN LOOP - 0031 ;*************************************; 0031 : CE FF FF ldx #$FFFF ; load X with value FFFFh ( or 78h ) 0034 : 5F clrb ; clear (00) B 0035 : E9 00 adcb $00,x ; add B + X + 00h with Carry into B 0037 : 86 01 ldaa #$01 ; load A with value 01h (0000 0001) ;*************************************; ;PARAM1 - Vari Loader - 0039 ;*************************************; ;VARILD 0039 : 16 tab ; transfer A to B 003A : 48 asla ; arith shift left in A (x2) 003B : 48 asla ; arith shift left in A (x4) 003C : 48 asla ; arith shift left in A (x8) 003D : 1B aba ; add A + B into A (x9) 003E : CE 00 06 ldx #$0006 ; load X with value 0006 0041 : DF 02 stx $02 ; store X in addr 02 0043 : CE 01 0E ldx #$010E ; load X with value 010E (FOSHIT) 0046 : BD 01 00 jsr L0100 ; jump sub ADDX 0049 : C6 09 ldab #$09 ; load B with 09h (0000 1001) ;*************************************; ;UTIL1 - Parameter Transfer - 004B ;**************************************; ;TRANS 004B : 36 psha ; push A into stack(A into SP) ;TRANS1 004C : A6 00 ldaa $00,x ; load A with value in X + 00h 004E : DF 00 stx $00 ; store X in 00 0050 : DE 02 ldx $02 ; load X with value in 02 0052 : A7 00 staa $00,x ; store A in X + 00h 0054 : 08 inx ; increment X 0055 : DF 02 stx $02 ; store X in 02 0057 : DE 00 ldx $00 ; load X with value in 00 0059 : 08 inx ; increment X 005A : 5A decb ; decrement B 005B : 26 EF bne L004C ; branch Z=0 PC - EFh (TRANS1)(-17) 005D : 32 pula ; pull into A from stack (SP into A) ;*************************************; ;SYNTH1 - Variable Duty Cycle Square Wave Routine - 005E ;*************************************; ;VARI 005E : 96 0E ldaa $0E ; load A with value in addr 0E 0060 : B7 80 00 staa $8000 ; store A in addr 8000 (SOUND) ;VAR0 0063 : 96 06 ldaa $06 ; load A with value in addr 06 0065 : 97 0F staa $0F ; store A in addr 0F 0067 : 96 07 ldaa $07 ; load A with value in addr 07 0069 : 97 10 staa $10 ; store A in addr 10 ;V0 006B : DE 0B ldx $0B ; load X with value in 0B ;V0LP 006D : 96 0F ldaa $0F ; load A with value in addr 0F 006F : 73 80 00 com $8000 ; complement 1s in addr 8000 (invert)(SOUND) ;V1 0072 : 09 dex ; decrement X (X = X - 1) 0073 : 27 10 beq L0085 ; branch Z=1 PC + 10h (VSWEEP) 0075 : 4A deca ; decrement A (A = A - 1) 0076 : 26 FA bne L0072 ; branch Z=0 PC - FAh (V1)(-6) 0078 : 73 80 00 com $8000 ; complements 1s in addr 8000 (SOUND) 007B : 96 10 ldaa $10 ; load A with value in 10 ;V2 007D : 09 dex ; decrement X 007E : 27 05 beq L0085 ; branch Z=1 PC + 05h (VSWEEP)(+5) 0080 : 4A deca ; decrement A 0081 : 26 FA bne L007D ; branch Z=0 PC - FAh (V2)(-6) 0083 : 20 E8 bra L006D ; branch always to addr PC - E8h (V0LP)(-24) ;VSWEEP 0085 : B6 80 00 ldaa $8000 ; load A with value in addr 8000 (SOUND) 0088 : 2B 01 bmi L008B ; branch N=1 PC + 01h (VS1) 008A : 43 coma ; complements 1s in A ;VS1 008B : 8B 00 adda #$00 ; add A with 00h (A = A + 00h) 008D : B7 80 00 staa $8000 ; store A in addr 8000 (SOUND) 0090 : 96 0F ldaa $0F ; load A with value in 0F 0092 : 9B 08 adda $08 ; add A with value in addr 08 0094 : 97 0F staa $0F ; store A in addr 0F 0096 : 96 10 ldaa $10 ; load A with value in 10 0098 : 9B 09 adda $09 ; add A with value in addr 09 009A : 97 10 staa $10 ; store A in addr 10 009C : 91 0A cmpa $0A ; compare A with value in addr 0A 009E : 26 CB bne L006B ; branch Z=0 PC - CBh (V0)(-53) 00A0 : 96 0D ldaa $0D ; load A with value in 0D 00A2 : 27 06 beq L00AA ; branch Z=1 PC + 06h (VARX) 00A4 : 9B 06 adda $06 ; add A with value in addr 06 00A6 : 97 06 staa $06 ; store A in addr 06 00A8 : 26 B9 bne L0063 ; branch Z=0 PC - B9h (VAR0)(-71) ;VARX 00AA : 8D 05 bsr L00B1 ; branch sub to PIA read PC + 05h 00AC : 86 02 ldaa #$02 ; load A with value 02h (0000 0010) 00AE : 7E 00 31 jmp L0031 ; jump to start L0031 ;*************************************; ; PIA B read subroutine - 00B1 ;*************************************; 00B1 : 4F clra ; clear A 00B2 : B6 80 02 ldaa $8002 ; load A with PIA1 B 00B5 : 43 coma ; complement A 00B6 : B7 01 0E staa $010E ; store A in 010E (p1) 00B9 : B6 40 02 ldaa $4002 ; load A with PIA2 B 00BC : 43 coma ; complement A 00BD : B7 01 10 staa $0110 ; store A in 0110 (p3) 00C0 : 39 rts ; return from subroutine ;*************************************; ;CALCOS (Add A to Index Register) - 0100 ;*************************************; ;ADDX 0100 : DF 00 stx $00 ; store X in 00 0102 : 9B 01 adda $01 ; add A with value in 01 0104 : 97 01 staa $01 ; store A in 01 0106 : 24 05 bcc L00BF ; branch C=0 PC + 05 (ADDX1) 0108 : 7C 00 00 inc $0000 ; increment value in 00 010B : DE 00 ldx $00 ; load X with value in 00 ;ADDX1 010D : 39 rts ; return from subroutine ;*************************************; ;PARAM WAVEFORM FCB - Vari Vector ;*************************************; ; :|p1|p2|p3|p4|p5|p6|p7|count ; 010E : 28 01 00 08 81 02 00 FF FF ; FOSHIT, Williams Boot ;*************************************; alternative VVECTS: 010E : 40 01 00 10 E1 00 80 FF FF ;SAW 010E : 28 81 00 FC 01 02 00 FC FF ;QUASAR 010E : FF 01 00 18 41 04 80 00 FF ;CABSHK ;*************************************;





Williams Boot Sound Mods

WiLL-i-ROMS fringe set album cover

Williams Boot sound assembly code (edited to 250 bytes) routines RESET, NMI, PARAM1, CALCOS, UTIL1, SYNTH1 on a 6800 and 6810 piggybacked to a System 7 DAC chip on a Williams sound board. Original parameters (p1-p7, ct): 28 01 00 08 81 02 00 FF FF are changed for each track with suitable values. (all tracks @ 320kbps pitched up to arcade mpu speed)

Zip wav files 14mb





Heathkit Sound Mods

WiLL-i-ROMS fringe set album cover

Heathkit mods using Williams Sound ROM synth routines assembly code using two PIA parameters on a breakout board and 8 bit audio data jumpered to a System 7 DAC chip on a Williams sound board. Assembly code edited to fit available RAM in Heathkit ET-3400 (user RAM limit 453 bytes) running the monitor ROM and necessary address changes, otherwise code is as disassembled from original ROM. Addition of PIA parameters to change two values of either wavetables, loop length, frequency/pitch etc.(all tracks @ 320kbps)

no zip yet





Heathkit Rat Race Sound Mods

WiLL-i-ROMS fringe set album cover

Heathkit mods using the sound ROM (8K, E000-FFFF) from Williams non-production prototype game Rat Race, only 10 made in January 1983, using System 7. Synth routines of assembly code and using two PIA parameters on a breakout board and 8 bit audio data jumpered to a System 7 DAC chip on a Williams sound board. Assembly code edited to fit available RAM in Heathkit ET-3400 (user RAM limit 453 bytes) running the monitor ROM and necessary address changes, otherwise code is as disassembled from original ROM. Addition of PIA parameters to change two values of either wavetables, loop length, frequency/pitch etc.(all tracks @ 320kbps)

no zip yet



Image of spectrogram of the Synth7 Heathkit modded assembly routine, recorded off the original sound board hardware.
Spectrogram of Synth7 mod sound wave