/
galaga.cpp
3549 lines (2925 loc) · 181 KB
/
galaga.cpp
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
// license:BSD-3-Clause
// copyright-holders:Nicola Salmoria
/***************************************************************************
Bosconian (c) 1981 Namco
Galaga (c) 1981 Namco
Xevious (c) 1982 Namco
Dig Dug (c) 1982 Namco
driver by Nicola Salmoria
based on previous work by Martin Scragg, Mirko Buffoni, Aaron Giles
All these games are based on the same 3xZ80, shared memory, CPU design.
Bosconian and Galaga use the same CPU board, with minor differences
(Galaga has one missing RAM and no 50XX custom)
Xevious is physically different, but logically identical.
Dig Dug is the only one a bit different, because it reads the dip switches
through a custom chip instead of having them mapped in memory.
The video board, on the other hand, is completely different for all the games,
that's why they use separate video/ source files.
Custom ICs:
----------
Bosconian:
---------
CPU board:
06XX interface to custom 5xXX
07XX clock divider
08XX(x3) bus controller
50XX player score control (protection)
51XX I/O
54XX explosion sound generator
Video board:
03XX(x2) ?
05XX starfield generator
06XX interface to custom 5xXX
07XX clock divider
50XX player score control (only used as protection check)
52XX sample player
Galaga:
------
CPU board:
06XX interface to custom 5xXX
07XX clock divider
08XX(x3) bus controller
51XX I/O
54XX explosion sound generator
Video board:
00XX tilemap address generator with scrolling capability (only Super Pacman)
02XX gfx data shifter and mixer (16-bit in, 4-bit out)
04XX sprite address generator
05XX starfield generator
07XX clock divider
Xevious:
-------
CPU board:
06XX interface to custom 5xXX
07XX clock divider
08XX(x3) bus controller
50XX player score control (only used for a protection check on startup)
51XX I/O
54XX explosion sound generator
Video board:
03XX(x2) ?
04XX sprite address generator
07XX clock divider
11XX(x2) gfx data shifter and mixer (16-bit in, 4-bit out)
12XX sprite generator
13XX dual scrolling tilemap address generator
Dig Dug:
-------
CPU board:
06XX interface to custom 5xXX
07XX clock divider
08XX(x3) bus controller
51XX I/O
53XX I/O
Video board:
00XX tilemap address generator
02XX gfx data shifter and mixer (16-bit in, 4-bit out)
04XX sprite address generator
07XX clock divider
Memory maps:
-----------
Bosconian:
---------
MAIN CPU:
Address Dir Data Name Description
---------------- --- -------- --------- -----------------------
0000xxxxxxxxxxxx R xxxxxxxx ROM 3N program ROM
0001xxxxxxxxxxxx R xxxxxxxx ROM 3M program ROM
0010xxxxxxxxxxxx R xxxxxxxx ROM 3L program ROM
0011xxxxxxxxxxxx R xxxxxxxx ROM 3K program ROM
the rest of the memory map is common to the other CPUs
SUB CPU:
Address Dir Data Name Description
---------------- --- -------- --------- -----------------------
0000xxxxxxxxxxxx R xxxxxxxx ROM 3J program ROM
0001xxxxxxxxxxxx R xxxxxxxx ROM 3H program ROM
0010------------ n.c.
0011------------ n.c.
the rest of the memory map is common to the other CPUs
SOUND CPU:
Address Dir Data Name Description
---------------- --- -------- --------- -----------------------
0000xxxxxxxxxxxx R xxxxxxxx ROM 3E program ROM
0001------------ n.c.
0010------------ n.c.
0011------------ n.c.
the rest of the memory map is common to the other CPUs
COMMON:
Address Dir Data Name Description
---------------- --- -------- --------- -----------------------
01000----------- n.c.
01001----------- n.c.
01010----------- n.c.
01011----------- n.c.
01100----------- n.c.
01101-----00xxxx W ----xxxx RAM 2A \ sound control registers
01101-----01xxxx W ----xxxx RAM 2B /
01101-----10-000 W -------x IRQ1 main CPU irq enable/acknowledge
01101-----10-001 W -------x IRQ2 motion CPU irq enable/acknowledge
01101-----10-010 W -------x NMION sound CPU nmi enable
01101-----10-011 W -------x RESET reset sub and sound CPU, and 5xXX chips on CPU board
01101-----10-100 W -------x n.c.
01101-----10-101 W -------x MOD 0 unused?
01101-----10-110 W -------x MOD 1 unused?
01101-----10-111 W -------x MOD 2 unused?
01101-----11---- W -------- WDR watchdog reset
01101-----00-xxx R -------x DIP SW dip switch B
01101-----00-xxx R ------x- DIP SW dip switch A
01101-----01---- R n.c.
01101-----10---- R n.c.
01101-----11---- R n.c.
01110--0-------- R/W xxxxxxxx I/O custom 06XX data
01110--1-------- R/W xxxxxxxx I/O custom 06XX control
01111xxxxxxxxxxx R/W xxxxxxxx RAM 2N work RAM (not present in Galaga)
10000xxxxxxxxxxx R/W xxxxxxxx DHRAM tilemap RAM (tile code) [1]
10001xxxxxxxxxxx R/W xxxxxxxx VCRAM tilemap RAM (tile attr) [1]
10010--0-------- R/W xxxxxxxx EXCS custom 06XX #2 data
10010--1-------- R/W xxxxxxxx EXCS custom 06XX #2 control
10011----000xxxx W ----xxxx SOWR bullets shape and X pos msb [2]
10011----001---- W xxxxxxxx POSI X playfield X scroll
10011----010---- W xxxxxxxx POSI Y playfield Y scroll
10011----011---- W -----xxx STAR to 05XX: starfield X scroll speed
10011----011---- W --xxx--- STAR to 05XX: starfield Y scroll speed
10011----100---- W -------- STARCLR to 05XX: unknown
10011----101---- W n.c.
10011----110---- W n.c.
10011----111-000 W -------x FLIP flip screen
10011----111-001 W -------x n.c.
10011----111-010 W -------x n.c.
10011----111-011 W -------x n.c.
10011----111-100 W -------x BLK 0 \ to 05XX: starfield blink
10011----111-101 W -------x BLK 1 / (select active subset)
10011----111-110 W -------x n.c.
10011----111-111 W -------x RESET reset 5xXX chips on video board
10100----------- n.c.
10101----------- n.c.
10110----------- n.c.
10111----------- n.c.
[1] 1st half is radar + sprite registers, 2nd half is scrolling playfield
[2] SO = Small Objects? Only locations 4-F are used.
Galaga:
------
MAIN CPU:
Address Dir Data Name Description
---------------- --- -------- --------- -----------------------
0000xxxxxxxxxxxx R xxxxxxxx ROM 3N program ROM
0001xxxxxxxxxxxx R xxxxxxxx ROM 3M program ROM
0010xxxxxxxxxxxx R xxxxxxxx ROM 3L program ROM
0011xxxxxxxxxxxx R xxxxxxxx ROM 3K program ROM
the rest of the memory map is common to the other CPUs
SUB CPU:
Address Dir Data Name Description
---------------- --- -------- --------- -----------------------
0000xxxxxxxxxxxx R xxxxxxxx ROM 3J program ROM
0001------------ n.c.
0010------------ n.c.
0011------------ n.c.
the rest of the memory map is common to the other CPUs
SOUND CPU:
Address Dir Data Name Description
---------------- --- -------- --------- -----------------------
0000xxxxxxxxxxxx R xxxxxxxx ROM 3E program ROM
0001------------ n.c.
0010------------ n.c.
0011------------ n.c.
the rest of the memory map is common to the other CPUs
COMMON:
Address Dir Data Name Description
---------------- --- -------- --------- -----------------------
01000----------- n.c.
01001----------- n.c.
01010----------- n.c.
01011----------- n.c.
01100----------- n.c.
01101-----00---- W ----xxxx RAM 2A \ sound control registers
01101-----01---- W ----xxxx RAM 2B /
01101-----10-000 W -------x IRQ1 main CPU irq enable/acknowledge
01101-----10-001 W -------x IRQ2 motion CPU irq enable/acknowledge
01101-----10-010 W -------x NMION sound CPU nmi enable
01101-----10-011 W -------x RESET reset sub and sound CPU, and 5xXX chips on CPU board
01101-----10-100 W -------x n.c.
01101-----10-101 W -------x MOD 0 unused?
01101-----10-110 W -------x MOD 1 unused?
01101-----10-111 W -------x MOD 2 unused?
01101-----11---- W -------- WDR watchdog reset
01101-----00-xxx R -------x DIP SW dip switch B
01101-----00-xxx R ------x- DIP SW dip switch A
01101-----01---- R n.c.
01101-----10---- R n.c.
01101-----11---- R n.c.
01110--0-------- R/W xxxxxxxx I/O custom 06XX data
01110--1-------- R/W xxxxxxxx I/O custom 06XX control
10000xxxxxxxxxxx R/W xxxxxxxx RAM 1K tilemap RAM
10001-xxxxxxxxxx R/W xxxxxxxx RAM 3E/3F work RAM
10001-111xxxxxxx R/W xxxxxxxx portion holding sprite registers
10010-xxxxxxxxxx R/W xxxxxxxx RAM 3K/3L work RAM
10010-111xxxxxxx R/W xxxxxxxx portion holding sprite registers
10011-xxxxxxxxxx R/W xxxxxxxx RAM 3H/3J work RAM
10011-111xxxxxxx R/W xxxxxxxx portion holding sprite registers
10100--------000 W -------x \
10100--------001 W -------x > to 05XX: starfield X scroll speed
10100--------010 W -------x /
10100--------011 W -------x \ to 05XX: starfield blink
10100--------100 W -------x / (select active subset)
10100--------101 W -------x to 05XX: unknown. It is the same as STARCLR in Bosconian
10100--------110 W -------x n.c.
10100--------111 W -------x FLIP flip screen
10101----------- n.c.
10110----------- n.c.
10111----------- n.c.
Namco vs Midway ROM names and locations
---------------------------------------
Location ID Location ID
-------- ---- -------- -----
CPU 3P GG1-1 CPU 3N 3200A
CPU 3M GG1-2 CPU 3M 3300B
CPU 2M GG1-3 CPU 3L 3400C
CPU 2L GG1-4 CPU 3K 3500D
CPU 3F GG1-5 CPU 3J 3600E
CPU 2C GG1-7 CPU 3E 3700G
CPU 1D GG1-1[bpr] CPU 1D
CPU 5C GG1-2[bpr] CPU 5C
VID 4L GG1-9 VID 4L 2600J
VID 4F GG1-10 VID 4F 2700K
VID 4D GG1-11 VID 4D 2800L
VID 1C GG1-3[bpr] VID 1C
VID 2N GG1-4[bpr] VID 2N
VID 5N GG1-5[bpr] VID 5N
Xevious:
-------
MAIN CPU:
Address Dir Data Name Description
---------------- --- -------- --------- -----------------------
000xxxxxxxxxxxxx R xxxxxxxx ROM 1 program ROM
001xxxxxxxxxxxxx R xxxxxxxx ROM 2 program ROM
the rest of the memory map is common to the other CPUs
MOTION CPU:
Address Dir Data Name Description
---------------- --- -------- --------- -----------------------
000xxxxxxxxxxxxx R xxxxxxxx ROM 3 program ROM
the rest of the memory map is common to the other CPUs
SOUND CPU:
Address Dir Data Name Description
---------------- --- -------- --------- -----------------------
00-xxxxxxxxxxxxx R xxxxxxxx ROM 4 program ROM
the rest of the memory map is common to the other CPUs
COMMON:
a small part of the decoding for the video board is done by a PAL so it is inferred by program behaviour
Address Dir Data Name Description
---------------- --- -------- --------- -----------------------
01000----------- n.c.
01001----------- n.c.
01010----------- n.c.
01011----------- n.c.
01100----------- n.c.
01101-----00---- W ----xxxx SRAM 0 \ sound control registers
01101-----01---- W ----xxxx SRAM 1 /
01101-----10-000 W -------x IRQ1 main CPU irq enable/acknowledge
01101-----10-001 W -------x IRQ2 motion CPU irq enable/acknowledge
01101-----10-010 W -------x NMION sound CPU nmi enable
01101-----10-011 W -------x RESET reset sub and sound CPU, and 5xXX chips on CPU board
01101-----10-100 W -------x n.c.
01101-----10-101 W -------x n.c.
01101-----10-110 W -------x n.c.
01101-----10-111 W -------x n.c.
01101-----11---- W -------- WDR watchdog reset
01101-----00-xxx R -------x DIP SW dip switch B
01101-----00-xxx R ------x- DIP SW dip switch A
01101-----01---- R n.c.
01101-----10---- R n.c.
01101-----11---- R n.c.
01110--0-------- R/W xxxxxxxx I/O custom 06XX data
01110--1-------- R/W xxxxxxxx I/O custom 06XX control
01111xxxxxxxxxxx R/W xxxxxxxx work RAM
1000-xxxxxxxxxxx R/W xxxxxxxx work RAM
1000-1111xxxxxxx R/W xxxxxxxx portion holding sprite registers (x, y)
1001-xxxxxxxxxxx R/W xxxxxxxx work RAM
1001-1111xxxxxxx R/W xxxxxxxx portion holding sprite registers (flip, size)
1010-xxxxxxxxxxx R/W xxxxxxxx work RAM
1010-1111xxxxxxx R/W xxxxxxxx portion holding sprite registers (sprite number & color)
10110xxxxxxxxxxx R/W xxxxxxxx PF0 fg tilemap RAM (tile attributes)
10111xxxxxxxxxxx R/W xxxxxxxx PF1 bg tilemap RAM (tile attributes)
11000xxxxxxxxxxx R/W xxxxxxxx PF2 fg tilemap RAM (tile code)
11001xxxxxxxxxxx R/W xxxxxxxx PF3 bg tilemap RAM (tile code)
1101-----000---x W xxxxxxxx bg X scroll (9-bit data: A0 is the msb)
1101-----001---x W xxxxxxxx fg X scroll (9-bit data: A0 is the msb)
1101-----010---x W xxxxxxxx bg Y scroll (9-bit data: A0 is the msb)
1101-----011---x W xxxxxxxx fg Y scroll (9-bit data: A0 is the msb)
1101-----111---- W -------x FLIP flip screen
1110------------ n.c.
1111-----------0 W xxxxxxxx BS0 \ address to read from background data ROMs
1111-----------1 W xxxxxxxx BS1 / (see xevious_bb_r)
1111-----------0 R xxxxxxxx BB0 \ read from background data ROMs
1111-----------1 R xxxxxxxx BB1 /
Namco vs Atari ROM names and locations
--------------------------------------
Location ID Location ID
-------- ---- -------- ----------
CPU 3P XVI-1 CPU 1M 136018-118
CPU 3M XVI-2 " " " "
CPU 2M XVI-3 CPU 1L 136018-119
CPU 2L XVI-4 " " " "
CPU 3F XVI-5 CPU 4C 136018-120
CPU 3J XVI-6 " " " "
CPU 2C XVI-7 CPU 2C 136018-127
CPU 5N XVI-1[bpr] CPU 6M 136018-028
CPU 7N XVI-2[bpr] CPU 8M 136018-029
VID 2A XVI-9 VID 2A 136018-101
VID 2B XVI-10 VID 2B 136018-102
VID 2C XVI-11 VID 2C 136018-103
VID 3B XVI-12 VID 3B 136018-104
VID 3C XVI-13 VID 3C 136018-105
VID 3D XVI-14 VID 3D 136018-106
VID 4M XVI-15 VID 4M 136018-107
VID 4N XVI-16 VID 4N 136018-108
VID 4P XVI-17 VID 4P 136018-109
VID 4R XVI-18 VID 4R 136018-110
VID 3L XVI-4[bpr] VID 3L 136018-011
VID 3M XVI-5[bpr] VID 3M 136018-012
VID 4F XVI-6[bpr] VID 4F 136018-013
VID 4H XVI-7[bpr] VID 4H 136018-014
VID 6A XVI-8[bpr] VID 6A 136018-015
VID 6D XVI-9[bpr] VID 6D 136018-016
VID 6E XVI-10[bpr] VID 6E 136018-017
Dig Dug:
-------
MAIN CPU:
Address Dir Data Name Description
---------------- --- -------- --------- -----------------------
0000xxxxxxxxxxxx R xxxxxxxx ROM 0 program ROM
0001xxxxxxxxxxxx R xxxxxxxx ROM 1 program ROM
0010xxxxxxxxxxxx R xxxxxxxx ROM 2 program ROM
0011xxxxxxxxxxxx R xxxxxxxx ROM 3 program ROM
the rest of the memory map is common to the other CPUs
SUB CPU:
Address Dir Data Name Description
---------------- --- -------- --------- -----------------------
0000xxxxxxxxxxxx R xxxxxxxx ROM 4 program ROM
0001xxxxxxxxxxxx R xxxxxxxx ROM 5 program ROM
0010------------ n.c.
0011------------ n.c.
the rest of the memory map is common to the other CPUs
SOUND CPU:
Address Dir Data Name Description
---------------- --- -------- --------- -----------------------
0000xxxxxxxxxxxx R xxxxxxxx ROM 6 program ROM
0001xxxxxxxxxxxx R xxxxxxxx ROM 7 program ROM (optional, not used)
0010------------ n.c.
0011------------ n.c.
the rest of the memory map is common to the other CPUs
COMMON:
Address Dir Data Name Description
---------------- --- -------- --------- -----------------------
01000----------- n.c.
01001----------- n.c.
01010----------- n.c.
01011----------- n.c.
01100----------- n.c.
01101-----00---- W ----xxxx AUDIO 0 \ sound control registers
01101-----01---- W ----xxxx AUDIO 1 /
01101-----10-000 W -------x IRQ1 main CPU irq enable/acknowledge
01101-----10-001 W -------x IRQ2 sub CPU irq enable/acknowledge
01101-----10-010 W -------x NMION sound CPU nmi enable
01101-----10-011 W -------x RESET reset sub and sound CPU, and 5xXX chips on CPU board
01101-----10-100 W -------x n.c.
01101-----10-101 W -------x MOD 0 \
01101-----10-110 W -------x MOD 1 | to custom 53XX
01101-----10-111 W -------x MOD 2 /
01101-----11---- W -------- WDDIS watchdog reset
01110--0-------- R/W xxxxxxxx I/O custom 06XX data
01110--1-------- R/W xxxxxxxx I/O custom 06XX control
01111----------- n.c.
10000xxxxxxxxxxx R/W xxxxxxxx RAM 0 tilemap RAM + work RAM
10001-xxxxxxxxxx R/W xxxxxxxx OBJRAM work RAM
10001-111xxxxxxx R/W xxxxxxxx portion holding sprite registers (sprite number and color)
10010-xxxxxxxxxx R/W xxxxxxxx POSRAM work RAM
10010-111xxxxxxx R/W xxxxxxxx portion holding sprite registers (x and y)
10011-xxxxxxxxxx R/W xxxxxxxx FLPRAM work RAM
10011-111xxxxxxx R/W xxxxxxxx portion holding sprite registers (flip)
10100--------000 W -------x \ background ROM (114) bank select
10100--------001 W -------x /
10100--------010 W -------x tilemap color select (low or high 4 bits of tilemap RAM)
10100--------011 W -------x background enable
10100--------100 W -------x \ background color lookup PROM (112) bank select
10100--------101 W -------x /
10100--------110 W -------x n.c.
10100--------111 W -------x FLIP flip screen
10101----------- n.c.
10110----------- n.c.
10111----0xxxxxx W xxxxxxxx EAROM non volatile memory address latch and data write
10111----0------ R xxxxxxxx EAROM non volatile memory read
10111----1------ W ----xxxx EAROM non volatile memory control
Namco vs Atari ROM names and locations
--------------------------------------
The Namco version is composed of two boards, while the Atari version is
single board. There are two revisions of the Atari version.
Location ID Location Location ID
(type 1) (type 2)
-------- ---- -------- -------- ----------
CPU 3P DD1-1 6L 2C/D 136007-101
CPU 3M DD1-2 6M 2E 136007-102
CPU 2M DD1-3 6N/P 2B/C 136007-103
CPU 2L DD1-4 6R 2A 136007-104
CPU 3F DD1-5 6C 2P 136007-105
CPU 3J DD1-6 6D 2N 136007-106
CPU 2C DD1-7 5L 2K/L 136007-107
CPU 5N [bpr] 2K/L 10A 136007-109
CPU 7N [bpr] 2P 11A 136007-110
VID 2C DD1-9 8R 5K 136007-108
VID 1C [bpr] 4G 8F 136007-111
VID 2N [bpr] 10K/L 4N 136007-112
VID 5N [bpr] 1R 8L 136007-113
VID 2D DD1-10 9N 4J 136007-114
VID 5C DD1-11 10C/D 4F 136007-115
VID 5F DD1-12 7A/B 5B 136007-119
VID 5H DD1-13 8A/B 5A 136007-118
VID 5J DD1-14 7C 5C 136007-117
VID 5K DD1-15 8C 5D 136007-116
Gatsbee (Galaga mod/bootleg)
----------------------------
This game runs on modified bootleg Galaga hardware (blue board with PCB numbers DG-09-02 and DG-07-02)
ROM8: is a 2764. pins 1, 26, 27, 28 tied together.
pin2 out of socket, has wire that is tied to pin 4 of a LS259 that sits on top of the main Z80
CPU located at 5B/6B
Z80: There are 2 logic chips sitting on top of it which are wired up to the Z80 and to each other.
Looks like this....
|-------------------|
| LS32 LS259 <
|-------------------|
Bend all the legs outwards.
Line up the LS259 so pin 16 is in line with Z80 pin 11
Line up the LS32 so pin 7 is in line with Z80 pin 29
Atach the 2 chips to the top of the Z80 with some glue
Connect like this....
LS32 pin 1 tied to Z80 pin 22 (WR)
LS32 pin 2 tied to Z80 pin 19 (MREQ)
LS32 pin 3,4 tied together
LS32 pin 5 tied to Z80 pin 4 (A14)
LS32 pin 6 tied to pin 10 LS32
LS32 pin 7 tied to Z80 pin 29 (GND)
LS32 pin 8 tied to LS259 pin 14
LS32 pin 9 tied to Z80 pin 5 (A15)
LS32 pins 11, 12, 13 have NC
LS32 pin 14 tied to Z80 pin 11 (+5V)
LS259 pin 1 tied to Z80 pin 30 (A0)
LS259 pin 2 tied to Z80 pin 31 (A1)
LS259 pin 3 tied to Z80 pin 32 (A2)
LS259 pin 4 to ROM 8 (as above)
LS259 pins 5, 6, 7 have NC
LS259 pin 8 tied to Z80 pin 29 (GND)
LS259 pins 9, 10, 11, 12 have NC
LS259 pin 13 tied to Z80 pin 14 (D0)
LS259 pin 15 tied to Z80 pin 26 (RESET)
LS259 pin 16 tied to Z80 pin 11 (+5V)
Easter eggs:
-----------
- Bosconian:
- enter service mode
- keep B1 pressed and enter the following sequence:
5xU 6xR 1xD 4xL
(c) 1981 NAMCO LTD. will be added at the bottom of the screen.
- Galaga:
- enter service mode
- keep B1 pressed and enter the following sequence:
5xR 6xL 3xR 7xL
(c) 1981 NAMCO LTD. will appear on the screen.
- Xevious:
- start a game
- go to the bottom right of the screen and keep B2 pressed
NAMCO ORIGINAL
program by EVEZOO
will be written at the bottom of the screen
In Super Xevious this is changed to
special thanks for you
by game designer EVEZOO
- Dig Dug:
- enter service mode
- keep B1 pressed and enter the following sequence:
6xU 3xR 4xD 8xL
(c) 1982 NAMCO LTD. will appear on the screen.
Notes:
-----
- The Cabinet Type "dip switch" actually comes from the edge connector, but is mapped
in memory in place of dip switch #8. dip switch #8 selects single/dual coin counters
and is entirely handled by hardware.
- galaga: there is a bug in the sound CPU program. During initialization, it enables
NMI before clearing RAM, but the NMI handler doesn't save the registers, so it cannot
interrupt program execution. If the NMI happens before the LDIR that clears RAM has
finished, the program will crash.
- galaga: there were "fast shoot" hacks available, which are not supported.
Their effects can be replicated with this line in cheat.dat:
galaga:1:070D:0D:100:Fast Shoot
- bosco: there appears to be a bug in the code at 0BB1, which handles communication
with the 06XX custom chip. First it saves in A' the command to write, then if a
transfer is still in progress it jumps to 0BC1, does other things, then restores
the command from A' and stores it in RAM. At that point (0BE1) it checks again if
a transfer is in progress. If the transfer has terminated, it jumps to 0BEB, which
restores the command from RAM, and jumps back to 0BBA to send the command. However,
the instruction at 0BBA is ex af,af', so the command is overwritten with garbage.
There's also an exx at 0BBB which seems unnecessary but that's harmless.
Anyway, what this bug means is that we must make sure that the 06XX generates NMIs
quickly enough to ensure that 0BB1 is usually not called with a transfer still is
progress. It doesn't seem possible to prevent it altogether though, so we can only
hope that the transfer doesn't terminate in the middle of the function.
- bosco: we have two dumps of the sound shape ROM, "prom.1d" and "bosco.spr". Music
changes a lot from one version to the other.
I'm using the former because it is more similar to the other Namco games. The latter,
after masking off the unused top 4 bits and inverting bit 3, matches the Galaga one,
so it might have come from a (bootleg?) conversion.
- bosco & galaga: the Midway arcade cabinet had an optional rapid fire board, using
a 556 to generate autofire while the button was held. That really makes little
sense in Galaga! For Bosconian, I guess it was for the boscomdo set I, because the
other sets have autofire built-in.
- the bosconian video system is (apart from the starfield) almost identical functionally
to Rally X, but the hardware is quite different: Rally X has no custom ICs.
- digdug: if you enter service mode and press press service coin something like
the following is written at the bottom of the screen:
99.9999.9999.9999.9999.
This is explained in the manual: it is the number of games played, of points, etc.
The counters start from 999 and count backwards.
- gallag is identical to galagao, apart from the title changed to "GALLAG" and the
copyright notice changed from "(c) 1981 NAMCO LTD" to "1 9 8 2" (and the Namco logo
removed from the gfx). The only interesting thing about it is the 4th Z80, used to
simulate the custom 5xXX chips of the original.
It also has different explosion and starfield circuitries, to do without the Namco
custom chips.
- differences between versions of digdug:
- the background graphics are slightly different in the Atari versions; the earth is
less regular.
- "digduga1" is identical to "digdugb", apart from the gfx and copyright notices
changed from "NAMCO LTD." to "ATARI INC.".
- "digdug" fixes two bugs that were present in "digdugb": First, as monster speed
increased in later rounds it could eventually roll over to 0, causing the monsters
to stop moving altogether. Second, "double-killing" a monster by bursting it and
immediately dropping a rock on the corpse could result in the round not ending
even after all monsters were killed.
This set also has the code to save high scores to EEPROM rewritten, though the
reason for the changes is unclear.
- "digdugat" is almost identical to "digdug" (apart from the Atari gfx/copyright
changes), but there are three added instructions in the CPU0 program that change
the code alignment. The change eliminates the "kill screen" at round 256 by
making the round number roll over to 156, and hides the rollover from the player
by only ever displaying the lower two digits of the round number. Interestingly,
"digdug" actually contains all the code to implement the rollover (at $0018-$0026)
but just doesn't call it, implying that Namco deliberately chose to keep the kill
screen in this version.
- "digsid" is intermediate between "digdugb" and "digdug"; it has the changed EEPROM
handling, but not the gameplay bug fixes. It has some unique changes as well:
the initial high scores are 25000 instead of 10000, and the game begins on the
screen that is round 4 in the other sets, skipping the first three screens.
The latter change seems likely to have been done by Namco themselves and not by
Sidam, as it involves insertion of code right in the middle of the CPU0 program
and realignment of all the code after the insertion.
- "dzigzag" and "digdugb" are identical, apart from the hacked gfx and the copyright
notices changed from "NAMCO LTD." to "1 9 8 2". It's a bootleg of "digdugb", and
not of "digduga1", because the hidden "NAMCO" string at offset 0x1eea of CPU2 is
still present, while it is replaced by "ATARI" in digduga1.
The only interesting thing about the bootleg is the 4th Z80, used to simulate
the custom 5xXX chips of the original.
TODO:
----
- bosco: is the screen horizontal resolution maybe 285? PCB videos do show a slightly
larger right border though
- gallag/gatsbee: explosions are not emulated since the bootleg board doesn't have
the 54XX custom. Should probably use samples like Battles?
- Xevios: emulate the 4th Z80 (ROM dump is complete)
- xevious: I haven't found any Easter egg in service mode. The main loop is very
simple so there might just not be one, though this would be the only Namco game
of that era to not have a service mode Easter egg. On the other hand, the service
mode in this game is VERY spartan when compared to the other Namco games.
- dzigzag: emulate the 4th CPU (should be similar to battles)
***************************************************************************/
#include "emu.h"
#include "bosco.h"
#include "digdug.h"
#include "galaga.h"
#include "xevious.h"
#include "namco52.h"
#include "namco54.h"
#include "cpu/mb88xx/mb88xx.h"
#include "cpu/z80/z80.h"
#include "namco06.h"
#include "namco50.h"
#include "namco51.h"
#include "namco53.h"
#include "machine/rescap.h"
#include "machine/watchdog.h"
#include "sound/samples.h"
#include "speaker.h"
#define MASTER_CLOCK (XTAL(18'432'000))
#define STARFIELD_X_OFFSET_GALAGA 16
#define STARFIELD_X_LIMIT_GALAGA 256 + STARFIELD_X_OFFSET_GALAGA
#define STARFIELD_Y_OFFSET_BOSCO 16
#define STARFIELD_X_LIMIT_BOSCO 224
uint8_t galaga_state::bosco_dsw_r(offs_t offset)
{
int bit0,bit1;
bit0 = (ioport("DSWB")->read() >> offset) & 1;
bit1 = (ioport("DSWA")->read() >> offset) & 1;
return bit0 | (bit1 << 1);
}
void galaga_state::irq1_clear_w(int state)
{
m_main_irq_mask = state;
if (!m_main_irq_mask)
m_maincpu->set_input_line(0, CLEAR_LINE);
}
void galaga_state::irq2_clear_w(int state)
{
m_sub_irq_mask = state;
if (!m_sub_irq_mask)
m_subcpu->set_input_line(0, CLEAR_LINE);
}
void galaga_state::nmion_w(int state)
{
m_sub2_nmi_mask = !state;
}
void galaga_state::out(uint8_t data)
{
m_leds[1] = BIT(data, 0);
m_leds[0] = BIT(data, 1);
machine().bookkeeping().coin_counter_w(1,~data & 4);
machine().bookkeeping().coin_counter_w(0,~data & 8);
}
void galaga_state::lockout(int state)
{
machine().bookkeeping().coin_lockout_global_w(state);
}
uint8_t galaga_state::namco_52xx_rom_r(offs_t offset)
{
uint32_t length = memregion("52xx")->bytes();
//printf("ROM read %04X\n", offset);
if (!(offset & 0x1000))
offset = (offset & 0xfff) | 0x0000;
else if (!(offset & 0x2000))
offset = (offset & 0xfff) | 0x1000;
else if (!(offset & 0x4000))
offset = (offset & 0xfff) | 0x2000;
else if (!(offset & 0x8000))
offset = (offset & 0xfff) | 0x3000;
return (offset < length) ? memregion("52xx")->base()[offset] : 0xff;
}
uint8_t galaga_state::namco_52xx_si_r()
{
/* pulled to GND */
return 0;
}
TIMER_CALLBACK_MEMBER(galaga_state::cpu3_interrupt_callback)
{
int scanline = param;
if(m_sub2_nmi_mask)
m_subcpu2->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
scanline = scanline + 128;
if (scanline >= 272)
scanline = 64;
/* the vertical synch chain is clocked by H256 -- this is probably not important, but oh well */
m_cpu3_interrupt_timer->adjust(m_screen->time_until_pos(scanline), scanline);
}
uint8_t digdug_state::earom_read()
{
return m_earom->data();
}
void digdug_state::earom_write(offs_t offset, uint8_t data)
{
m_earom->set_address(offset & 0x3f);
m_earom->set_data(data);
}
void digdug_state::earom_control_w(uint8_t data)
{
// CK = DB0, C1 = /DB1, C2 = DB2, CS1 = DB3, /CS2 = GND
m_earom->set_control(BIT(data, 3), 1, !BIT(data, 1), BIT(data, 2));
m_earom->set_clk(BIT(data, 0));
}
void galaga_state::machine_start()
{
m_leds.resolve();
/* create the interrupt timer */
m_cpu3_interrupt_timer = timer_alloc(FUNC(galaga_state::cpu3_interrupt_callback), this);
save_item(NAME(m_main_irq_mask));
save_item(NAME(m_sub_irq_mask));
save_item(NAME(m_sub2_nmi_mask));
}
void digdug_state::machine_start()
{
galaga_state::machine_start();
earom_control_w(0);
}
void galaga_state::machine_reset()
{
m_cpu3_interrupt_timer->adjust(m_screen->time_until_pos(64), 64);
}
void battles_state::machine_reset()
{
galaga_state::machine_reset();
m_customio_command = 0;
m_customio_prev_command = 0;
m_customio_command_count = 0;
m_customio_data = 0;
m_sound_played = 0;
}
/* the same memory map is used by all three CPUs; all RAM areas are shared */
void bosco_state::bosco_map(address_map &map)
{
map(0x0000, 0x3fff).rom().nopw(); /* the only area different for each CPU */
map(0x6800, 0x6807).r(FUNC(bosco_state::bosco_dsw_r));
map(0x6800, 0x681f).w(m_namco_sound, FUNC(namco_device::pacman_sound_w));
map(0x6820, 0x6827).w("misclatch", FUNC(ls259_device::write_d0));
map(0x6830, 0x6830).w("watchdog", FUNC(watchdog_timer_device::reset_w));
map(0x7000, 0x70ff).rw("06xx_0", FUNC(namco_06xx_device::data_r), FUNC(namco_06xx_device::data_w));
map(0x7100, 0x7100).rw("06xx_0", FUNC(namco_06xx_device::ctrl_r), FUNC(namco_06xx_device::ctrl_w));
map(0x7800, 0x7fff).ram().share("share1");
map(0x8000, 0x8fff).ram().w(FUNC(bosco_state::bosco_videoram_w)).share("videoram");/* + sprite registers */
map(0x9000, 0x90ff).rw("06xx_1", FUNC(namco_06xx_device::data_r), FUNC(namco_06xx_device::data_w));
map(0x9100, 0x9100).rw("06xx_1", FUNC(namco_06xx_device::ctrl_r), FUNC(namco_06xx_device::ctrl_w));
map(0x9800, 0x980f).writeonly().share("bosco_radarattr");
map(0x9810, 0x9810).w(FUNC(bosco_state::bosco_scrollx_w));
map(0x9820, 0x9820).w(FUNC(bosco_state::bosco_scrolly_w));
map(0x9830, 0x9830).writeonly().share("starcontrol");
map(0x9840, 0x9840).w(FUNC(bosco_state::bosco_starclr_w));
map(0x9870, 0x9877).w(m_videolatch, FUNC(ls259_device::write_d0));
}
void galaga_state::galaga_map(address_map &map)
{
map(0x0000, 0x3fff).rom().nopw(); /* the only area different for each CPU */
map(0x6800, 0x6807).r(FUNC(galaga_state::bosco_dsw_r));
map(0x6800, 0x681f).w(m_namco_sound, FUNC(namco_device::pacman_sound_w));
map(0x6820, 0x6827).w("misclatch", FUNC(ls259_device::write_d0));
map(0x6830, 0x6830).w("watchdog", FUNC(watchdog_timer_device::reset_w));
map(0x7000, 0x70ff).rw("06xx", FUNC(namco_06xx_device::data_r), FUNC(namco_06xx_device::data_w));
map(0x7100, 0x7100).rw("06xx", FUNC(namco_06xx_device::ctrl_r), FUNC(namco_06xx_device::ctrl_w));
map(0x8000, 0x87ff).ram().w(FUNC(galaga_state::galaga_videoram_w)).share("videoram");
map(0x8800, 0x8bff).ram().share("galaga_ram1");
map(0x9000, 0x93ff).ram().share("galaga_ram2");
map(0x9800, 0x9bff).ram().share("galaga_ram3");
map(0xa000, 0xa007).w(m_videolatch, FUNC(ls259_device::write_d0));
}
void galaga_state::gatsbee_main_map(address_map &map)
{
galaga_map(map);
map(0x0000, 0x0007).mirror(0x3ff8).w("extralatch", FUNC(ls259_device::write_d0));
}
void xevious_state::xevious_map(address_map &map)
{
map(0x0000, 0x3fff).rom().nopw(); /* the only area different for each CPU */
map(0x6800, 0x6807).r(FUNC(xevious_state::bosco_dsw_r));
map(0x6800, 0x681f).w(m_namco_sound, FUNC(namco_device::pacman_sound_w));
map(0x6820, 0x6827).w("misclatch", FUNC(ls259_device::write_d0));
map(0x6830, 0x6830).w("watchdog", FUNC(watchdog_timer_device::reset_w));
map(0x7000, 0x70ff).rw("06xx", FUNC(namco_06xx_device::data_r), FUNC(namco_06xx_device::data_w));
map(0x7100, 0x7100).rw("06xx", FUNC(namco_06xx_device::ctrl_r), FUNC(namco_06xx_device::ctrl_w));
map(0x7800, 0x7fff).ram().share("share1"); /* work RAM */
map(0x8000, 0x87ff).ram().share("xevious_sr1"); /* work RAM + sprite registers */
map(0x9000, 0x97ff).ram().share("xevious_sr2"); /* work RAM + sprite registers */
map(0xa000, 0xa7ff).ram().share("xevious_sr3"); /* work RAM + sprite registers */
map(0xb000, 0xb7ff).ram().w(FUNC(xevious_state::xevious_fg_colorram_w)).share("fg_colorram");
map(0xb800, 0xbfff).ram().w(FUNC(xevious_state::xevious_bg_colorram_w)).share("bg_colorram");
map(0xc000, 0xc7ff).ram().w(FUNC(xevious_state::xevious_fg_videoram_w)).share("fg_videoram");
map(0xc800, 0xcfff).ram().w(FUNC(xevious_state::xevious_bg_videoram_w)).share("bg_videoram");
map(0xd000, 0xd07f).w(FUNC(xevious_state::xevious_vh_latch_w));
map(0xf000, 0xffff).rw(FUNC(xevious_state::xevious_bb_r), FUNC(xevious_state::xevious_bs_w));
}
void digdug_state::digdug_map(address_map &map)
{
map(0x0000, 0x3fff).rom().nopw(); /* the only area different for each CPU */
map(0x6800, 0x681f).w(m_namco_sound, FUNC(namco_device::pacman_sound_w));
map(0x6820, 0x6827).w("misclatch", FUNC(ls259_device::write_d0));
map(0x6830, 0x6830).w("watchdog", FUNC(watchdog_timer_device::reset_w));
map(0x7000, 0x70ff).rw("06xx", FUNC(namco_06xx_device::data_r), FUNC(namco_06xx_device::data_w));
map(0x7100, 0x7100).rw("06xx", FUNC(namco_06xx_device::ctrl_r), FUNC(namco_06xx_device::ctrl_w));
map(0x8000, 0x83ff).ram().w(FUNC(digdug_state::digdug_videoram_w)).share("videoram"); /* tilemap RAM (bottom half of RAM 0 */
map(0x8400, 0x87ff).ram().share("share1"); /* work RAM (top half for RAM 0 */
map(0x8800, 0x8bff).ram().share("digdug_objram"); /* work RAM + sprite registers */
map(0x9000, 0x93ff).ram().share("digdug_posram"); /* work RAM + sprite registers */
map(0x9800, 0x9bff).ram().share("digdug_flpram"); /* work RAM + sprite registers */
map(0xa000, 0xa007).nopr().w(m_videolatch, FUNC(ls259_device::write_d0)); /* video latches (spurious reads when setting latch bits) */
map(0xb800, 0xb83f).rw(FUNC(digdug_state::earom_read), FUNC(digdug_state::earom_write)); /* non volatile memory data */
map(0xb840, 0xb840).w(FUNC(digdug_state::earom_control_w)); /* non volatile memory control */
}
/* bootleg 4th CPU replacing the 5xXX chips */
void galaga_state::galaga_mem4(address_map &map)
{
map(0x0000, 0x0fff).rom();
map(0x1000, 0x107f).ram();
}
void battles_state::battles_mem4(address_map &map)
{
map(0x0000, 0x0fff).rom();
map(0x4000, 0x4003).r(FUNC(battles_state::input_port_r));
map(0x4001, 0x4001).w(FUNC(battles_state::cpu4_coin_w));
map(0x5000, 0x5000).w(FUNC(battles_state::noise_sound_w));
map(0x6000, 0x6000).rw(FUNC(battles_state::customio3_r), FUNC(battles_state::customio3_w));
map(0x7000, 0x7000).rw(FUNC(battles_state::customio_data3_r), FUNC(battles_state::customio_data3_w));
map(0x8000, 0x80ff).ram();
}
void galaga_state::dzigzag_mem4(address_map &map)
{
map(0x0000, 0x0fff).rom();
map(0x1000, 0x107f).ram();
map(0x4000, 0x4007).readonly(); // dip switches? bits 0 & 1 used
}
static INPUT_PORTS_START( bosco )
PORT_START("IN0")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_COCKTAIL
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_COCKTAIL
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_COCKTAIL
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_COCKTAIL
PORT_START("IN1")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START1 )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START2 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_COIN2 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 )
PORT_SERVICE( 0x80, IP_ACTIVE_LOW )
PORT_START("DSWA")
PORT_DIPNAME( 0x03, 0x03, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SWB:1,2")
PORT_DIPSETTING( 0x01, DEF_STR( Easy ) )
PORT_DIPSETTING( 0x03, DEF_STR( Medium ) )
PORT_DIPSETTING( 0x02, DEF_STR( Hardest ) )
PORT_DIPSETTING( 0x00, "Auto" )
PORT_DIPNAME( 0x04, 0x04, DEF_STR( Allow_Continue ) ) PORT_DIPLOCATION("SWB:3")
PORT_DIPSETTING( 0x00, DEF_STR( No ) )
PORT_DIPSETTING( 0x04, DEF_STR( Yes ) ) // factory default = "Yes"
PORT_DIPNAME( 0x08, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SWB:4")
PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )