-
Notifications
You must be signed in to change notification settings - Fork 2k
/
galaxian.cpp
16876 lines (13975 loc) · 848 KB
/
galaxian.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:Aaron Giles, Couriersud, Stephane Humbert, Robbbert
/***************************************************************************
Galaxian-derived hardware
Galaxian is the root hardware for many, many systems developed in the
1980-1982 timeframe. The basic design, which originated with Namco(?),
was replicated, tweaked, bootlegged, and used numerous times.
The basic hardware design comprises three sections on a single PCB:
a CPU section, a sound section, and a video section.
The CPU section is based around a Z80 (though there are modified
designs that changed this to an S2650). The base galaxian hardware
is designed to allow access to up to 16k of program ROM and 2k of
working RAM.
The sound section consists of three parts. The first part is
a programmable 8-bit down counter that clocks a 4-bit counter which
generates a primitive waveform whose shape is hardcoded but can be
controlled by a pair of variable resistors. The second part is
a set of three 555 timers which can be individually enabled and
combined to produce square waves at fixed separated pitches. A
fourth 555 timer is configured via a 4-bit frequency parameter to
control the overall pitch of the other three. Finally, two single
bit-triggered noise circuits are available. A 17-bit noise LFSR
(which also generates stars for the video circuit) feeds into both
circuits. A "HIT" line enables a simple on/off control of one
filtered output, while a "FIRE" line triggers a fixed short duration
pulse (controlled by another 555 timer) of modulated noise.
See video/galaxian.cpp for a description of the video section.
****************************************************************************
Schematics are known to exist for these games:
* Galaxian
* Moon Alien Part 2
* King and Balloon
* Moon Cresta
* Moon Shuttle
* Frogger
* Amidar
* Turtles
* Scramble
* The End
* Super Cobra
* Dark Planet
* Lost Tomb
* Dambusters
****************************************************************************
Main clock: XTAL = 18.432 MHz
Z80 Clock: XTAL/6 = 3.072 MHz
Horizontal video frequency: HSYNC = XTAL/3/192/2 = 16 kHz
Video frequency: VSYNC = HSYNC/132/2 = 60.606060 Hz
VBlank duration: 1/VSYNC * (20/132) = 2500 us
Notes:
-----
- The only code difference between 'galaxian' and 'galmidw' is that the
'BONUS SHIP' text is printed on a different line.
Moon Cresta versions supported:
------------------------------
mooncrst Nichibutsu - later revision with better demo mode and
text for docking. Encrypted. No ROM/RAM check
mooncrsu Nichibutsu USA - later revision with better demo mode and
text for docking. Unencrypted. No ROM/RAM check
mooncrsa Nichibutsu - older revision with better demo mode and
text for docking. Encrypted. No ROM/RAM check
mooncrs2 Nichibutsu - probably first revision (no patches) and ROM/RAM check code.
This came from a bootleg board, with the logos erased
from the graphics
mooncrsg Gremlin - same docking text as mooncrst
mooncrsb bootleg of mooncrs2. ROM/RAM check erased.
Notes about 'azurian' :
-----------------------
bit 6 of IN1 is linked with bit 2 of IN2 (check code at 0x05b3) to set difficulty :
bit 6 bit 2 contents of
IN1 IN2 0x40f4 consequences difficulty
OFF OFF 2 aliens move 2 frames out of 3 easy
ON OFF 4 aliens move 4 frames out of 5 hard
OFF ON 3 aliens move 3 frames out of 4 normal
ON ON 5 aliens move 5 frames out of 6 very hard
aliens movements is handled by routine at 0x1d59 :
- alien 1 moves when 0x4044 != 0 else contents of 0x40f4 is stored at 0x4044
- alien 2 moves when 0x4054 != 0 else contents of 0x40f4 is stored at 0x4054
- alien 3 moves when 0x4064 != 0 else contents of 0x40f4 is stored at 0x4064
Notes about 'smooncrs' :
------------------------
Due to code at 0x2b1c and 0x3306, the game ALWAYS checks the inputs for player 1
(even for player 2 when "Cabinet" Dip Switch is set to "Cocktail")
Notes about 'scorpnmc' :
-----------------------
As the START buttons are also the buttons for player 1, how should I map them ?
I've coded this the same way as in 'checkman', but I'm not sure this is correct.
I can't tell if it's a bug, but if you reset the game when the screen is flipped,
the screens remains flipped (the "flip screen" routine doesn't seem to be called) !
Notes about 'frogg' :
---------------------
If bit 5 of IN0 or bit 5 of IN1 is HIGH, something strange occurs (check code
at 0x3580) : each time you press START2 a counter at 0x47da is incremented.
When this counter reaches 0x2f, each next time you press START2, it acts as if
you had pressed COIN2, so credits are added !
Bit 5 of IN0 is tested if "Cabinet" Dip Switch is set to "Upright" and
bit 5 of IN1 is tested if "Cabinet" Dip Switch is set to "Cocktail".
Notes about 'Space Battle' by Hoei :
------------------------------------
The main board is based on Galaxian with the following changes...
1. Adjustable 555 sound circuit has been removed.
2. Two additional noise circuits have been added similar to the 'hit' noise
but using different vertical counts.
3. Six paged graphic roms are supported on board.
4. Different memory map.
5. 2K of ram.
6. Sockets for upto 26K of rom.
7. Socket for connecting speech synthesis board.
Roms from two boards have been dumped. The graphics roms are the same.
The game roms differ as follows:
Set 1 Rom A contains a 16bit checksum at address 0x64/0x65.
Rom I contains a 16bit checksum at address 0x7fe/0x7ff
No other roms from this set contain a checksum.
Set 2 Rom A does not contain a valid checksum.
Roms B, C, E, F, G, H, and I contain a 16bit checksum at 0x7fe/0x7ff
Rom D contains a 16bit checksum at address 0x5e3/0x534
Rom D contains inline code for one subroutine rather than calling the
routine. It also has a check a for condition which can't happen
removed.
Rom G checks the TEST button input on power up and calls 0x5800 if it
is active. We do not have a dump of this (test ?) rom.
At no point are the checksums validated.
From a game point of view both rom sets function exactly the same.
Interestingly, the overlapped 4764 ROM is actually from sstrangr2 (aka Super
Space Stranger, marketed by Hoei), That's on completely different hardware.
It looks like it's used here for crude protection.
Galaxian Bootleg Single Board Layout:
-------------------------------------
|----------------------------------------------------------------------------------------------|
| |
A | AM27LS00 7486 7486 74163 74163 74LS393 LM324 NE555 ECG740A |
| |
B | AM27LS00 74LS00 74LS32 74LS161 74LS161 74LS74 NE555 NE555 |
| |
C | AM27LS00 7408 74LS02 74LS161 74LS161 74175 4066 NE555 NE555 |
| |
D | AM27LS00 74LS00 74LS20 74LS10 74LS74 74LS377 2114 74LS138 |
| |
E | AM27LS00 7408 74LS20 74LS283 74LS283 74LS02 2114 74LS138 DM8334 |
| |
F | 7486 74LS273 74LS?? 74LS367 74LS367 74LS273 74LS138 DM8334 |
| G |
G | F 74LS194 74LS157 74LS273 74LS367 6331-1J PRG1 74LS00 DM8334 |--|
| X |
H | 1 74LS194 74LS157 UPB8216 74161 74161 |
| |
I | G 74LS194 74LS157 UPB8216 74LS157 74LS273 |
| F |
J | X 74LS194 2114 2 2 7408 UPB8216 |
| 2 1 1 PRG2 |
K | 18.432MHZ 74LS157 2114 0 0 74LS74 UPB8216 74LS368 |
| 1 1 |
L | 74LS368 74LS157 74LS157 74LS157 74LS157 74LS04 74LS139 74LS368 |--|
| |
M | 74LS107 7474 74LS74 74LS139 74LS10 74LS02 74LS367 74LS367 74LS368 2 |
| | |
N | 7474 74LS20 74LS139 74LS74 74LS74 74LS367 74LS368 U |
| P |
O | 74LS164 74LS366 7486 7486 7486 7486 Z80 C |
| G |
P | 74LS164 74LS30 74LS161 74LS161 74LS161 74LS161 |
|----------------------------------------------------------------------------------------------|
1 2 3 4 5 6 7 8 9 1
0
****************************************************************************
Stephh's notes (based on the games Z80 code and some tests) for games based on 'scobra' MACHINE_DRIVER :
1) 'scobra' and clones
1a) 'scobra'
- Player 2 controls are used for player 2 regardless of the "Cabinet" Dip Switch.
- COIN1 and SERVICE1 share the same coinage while COIN2 always awards 3 credits per coin;
when "Coinage" is set to "99 Credits", credits are always set to 99 when pressing COIN1 (code at 0x037d).
- There is an unused coinage routine at 0x0159 with the following settings :
PORT_DIPNAME( 0x06, 0x00, DEF_STR( Coinage ) )
PORT_DIPSETTING( 0x00, "A 2/1 B 99" )
PORT_DIPSETTING( 0x06, "A 1/2 B 1/1" )
PORT_DIPSETTING( 0x04, "A 1/5 B 1/1" )
PORT_DIPSETTING( 0x02, "A 1/7 B 1/1" )
I can't tell at the moment if it's a leftover from another Konami game on similar hardware.
- You can have 3 or 4 lives at start, and you can only continue 4 times (code at 0x0ebf).
1b) 'scobrase'
- The only difference in main CPU with 'scobra' is not in code but in data :
* data at 0x1323+ and 0x1575+ displays " (c) SEGA 1981 " instead of "(c) KONAMI 1981".
* data from 0x3d0c to 0x3fff has an unknown effect (this area is filled with 0xff in 'scobra').
* data from 0x5b62 to 0x5b6f displays "SEGA" instead of "OSAKA" on the first building in the "BASE"
(last) level ("KONAMI" is always still displayed on other buildings).
As the code is the same, comments from 'scobra' also apply to this set.
- Audio CPU is different than the one in 'scobra'. More investigation is needed !
1c) 'scobras'
- Main CPU is different than the one in 'scobra', but audio CPU is the same as 'scobrase' !
- Player 2 controls are used for player 2 regardless of the "Cabinet" Dip Switch.
- COIN1 and SERVICE1 share the same coinage while COIN2 always awards 3 credits per coin;
when "Coinage" is set to "99 Credits", credits are always set to 99 when pressing COIN1 (code at 0x0bec).
- There is NO unused coinage routine.
- You can have 3 or 5 lives at start, and you can only continue 255 times (code at 0x00e3).
- On the first building in the "BASE" (last) level is written "STERN" instead of "OSAKA".
1d) 'scobrab'
- The only difference in main CPU with 'scobras' is not in code but in data :
* data from 0x0434 to 0x043e affects the addresses in ROM area of the strings to display.
* data from 0x0456 to 0x07a0 affects the strings which are displayed (almost all of them).
- Audio CPU is the same as the one in 'scobra' (with different ROM names though).
1e) 'suprheli'
- The only difference in main CPU with 'scobras' is not in code but in data :
* data at 0x0522+ displays "- SUPER HELI - " instead of "- SUPER COBRA -".
* data at 0x0547+ and 0x0799+ displays " " instead of "(c) STERN 1981 ".
* data from 0x5b26 to 0x5b32 displays "APPLE" instead of "STERN" on the first building in the "BASE"
(last) level.
* data from 0x5bbb to 0x5bc9 displays "ORANGE" instead of "KONAMI" on the other buildings in the "BASE"
(last) level.
As the code is the same, comments from 'scobras' also apply to this set.
- There is only ONE byte of difference with audio CPU in 'scobrase' :
Z:\MAME\data>fc /B epr1277.5e 9.9d
Comparaison des fichiers epr1277.5e et 9.9D
00001332: FD FF
Could it be a rotten bit ? As I have no evidence of this, I don't flag the ROM as BAD_DUMP.
2) 'moonwar' and clones
- "8255 Port C bit 4 was originally designed so when bit4=0, 1P spinner is selected, and when bit4=1,
2P spinner gets selected. But they forgot to change the 8255 initialization value and Port C was set
to input, setting the spinner select bit to HI regardless what was written to it. This bug has been
corrected in the newer set, but, to maintain hardware compatibility with older PCB's, they had to reverse
to active status of the select bit. So in the newer set, Bit4=1 selects the 1P spinner and Bit4=0 selects
the 2P spinner".
2a) 'moonwar'
- Press START1 when reseting the game to enter sort of inputs "test mode".
- "Hyperflip" button is ignored when "Cabinet" is set to "Cocktail" (code at 0x108d).
- When in "Free Play" mode, you only 3 lives at start.
2b) 'moonwara'
- Press START1 when reseting the game to enter sort of inputs "test mode".
- "Hyperflip" button is ignored when "Cabinet" is set to "Cocktail" (code at 0x107f).
- Besides the spinner bug, coinage is very weird in this set (no correlation between COIN1 and COIN2).
3) 'armorcar' and clones
3a) 'armorcar'
- Press P2 BUTTON2 when reseting the game to enter sort of inputs "test mode".
You'll notice that there is some leftover code from 'moonwar' as you can see 2 (muxed) PORT A
(and there are still writes to PORT C bit 4). This has no effect in the game though.
- After the 3 ports are read, when "Cabinet" is set to "Cocktail" and its player 2 turn, player 2 inputs
are "copied" into player 1 ones (code at 0x0fd2 : start reading inputs).
3b) 'armorcar2'
- When IN1 bit 2 is ON when reseting the game, you enter sort of inputs "test mode".
You'll notice that there is some leftover code from 'moonwar' as you can see 2 (muxed) PORT A
(and there are still writes to IN2 bit 4). This has no effect in the game though.
As this bit is marked as "unused" (see below why), you can never access to this "test mode".
- IN2 bit 3 has no real effect in this set : even if contents of 0x8627 is updated each time player changes,
screen flipping (0xa806 and 0xa807) is always set to "normal" (0x00 * 2) due to code at 0x0598, there is a
missing call to 0x0abf at 0x0a8c (there is even a 'ret' for call from 0x15aa), and there is no code to "copy"
player 2 inputs into player 1 ones (code at 0x0fb2 : start reading inputs).
There is still a leftover from 'armorcar' code, so this bit affects display (how ?) when IN2 bit 3 is ON
and it is player 2 turn (code at 0x0b66 is the same as the one at 0x0b87 in 'armorcar').
4) 'tazmania'
- Press P1 BUTTON2 when reseting the game to enter sort of inputs "test mode".
- After the 3 ports are read, when "Cabinet" is set to "Cocktail" and its player 2 turn, player 2 inputs
are "copied" into player 1 ones (code at 0x124e : start reading inputs).
- When "Cabinet" is set to "Upright", press any player 2 joystick direction to end current level
(code at 0x38dd). This trick does NOT work in bonus rooms though.
5) 'anteater'
- Press P1 BUTTON1 when reseting the game to enter sort of inputs "test mode".
- IN2 bit 3 has no effect in this set : even if contents of 0x86c4 is updated each time player changes,
screen flipping (0xa806 and 0xa807) is always reset to "normal" (0x00 * 2) after possible screen inversion
due to code at 0x05c7, and there is no code to "copy" player 2 inputs into player 1 ones (code at 0x0f7a :
start reading inputs).
6) 'calipso'
- Press P1 BUTTON1 when reseting the game to enter sort of inputs "test mode".
- Press P1 BUTTON1 to start a 1 player game or press P2 BUTTON1 to start a 2 players game ("Team-Play").
- IN2 bit 3 has no effect in this set : even if there is code to "copy" player 2 inputs into player 1 ones
(code at 0x1448 : start reading inputs), contents of 0x8669 is always set to 0x01 regardless of number players
and is NEVER updated (there is even no code for this). Furthermore, the screen flipping routine forces the
screen to be "normal" ([0xa806] = [0xa807] = 0x00) because of the 'jr' instruction at 0x2988.
It's possible that there is a cocktail version of the game, but I'm not really convinced about it.
7) 'losttomb' and clones
7a) 'losttomb'
- Press P1 right joystick UP when reseting the game to enter sort of inputs "test mode".
- There is no "Cabinet" Dip Switch for this game and no possible muxed input for a 2nd player.
Furthermore, the routine at 0x254b is NEVER called, so the screen NEVER flips !
- The routine that reads inputs (code at 0x0ef4) behaves differently if you are in "attract mode" or not :
* when playing ([0x865f] = 0x00), it reads the 3 inputs ports
* when in "attract mode" ([0x865f] = 0xff), it only reads IN0 (to get status of COINn and STARTn)
and IN1 (to get the status of the "Lives" Dip Switch), and IN2 is completely ignored
The side effect of such thing is that the status of the "Demo Sounds" Dip Switch will be taken into
consideration only after a game has been played (for example, the game will always be silenced in
"attract mode" after resetting the machine because 0x00 is stored at 0x8613 during initialisation).
- When in "Free Play" mode, you only 3 lives at start.
7b) 'losttombh'
- The only difference with 'losttomb' is not in code but in data :
Z:\MAME\data>fc /B 2h-easy lthard
Comparaison des fichiers 2h-easy et LTHARD
00000399: 0A 0B
0000039E: 0D 11
000003A3: 0F 14
000003A8: 13 19
000003AD: 15 1A
000003B2: 18 1B
000003B7: 1A 1C
000003BC: 1B 1D
000003C1: 1C 1E
000003C6: 1D 1F
000003CB: 1E 20
000003D0: 1F 21
000003D5: 20 22
000003D9: 03 05
000003E6: 0E 10
000003F0: 12 15
000003FD: 14 17
00000409: 0E 10
00000415: 0E 10
0000099B: AA 76 altered value to please the checksum routine
So the game is harder, but it has the same ingame bugs as 'losttomb'.
8) 'spdcoin'
- Press START1 or START2 when reseting the game to enter sort of inputs "test mode" (in fact, only IN0 is tested).
Press BOTH START1 and START2 to exit from it.
- Press START1 + START2 + P1 joystick LEFT when reseting the game to display some statistics (code at 0x0226).
Release BOTH START1 and START2 to exit this screen.
9) 'superbon'
- This game is heavily based on 'losttomb', so not surprisingly is the code similar.
- The main difference in terms of gameplay is that you only have 1 joystick to control your character
and that you shoot in the direction you are running unless you press the "HOLD" button.
- There are no tests at startup and it's not possible to enter sort of inputs "test mode" (even if code exists)
by pressing P1 joystick UP because of 'jump' instruction at 0x007d. If you try to check the ROMS, you'll
notice that they have the same name as in 'losttomb' and that they fail the checksum routines.
- There is no "Cabinet" Dip Switch for this game and no possible muxed input for a 2nd player.
Furthermore, the routine at 0x2a48 is NEVER called, so the screen NEVER flips !
- The routine that reads inputs (code at 0x0eb7) behaves differently if you are in "attract mode" or not :
* when playing ([0x8667] = 0x00), it reads the 3 inputs ports
* when in "attract mode" ([0x8667] = 0xff), it only reads IN0 (to get status of COINn and STARTn)
and IN1 (to get the status of the "Lives" Dip Switch), and IN2 is completely ignored
The side effect of such thing is that the status of the "Demo Sounds" Dip Switch will be taken into
consideration only after a game has been played (for example, the game will always be silenced in
"attract mode" after resetting the machine because 0x00 is stored at 0x8613 during initialisation).
- When in "Free Play" mode, you only 3 lives at start.
Stephh's additional notes (based on the games Z80 code and some tests) for "Moon Cresta" and its numerous clones :
a) 'mooncrst'
- made by Nichibutsu
- inputs :
* player 1 controls are used by player 1
* player 2 controls are used by player 2, even in an "upright" cabinet
- 2 coins slots with different settings :
* coin A : 1C_1C / 2C_1C / 3C_1C / 4C_1C
* coin B : 1C_1C / 1C_2C / 1C_3C / "Free Play"
- no writes to 0xa003, so no coin counters
- bonus life at 30000 or 50000 based on a Dip Switch
- possible partial Japanese text based on a Dip Switch
- hi-score : 11 chars (even if only 10 will be displayed), 60 seconds to enter
- players bullet speed : 4 pixels - lower limit : 0x04
- ingame bug : if you reset the game when screen is flipped, it isn't flipped back
- driver possible bug (which occurs for all "Moon Cresta" sets but 'mooncrgx') :
when the screen is flipped, sprites are too shifted (see for example player 2
score which misses ending '0') while bullets shall be good
as a consequence, square around letters is wrong when entering player name
for hi-score table when screen is flipped
b) 'mooncrsu'
- made by Nichibutsu
- very similar to 'mooncrst' with the only following differences :
* additional "USA" display after "Nichibutsu" (which is shifted left)
* writes to 0xb000 to 0xb0ff on reset ('mooncrst' only writes to 0xb000),
so there is no screen flipped ingame bug as in 'mooncrst'
c) 'mooncrsa'
- made by Nichibutsu
- additional "(c)" display before "Nichibutsu"
- "(c) 1980 NIHON BUSSAN CO. , LTD" display replaced with "May 1980" in yellow
- code at 0x1f00 has been removed ! I can't determine was is was supposed to do,
but it's based on number of enemies left (stored at 0x823c) and possible time
spent on the level (stored at 0x8226). Any hint is fully welcome !
- this version is easier than 'mooncrst' : look at high nibbles that are stored
at 0x809b and 0x809c via code at 0x0cb8 (0x01 and 0x02 instead of 0x11 and 0x12).
- 2 coins slots, but same settings : 1C_1C / 1C_2C / 1C_3C / "Free Play"
- same other infos as in 'mooncrst'
- same ingame bug as in 'mooncrst'
d) 'mooncrs2'
- bootleg (possibily based on a Gremlin version we don't have)
- heavily based on 'mooncrsa' with additional RAM/ROM check routine at 0x3ea1
- some "chars" have been erased from the GFX ROMS but some routines which
"prints" them are still there (but there are less than in 'mooncrsa')
- same other infos as in 'mooncrst'
- due to numerous writes in the RAM/ROM check routine, there is no screen flipped
ingame bug as in 'mooncrst'
e) 'mooncrsb'
- bootleg (possibily based on a Gremlin version we don't have)
- the only difference with 'mooncrs2' is that RAM/ROM check routine at 0x3ea1
has completely been "noped" and the jump at address 0x0004 has been changed
- all "chars" from the GFX ROMS haven't been erased, so you can see the top
of the "Gremlin" logo as copyright and hi-scores names
- same ingame bug as in 'mooncrst'
f) 'mooncrs3'
- bootleg
- very similar to 'mooncrs2' with the only following differences :
* checksum of ROM area 0x0000-0x3fff is computed, but the result is discarded
(see "xor a" operation at 0x3fc0 instead of "and a")
* coins stuff is different (see below)
- 2 coins slots with different settings (same as 'mooncrst') :
* coin A : 1C_1C / 2C_1C / 3C_1C / 4C_1C
* coin B : 1C_1C / 1C_2C / 1C_3C / "Free Play"
- there are writes to 0xa003 (check code at 0x1b8e and 0x1b9e) which occur
when you insert a coin, but I can't confirm it's related to coin counters
as the same value is written when you press COIN1 or COIN2
g) 'mooncrsg'
- made by Gremlin
- there are MANY changes and additions, and I wonder if there's such a Nichibutsu set;
anyway, closest set to this one seems to be 'mooncrst'
- Gremin "logo" on 2 lines instead of Nichibutsu copyright messages (2 lines)
- additional test for IN0 bit 7 (code at 0x0174) which always adds 1 credit
- there are writes to 0xa003 (check code at 0x0158 and 0x0160) which occur
when you insert a coin, but I can't confirm it's related to coin counters
as the same value is written when you press COIN1 or COIN2
- only English text (Dip Switch has no effect due to code at 0x2f77)
- hi-score : 3 chars, 10 seconds to enter
- same difficulty as in 'monncrst' (but stored at 0x809e and 0x809f)
- same other infos as in 'mooncrst'
- same ingame bug as in 'mooncrst'
h) 'fantazia'
- made by Subelectro
- closest set to this one seems to be 'mooncrsb'
- all intro texts have been changed as well as colors
- inputs :
* player 1 controls are used by player 1
* player 2 controls are used by player 2, only in a "cocktail" cabinet
look at additional routine at 0x29e0
- 2 coins slots with different settings (inverted coin A/B compared to 'mooncrst') :
* coin A : 1C_1C / 1C_2C / 1C_3C / "Free Play"
* coin B : 1C_1C / 2C_1C / 3C_1C / 4C_1C
- only English text (Dip Switch has no effect due to code at 0x2f53)
- hi-score : 3 chars, 60 seconds to enter
- same other infos as in 'mooncrst'
- same ingame bug as in 'mooncrst'
i) 'eagle'
- made by Centuri
- very similar to 'mooncrsb' with the only following differences :
* only 3 chars for hi-score instead of 11
* all other changes are modified "strings" to be displayed
(the intro texts but copyright remains though) as well as
new GFX (I can't test the sound for now to check)
- same ingame bug as in 'mooncrst'
j) 'eagle2'
- made by Centuri
- very similar to 'eagle' with the only following differences :
* only 20 seconds to enter hi-score instead of 60
* coins stuff is different (see below)
* one GFX ROM is slighlty different
- 2 coins slots, but same settings : 1C_1C / 2C_1C / 3C_1C / 4C_1C
- previous "Coin B" Dip Switch is now only tested to see if in "Freeplay" mode
- same ingame bug as in 'mooncrst'
k) 'eagle3'
- made by Centuri
- PRG ROMS are the same as for 'eagle' while two GFX ROMS are slighly different
(so the game is having 'mooncrst' ships and 'eagle' enemies)
- same ingame bug as in 'mooncrst'
l) 'spctbird'
- made by Fortrek
- very similar to 'mooncrsb' with the only following difference :
* coins stuff is different (same as in 'eagle2' - see below)
- 2 coins slots, but same settings : 1C_1C / 2C_1C / 3C_1C / 4C_1C
- previous "Coin B" Dip Switch is now only tested to see if in "Freeplay" mode
- same ingame bug as in 'mooncrst'
m) 'smooncrs'
- made par Gremlin (bootleg based on a Nichibutsu version we don't have ?)
- same RAM/ROM check routine as in 'mooncrs2' (so there is no screen flipped
ingame bug as in 'mooncrst'), but LOTS of new features !
- only top of the Gremlin logo is displayed and it is also used for hi-scores
- all intro texts have been changed
- "2'ST" instead of "2'ND" and "RECORD" instead of "HI-SCORE"
- additional "PLAYER 1/2" messages when player changes
- inputs : player 1 controls are used by players 1 and 2, even in a "cocktail"
cabinet (player 2 inputs are never read due to code at 0x2b1c and 0x3313)
- 2 coins slots with different settings :
* coin A : 1C_1C / 2C_1C / 3C_1C / 4C_1C
* coin B : 1C_1C / 1C_2C / 1C_3C / "Free Play"
additional wrong (Spanish) text displayed when "Coin B" set to 1C_1C
(check additional code at 0x0fae) :
* if "Coin A" set to 4C_1C, "1 MONEDA 1 PARTIDA" on one line
* if "Coin A" set to 2C_1C, "1 MONEDA 1 PARTIDA" on one line
and "2 MONEDAS 3 PARTIDAS" on another line below
when "Coin B" set to "Free Play", "CREDIT 04" instead of "FREE PLAY" string
(even if this number of credits is decremented when you press a START button,
it is put back to 04 when the game is over for all players)
- additional "POR" display after the number of credits
- bonus life always 50000 due to code at 0x2f68
- only English text due to code at 0x2f53
- hi-score : 3 chars, 60 seconds to enter
- players bullet speed : 9 or 12 pixels (using previous "Language" Dip Switch) -
lower limit : 0x0f (see additional routine at 0x0007 and call from 0x3407)
- game difficulty using previous "Bonus Life" Dip Switch (code at 0x2962)
however, even with "Easy" difficulty, the game is much harder as in 'mooncrs2'
as enemies as enemies move much faster and as they shoot on some levels
- docking stage is harder has there are gaps of 2 pixels instead of 1
- when you complete the 8 stages, "O.K." "FANTASTIC" messages on 2 lines
instead of "FAR OUT !" message on 1 line
- same ingame bug as in 'mooncrst'
- another ingame bug : when in "cocktail mode", "PLAYER 1/2" messages are
displayed BEFORE the screen is flipped (back)
- driver other bugs :
* when screen is flipped, player's bullets aren't displayed
* when screen is flipped, enemies' bullets aren't flipped
n) 'spcdrag'
- bootleg
- heavily based on 'smooncrs' (so there's a RAM/ROM check) but some differences though
- same intro texts as in 'mooncrs2'
- 2 coins slots with different settings :
* coin A : 1C_1C / 2C_1C / 3C_1C / 4C_1C
* coin B : 1C_2C / 1C_3C / 1C_4C / "Free Play"
additional wrong (Engrish) text displayed when "Coin B" set to 1C_2C
(check additional code at 0x0fae) :
* if "Coin A" set to 4C_1C, "1 COIN 1 PLAY " on one line
* if "Coin A" set to 2C_1C, "1 COIN 1 PLAY " on one line
and "2 COINS 3 PLAYES " (notice the spelling) on another line below
when "Coin B" set to "Free Play", "CREDIT 04" instead of "FREE PLAY" string
(even if this number of credits is decremented when you press a START button,
it is put back to 04 when the game is over for all players)
- "CAP 2" display instead of "POR" after the number of credits
- hi-score : 11 chars (even if only 10 will be displayed), 60 seconds to enter
(same as in 'mooncrs2')
- players bullet speed : 6 or 9 pixels (using previous "Language" Dip Switch) -
lower limit : 0x04 (instead of speed 9/12 and lower limit 0x0f)
- even if there's also the "Difficulty" Dip Switch, the game is a little bit easier
(enemies speed is slower and docking stage is back to 1 pixel to fit 'mooncrs2')
- when you complete the 8 stages, same "FAR OUT !" message as in 'mooncrs2'
- driver bug : even if player's bullets are displayed when screen is flipped as in
other sets, enemies' bullets are still not flipped as in 'smooncrs'
o) 'floritas'
- bootleg ? (there's a Nichibutsu logo which is displayed in the "title" screen
as well as in the hi-scores)
- very similar to 'spcdrag' with the only following (comestical) differences :
* unused routine at 0x37a8 has been "noped"
* no text after the number of credits
* all texts have been translated to Spanish
p) 'mooncrgx'
- bootleg on "Galaxian" hardware
- very similar to 'mooncrsb' with the only following differences :
* all unused routines have been "noped"
* settings are different (see below)
- 2 coins slots with different settings :
* coin A : 1C_1C / 2C_1C
* coin B : 1C_3C / 1C_5C
- there are writes to 0x6003 when you press COIN1 but not when you press COIN2
- there are also writes to (unmapped) 0x6804 when you press either COIN1 or COIN2 :
* when you press COIN1, 0x00 is written once
* when you press COIN2, 0x01 is written 5 times, then 0x00 is written once
- only English text (Dip Switch has no effect due to code at 0x2f4b)
- no ingame bug due to code at 0x2f77
- driver possible bug : while sprites are now correct when screen is flipped,
they are too shifted when screen is not flipped (again, see for example player 2
score which misses ending '0') while bullets shall be good
as a consequence, square around letters is wrong when entering player name
for hi-score table when screen not is flipped
q) 'bongo'
- IN0 bit 1 is supposed to be COIN2 (see coinage routine at 0x0288), but
there is a test on it at 0x0082 (in NMI routine) which jumps to 0xc003
(unmapped memory) if it pressed (HIGH).
- IN0 bit 7 is tested on startup (code at 0x0048) in combination with bits 0 and 1
(which are supposed to be COIN1 and COIN2). If all of them are pressed (HIGH),
the game displays a "CREDIT FAULT" message then jumps back to 0x0048.
- IN0 bit 4 and IN1 bit 4 should have been IPT_JOYSTICK_DOWN (Upright and Cocktail)
but their status is discarded with 3 'NOP' instructions at 0x06ca.
- IN0 bit 7 and IN0 bit 6 should have been IPT_BUTTON1 (Upright and Cocktail)
but their status is discarded with 3 'NOP' instructions at 0x06d1.
- IN2 is read via code at 0x2426, but its contents is directly overwritten
with value read from DSW (AY port A) via code at 0x3647.
r) 'ozon1'
- Player 2 controls are used for player 2 regardless of the "Cabinet" Dip Switch
(check code at 0x03c6 which changes player and routines that handle players inputs :
0x0dc3 and 0x1e31 LEFT and RIGHT - 0x0e76 BUTTON1).
- Credits are coded on 1 byte (range 0x00-0xff) and stored at 0x4002.
To display them, they are converted to BCD on 1 byte via routine at 0x1421.
As a result, it will always display 0 to 99 (eg: 0xf0 = 240 will display 40).
When you get 256 credits, 0x4002 = 0x00, so the game thinks you have no credit
at all and enters "attract mode" again (but the game does NOT reset).
- There's an ingame bug when you get 101 or 201 credits : due to code at 0x0239,
the game checks the BCD value (0x01) instead of the correct one at 0x4002,
so you can't start a 2 players game !
- There is another ingame bug when "Coinage" settings are "A 1C/2C B 1C/1C"
and you press COIN2 : due to code at 0x0473, contents of 0x4004 is NEVER reset
to 0x00, so routine at 0x042a ALWAYS thinks that you've pressed COIN2,
and as a consequence, it ALWAYS adds 1 credit (even when you are playing) !
s) 'porter'
- It's difficult to map correctly players buttons because of what they do :
on one side, both buttons do the same thing (code at 0x0940 for player 1 and
player 2 in "Upright" cabinet, or 0x1cc0 for player 2 in "Cocktail" cabinet),
but on the other side, due to code at 0x0910, player 1 BUTTON1 acts as a
START1 button while player 1 BUTTON2 acts as a START2 button. Any help is welcome !
t) 'bagmanmc'
- DSW bit 6 was previously used for "Bonus Lives" settings, but it has no effect
in this set because of 'NOP' instructions from 0x3501 to 0x3507.
****************************************************************************
TODO:
- Problems with Galaxian based on the observation of a real machine:
- Background humming is incorrect. It's faster on a real machine
- Explosion sound is much softer. Filter involved?
- streakng/ghostmun: $4800-4bff
- smooncrs : fix read/writes at/to unmapped memory (when player 2, "cocktail" mode) + fix the ?#! bug with "bullets" (when player 2, "cocktail" mode)
- timefgtr : missing player bullets, sprite ROM extend(see later levels), sound is too slow, some sprites missing
- zigzag : full DIP Switches and Inputs
- zigzag2 : full DIP Switches and Inputs
- jumpbug : full DIP Switches and Inputs - missing possible discrete sounds
- jumpbugb : full DIP Switches and Inputs - missing possible discrete sounds
- levers : full DIP Switches and Inputs
- kingball : full DIP Switches and Inputs
- kingbalj : full DIP Switches and Inputs
- frogg : fix read/writes at/to unmapped/wrong memory
- scprpng : fix read/writes at/to unmapped/wrong memory
- scorpion : check whether konami filters are used
- explorer : check whether konami filters are used
- superbon : needs correct color PROM
***************************************************************************/
#include "emu.h"
#include "galaxian.h"
#include "galaxian_a.h"
#include "cclimber_a.h"
#include "cpu/m6502/m6502.h"
#include "cpu/s2650/s2650.h"
#include "cpu/z80/z80.h"
#include "machine/nvram.h"
#include "machine/watchdog.h"
#include "screen.h"
#include "speaker.h"
#include "nl_konami.h"
/*************************************
*
* Interrupts
*
*************************************/
void galaxian_state::vblank_interrupt_w(int state)
{
// interrupt line is clocked at VBLANK
// a flip-flop at 6F is held in the preset state based on the NMI ON signal
if (state && m_irq_enabled)
m_maincpu->set_input_line(m_irq_line, ASSERT_LINE);
}
INPUT_CHANGED_MEMBER(tenspot_state::tenspot_fake)
{
if (newval)
{
m_current_game = (m_current_game + 1) % 10;
set_game_bank(m_current_game, true);
}
m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? ASSERT_LINE : CLEAR_LINE);
}
void galaxian_state::irq_enable_w(uint8_t data)
{
// the latched D0 bit here goes to the CLEAR line on the interrupt flip-flop
m_irq_enabled = data & 1;
// if CLEAR is held low, we must make sure the interrupt signal is clear
if (!m_irq_enabled)
m_maincpu->set_input_line(m_irq_line, CLEAR_LINE);
}
/*************************************
*
* DRIVER latch control
*
*************************************/
void galaxian_state::start_lamp_w(offs_t offset, uint8_t data)
{
// offset 0 = 1P START LAMP
// offset 1 = 2P START LAMP
m_lamps[offset] = BIT(data, 0);
}
void galaxian_state::coin_lock_w(uint8_t data)
{
// many variants and bootlegs don't have this
machine().bookkeeping().coin_lockout_global_w(~data & 1);
}
void galaxian_state::coin_count_0_w(uint8_t data)
{
machine().bookkeeping().coin_counter_w(0, data & 1);
}
void galaxian_state::coin_count_1_w(uint8_t data)
{
machine().bookkeeping().coin_counter_w(1, data & 1);
}
/*************************************
*
* General Konami sound I/O
*
*************************************/
uint8_t galaxian_state::konami_ay8910_r(offs_t offset)
{
// the decoding here is very simplistic, and you can address both simultaneously
uint8_t result = 0xff;
if (offset & 0x20) result &= m_ay8910[1]->data_r();
if (offset & 0x80) result &= m_ay8910[0]->data_r();
return result;
}
void galaxian_state::konami_ay8910_w(offs_t offset, uint8_t data)
{
// AV 4,5 ==> AY8910 #2
// the decoding here is very simplistic, and you can address two simultaneously
if (offset & 0x10)
m_ay8910[1]->address_w(data);
else if (offset & 0x20)
m_ay8910[1]->data_w(data);
// AV6,7 ==> AY8910 #1
if (offset & 0x40)
m_ay8910[0]->address_w(data);
else if (offset & 0x80)
m_ay8910[0]->data_w(data);
}
void galaxian_state::konami_sound_control_w(uint8_t data)
{
uint8_t old = m_konami_sound_control;
m_konami_sound_control = data;
/* the inverse of bit 3 clocks the flip flop to signal an INT.
It is automatically cleared on the acknowledge */
if ((old & 0x08) && !(data & 0x08))
m_audiocpu->set_input_line(0, HOLD_LINE);
// bit 4 is sound disable
machine().sound().system_mute(data & 0x10);
}
uint8_t galaxian_state::konami_sound_timer_r()
{
/*
The timer is clocked at KONAMI_SOUND_CLOCK and cascades through a
series of counters. It first encounters a chained pair of 4-bit
counters in an LS393, which produce an effective divide-by-256. Next
it enters the divide-by-2 counter in an LS93, followed by the
divide-by-8 counter. Finally, it clocks a divide-by-5 counter in an
LS90, followed by the divide-by-2 counter. This produces an effective
period of 16*16*2*8*5*2 = 40960 clocks.
The clock for the sound CPU comes from output C of the first
divide-by-16 counter, or KONAMI_SOUND_CLOCK/8. To recover the
current counter index, we use the sound cpu clock times 8 mod
16*16*2*8*5*2.
*/
uint32_t cycles = (m_audiocpu->total_cycles() * 8) % (uint64_t)(16*16*2*8*5*2);
uint8_t hibit = 0;
// separate the high bit from the others
if (cycles >= 16*16*2*8*5)
{
hibit = 1;
cycles -= 16*16*2*8*5;
}
// the top bits of the counter index map to various bits here
return (hibit << 7) | // B7 is the output of the final divide-by-2 counter
(BIT(cycles,14) << 6) | // B6 is the high bit of the divide-by-5 counter
(BIT(cycles,13) << 5) | // B5 is the 2nd highest bit of the divide-by-5 counter
(BIT(cycles,11) << 4) | // B4 is the high bit of the divide-by-8 counter
0x0e; // assume remaining bits are high, except B0 which is grounded
}
void galaxian_state::konami_sound_filter_w(offs_t offset, uint8_t data)
{
if (m_netlist != nullptr)
{
// the offset is used as data, 6 channels * 2 bits each
// AV0 .. AV5 ==> AY8910 #2 - 3C
// AV6 .. AV11 ==> AY8910 #1 - 3D
for (int which = 0; which < 2; which++)
{
if (m_ay8910[which] != nullptr)
{
for (int flt = 0; flt < 6; flt++)
{
const int fltnum = (flt + 6 * which);
const uint8_t bit = (offset >> (flt + 6 * (1 - which))) & 1;
// low bit goes to 0.22uF capacitor = 220000pF
// high bit goes to 0.047uF capacitor = 47000pF
m_filter_ctl[fltnum]->write(bit);
}
}
}
}
}
void galaxian_state::konami_portc_0_w(uint8_t data)
{
logerror("%s:ppi0_portc_w = %02X\n", machine().describe_context(), data);
}
void galaxian_state::konami_portc_1_w(uint8_t data)
{
logerror("%s:ppi1_portc_w = %02X\n", machine().describe_context(), data);
}
/*************************************
*
* The End I/O
*
*************************************/
uint8_t galaxian_state::theend_ppi8255_r(offs_t offset)
{
// the decoding here is very simplistic, and you can address both simultaneously
uint8_t result = 0xff;
if (offset & 0x0100) result &= m_ppi8255[0]->read(offset & 3);
if (offset & 0x0200) result &= m_ppi8255[1]->read(offset & 3);
return result;
}
void galaxian_state::theend_ppi8255_w(offs_t offset, uint8_t data)
{
// the decoding here is very simplistic, and you can address both simultaneously
if (offset & 0x0100) m_ppi8255[0]->write(offset & 3, data);
if (offset & 0x0200) m_ppi8255[1]->write(offset & 3, data);
}
void galaxian_state::theend_coin_counter_w(uint8_t data)
{
machine().bookkeeping().coin_counter_w(0, data & 0x80);
}
void galaxian_state::theend_protection_w(uint8_t data)
{
/*
Handled by a PAL16VR8(?) at 6J. Both inputs and outputs are a nibble.
Logic is not exactly known, but this implementation works well enough.
*/
m_protection_state = (m_protection_state << 4) | (data & 0x0f);
const uint8_t num1 = (m_protection_state >> 8) & 0x0f;
const uint8_t num2 = (m_protection_state >> 4) & 0x0f;
const uint8_t op = m_protection_state & 0x0f;
// TODO: theend writes several, other mystery sequences
switch (op)
{
case 0x6:
// scrambles
m_protection_result ^= 0x80;
break;
case 0x9:
// scramble
m_protection_result = std::min(num1 + 1, 0xf) << 4; // does not want overflow
break;
case 0xb:
// theend
m_protection_result = std::max(num2 - num1, 0) << 4; // assume no underflow
break;
case 0xa:
// theend