-
Notifications
You must be signed in to change notification settings - Fork 2
/
VSNDRM9.ASM
3281 lines (3032 loc) · 108 KB
/
VSNDRM9.ASM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;
; SSSS IIIII N N IIIII SSSS TTTTT AAA RRRR
; S I NN N I S T A A R R
; SSS I N N N I SSS T AAAAA RRRR
; S I N NN I S T A A R R
; SSSS IIIII N N IIIII SSSS T A A R R
;
; SINISTAR SOUND ROM (Recreation started by SynaMax - 07/14/2023)
; Re-targeted for Macroassembler {AS} - 1/15/2024
;
; 6800 Assembly code to build both Video Sound Rom 9 and 10
;
; For more info on how this source code was recreated, you watch my
; documentary on YouTube, "Rescuing the Lost Code and Stereo Sound to Sinistar":
; https://www.youtube.com/watch?v=ZRDdKZ7V54I
;
;;---------------------------------------------------------------------
;
; Sinistar's upright cabinet uses VSNDRM9 for mono audio, but
; the rare cockpit version uses both VSNDRM9 and VSNDRM10 for stereo.
;
;STEREO EQU 1
;
; Remove the semi-colon in front of "STEREO EQU 1" to build VSNDRM10.
; Can be combined with "ChecksumFix"
;
;;---------------------------------------------------------------------
;
; The very first byte of VSNDRM9 is the checksum for the diagnostics,
; however the original value $AA is invalid and the test fails.
; The same issue applies to VSNDRM10 as well. A new define has been
; added called, "ChecksumFix" to replace the incorrect value with
; $24 (VSNDRM9) or $70 (VSNDRM10):
;
;ChecksumFix EQU 1
;
; Remove the semi-colon in front of "ChecksumFix EQU 1" to make the
; diagnostic test work again. Note that this only works on hardware
; by pressing the switch on the D8224 sound board. Changing the
; original value will result in an incorrect checksum warning in MAME.
;
; If you want to hear this sound in MAME, hex edit the last two bytes
; of the assembled sound rom to the address for NMI (usually $F1B6),
; then run MAME in debug mode.
;
; Upon running MAME, the debugger should pause before launching
; the game. Before hitting F5, type in: soundcpu.rw@fffe = f001
; This will change the NMI vector back to the normal SETUP vector.
; Hit F5 and the sound cpu should start at $F1B6 and proceed to play
; the diagnostic sound forever.
;
;;---------------------------------------------------------------------
;
;SpeechTest EQU 1
;
; The diagnostic test is also missing the ability to play through
; all the speech audio, even though there is a valid diagnostic routine
; in the speech processing program. Does not work with "STEREO" because
; the speech board is not connected to Video Sound Rom 10.
;
; This overrides "ChecksumFix" as it replaces the first byte with $E4.
;
;;---------------------------------------------------------------------
;
; To build this code, first download Macroassembler {AS}, then place
; VSNDRM9.ASM in the same directory as ASL and P2BIN. Type in the
; following in a terminal/command line prompt:
;
; asl VSNDRM9.ASM -o vsndrm9.p
;
; Then use P2BIN to generate the binary ROM file:
;
; p2bin vsndrm9.p -l 00 video_sound_rom_9_std.808.ic12
;
; To build the cockpit-exclusive Video Sound Rom 10, simply remove
; the semi-colon in front of "STEREO EQU 1", save the file and
; type in:
; p2bin vsndrm9.p -l 00 video_sound_rom_10_std.ic12
;
;;---------------------------------------------------------------------
;
; I originally wrote this source code for vasm, but after rewriting
; Sinistar's game code to target Macroassembler {AS}, I realized
; that I can do the same for the Sound ROM source so that both can
; be built with the same assembler. And I feel that keeping both
; sources together in the same repository is important.
;
; Retargeting the source to {AS} had the nice side-effect of making
; the Sound ROM source actually easier to assemble, and more accurate
; to how it was done back in 1982. My original recreated source had
; the Walsh synth routine taken out and assembled separately because
; I was running into errors with vasm. This is no longer the case,
; and for the first time ever, we can build Video Sound ROMs 9 and 10
; from a single source file, just like Joust's sound rom.
;
;;---------------------------------------------------------------------
;
; Thanks to historicalsource for preserving the source code
; to the first four Video Sound ROMs found in the following
; classic Williams arcade games: Defender, Stargate, Robotron,
; and Joust. Sinistar reuses code from all of them. For example,
; Joust and Sinistar share the Walsh Function routine (which is
; the most complex synth found in any of these ROMs).
; If none of these source files existed, my reassembly of
; Sinistar's sound code would've been impossible.
;
; Huge thanks also goes out to Will-I-ROMS aka kaputnikGo,
; you can view their extensive Williams disassembly files here:
; https://github.com/kaputnikGo/WiLL-i-ROMS/blob/master/Video%20Sound%20ROMS/Video%20Sound%20ROM%209.asm
;
; Their disassembly of Sinistar's sound ROM was extremely helpful
; in deciphering much of the code, including unused routines.
; Their work also led me to discovering the unused Extra Ship
; sounds found in WALSHT and Mike Metz's corrupted ODDTBL.
;
; Thanks to mwenge for the inspiration to attempt reassembling
; Sinistar's sound ROM by showing that it's possible to rebuild
; Defender's sound code with vasm. His code fixes to VSNDRM1.SRC
; helped me at times where I was completely stuck and had no idea
; where to go.
;
; A big shout out goes to Daniel Lopez for creating the
; Defender Sound Studio javascript app. I highly recommend checking
; it out. His app was very helpful to me when I was struggling to
; understand how the various synths work. You can also create or
; import your own GWAVE sounds including Sinistar's sfx; fun stuff!
; http://zapspace.net/defender_sound/
;
; And last but not least, thanks to my loving spouse for their
; patience and support during this project.
;
;;---------------------------------------------------------------------
;
; In order to get this ROM to build correctly, several modifications
; had to be made. When possible, I will point out code differences
; between Sinistar's sound code and other Williams Sound ROMs.
;
; Original programmer comments are usually UPPER-CASE and have one
; semicolon (;). My comments will have both upper and lower-cases,
; sometimes with parenthesis and always start with two semicolons.
; ;;(like this)
;
;;---------------------------------------------------------------------
CPU 6800 ;;Macroassembler {AS} needs this
;
;
;
;
; NAM JOUST SOUND ROM STARTED 06/15/1982
; SUBTTL
;*COPYRIGHT WILLIAMS ELECTRONICS INC. 1982
;*PROGRAMMERS: EUGENE P. JARVIS, SAM DICKER,RANDY PFEIFFER,JOHN KOTLARIK
;* PAUL G. DUSSAULT,CARY W. KOLKER,TIM MURPHY
;* AND A CAST OF THOUSANDS......
;;SINISTAR SOUND DESIGNER/VIDEO SOUND ROM 9 & 10 PROGRAMMER: MIKE METZ
;;ADDITIONAL SINIBOMB (ED'S SOUND 17) SOUND DESIGN: ED SUCHOCKI
;*
;*
;*
;*SYSTEM CONSTANTS
;*
;*
ROM EQU $F000
SOUND SET $400
CKORG EQU $EF00 ;CHECKSUM PROG ORG
ENDRAM SET $7F
VECTOR EQU $FFF8 ;RESET,INT VECTORS
WVELEN EQU 72
;*
BG1FLG EQU $04
NIN EQU 5
FIF EQU 6
TACC EQU 4 ;TACCATA TEMPO CONSTANT
PHANC EQU 3 ;PHANTOM TEMPO CONTANT
TAF EQU 34715>>1 ;NOTE TIMES ;;43CD
TA EQU 36780>>1
TBF EQU 38967>>1
TB EQU 41284>>1
TC EQU 43739>>1
TCS EQU 46340>>1
TD EQU 49096>>1
TEF EQU 52015>>1
TE EQU 55108>>1
TF EQU 58385>>1
TFS EQU 61857>>1
TG EQU 65535>>1
;; Added Constants
RAM SET $0000
TALKJMP EQU $FFF3 ;;(speech rom entry for ADDX)
;*
;*
;* TALKING EQUATES
;*
TALK EQU $EFFD ;ENTRY TO TALKING
TALKD EQU $EFFA ;ENTRY FOR DIAGNOSTICS
;*
;*
;*GLOBALS
;*
;;
;; (A dummy global was added for padding.)
;;
ORG RAM
;;
DUMMY RMB 1 ;;(to help align ram)
;;
HI RMB 1 ;RANDOM SEED
LO RMB 1 ;RANDOM SEED
XDECAY RMB 2 ;;($03)
DUMMY2 RMB 1 ;;($05)
;*
;*
;*TEMPORARIES
;*
;;
;; (TMPRAM originally had *, but vasm doesn't like this
;; so $0006 was used instead.)
;;
TMPRAM EQU $0006 ;TEMPORARY RAM
TEMPX RMB 2 ;X TEMPS
XPLAY RMB 2 ;;($08)
XPTR RMB 2 ;;($0A)
TEMPA RMB 1 ;ACCA TEMP ;;($0C)
TEMPB RMB 1 ;;($0D)
;;
;; (LOCRAM originally had *, but vasm doesn't like this
;; so $000E was used instead.)
;;
LOCRAM EQU $000E
;*
;*GWAVE PARAMETERS
;*
ORG LOCRAM
GECHO RMB 1 ;ECHO FLAG ;;($0E)
GCCNT RMB 1 ;CYCLE COUNT ;;($0F)
GECDEC RMB 1 ;# OF DECAYS PER ECHO ;;($10)
GDFINC RMB 1 ;DELTA FREQ INC ;;($11)
GDCNT RMB 1 ;DELTA FREQ COUNT ;;($12)
GWFRM RMB 2 ;WAVEFORM ADDRESS ;;($13)
;*TEMPORARY OR COMPUTED PARAMETERS
PRDECA RMB 1 ;PRE-DECAY FACTOR ;;($15)
GWFRQ RMB 2 ;FREQ TABLE ADDR ;;($16)
FRQEND RMB 2 ;END ADDR FREQ TABLE ;;($18)
WVEND RMB 2 ;WAVE END ADDR ;;($1A)
GPER RMB 1 ;PERIOD ;;($1C)
GECNT RMB 1 ;# OF ECHOES COUNTER ;;($1D)
FOFSET RMB 1 ;FREQUENCY OFFSET ;;($1E)
;*
DUMMY3 RMB 1 ;;???
;*
;*GWAVE TABLES
;*
GWTAB RMB WVELEN ;WAVE TABLE ;;($20)
;*
;*
;*ORGAN PARAMETERS
;*
ORG LOCRAM
ORGFLG RMB 1 ;;($0E)
DUR RMB 2 ;NOTE DURATION ;;($0F)
OSCIL RMB 1 ;OSCILLATORS ;;($11)
RDELAY RMB 60 ;RAM DELAY LOAD ;;($12)
;;
;; These labels had to be modified in order for vasm to build.
;; "$" have been replaced with "S".
;;
ORG LOCRAM+1
FREQS RMB 1 ;START FREQUENCY ;;($0F)
CSFRQ RMB 1 ;CYCLES AT FREQUENCY
DSFRQ RMB 1 ;DELTA FREQUENCY
ESFRQ RMB 1 ;END FREQUENCY
CSAMP RMB 1 ;CYCLES AT AMPLITUDE
DSAMP RMB 1 ;DELTA AMPLITUDE
CSAMPS RMB 1 ;CYCLE COUNTER
CSFRQS RMB 1 ;CYCLE COUNTER ;;($16)
DUMMY4 RMB 1 ;;(more padding)
AMP0 RMB 1 ;;($18)
;*
;*
;*
;*NOISE/CROWD ROAR ROUTINE PARAMETERS
;*
ORG LOCRAM
DECAY RMB 1 ;;($0E)
NAMP RMB 1 ;;($0F)
CYCNT RMB 1 ;;($10)
NFRQ1 RMB 2 ;;($11)
NFFLG RMB 1 ;;($13)
LFREQ RMB 1 ;;($14)
DFREQ RMB 1 ;;($15)
GALPAM EQU * ;;($16)
CYCNT2 RMB 1 ;;($16)
NAMP2 RMB 1 ;;($17)
DECAY2 RMB 1 ;;($18)
NFFLG2 RMB 1 ;;($19)
NFR2 RMB 1 ;;($1A)
GALCNT RMB 1 ;;($1B)
WHIS RMB 1 ;CROWD ROAR AMP
WFRQ RMB 1 ;CROWD WHISTLE FREQ
WCNT RMB 1 ;WHISTLE PASSCOUNTER
PTRHI RMB 2 ;WHIS ADR PTR ;;($1F)
WFRQ2 RMB 1 ;;($21)
WCNT2 RMB 1 ;;($22)
CURVAL RMB 1 ;WHISTLING NOISE OUTPUT
ATP RMB 1 ;INTERM NOISE VAL
MINWIS RMB 1 ;MIN WHISTLE FREQ
CY2 RMB 1 ;NOISE CYCLE COUNTER
DFRQ RMB 1 ;WHISTLE FREQ CHANGE
DFRQ2 RMB 1 ;INIT WHISTLE FREQ CHANGE
NNOIS RMB 1 ;NEXT NOISE VALUE ;;($29)
NFRQ RMB 1 ;NOISE FREQ ;;($2A)
NFRQ2 RMB 1 ;INIT NOISE FREQ ;;($2B)
RCNT2 RMB 1 ;;($2C)
;*
;*FILTERED NOISE ROUTINE PARAMETERS
;*
ORG LOCRAM
FMAX RMB 1 ;MAXIMUM_FREQUENCY ;;($0E)
FHI RMB 1 ;FREQUENCY ;;($0F)
FLO RMB 1 ;;($10)
SAMPC RMB 2 ;SAMPLE COUNT ;;($11)
FDFLG RMB 1 ;FREQUENCY DECREMENT FLAG ;;($13)
DSFLG RMB 1 ;DISTORTION FLAG ;;($14)
;*
;*
;* MAIN PROGRAM
;*
ORG ROM
IFDEF SpeechTest
FCB $E4
ELSE
IFNDEF ChecksumFix
FCB $AA ;CHECKSUM BYTE
ELSE
IFDEF STEREO
FCB $70
ELSE
FCB $24
ENDIF
ENDIF
ENDIF
;*
;*
SETUP SEI ;SET INTERRUPT MASK
LDS #ENDRAM ;INITIALIZE STACK POINTER
LDX #SOUND ;INDEX TO PIA
CLR 1,X ;ACCESS DDRA
CLR 3,X ;ACCESS DDRB
LDAA #$FF ;PA0-PA7
STAA 0,X ;SET SIDE A AS OUTPUTS
LDAB #ENDRAM+1 ;;(new instruction) (used for clearing RAM)
STAB 2,X ;;(only found in Sinistar/Bubbles) (Joust has CLR 2,X)
LDAA #$37 ;CB2 LOW, IRQ ALLOWED
STAA 3,X ;PROGRAM B CONTROL REG
LDAA #$3C ;CA2 SET INIT HIGH, NO IRQS
STAA 1,X ;PROGRAM A SIDE
STAB 2,X ;;(new instruction) (store in port B PIA1)
LDX #ENDRAM
RAMCLR CLR 0,X ;;(wipe out the RAM)
DEX
BNE RAMCLR ;;(are we done yet?)
LDAA #$3C ;;(grab number for the random generator)
STAA HI ;START RANDOM GENERATOR
CLI ;CLEAR INTERRUPTS
BRA * ;WAIT FOR INTERRUPT
;*
;*ORGAN TUNE
;*
ORGASM CLR ORGFLG
STAA TEMPA ;TUNE NUMBER
;;
PSHA ;;(this is a new instruction)
;;
LDX #ORGTAB
ORGNT2 LDAA 0,X ;TUNE TABLE LENGTH
BEQ ORGNT5 ;INVALID TUNE
DEC TEMPA
BEQ ORGNT3
INCA
JSR ADDX
BRA ORGNT2
ORGNT3 INX
STX XPTR ;NOTE POINTER
JSR ADDX
STX XPLAY ;TUNE END
LDX XPTR
ORGNT4 LDAA 0,X ;TUNE LOOP
STAA OSCIL
LDAA 1,X
LDX 2,X
STX DUR
BSR ORGANL
LDX XPTR
INX
INX
INX
INX
STX XPTR
CPX XPLAY
BNE ORGNT4
ORGNT5 PULA ;;(In VSNDRM3, this is just an RTS)
BRA BGTEST
;*
;*ORGAN NOTE
;*4 BYTES(MODE,OSCILLATOR MASK HI+1,LO+1,NOTE#)
;*
;*ORGAN LOADER
;*OSCIL=OSCILLATOR MASK, ACCA=DELAY, DUR=DURATION
;*
ORGANL LDX #RDELAY ;;(There's some changes here from VSNDRM3)
LDLP CMPA #0 ;;(original was: SUBA #2)
BEQ LD1 ;;(original was: LDLP BLS LD1)
CMPA #3
BEQ LD2
LDAB #1 ;NOP
STAB 0,X
INX
SUBA #2
BRA LDLP
LD2 LDAB #$91 ;CMPA 0
STAB 0,X
CLR 1,X
INX
INX
LD1 LDAB #$7E ;JMP START2
STAB 0,X
LDAB #ORGAN1>>8 ;;(original was: LDAB #ORGAN1!>8 ;MSB)
STAB 1,X
LDAB #ORGAN1&$FF ;;(original was: LDAB #ORGAN1!.$FF ;LSB)
STAB 2,X
;*
;*ORGAN ROUTINE
;*DUR=DURATION, OSCILLATOR MASK
;*
ORGAN LDX DUR
ORGAN1 CLRA
FCB $F6 ;LOAD B EXTND TEMPB
FDB TEMPB
INCB
STAB TEMPB
ANDB OSCIL ;MASK OSCILLATORS
LSRB
ADCA #0
LSRB
ADCA #0
LSRB
ADCA #0
LSRB
ADCA #0
LSRB
ADCA #0
LSRB
ADCA #0
LSRB
ADCA #0
;; (Robotron's VSNDRM3 has an ABA opcode here)
ASLA
ASLA
ASLA
ASLA
ASLA
STAA SOUND
DEX
BEQ ORGAN2 ;NOTE OVER?
JMP RDELAY
ORGAN2 RTS
;*
;* INTERRUPT PROCESSING
;*
;;
;; The sound IDs referenced in the game logic's sound calls
;; are actually inverted so $BE = 1, $BD = 2, $BC = 3, etc.
;; We start by loading the input trigger at $0402, invert it,
;; then AND it until we get the final number.
;;
IRQ LDS #ENDRAM ;RE-INITIALIZE STACK
LDAA SOUND+2 ;GET INPUT TRIGGER
CLI ;NOW ALLOW IRQS
COMA ;INVERT INPUT
ANDA #$1F ;MASK GARB
BSR QMESG ;;(start checking sound ID)
;;
;; In the original VSNDRM source code files, the interrupts have
;; labels that aren't very descriptive (such as IRQ000).
;; To better understand how the interrupts are processed,
;; I took the liberty of renaming the labels in this section.
;;
;; Some sound effect names have a "Q" in front. These are symbols
;; taken from the game logic source code.
;;
;;---------------------------------------------------------------------
;;
;; ***BGTEST***
;; When no sound is playing, BGTEST is constantly
;; testing to see if the BG1FLAG is on. When the weird
;; drone flag is enabled, this ensures that it continues
;; playing forever until an interrupt breaks the loop.
;; When the current sound finishes, we go back to checking this flag.
;;
;; Sound trigger #4 must be called to mute this sound.
;;
BGTEST TST BG1FLG ;;(Check if drone is on)
BEQ BGTEST ;;(No? Check again!)
JMP DROSYN ;;(Yes? Go make some noise)
;;---------------------------------------------------------------------
;;
;; ***SINISTAR SOUND SELECT***
;;
;; A = Sound ID
;;
;; The sound effects are cued up by comparing A register's value.
;; If it's a bigger number, then we check for the next sound.
;; Otherwise, if the value matches, then we proceed with getting
;; the synth routine started.
;;
;;---------------------------------------------------------------------
;;
;; 1) WARNING CUE
;;
QMESG CMPA #$01 ;;(what sound ID is this?)
BGT SINROAR ;;(if it's a bigger number, then check for the next sound)
JMP ORGASM ;;(otherwise, play the organ warning cue)
;;---------------------------------------------------------------------
;;
;; 2) SINISTAR ROAR
;;
SINROAR CMPA #$02 ;;(check sound ID)
BGT QNEWSH ;;(bigger number? keep going down the line, buddy)
;;
;; Sinistar speech is handled outside of the sound rom.
;; Any jumps to $EFFD are speech calls that are then handled by code
;; located at $EE00 (found in speech IC4).
;;
;; Amazingly, because VSNDRM1 is based off of Firepower's sound ROM,
;; Defender's sound code has the same speech routines Sinistar uses.
;;
;; While writing the documentation here, I discovered a really awesome
;; "easter egg" that Mike Metz left in. If you disconnect the speech
;; board, brand new sounds will play instead of Sinistar's taunts.
;;
;; During any dialouge, if the $7E opcode is not found, a generic
;; error sound plays instead (ERROR).
;;
;; However, if no opcode is found during Sinistar's roar, a new
;; LOUD Walsh Function sound plays that tries to emulate the
;; scary scream (ERROAR). I wonder if this feature was added so that
;; the game can still work without the speech board.
;;
;*
;* CHECK FOR PRESENCE OF TALKING PROGRAM
;*
LDAB TALK ;CHECK FOR PROGRAM TO BE THERE
CMPB #$7E ;IS IT?
BNE ERROAR ;NO, SKIP THE TALKING
LDAA #$09 ;;(load roar speech phrase)
JMP TALK ;GO PLAY OUT 1 PHRASE
;;---------------------------------------------------------------------
;;
;; 3) EXTRA SHIP / ERROR ROAR
;;
QNEWSH CMPA #$03 ;;(check sound ID)
BGT BGMUTE ;;(if not, keep going)
;;
;; The Walsh Function sound machine is normally only used for
;; the Extra Ship sound. But if the speech board is disconnected,
;; then ERROAR is called whenever the Sinistar roars. Both QNEWSH
;; and ERROAR use the A register as the Walsh Table offset.
;;
;; After subtracting by 2, if A = 0 then play ERROAR.
;; If A = 1, play QNEWSH.
;;
;; In the cockpit-exclusive Video Sound ROM 10, the Walsh synth is
;; muted by replacing the SUBA and JMP instructions with an RTS.
;;
ERROAR IFNDEF STEREO
SUBA #$02 ;;(suba to get WALSHT offset)
JMP WALSH ;;(go to Walsh synth)
ELSE
RTS ;;(nevermind, skip it)
ENDIF
;;---------------------------------------------------------------------
;;
;; 4) SHUT UP UNUSED DRONE
;;
BGMUTE CMPA #$04
BGT DRONE
CLR BG1FLG
RTS
;;---------------------------------------------------------------------
;;
;; 5) UNUSED DRONE
;;
DRONE CMPA #$05 ;;(check sound ID)
BGT HUNCOW
JMP DRONELD
;;---------------------------------------------------------------------
;;
;; 6) "I HUNGER COWARD"
;;
HUNCOW CMPA #$06
BGT IMPACT
LDAB TALK
CMPB #$7E
BEQ HANGRY
JMP ERROR
HANGRY LDAA #$08
JMP TALK
;;---------------------------------------------------------------------
;;
;; 7) IMPACT (QPLDIE)
;;
IMPACT CMPA #$07
BGT XPLODE
JMP GUNSHOT
;;---------------------------------------------------------------------
;;
;; 8) PLAYER EXPLOSION (QPLDIE)
;;
XPLODE CMPA #$08
BGT NOISE
JMP C4NNON
;;---------------------------------------------------------------------
;;
;; 9 & 10) TWO UNUSED NOISE EFFECTS
;;
NOISE CMPA #$0A
BGT RUNCOW
SUBA #$09
JMP NOISELD
;;---------------------------------------------------------------------
;;
;; 11) "RUN COWARD"
;;
RUNCOW CMPA #$0B
BGT QBANG
LDAB TALK
CMPB #$7E
BNE ERROR
LDAA #$06
JMP TALK
;;---------------------------------------------------------------------
;;
;; 12) BANG (Explosion used for Enemies and Planetoids)
;;
QBANG CMPA #$0C
BGT IAMSINI
JMP CANNON
;;---------------------------------------------------------------------
;;
;; 13) "I AM SINISTAR"
;;
IAMSINI CMPA #$0D
BGT BEWARE
LDAB TALK
CMPB #$7E
BNE ERROR
LDAA #$02
JMP TALK
;;---------------------------------------------------------------------
;;
;; 14) "BEWARE I LIVE"
;;
BEWARE CMPA #$0E
BGT HUNGER
LDAB TALK
CMPB #$7E
BNE ERROR
LDAA #$03
JMP TALK
;;---------------------------------------------------------------------
;;
;; 15) "I HUNGER"
;;
HUNGER CMPA #$0F
BGT COWARE
LDAB TALK
CMPB #$7E
BNE ERROR
LDAA #$04
JMP TALK
;;---------------------------------------------------------------------
;;
;; 19) "BEWARE COWARD"
;;
COWARE CMPA #$13
IFNDEF STEREO
BNE GWAVSFX
ELSE
BNE GDELAY
ENDIF
LDAB TALK
CMPB #$7E
BNE ERROR
LDAA #$05
JMP TALK
;;---------------------------------------------------------------------
;;
;; STEREO SEPARATION DELAY (FOR VSNDRM10 ONLY)
;;
;; In order to create the stereo separation effect for GWAVE
;; sounds, the rear channel has to start playing shortly after the
;; front channel.
;;
;; This was done by loading $10FF into the X register and then
;; decrementing X before continuing. This adds around
;; 0.097 seconds of delay.
;;
;; Changing it to a max value of $FFFF increases the delay to
;; around 0.644 to 0.692 seconds.
;;
;; Looking at the disassembly for the Gorgar sound ROM, the same
;; trick was used to add a delay between the continuous heartbeats.
;; The instruction can be found at $FA3C and uses $3200 as the
;; delay amount instead of $10FF.
;;
;; These instructions also creates the side effect of muting the
;; bounce sound effect entirely since it plays so briefly.
;;
GDELAY IFDEF STEREO
LDX #$10FF
DELAY DEX
BNE DELAY
ENDIF
;;---------------------------------------------------------------------
;;
;; 16-18, 20-28) GWAVE SOUND EFFECTS
;;
;; Once the time delay for the stereo separation has finished,
;; we check for GWAVE sounds. Sound ID $AF is the first GWAVE
;; sound in the list, and A register is the offset used to select
;; the specific parameters from the GWAVE table.
;;
;; To play all the different GWAVE sounds (including unused ones),
;; type this in MAME's debugger to trigger the Sinibomb sound ($AF)
;; when inserting a coin:
;;
;; maincpu.rw@4dfd = b0af
;;
;; Then change the value at $F18A so that the soundcpu can pull
;; up a different sound:
;;
;; soundcpu.rb@f18a = 10 (UNUSED WARNING?)
;; soundcpu.rb@f18a = 0F (SINISTAR SPEECH ERROR)
;; soundcpu.rb@f18a = 0E (AF = SINI-BOMB) (Original value) (QSFire)
;; soundcpu.rb@f18a = 0D (AE = PLAYER FIRE) (QFIRE)
;; soundcpu.rb@f18a = 0C (AD = WARRIOR FIRE) (QWFIRE)
;; soundcpu.rb@f18a = 0B (UNUSED ALTERNATE BOUNCE)
;; soundcpu.rb@f18a = 0A (AB = BOUNCE) (QBOUNCE)
;; soundcpu.rb@f18a = 09 (AA = WORKER CRYSTAL PICKUP) (QWorkCr)
;; soundcpu.rb@f18a = 08 (A9 = UNUSED "LANDER" FIRE) (FOUND IN DEFENDER VSNDRM1 AS DP1V)
;; soundcpu.rb@f18a = 07 (A8 = CRYSTAL BOMB-BAY FULL) (QFulCr)
;; soundcpu.rb@f18a = 06 (A7 = CRYSTAL FLASHING) (QCRYFLA)
;; soundcpu.rb@f18a = 05 (A6 = PIECE ADDED / GAME OVER) (QWorkSi/QGamEnd) (Also used in Splat!)
;; soundcpu.rb@f18a = 04 (A5 = UNUSED BLASTER "ENERGY CRITICAL" ALARM)
;; soundcpu.rb@f18a = 03 (A4 = PLAYER START CUE) (QPlStr)
;; soundcpu.rb@f18a = 02 (A3 = PLAYER CRYSTAL PICKUP) (QPlayCr)
;;
;; There is a glitch in MAME's debugger that prevents $0B
;; from showing up in RAM. Another way play these sounds is to
;; set up a breakpoint at $F7E5, then type in:
;; do x = [SVTAB address]
;;
GWAVSFX CMPA #$1C
BGT RUNRUN
SUBA #$0E
PLAYSFX JSR GWLD
JMP GWAVE
;;---------------------------------------------------------------------
;;
;; 29) "RUN RUN RUN"
;;
RUNRUN CMPA #$1D
BGT SHUTUP
LDAB TALK
CMPB #$7E
BNE ERROR
LDAA #$07
JMP TALK
;;---------------------------------------------------------------------
;;
;; 31) SHUT UP SINISTAR
;;
;; This is used to mute Sinistar speech.
;;
SHUTUP RTS
;;---------------------------------------------------------------------
;;
;; NO SPEECH ERROR NOISE
;;
;; If the speech board is disconnected for VSNDRM9, then play the
;; Sinistar Error noise. Since there's no speech board attached
;; to VSNDRM10's sound board, an RTS replaces the error noise,
;; muting the sound call entirely.
;;
IFNDEF STEREO
ERROR LDAA #$01
JMP PLAYSFX
ELSE
ERROR RTS
ENDIF
;;---------------------------------------------------------------------
;*
;* ADD A TO INDEX REGISTER
;*
ADDX STX XPLAY
ADDA XPLAY+1
STAA XPLAY+1
LDAA XPLAY
ADCA #0
STAA XPLAY
ADDX1 LDX XPLAY
RTS
;*
;* DIAGNOSTIC PROCESSING HERE
;*
NMI SEI
LDS #ENDRAM ;RESET THE STACK
LDX #$FFFF
CLRB
NMI1 ADCB 0,X
DEX
CPX #$F000
BNE NMI1
CMPB 0,X
BEQ NMI2
WAI ;;(test failed, wait forever)
NMI2 JSR DIAGNOI ;;(play unused Diagnoistic Synth Noise)
IFDEF SpeechTest ;;Added new SpeechTest define for diagnostics
JSR DIAGNOI ;;play test noise two more times
JSR DIAGNOI
LDAB TALKD ;;load TALKD address into B
CMPB #$7E ;;check if JMP opcode exists
BNE NMI ;; NO opcode! Go back to NMI
JSR TALKD ;; If opcode exists, then start talkin'
ENDIF
BRA NMI ;;(loop forever)
;;---------------------------------------------------------------------
;*
;* NOTE DEFINITIONS AND ALL THAT JAZZ
;*
AF1 EQU $F847
A1 EQU $F83F
BF1 EQU $F837
B1 EQU $F830
C1 EQU $F829
CS1 EQU $F823
D1 EQU $F81D
EF1 EQU $F817
E1 EQU $F812
F1 EQU $F80D
FS1 EQU $F808
G2 EQU $F804
AF2 EQU $7C47
A2 EQU $7C3F
BF2 EQU $7C37
B2 EQU $7C30
C2 EQU $7C29
CS2 EQU $7C23
D2 EQU $7C1D
EF2 EQU $7C17
E2 EQU $7C12
F2 EQU $7C0D
FS2 EQU $7C08
G3 EQU $7C04
AF3 EQU $3E47
A3 EQU $3E3F
BF3 EQU $3E37
B3 EQU $3E30
C3 EQU $3E29
CS3 EQU $3E23
D3 EQU $3E1D
EF3 EQU $3E17
E3 EQU $3E12
F3 EQU $3E0D
FS3 EQU $3E08
G4 EQU $3E04
AF4 EQU $1F47
A4 EQU $1F3F
BF4 EQU $1F37
B4 EQU $1F30
C4 EQU $1F29
CS4 EQU $1F23
D4 EQU $1F1D
EF4 EQU $1F17
E4 EQU $1F12
F4 EQU $1F0D
FS4 EQU $1F08
;; (Actual Sinistar Notes)
AF7 EQU $0347
C7 EQU $0329
E7 EQU $0312
;;
RS EQU $0004
TR EQU TG
;*
;* ORGAN TUNE TABLE
;* OSCILLATOR MASK(1),DELAY(1),DURATION(2)
;*
ORGTAB FCB 3*4
;;
;; (Listed as A Flat in 7th octave (AF7), but it sounds like a G6 note)
;; $03 = octave, $47 = AF, $05 = delay?, $FC = duration?
;;
FDB AF7,$05FC
;;
;; (Listed as E in 7th octave (E7), but it sounds like a D#7 note)
;; $03 = octave, $12 = E, $11 = delay?, $F0 = duration?
;;
FDB E7,$11F0
;;
;; (Listed as C in 7th octave (C7), but it sounds like a B6 note)
;; $03 = octave, $29 = C, $07= delay?, $1E = duration?
;;
FDB C7,$071E
;;
;; Organ note durations are calculated, so it's currently unknown
;; how to get to these numbers. The first word for each note is
;; the Note Time shifted to the right by 1 (TAF, TC, TE).
;; 43CD / ? / ? = 05FC
;; 6BA2 / ? / ? = 11F0
;; 556D / ? / ? = 071E
;;
;; An example of note durations from VSNDRM3.SRC (Robotron):
;;FIFTH EQU *
;;FIF EQU 6
;; FDB G2,TG/FIF/4
;; FDB RS,TR/FIF/4
;; FDB G2,TG/FIF/4
;; FDB RS,TR/FIF/4
;; FDB G2,TG/FIF/4
;; FDB RS,TR/FIF/4
;; FDB EF1,TEF/FIF/2*7
;; FCB TUNEND-NINTH
;;
;; To play this in Defender Sound Studio import the following code:
;;{
;; "sound": "Music",
;; "params": ["03,71,1532,\n03,18,4592,\n03,41,1822"]
;;}
;;
;;---------------------------------------------------------------------
;;
;; ***WALSH FUNCTION SOUND MACHINE***
;;
;; (This is where the Walsh Function synth code begins. This routine
;; is huge and accounts for almost 30% of the entire ROM. Because
;; the Walsh Function isn't used in the cockpit rear sound board ROM,
;; the routine gets skipped completely and never runs! This means you
;; could technically build VSNDRM10 without the Walsh routine, but the
;; checksum would be different.)
;;
;;---------------------------------------------------------------------
RADIX 10 ;;Decimal values ahead
;*SYSTEM CONSTANTS
;*
;;STEREO EQU 1 ;;(use this to build VSNDRM10)
;*
;* NAM WALSH FUNCTION SOUND MACHINE V2
;
;* T. MURPHY 11/10/81
MINPER EQU 25 ;6*25 = 150 MICROSECS IS MIN SAMPLE PERIOD
SOUND SET $400
WORG ;;Make Walsh routine start here
ORG 0
RMB 8 ;GLOBALS
FCMDPT RMB 2 ;PTR TO CURRENT FILTER COMMAND (USER INITIALIZED)
PCMDPT RMB 2 ;SAME FOR PITCH PROGRAM
SMPPER RMB 2 ;HI BYTE * 6 IS SAMPLE DELAY
HRMTBL RMB 2 ;PTR TO HARMONIC FN VALUE TABLE
WAVSRT RMB 16 ;WAVEFORM
PERVEL RMB 2 ;ADDED TO SMPPER EACH WAVE (PITCH CONTROL)
GLBPRO RMB 1 ;GLOBAL PERIOD OFFSET
TMPPER RMB 1 ;= SMPPER + GLBPRO
PERACM RMB 1 ;USED TO CALCULATE SMALL PITCH ADJUSTS
PWVCNT EQU * ;#OF WAVES TO PLAY BEFORE NEXT PITCH CMD (P PROGRAM)
PSTK RMB 2 ;TOP OF PITCH RETURN/COUNT STACK
PWAVPT RMB 2 ;PTR TO CURRENT SAMPLE BEING PLAYED
PCMD RMB 1 ;CURRENT PITCH CMD