/
nmk16.cpp
9218 lines (7665 loc) · 452 KB
/
nmk16.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:Mirko Buffoni,Nicola Salmoria,Bryan McPhail,David Haywood,R. Belmont,Alex Marshall,Angelo Salese,Luca Elia
// thanks-to:Richard Bush
/********************************************************************
Task Force Harrier 1989 UPL 68000 Z80 YM2203 2xOKIM6295
Many Block 1991 Bee-Oh 68000 Z80 YM2203 2xOKIM6295 (hack of "Jewels" by UPL)
Mustang 1990 UPL 68000 NMK004 YM2203 2xOKIM6295
Bio-ship Paladin 1990 UPL 68000 NMK004 YM2203 2xOKIM6295
Vandyke 1990 UPL 68000 NMK004 YM2203 2xOKIM6295
Black Heart 1991 UPL 68000 NMK004 YM2203 2xOKIM6295
Acrobat Mission 1991 UPL 68000 NMK004 YM2203 2xOKIM6295
Strahl 1992 UPL 68000 NMK004 YM2203 2xOKIM6295
Thunder Dragon 1991 NMK/Tecmo 68000 NMK004 YM2203 2xOKIM6295
Hacha Mecha Fighter proto 1991 NMK 68000 NMK004 YM2203 2xOKIM6295
Hacha Mecha Fighter 1991 NMK 68000 NMK004 YM2203 2xOKIM6295
Macross 1992 Banpresto 68000 NMK004 YM2203 2xOKIM6295
GunNail 1993 NMK/Tecmo 68000 NMK004 YM2203 2xOKIM6295
Macross II 1993 Banpresto 68000 Z80 YM2203 2xOKIM6295
Thunder Dragon 2 1993 NMK 68000 Z80 YM2203 2xOKIM6295
Arcadia / Rapid Hero 1994 NMK 68000 tmp90c841 YM2203 2xOKIM6295
S.S. Mission 1992 Comad 68000 Z80 OKIM6295 (hack of Thunder Dragon)
Air Attack 1996 Comad 68000 Z80 OKIM6295 (hack of Thunder Dragon)
Acrobat Mission (bootleg) 68000 Z80 YM3812 OKIM6295
Mustang (bootleg) 68000 Z80 YM3812 OKIM6295
Thunder Dragon (bootleg) 68000 Z80 YM3812 OKIM6295
Thunder Dragon 3 (bootleg) 1996 Conny 68000 Z80 (Unknown, Single OKIM6295 identified)
Saboten Bombers 1992 NMK/Tecmo 68000 2xOKIM6295
Bombjack Twin 1993 NMK 68000 2xOKIM6295
Nouryoku Koujou Iinkai 1995 Tecmo 68000 2xOKIM6295
driver by Mirko Buffoni, Richard Bush, Nicola Salmoria, Bryan McPhail,
David Haywood, R. Belmont, Alex Marshal and Luca Elia.
Afega based their hardware on the NMK hardware, not surprising considering Twin
Action is simply a hack of USSAF Mustang.
The NMK004 CPU is a Toshiba TMP90C840 with internal ROM.
The dumped internal ROM has a date string of 900315 in ROM and a version number of V-00
The later games (from GunNail onwards) have a higher resolution (384x224 instead
of 256x224) but the hardware is pretty much the same. It's obvious that the higher
res is an afterthought, because the tilemap layout is weird (the left 8 screen
columns have to be taken from the rightmost 8 columns of the tilemap), and the
games rely on mirror addresses to access the tilemap sequentially.
TODO:
- tharrier performs a handshake operation which is the same as that used by the
other games to initialize the NMK004 at boot, however it doesn't have an NMK004
(it uses a Z80 based sound system and also predates the NMK004)
maybe it has a pre-NMK004 chip using the same communication protocol but used
for protection instead.
- tharrier: Current emulation is stuck when try to access test mode.
- Protection is patched in several games.
- In Bioship, there's an occasional flicker of one of the sprites composing big
ships. Increasing CPU speed from 12 to 16 MHz improved it, but it's still not
100% fixed. (the CPU speed has been verified to be 10Mhz??)
- (PCB owners): Measure pixel clock / vblank duration for all of these games.
- for the Afega games (Guardian Storm especially) the lives display has bad colours,
it doesn't matter if this is drawn with the TX layer (some sets) or the sprites (others)
so it's probably something else funky with the memory access.
- Thunder Dragon 3 (bootleg of Thunder Dragon 2) :
Sound System isn't hooked up correctly for this set.
- Verify sprite limits for games when resolution is 384x224
NOT BUGS:
- Black Heart: test mode text are buggy
- Hacha Mecha Fighter: (BTANB) the bomb graphics are pretty weird when the game
is in japanese mode, but it's like this on the original game.
- Vandyke: Many enemies make very strange sounds because they seem to have no
rate limit for making their sound effect. This is normal, it's like this on all
PCB recordings.
- Sprite number is limited related to screen size and each sprite size.
reference : http://upl-gravedigger.boo.jp/pcb_info/pcb_manual_7.jpg
----
tharrier test mode:
1) Press player 2 buttons 1+2 during reset. "Are you ready?" will appear
2) Press player 1 buttons in this sequence:
2,1,2,2,1,1,↓,↓
Note: this doesn't currently work, the message never appears (most likely an error in the protection simulation).
tdragon and hachamf test mode:
1) Press player 2 buttons 1+2 during reset. "Ready?" will appear
2) Press player 1 button 2 14 (!) times
mustang and blkheart test mode:
1) Press player 2 buttons 1+2 during reset. "Ready?" will appear
2) Press player 1 button 1 14 (!) times
Note: blkheart has a buggy service mode, apparently they shifted the ASCII gfx bank at $3xx but
forgot to update the routines so it treats the VRAM as if ASCII bank is at $0xx (cfr. the move.w imm,Ax).
gunnail test mode:
1) Press player 2 buttons 1+2 during reset. "Ready?" will appear
2) Press player 2 button 1 3 times
bjtwin test mode:
1) Press player 2 buttons 1+2 during reset. "Ready?" will appear
2) Press player 1 buttons in this sequence:
2,2,2, 1,1,1, 2,2,2, 1,1,1
The release date of this program will appear.
Note: Some code has to be patched out for this to work (cfr. init_bjtwin fn).
The program remaps button 2 and 3 to button 1, so you can't enter the above sequence.
---
'gunnailp' observed differences (from notes by trap15)
- Different introduction scene
- Many unique enemy types that ended up unused
- Tweaked enemy attack patterns
- Tweaked boss behavior and attack patterns
- Dramatically different stages (and only 7 of them):
- Stage 1: Became Stage 5, very different layouts
- Stage 2: Became Stage 7, with mostly slight enemy layout changes
- Stage 3: Became Stage 6, almost the same as final
- Stage 4: Stayed as Stage 4, with very minor enemy layout changes
- Stage 5: Entirely unique stage, majorly reworked to become final Stage 2
- Stage 6: Became Stage 3, many enemy layout changes
- Stage 7: Entirely unique stage, majorly reworked to become final Stage 1
- No ending, instead loops forever
- Loop has extremely fast bullets
- The difficulty seems the same on all loops
- Player's blue shot has a wider maximum and minimum spread
- Player's main shot hitbox is symmetrical and wider than final
- When the hitbox was shrunk for the final, it was only shrunk in one direction, making it extended to the right
---
Questions / Notes
'manybloc' :
- This is a bootleg / hack of Jewels by UPL
- The MCU code was patched to use standard IO, it may be running code that is no longer used.
- There are writes to 0x080010.w and 0x080012.w (MCU ?) in code between
0x005000 to 0x005690, but I see no call to "main" routine at 0x005504 !
- There are writes to 0x08001c.w and 0x08001e.w but I can't tell what
the effect is ! Could it be related to sound and/or interrupts ?
- In the "test mode", press BOTH player 1 buttons to exit
- When help is available, press BUTTON2 twice within the timer to "solve"
---
Sound notes for games with a Z80:
acrobatmbl, mustangb, strahljb and tdragonb use the Seibu Raiden sound hardware and a modified
Z80 program (but the music is intact and recognizable). See audio/seibu.cpp
for more info on this.
---
Afega Games
95 Twin Action this is a hack of Mustang with new graphics
97 Red Hawk
98 Sen Jin - Guardian Storm
98 Stagger I Japanese release of Red Hawk
98 Bubble 2000 By Tuning, but it seems to be the same HW
/ Hot Bubble
00 Spectrum 2000 By YomaTech -- NOTE sprite bugs happen on real hw!!
01 Fire Hawk By ESD with different sound hardware: 2 M6295,
this doesn't have the glitches present in spec2k
Afega stands for "Art-Fiction Electronic Game"
Reference of music tempo:
tdragon3h - https://youtu.be/-cHM5EQnxA8
stagger1 - https://www.youtube.com/watch?v=xWszb2fP07M
********************************************************************/
#include "emu.h"
#include "nmk16.h"
#include "nmk004.h"
#include "cpu/m68000/m68000.h"
#include "cpu/pic16c5x/pic16c5x.h"
#include "cpu/tlcs90/tlcs90.h"
#include "cpu/z80/z80.h"
#include "machine/nmk112.h"
#include "sound/okim6295.h"
#include "sound/ymopm.h"
#include "sound/ymopn.h"
#include "sound/ymopl.h"
#include "multibyte.h"
#include "screen.h"
#include "speaker.h"
#define VERBOSE 0
#include "logmacro.h"
void nmk16_state::nmk004_x0016_w(u16 data)
{
// this is part of a watchdog scheme
// generating an NMI on the NMK004 keeps a timer alive
// if that timer expires the NMK004 resets the system
m_nmk004->nmi_w(BIT(data, 0) ? ASSERT_LINE : CLEAR_LINE);
}
void nmk16_state::nmk004_bioship_x0016_w(u16 data)
{
// ugly, ugly logic invert hack, but otherwise bioship doesn't hit the NMI enough to keep the game alive!
m_nmk004->nmi_w(BIT(data, 0) ? CLEAR_LINE : ASSERT_LINE);
}
/**********************************************************
Protection: Memory Scrambling
Several NMK and Afega games (notably the ones running at
the lower resolution) require strange handling of work
RAM when performing 8-bit writes. This handling breaks
some of the later games if used, but is essential for
Mustang, Black Heart, Task Force Harrier, and the Afega
shooters to work correctly without ROM patches. Tests
on the board would help verify this as correct.
I'm not sure if this is actually protection, or just
poor board design.
**********************************************************/
void nmk16_state::mainram_strange_w(offs_t offset, u16 data/*, u16 mem_mask*/)
{
#if 0
if (!ACCESSING_BITS_8_15)
{
m_mainram[offset] = (data & 0x00ff) | ((data & 0x00ff)<<8);
}
else if (!ACCESSING_BITS_0_7)
{
m_mainram[offset] = (data & 0xff00) | ((data & 0xff00) >> 8);
}
else
{
m_mainram[offset] = data;
}
#endif
// as of SVN 30715 the 68k core replicates the above behavior, providing mirrored bits in 'data' regardless of the value of 'mem_mask'
m_mainram[offset] = data;
}
// tdragon2, raphero has address-swapped mainram handler
u16 nmk16_state::mainram_swapped_r(offs_t offset)
{
return m_mainram[bitswap<16>(offset, 15, 14, 13, 12, 11, 7, 9, 8, 10, 6, 5, 4, 3, 2, 1, 0)];
}
void nmk16_state::mainram_swapped_w(offs_t offset, u16 data, u16 mem_mask)
{
COMBINE_DATA(&m_mainram[bitswap<16>(offset, 15, 14, 13, 12, 11, 7, 9, 8, 10, 6, 5, 4, 3, 2, 1, 0)]);
}
void nmk16_state::ssmissin_soundbank_w(u8 data)
{
m_okibank[0]->set_entry(data & 0x3);
}
void nmk16_state::tharrier_mcu_control_w(u16 data)
{
// LOG("%04x: mcu_control_w %02x\n",m_maincpu->pc(),data);
}
u16 nmk16_state::tharrier_mcu_r(offs_t offset, u16 mem_mask)
{
/* The MCU is mapped as the top byte for byte accesses only,
all word accesses are to the input port */
if (ACCESSING_BITS_8_15 && !ACCESSING_BITS_0_7)
{
static const u8 to_main[] =
{
0x82,0xc7,0x00,0x2c,0x6c,0x00,0x9f,0xc7,0x00,0x29,0x69,0x00,0x8b,0xc7,0x00
};
int res;
if (m_maincpu->pc()==0x8aa) res = (m_mainram[0x9064/2])|0x20; // Task Force Harrier
else if (m_maincpu->pc()==0x8ce) res = (m_mainram[0x9064/2])|0x60; // Task Force Harrier
else
{
res = to_main[m_prot_count++];
if (m_prot_count == sizeof(to_main))
m_prot_count = 0;
}
return res << 8;
}
else
{
// the above statement appears to be incorrect, it should also read DSW1 from here, almost certainly
// through the MCU. The weird 0x080202 address where we read IN2 is also probably just a mirror of 0x080002 (here)
return ~m_in_io[1]->read();
}
}
void nmk16_state::macross2_sound_reset_w(u16 data)
{
/* PCB behaviour verified by Corrado Tomaselli at MAME Italia Forum:
every time music changes Z80 is reset */
m_audiocpu->set_input_line(INPUT_LINE_RESET, data ? CLEAR_LINE : ASSERT_LINE);
}
void nmk16_state::macross2_sound_bank_w(u8 data)
{
m_audiobank->set_entry(data & 0x07);
}
template<unsigned Chip>
void nmk16_state::tharrier_oki_bankswitch_w(u8 data)
{
data &= 3;
if (data != 3)
m_okibank[Chip]->set_entry(data);
}
/***************************************************************************
VRAM handlers
***************************************************************************/
template<unsigned Layer>
void nmk16_state::bgvideoram_w(offs_t offset, u16 data, u16 mem_mask)
{
COMBINE_DATA(&m_bgvideoram[Layer][offset]);
if ((offset >> 13) == m_tilerambank)
m_bg_tilemap[Layer]->mark_tile_dirty(offset & 0x1fff);
}
void nmk16_state::txvideoram_w(offs_t offset, u16 data, u16 mem_mask)
{
COMBINE_DATA(&m_txvideoram[offset]);
m_tx_tilemap->mark_tile_dirty(offset);
}
template<unsigned Layer>
void nmk16_state::scroll_w(offs_t offset, u8 data)
{
m_scroll[Layer][offset] = data;
if (offset & 2)
{
m_bg_tilemap[Layer]->set_scrolly(0,((m_scroll[Layer][2] << 8) | m_scroll[Layer][3]));
}
else
{
if ((m_bgvideoram[Layer].bytes() > 0x4000) && (offset == 0))
{
int newbank = (m_scroll[Layer][0] >> 4) & ((m_bgvideoram[Layer].bytes() >> 14) - 1);
if (m_tilerambank != newbank)
{
m_tilerambank = newbank;
if (m_bg_tilemap[Layer])
m_bg_tilemap[Layer]->mark_all_dirty();
}
}
m_bg_tilemap[Layer]->set_scrollx(0,(m_scroll[Layer][0] << 8) | m_scroll[Layer][1]);
}
}
/***************************************************************************/
void nmk16_state::vandyke_map(address_map &map)
{
map(0x000000, 0x03ffff).rom();
map(0x080000, 0x080001).portr("IN0");
map(0x080002, 0x080003).portr("IN1");
map(0x080008, 0x080009).portr("DSW1");
map(0x08000a, 0x08000b).portr("DSW2");
map(0x08000f, 0x08000f).r(m_nmk004, FUNC(nmk004_device::read));
map(0x080016, 0x080017).w(FUNC(nmk16_state::nmk004_x0016_w));
map(0x080019, 0x080019).w(FUNC(nmk16_state::tilebank_w));
map(0x08001f, 0x08001f).w(m_nmk004, FUNC(nmk004_device::write));
map(0x088000, 0x0887ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x08c000, 0x08c007).w(FUNC(nmk16_state::vandyke_scroll_w));
map(0x090000, 0x093fff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x094000, 0x097fff).ram(); // what is this?
map(0x09d000, 0x09d7ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
map(0x0f0000, 0x0fffff).ram().w(FUNC(nmk16_state::mainram_strange_w)).share("mainram");
}
void nmk16_state::vandykeb_map(address_map &map)
{
map(0x000000, 0x03ffff).rom();
map(0x080000, 0x080001).portr("IN0");
map(0x080002, 0x080003).portr("IN1");
map(0x080008, 0x080009).portr("DSW1");
map(0x08000a, 0x08000b).portr("DSW2");
// map(0x08000f, 0x08000f).r(m_nmk004, FUNC(nmk004_device::read));
map(0x080010, 0x08001d).w(FUNC(nmk16_state::vandykeb_scroll_w)); // 10, 12, 1a, 1c
map(0x080016, 0x080017).nopw(); // IRQ enable?
map(0x080019, 0x080019).w(FUNC(nmk16_state::tilebank_w));
// map(0x08001f, 0x08001f).w(m_nmk004, FUNC(nmk004_device::write));
map(0x088000, 0x0887ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x08c000, 0x08c007).nopw(); // just in case...
map(0x090000, 0x093fff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x094000, 0x097fff).ram(); // what is this?
map(0x09d000, 0x09d7ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
map(0x0f0000, 0x0fffff).ram().w(FUNC(nmk16_state::mainram_strange_w)).share("mainram");
}
void nmk16_state::manybloc_map(address_map &map)
{
map(0x000000, 0x03ffff).rom();
map(0x080000, 0x080001).portr("IN0");
map(0x080002, 0x080003).portr("IN1");
map(0x080004, 0x080005).portr("DSW1");
map(0x080010, 0x080011).nopw(); // See notes at the top of the driver
map(0x080012, 0x080013).nopw(); // See notes at the top of the driver
map(0x080015, 0x080015).w(FUNC(nmk16_state::flipscreen_w));
map(0x08001c, 0x08001d).nopw(); // See notes at the top of the driver
map(0x08001f, 0x08001f).r("soundlatch2", FUNC(generic_latch_8_device::read)).w(m_soundlatch, FUNC(generic_latch_8_device::write)).umask16(0x00ff);
map(0x088000, 0x0883ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x090000, 0x093fff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x09c000, 0x09cfff).ram().w(FUNC(nmk16_state::manybloc_scroll_w)).share("scrollram");
map(0x09d000, 0x09d7ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
map(0x0f0000, 0x0fffff).ram().share("mainram");
}
void nmk16_tomagic_state::tomagic_map(address_map &map)
{
map(0x000000, 0x07ffff).rom().region("maincpu", 0);
map(0x080000, 0x080001).portr("IN0");
map(0x080002, 0x080003).portr("IN1");
map(0x080008, 0x080009).portr("DSW1");
map(0x08000a, 0x08000b).portr("DSW2");
map(0x080014, 0x080015).w(FUNC(nmk16_tomagic_state::flipscreen_w));
map(0x080018, 0x080019).w(FUNC(nmk16_tomagic_state::tilebank_w));
map(0x08001f, 0x08001f).w(m_soundlatch, FUNC(generic_latch_8_device::write));
map(0x088000, 0x0887ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x08c000, 0x08c1ff).writeonly().share("scrollram");
map(0x08c200, 0x08c3ff).writeonly().share("scrollramy");
map(0x090000, 0x093fff).ram().w(FUNC(nmk16_tomagic_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x094001, 0x094001).w(m_oki[0], FUNC(okim6295_device::write));
map(0x094003, 0x094003).r(m_oki[0], FUNC(okim6295_device::read));
map(0x09c000, 0x09cfff).mirror(0x001000).ram().w(FUNC(nmk16_tomagic_state::txvideoram_w)).share("txvideoram");
map(0x0f0000, 0x0fffff).ram().share("mainram");
}
void nmk16_tomagic_state::tomagic_sound_map(address_map &map)
{
map(0x0000, 0x7fff).rom().region("audiocpu", 0);
map(0x8000, 0xbfff).bankr("audiobank");
map(0xc000, 0xdfff).ram();
}
void nmk16_tomagic_state::tomagic_sound_io_map(address_map &map)
{
map.global_mask(0xff);
map(0x00, 0x00).w(FUNC(nmk16_tomagic_state::macross2_sound_bank_w));
map(0x02, 0x03).rw("ymsnd", FUNC(ym3812_device::read), FUNC(ym3812_device::write));
map(0x06, 0x06).r(m_soundlatch, FUNC(generic_latch_8_device::read));
}
void nmk16_state::tharrier_map(address_map &map)
{
map(0x000000, 0x03ffff).rom();
map(0x080000, 0x080001).portr("IN0");
map(0x080002, 0x080003).r(FUNC(nmk16_state::tharrier_mcu_r)); // .portr("IN1");
map(0x080004, 0x080005).portr("DSW1");
map(0x08000f, 0x08000f).r("soundlatch2", FUNC(generic_latch_8_device::read)); // from Z80
map(0x080010, 0x080011).w(FUNC(nmk16_state::tharrier_mcu_control_w));
map(0x080012, 0x080013).nopw();
// map(0x080015, 0x080015).w(FUNC(nmk16_state::flipscreen_w));
// map(0x080019, 0x080019).w(FUNC(nmk16_state::tilebank_w));
map(0x08001f, 0x08001f).w(m_soundlatch, FUNC(generic_latch_8_device::write));
map(0x080202, 0x080203).portr("IN2");
map(0x088000, 0x0883ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
// map(0x08c000, 0x08c007).w(FUNC(nmk16_state::scroll_w<0>)).umask16(0x00ff);
map(0x090000, 0x093fff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x09c000, 0x09c7ff).ram(); // Unused txvideoram area?
map(0x09d000, 0x09d7ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
map(0x0f0000, 0x0fffff).ram().w(FUNC(nmk16_state::mainram_strange_w)).share("mainram");
}
void nmk16_state::tharrier_sound_map(address_map &map)
{
map(0x0000, 0xbfff).rom();
map(0xc000, 0xc7ff).ram();
map(0xf000, 0xf000).r(m_soundlatch, FUNC(generic_latch_8_device::read)).w("soundlatch2", FUNC(generic_latch_8_device::write));
map(0xf400, 0xf400).rw(m_oki[0], FUNC(okim6295_device::read), FUNC(okim6295_device::write));
map(0xf500, 0xf500).rw(m_oki[1], FUNC(okim6295_device::read), FUNC(okim6295_device::write));
map(0xf600, 0xf600).w(FUNC(nmk16_state::tharrier_oki_bankswitch_w<0>));
map(0xf700, 0xf700).w(FUNC(nmk16_state::tharrier_oki_bankswitch_w<1>));
}
void nmk16_state::tharrier_sound_io_map(address_map &map)
{
map.global_mask(0xff);
map(0x00, 0x01).rw("ymsnd", FUNC(ym2203_device::read), FUNC(ym2203_device::write));
}
//Read input port 1 030c8/ BAD
//3478 GOOD
void nmk16_state::mustang_map(address_map &map)
{
map(0x000000, 0x03ffff).rom();
map(0x080000, 0x080001).portr("IN0");
map(0x080002, 0x080003).portr("IN1");
map(0x080004, 0x080005).portr("DSW1");
map(0x08000f, 0x08000f).r(m_nmk004, FUNC(nmk004_device::read));
map(0x08000e, 0x08000f).nopw();
map(0x080015, 0x080015).w(FUNC(nmk16_state::flipscreen_w));
map(0x080016, 0x080017).w(FUNC(nmk16_state::nmk004_x0016_w)); // frame number?
map(0x08001f, 0x08001f).w(m_nmk004, FUNC(nmk004_device::write));
map(0x088000, 0x0887ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x08c000, 0x08c001).w(FUNC(nmk16_state::mustang_scroll_w));
map(0x08c002, 0x08c087).nopw(); // ??
map(0x090000, 0x093fff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x09c000, 0x09c7ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
map(0x0f0000, 0x0fffff).ram().w(FUNC(nmk16_state::mainram_strange_w)).share("mainram");
}
void nmk16_state::mustangb_map(address_map &map)
{
map(0x000000, 0x03ffff).rom();
map(0x080000, 0x080001).portr("IN0");
map(0x080002, 0x080003).portr("IN1");
map(0x080004, 0x080005).portr("DSW1");
map(0x08000e, 0x08000f).noprw();
map(0x080015, 0x080015).w(FUNC(nmk16_state::flipscreen_w));
map(0x080016, 0x080017).nopw(); // frame number?
map(0x08001e, 0x08001f).w("seibu_sound", FUNC(seibu_sound_device::main_mustb_w));
map(0x088000, 0x0887ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x08c000, 0x08c001).w(FUNC(nmk16_state::mustang_scroll_w));
map(0x08c002, 0x08c087).nopw(); // ??
map(0x090000, 0x093fff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x09c000, 0x09c7ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
map(0x0f0000, 0x0fffff).ram().w(FUNC(nmk16_state::mainram_strange_w)).share("mainram");
}
void nmk16_state::mustangb3_map(address_map &map)
{
map(0x000000, 0x03ffff).rom();
map(0x080000, 0x080001).portr("IN0");
map(0x080002, 0x080003).portr("IN1");
map(0x080004, 0x080005).portr("DSW1");
map(0x080006, 0x080007).lr16(NAME([this]() { if (m_maincpu->pc() == 0x416) return 0x9000; if (m_maincpu->pc() == 0x64e) return 0x548d; return 0x0000; })); // TODO: gross hack. Protection? Or probably something more obvious
map(0x08000f, 0x08000f).r("soundlatch2", FUNC(generic_latch_8_device::read));
map(0x08000e, 0x08000f).nopw();
map(0x080015, 0x080015).w(FUNC(nmk16_state::flipscreen_w));
map(0x080016, 0x080017).noprw();
map(0x08001f, 0x08001f).w(m_soundlatch, FUNC(generic_latch_8_device::write));
map(0x088000, 0x0887ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x08c000, 0x08c001).w(FUNC(nmk16_state::mustang_scroll_w));
map(0x08c002, 0x08c087).nopw();
map(0x090000, 0x093fff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x09c000, 0x09c7ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
map(0x0f0000, 0x0fffff).ram().w(FUNC(nmk16_state::mainram_strange_w)).share("mainram");
}
void nmk16_state::mustangb3_sound_map(address_map &map)
{
tharrier_sound_map(map);
// remove some leftover banking calls, not needed since this bootleg uses smaller ROMs
map(0xf600, 0xf600).unmapw();
map(0xf700, 0xf700).unmapw();
}
void nmk16_state::twinactn_map(address_map &map)
{
map(0x000000, 0x03ffff).rom();
map(0x080000, 0x080001).portr("IN0");
map(0x080002, 0x080003).portr("IN1");
map(0x080004, 0x080005).portr("DSW1");
map(0x08000e, 0x08000f).noprw();
map(0x080015, 0x080015).w(FUNC(nmk16_state::flipscreen_w));
map(0x080016, 0x080017).nopw(); // frame number?
map(0x08001f, 0x08001f).w(m_soundlatch, FUNC(generic_latch_8_device::write));
map(0x088000, 0x0887ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x08c000, 0x08c001).w(FUNC(nmk16_state::mustang_scroll_w));
map(0x08c002, 0x08c087).nopw(); // ??
map(0x090000, 0x093fff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x09c000, 0x09c7ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
map(0x0f0000, 0x0fffff).ram().w(FUNC(nmk16_state::mainram_strange_w)).share("mainram");
}
void nmk16_state::acrobatm_map(address_map &map)
{
map(0x00000, 0x3ffff).rom();
map(0x80000, 0x8ffff).ram().share("mainram");
map(0xc0000, 0xc0001).portr("IN0");
map(0xc0002, 0xc0003).portr("IN1");
map(0xc0008, 0xc0009).portr("DSW1");
map(0xc000a, 0xc000b).portr("DSW2");
map(0xc000f, 0xc000f).r(m_nmk004, FUNC(nmk004_device::read));
map(0xc0015, 0xc0015).w(FUNC(nmk16_state::flipscreen_w));
map(0xc0016, 0xc0017).w(FUNC(nmk16_state::nmk004_x0016_w));
map(0xc0019, 0xc0019).w(FUNC(nmk16_state::tilebank_w));
map(0xc001f, 0xc001f).w(m_nmk004, FUNC(nmk004_device::write));
map(0xc4000, 0xc45ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0xc8000, 0xc8007).ram().w(FUNC(nmk16_state::scroll_w<0>)).umask16(0x00ff);
map(0xcc000, 0xcffff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0xd4000, 0xd47ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
}
void nmk16_state::acrobatmbl_map(address_map &map)
{
map(0x00000, 0x3ffff).rom();
map(0x80000, 0x8ffff).ram().share("mainram");
map(0xc0000, 0xc0001).portr("IN0");
map(0xc0002, 0xc0003).portr("IN1");
map(0xc0008, 0xc0009).portr("DSW1");
map(0xc000a, 0xc000b).portr("DSW2");
map(0xc0015, 0xc0015).w(FUNC(nmk16_state::flipscreen_w));
map(0xc0019, 0xc0019).w(FUNC(nmk16_state::tilebank_w));
map(0xc001e, 0xc001f).w("seibu_sound", FUNC(seibu_sound_device::main_mustb_w));
map(0xc4000, 0xc45ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0xc8000, 0xc8007).ram().w(FUNC(nmk16_state::scroll_w<0>)).umask16(0x00ff);
map(0xcc000, 0xcffff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0xd4000, 0xd47ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
}
void nmk16_state::bioship_map(address_map &map)
{
map(0x000000, 0x03ffff).rom();
map(0x080000, 0x080001).portr("IN0");
map(0x080002, 0x080003).portr("IN1");
map(0x080008, 0x080009).portr("DSW1");
map(0x08000a, 0x08000b).portr("DSW2");
map(0x08000f, 0x08000f).r(m_nmk004, FUNC(nmk004_device::read));
// map(0xc0015, 0xc0015).w(FUNC(nmk16_state::flipscreen_w));
map(0x080016, 0x080017).w(FUNC(nmk16_state::nmk004_bioship_x0016_w));
map(0x08001f, 0x08001f).w(m_nmk004, FUNC(nmk004_device::write));
map(0x084001, 0x084001).w(FUNC(nmk16_state::bioship_bank_w));
map(0x088000, 0x0887ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x08c000, 0x08c007).ram().w(FUNC(nmk16_state::scroll_w<1>)).umask16(0xff00);
map(0x08c010, 0x08c017).ram().w(FUNC(nmk16_state::scroll_w<0>)).umask16(0xff00);
map(0x090000, 0x093fff).ram().w(FUNC(nmk16_state::bgvideoram_w<1>)).share("bgvideoram1");
map(0x09c000, 0x09c7ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
map(0x0f0000, 0x0fffff).ram().w(FUNC(nmk16_state::mainram_strange_w)).share("mainram");
}
void nmk16_state::hachamf_map(address_map &map)
{
map(0x000000, 0x03ffff).rom();
// I/O Region
map(0x080000, 0x080001).portr("IN0");
map(0x080002, 0x080003).portr("IN1");
map(0x080008, 0x080009).portr("DSW1");
map(0x08000a, 0x08000b).portr("DSW2");
map(0x08000f, 0x08000f).r(m_nmk004, FUNC(nmk004_device::read));
map(0x080015, 0x080015).w(FUNC(nmk16_state::flipscreen_w));
map(0x080016, 0x080017).w(FUNC(nmk16_state::nmk004_x0016_w));
map(0x080019, 0x080019).w(FUNC(nmk16_state::tilebank_w));
map(0x08001f, 0x08001f).w(m_nmk004, FUNC(nmk004_device::write));
// Video Region
map(0x088000, 0x0887ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x08c000, 0x08c007).w(FUNC(nmk16_state::scroll_w<0>)).umask16(0x00ff);
map(0x090000, 0x093fff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x09c000, 0x09c7ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
// Main RAM, inc sprites, shared with MCU
map(0x0f0000, 0x0fffff).ram().share("mainram"); // ram is shared with MCU
}
void nmk16_state::tdragon_map(address_map &map)
{
map(0x000000, 0x03ffff).rom();
map(0x044022, 0x044023).nopr(); // No Idea (ROM mirror? - does this even exist on originals?)
map(0x080000, 0x08ffff).mirror(0x030000).ram().share("mainram");
map(0x0c0000, 0x0c0001).mirror(0x020000).portr("IN0");
map(0x0c0002, 0x0c0003).mirror(0x020000).portr("IN1");
map(0x0c0008, 0x0c0009).mirror(0x020000).portr("DSW1");
map(0x0c000a, 0x0c000b).mirror(0x020000).portr("DSW2");
map(0x0c000f, 0x0c000f).mirror(0x020000).r(m_nmk004, FUNC(nmk004_device::read));
map(0x0c0015, 0x0c0015).mirror(0x020000).w(FUNC(nmk16_state::flipscreen_w)); // Maybe
map(0x0c0016, 0x0c0017).mirror(0x020000).w(FUNC(nmk16_state::nmk004_x0016_w));
map(0x0c0019, 0x0c0019).mirror(0x020000).w(FUNC(nmk16_state::tilebank_w)); // Tile Bank?
map(0x0c001f, 0x0c001f).mirror(0x020000).w(m_nmk004, FUNC(nmk004_device::write));
map(0x0c4000, 0x0c4007).ram().w(FUNC(nmk16_state::scroll_w<0>)).umask16(0x00ff);
map(0x0c8000, 0x0c87ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x0cc000, 0x0cffff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x0d0000, 0x0d07ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
}
// No sprites without this. Is it actually protection?
u16 nmk16_state::tdragonb_prot_r()
{
return 0x0003;
}
void nmk16_state::tdragonb_map(address_map &map)
{
map(0x000000, 0x03ffff).rom();
map(0x044022, 0x044023).r(FUNC(nmk16_state::tdragonb_prot_r));
map(0x0b0000, 0x0bffff).ram().share("mainram");
map(0x0c0000, 0x0c0001).portr("IN0");
map(0x0c0002, 0x0c0003).portr("IN1");
map(0x0c0008, 0x0c0009).portr("DSW1");
map(0x0c000a, 0x0c000b).portr("DSW2");
map(0x0c0015, 0x0c0015).w(FUNC(nmk16_state::flipscreen_w)); // Maybe
map(0x0c0019, 0x0c0019).w(FUNC(nmk16_state::tilebank_w)); // Tile Bank?
map(0x0c001e, 0x0c001f).w("seibu_sound", FUNC(seibu_sound_device::main_mustb_w));
map(0x0c4000, 0x0c4007).ram().w(FUNC(nmk16_state::scroll_w<0>)).umask16(0x00ff);
map(0x0c8000, 0x0c87ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x0cc000, 0x0cffff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x0d0000, 0x0d07ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
}
void nmk16_state::tdragonb3_map(address_map &map)
{
tdragonb_map(map);
map(0x044022, 0x044023).unmapr();
map(0x060000, 0x060021).lr16(NAME([] () -> u16 { return 0xee; })); // No sprites in attract mode without this. Is it actually protection? See routine at PC 260
}
void nmk16_state::tdragonb2_map(address_map &map)
{
map(0x000000, 0x03ffff).rom();
map(0x0b0000, 0x0bffff).ram().share("mainram");
map(0x0c0000, 0x0c0001).portr("IN0");
map(0x0c0002, 0x0c0003).portr("IN1");
map(0x0c0008, 0x0c0009).portr("DSW1"); // .w TODO oki banking?
map(0x0c000a, 0x0c000b).portr("DSW2");
//map(0x0c000e, 0x0c000f).r; TODO: what's this?
map(0x0c0015, 0x0c0015).w(FUNC(nmk16_state::flipscreen_w)); // Maybe
map(0x0c0019, 0x0c0019).w(FUNC(nmk16_state::tilebank_w)); // Tile Bank
map(0x0c001f, 0x0c001f).w("oki", FUNC(okim6295_device::write));
map(0x0c4000, 0x0c4007).ram().w(FUNC(nmk16_state::scroll_w<0>)).umask16(0x00ff);
map(0x0c8000, 0x0c87ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x0cc000, 0x0cffff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x0d0000, 0x0d07ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
}
void nmk16_state::ssmissin_map(address_map &map)
{
map(0x000000, 0x03ffff).rom();
map(0x0b0000, 0x0bffff).ram().share("mainram");
map(0x0c0000, 0x0c0001).portr("IN0");
map(0x0c0004, 0x0c0005).portr("IN1");
map(0x0c0006, 0x0c0007).portr("DSW1");
// map(0x0c000e, 0x0c000f).r(FUNC(nmk16_state::??));
map(0x0c0015, 0x0c0015).w(FUNC(nmk16_state::flipscreen_w)); // Maybe
map(0x0c0019, 0x0c0019).w(FUNC(nmk16_state::tilebank_w)); // Tile Bank?
map(0x0c001f, 0x0c001f).w(m_soundlatch, FUNC(generic_latch_8_device::write));
map(0x0c4000, 0x0c4007).ram().w(FUNC(nmk16_state::scroll_w<0>)).umask16(0x00ff);
map(0x0c8000, 0x0c87ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x0cc000, 0x0cffff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x0d0000, 0x0d07ff).mirror(0x1800).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram"); //mirror for airattck
}
void nmk16_state::ssmissin_sound_map(address_map &map)
{
map(0x0000, 0x7fff).rom();
map(0x8000, 0x87ff).ram();
map(0x9000, 0x9000).w(FUNC(nmk16_state::ssmissin_soundbank_w));
map(0x9800, 0x9800).rw(m_oki[0], FUNC(okim6295_device::read), FUNC(okim6295_device::write));
map(0xa000, 0xa000).r(m_soundlatch, FUNC(generic_latch_8_device::read));
}
void nmk16_state::oki1_map(address_map &map)
{
map(0x00000, 0x1ffff).rom().region("oki1", 0);
map(0x20000, 0x3ffff).bankr("okibank1");
}
void nmk16_state::oki2_map(address_map &map)
{
map(0x00000, 0x1ffff).rom().region("oki2", 0);
map(0x20000, 0x3ffff).bankr("okibank2");
}
void nmk16_state::strahl_map(address_map &map)
{
map(0x00000, 0x3ffff).rom();
map(0x80000, 0x80001).portr("IN0");
map(0x80002, 0x80003).portr("IN1");
map(0x80008, 0x80009).portr("DSW1");
map(0x8000a, 0x8000b).portr("DSW2");
map(0x8000f, 0x8000f).r(m_nmk004, FUNC(nmk004_device::read));
map(0x80015, 0x80015).w(FUNC(nmk16_state::flipscreen_w));
map(0x80016, 0x80017).w(FUNC(nmk16_state::nmk004_x0016_w));
map(0x8001f, 0x8001f).w(m_nmk004, FUNC(nmk004_device::write));
map(0x84000, 0x84007).ram().w(FUNC(nmk16_state::scroll_w<0>)).umask16(0x00ff);
map(0x88000, 0x88007).ram().w(FUNC(nmk16_state::scroll_w<1>)).umask16(0x00ff);
map(0x8c000, 0x8c7ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x90000, 0x93fff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x94000, 0x97fff).ram().w(FUNC(nmk16_state::bgvideoram_w<1>)).share("bgvideoram1");
map(0x9c000, 0x9c7ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
map(0xf0000, 0xfffff).ram().share("mainram");
}
void nmk16_state::strahljbl_map(address_map &map)
{
map(0x00000, 0x3ffff).rom();
map(0x80000, 0x80001).portr("IN0");
map(0x80002, 0x80003).portr("IN1");
map(0x80008, 0x80009).portr("DSW1");
map(0x8000a, 0x8000b).portr("DSW2");
map(0x80015, 0x80015).w(FUNC(nmk16_state::flipscreen_w));
map(0x8001e, 0x8001f).w("seibu_sound", FUNC(seibu_sound_device::main_mustb_w));
map(0x84000, 0x84007).ram().w(FUNC(nmk16_state::scroll_w<0>)).umask16(0x00ff);
map(0x88000, 0x88007).ram().w(FUNC(nmk16_state::scroll_w<1>)).umask16(0x00ff);
map(0x8c000, 0x8c7ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x90000, 0x93fff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x94000, 0x97fff).ram().w(FUNC(nmk16_state::bgvideoram_w<1>)).share("bgvideoram1");
map(0x9c000, 0x9c7ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
map(0xf0000, 0xfffff).ram().share("mainram");
}
void nmk16_state::macross_map(address_map &map)
{
map(0x000000, 0x07ffff).rom();
map(0x080000, 0x080001).portr("IN0");
map(0x080002, 0x080003).portr("IN1");
map(0x080008, 0x080009).portr("DSW1");
map(0x08000a, 0x08000b).portr("DSW2");
map(0x08000f, 0x08000f).r(m_nmk004, FUNC(nmk004_device::read));
map(0x080015, 0x080015).w(FUNC(nmk16_state::flipscreen_w));
map(0x080016, 0x080017).w(FUNC(nmk16_state::nmk004_x0016_w));
map(0x080019, 0x080019).w(FUNC(nmk16_state::tilebank_w));
map(0x08001f, 0x08001f).w(m_nmk004, FUNC(nmk004_device::write));
map(0x088000, 0x0887ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x08c000, 0x08c007).ram().w(FUNC(nmk16_state::scroll_w<0>)).umask16(0x00ff);
map(0x090000, 0x093fff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x09c000, 0x09c7ff).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
map(0x0f0000, 0x0fffff).ram().w(FUNC(nmk16_state::mainram_strange_w)).share("mainram");
}
void nmk16_state::gunnail_map(address_map &map)
{
map(0x000000, 0x07ffff).rom();
map(0x080000, 0x080001).portr("IN0");
map(0x080002, 0x080003).portr("IN1");
map(0x080008, 0x080009).portr("DSW1");
map(0x08000a, 0x08000b).portr("DSW2");
map(0x08000f, 0x08000f).r(m_nmk004, FUNC(nmk004_device::read));
map(0x080015, 0x080015).w(FUNC(nmk16_state::flipscreen_w));
map(0x080016, 0x080017).w(FUNC(nmk16_state::nmk004_x0016_w));
map(0x080019, 0x080019).w(FUNC(nmk16_state::tilebank_w));
map(0x08001f, 0x08001f).w(m_nmk004, FUNC(nmk004_device::write));
map(0x088000, 0x0887ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x08c000, 0x08c1ff).writeonly().share("scrollram");
map(0x08c200, 0x08c3ff).writeonly().share("scrollramy");
map(0x08c400, 0x08c7ff).nopw(); // unknown
map(0x090000, 0x093fff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x09c000, 0x09cfff).mirror(0x001000).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
map(0x0f0000, 0x0fffff).ram().share("mainram");
}
void nmk16_state::gunnailb_map(address_map &map)
{
map(0x000000, 0x07ffff).rom();
map(0x080000, 0x080001).portr("IN0");
map(0x080002, 0x080003).portr("IN1");
map(0x080008, 0x080009).portr("DSW1");
map(0x08000a, 0x08000b).portr("DSW2");
map(0x08000f, 0x08000f).r("soundlatch2", FUNC(generic_latch_8_device::read));
map(0x080015, 0x080015).w(FUNC(nmk16_state::flipscreen_w));
//map(0x080016, 0x080017).noprw();
map(0x080019, 0x080019).w(FUNC(nmk16_state::tilebank_w));
map(0x08001f, 0x08001f).w(m_soundlatch, FUNC(generic_latch_8_device::write));
map(0x088000, 0x0887ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x08c000, 0x08c1ff).writeonly().share("scrollram");
map(0x08c200, 0x08c3ff).writeonly().share("scrollramy");
map(0x08c400, 0x08c7ff).nopw(); // unknown
map(0x090000, 0x093fff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x09c000, 0x09cfff).mirror(0x001000).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
map(0x0f0000, 0x0fffff).ram().share("mainram");
map(0x194001, 0x194001).w(m_oki[0], FUNC(okim6295_device::write));
}
void nmk16_state::gunnailb_sound_map(address_map &map)
{
map(0x0000, 0x7fff).rom();
map(0x8000, 0xbfff).bankr("audiobank");
map(0xc000, 0xdfff).ram();
}
void nmk16_state::gunnailb_sound_io_map(address_map &map)
{
map.global_mask(0xff);
map(0x00, 0x00).w(FUNC(nmk16_state::macross2_sound_bank_w));
map(0x02, 0x03).rw("ymsnd", FUNC(ym2203_device::read), FUNC(ym2203_device::write));
map(0x04, 0x04).noprw(); // since the bootleggers used the same audio CPU ROM as airbustr but a different Oki ROM, they connected the Oki to the main CPU
map(0x06, 0x06).r(m_soundlatch, FUNC(generic_latch_8_device::read)).w("soundlatch2", FUNC(generic_latch_8_device::write));
}
void nmk16_state::macross2_map(address_map &map)
{
map(0x000000, 0x07ffff).rom();
map(0x100000, 0x100001).portr("IN0");
map(0x100002, 0x100003).portr("IN1");
map(0x100008, 0x100009).portr("DSW1");
map(0x10000a, 0x10000b).portr("DSW2");
map(0x10000f, 0x10000f).r("soundlatch2", FUNC(generic_latch_8_device::read)); // from Z80
map(0x100015, 0x100015).w(FUNC(nmk16_state::flipscreen_w));
map(0x100016, 0x100017).w(FUNC(nmk16_state::macross2_sound_reset_w)); // Z80 reset
map(0x100019, 0x100019).w(FUNC(nmk16_state::tilebank_w));
map(0x10001f, 0x10001f).w(m_soundlatch, FUNC(generic_latch_8_device::write)); // to Z80
map(0x120000, 0x1207ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x130000, 0x130007).ram().w(FUNC(nmk16_state::scroll_w<0>)).umask16(0x00ff);
map(0x140000, 0x14ffff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x170000, 0x170fff).mirror(0x1000).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
map(0x1f0000, 0x1fffff).ram().share("mainram");
}
void nmk16_state::tdragon2_map(address_map &map)
{ // mainram address scrambled
macross2_map(map);
map(0x1f0000, 0x1fffff).rw(FUNC(nmk16_state::mainram_swapped_r), FUNC(nmk16_state::mainram_swapped_w)).share("mainram");
}
void nmk16_state::tdragon3h_map(address_map &map)
{ // bootleg has these 2 swapped
tdragon2_map(map);
map(0x10000e, 0x10000f).portr("DSW2");
map(0x10000b, 0x10000b).r("soundlatch2", FUNC(generic_latch_8_device::read)); // from Z80
}
void nmk16_state::raphero_map(address_map &map)
{
map(0x000000, 0x07ffff).rom();
map(0x100000, 0x100001).portr("IN0");
map(0x100002, 0x100003).portr("IN1");
map(0x100008, 0x100009).portr("DSW1");
map(0x10000a, 0x10000b).portr("DSW2");
map(0x10000f, 0x10000f).r("soundlatch2", FUNC(generic_latch_8_device::read)); // from Z80
map(0x100015, 0x100015).w(FUNC(nmk16_state::flipscreen_w));
map(0x100016, 0x100017).nopw(); // IRQ enable or z80 sound reset like in Macross 2?
map(0x100019, 0x100019).w(FUNC(nmk16_state::tilebank_w));
map(0x10001f, 0x10001f).w(m_soundlatch, FUNC(generic_latch_8_device::write)); // to Z80
map(0x120000, 0x1207ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
map(0x130000, 0x1301ff).ram().w(FUNC(nmk16_state::raphero_scroll_w)).share("scrollram");
map(0x130200, 0x1303ff).ram().share("scrollramy");
map(0x130400, 0x1307ff).ram();
map(0x140000, 0x14ffff).ram().w(FUNC(nmk16_state::bgvideoram_w<0>)).share("bgvideoram0");
map(0x170000, 0x170fff).mirror(0x1000).ram().w(FUNC(nmk16_state::txvideoram_w)).share("txvideoram");
map(0x1f0000, 0x1fffff).rw(FUNC(nmk16_state::mainram_swapped_r), FUNC(nmk16_state::mainram_swapped_w)).share("mainram");
}
void nmk16_state::raphero_sound_mem_map(address_map &map)
{
map(0x0000, 0x7fff).rom();
map(0x8000, 0xbfff).bankr("audiobank");
map(0xc000, 0xc001).rw("ymsnd", FUNC(ym2203_device::read), FUNC(ym2203_device::write));
map(0xc800, 0xc800).rw(m_oki[0], FUNC(okim6295_device::read), FUNC(okim6295_device::write));
map(0xc808, 0xc808).rw(m_oki[1], FUNC(okim6295_device::read), FUNC(okim6295_device::write));
map(0xc810, 0xc817).w("nmk112", FUNC(nmk112_device::okibank_w));
map(0xd000, 0xd000).w(FUNC(nmk16_state::macross2_sound_bank_w));
map(0xd800, 0xd800).r(m_soundlatch, FUNC(generic_latch_8_device::read)).w("soundlatch2", FUNC(generic_latch_8_device::write)); // main cpu
map(0xe000, 0xffff).ram();
}
void nmk16_state::macross2_sound_map(address_map &map)
{
map(0x0000, 0x7fff).rom();
map(0x8000, 0xbfff).bankr("audiobank"); // banked ROM
map(0xa000, 0xa000).nopr(); // IRQ ack? watchdog?
map(0xc000, 0xdfff).ram();
map(0xe001, 0xe001).w(FUNC(nmk16_state::macross2_sound_bank_w));
map(0xf000, 0xf000).r(m_soundlatch, FUNC(generic_latch_8_device::read)).w("soundlatch2", FUNC(generic_latch_8_device::write)); // from 68000
}