/
igs011.cpp
4943 lines (4094 loc) · 177 KB
/
igs011.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:Luca Elia, Olivier Galibert
/***************************************************************************
-= IGS011 (Blitter) Based Hardware =-
driver by Luca Elia (l.elia@tin.it)
code decrypted by Olivier Galibert
CPU : 68000
Sound : M6295 + Optional FM or ICS2115
Custom : IGS011 (blitter, protection)
IGS012 (protection, optional)
IGS003 (8255, protection)
NVRAM : Battery for main RAM
---------------------------------------------------------------------------
Year + Game PCB Sound Chips
---------------------------------------------------------------------------
95 Da Ban Cheng NO-T0084-1 M6295 IGS011 8255
95 Long Hu Bang V033C NO-T0093 M6295 IGS011 8255
95 Long Hu Bang V035C ?
95 Mj Ryukobou NO-T0094 M6295 IGS011 8255
95 Dragon World V010C NO-0105-4 M6295 YM3812 IGS011 IGS003
95 Dragon World V011H (set 1) ?
95 Dragon World V011H (set 2) NO-T0105 M6295 YM3812 IGS011 IGS003 IGS012
95 Dragon World V020J ? M6295 YM3812 IGS011 IGS003 IGS012
95 Dragon World V021J ?
95 Dragon World V021O NO-0105-1 M6295 YM3812 IGS011 IGS003 IGS012
95 Dragon World V030O NO-0105-1 M6295 YM3812 IGS011 IGS003
97 Dragon World V040O NO-0105-5 M6295 YM3812 IGS011 IGS003c
97 Dragon World V040K NO-0105-5 M6295 YM3812 IGS011 IGS003c IGS012
96 Virtua Bowling V100JCM NO-0101-? ICS2115 IGS011 IGS003e IGS012
96 Virtua Bowling V101XCM NO-0101-1 ICS2115 IGS011 IGS003e IGS012
96 Virtua Bowling V101HJS NO-0101-? ICS2115 IGS011 IGS003e?IGS012
96 Long Hu Bang II V185H NO-0115 M6295 YM2413 IGS011 8255
96 Wanli Changcheng ?
96 Xingyun Man Guan ?
98 Mj Nenrikishu SP V250J NO-0115-5 M6295 YM2413 IGS011 8255
---------------------------------------------------------------------------
To do:
- Implement the I/O part of IGS003 as an 8255
- IGS003 parametric bitswap protection in nkishusp (instead of patching the roms)
- Interrupt controller at 838000 or a38000 (there's a preliminary implementation for lhb)
- A few graphical bugs
- vbowl, vbowlj: trackball support.
Wrong colors in "Game Over" screen.
- lhb: in the copyright screen the '5' in '1995' is drawn by the cpu on layer 5,
but with wrong colors (since the top nibble of the affected pixels is left to 0xf)
(drgnwrld is like this too, maybe hacked, or a cheap year replacement by IGS)
- dbc: in the title screen the '5' in '1995' is drawn by the cpu with wrong colors.
(see above comment)
Also the background palette is wrong since the fade routine is called with wrong
parameters, but in this case the PCB does the same.
Notes:
- In most games, keep test button pressed during boot for another test mode
***************************************************************************/
#include "emu.h"
#include "cpu/m68000/m68000.h"
#include "sound/ics2115.h"
#include "sound/okim6295.h"
#include "sound/ymopl.h"
#include "machine/nvram.h"
#include "machine/timer.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#define LOG_BLITTER (1U << 1)
#define VERBOSE (0)
#include "logmacro.h"
namespace {
class igs011_state : public driver_device
{
public:
igs011_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_oki(*this, "oki")
, m_screen(*this, "screen")
, m_palette(*this, "palette")
, m_ics(*this, "ics")
, m_priority_ram(*this, "priority_ram")
, m_vbowl_trackball(*this, "vbowl_trackball")
, m_maincpu_region(*this, "maincpu")
, m_gfx(*this, "blitter")
, m_gfx2(*this, "blitter_hi")
, m_io_in(*this, "IN%u", 0U)
, m_io_key(*this, "KEY%u", 0U)
, m_io_an(*this, "AN%u", 0U)
, m_io_dsw(*this, "DSW%u", 1U)
, m_io_coin(*this, "COIN")
{
}
int igs_hopper_r();
void init_lhbv33c();
void init_drgnwrldv21j();
void init_wlcc();
void init_nkishusp();
void init_drgnwrldv21();
void init_dbc();
void init_lhb();
void init_drgnwrld();
void init_drgnwrldv30();
void init_drgnwrldv11h();
void init_lhb2();
void init_xymg();
void init_drgnwrldv10c();
void init_drgnwrldv20j();
void init_drgnwrldv40k();
void init_vbowl();
void init_vbowlj();
void init_vbowlhk();
void init_ryukobou();
void igs011_base(machine_config &config);
void drgnwrld(machine_config &config);
void nkishusp(machine_config &config);
void wlcc(machine_config &config);
void vbowl(machine_config &config);
void vbowlhk(machine_config &config);
void xymg(machine_config &config);
void lhb2(machine_config &config);
void lhb(machine_config &config);
void drgnwrld_igs012(machine_config &config);
protected:
virtual void machine_start() override;
virtual void video_start() override;
private:
/* devices */
required_device<cpu_device> m_maincpu;
optional_device<okim6295_device> m_oki;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
optional_device<ics2115_device> m_ics;
/* memory pointers */
required_shared_ptr<u16> m_priority_ram;
optional_shared_ptr<u16> m_vbowl_trackball;
/* memory regions */
required_memory_region m_maincpu_region;
required_region_ptr<u8> m_gfx;
optional_region_ptr<u8> m_gfx2;
optional_ioport_array<3> m_io_in;
optional_ioport_array<5> m_io_key;
optional_ioport_array<2> m_io_an;
optional_ioport_array<5> m_io_dsw;
optional_ioport m_io_coin;
std::unique_ptr<u8[]> m_layer[8];
u16 m_priority;
u8 m_lhb2_pen_hi;
u16 m_igs_dips_sel;
u16 m_igs_input_sel;
u16 m_igs_hopper;
u8 m_prot1;
u8 m_prot1_swap;
u32 m_prot1_addr;
u8 m_prot2;
u8 m_igs012_prot;
u8 m_igs012_prot_swap;
u8 m_igs012_prot_mode;
u16 m_igs003_reg;
u16 m_lhb_irq_enable;
struct blitter_t
{
u16 x, y, w, h,
gfx_lo, gfx_hi,
depth,
pen,
flags;
};
blitter_t m_blitter;
u16 m_igs003_prot_hold;
u8 m_igs003_prot_x;
u8 m_igs003_prot_y;
u8 m_igs003_prot_z;
u8 m_igs003_prot_h1;
u8 m_igs003_prot_h2;
void igs011_priority_w(offs_t offset, u16 data, u16 mem_mask = ~0);
u16 igs011_layers_r(offs_t offset);
void igs011_layers_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void igs011_blit_x_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void igs011_blit_y_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void igs011_blit_gfx_lo_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void igs011_blit_gfx_hi_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void igs011_blit_w_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void igs011_blit_h_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void igs011_blit_depth_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void igs011_blit_pen_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void igs011_blit_flags_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void igs_dips_w(offs_t offset, u16 data, u16 mem_mask = ~0);
template<unsigned Num> u16 igs_dips_r();
void igs011_prot1_w(offs_t offset, u8 data);
u16 igs011_prot1_r();
void igs011_prot_addr_w(u16 data);
void igs011_prot2_reset_w(u8 data);
u16 igs011_prot2_reset_r();
void igs011_prot2_inc_w(u8 data);
void igs011_prot2_dec_w(u8 data);
void drgnwrld_igs011_prot2_swap_w(u8 data);
void lhb_igs011_prot2_swap_w(u8 data);
void wlcc_igs011_prot2_swap_w(u8 data);
void vbowl_igs011_prot2_swap_w(u8 data);
u16 drgnwrldv40k_igs011_prot2_r();
u16 drgnwrldv21_igs011_prot2_r();
u16 drgnwrldv20j_igs011_prot2_r();
u16 lhb_igs011_prot2_r();
u16 dbc_igs011_prot2_r();
u16 ryukobou_igs011_prot2_r();
u16 lhb2_igs011_prot2_r();
u16 vbowl_igs011_prot2_r();
u16 vbowlhk_igs011_prot2_r();
void igs012_prot_reset_w(u16 data);
void igs012_prot_mode_w(offs_t offset, u8 data);
void igs012_prot_inc_w(offs_t offset, u8 data);
void igs012_prot_dec_inc_w(offs_t offset, u8 data);
void igs012_prot_dec_copy_w(offs_t offset, u8 data);
void igs012_prot_copy_w(offs_t offset, u8 data);
void igs012_prot_swap_w(offs_t offset, u8 data);
u16 igs012_prot_r();
void igs003_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void drgnwrld_igs003_w(offs_t offset, u16 data, u16 mem_mask = ~0);
u16 drgnwrld_igs003_r();
void lhb_inputs_w(offs_t offset, u16 data, u16 mem_mask = ~0);
u16 lhb_inputs_r(offs_t offset);
void lhb2_igs003_w(offs_t offset, u16 data, u16 mem_mask = ~0);
u16 lhb2_igs003_r();
void wlcc_igs003_w(offs_t offset, u16 data, u16 mem_mask = ~0);
u16 wlcc_igs003_r();
void xymg_igs003_w(offs_t offset, u16 data, u16 mem_mask = ~0);
u16 xymg_igs003_r();
void vbowl_igs003_w(offs_t offset, u16 data, u16 mem_mask = ~0);
u16 vbowl_igs003_r();
void vbowlhk_igs003_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void lhb_irq_enable_w(offs_t offset, u16 data, u16 mem_mask = ~0);
u16 vbowl_unk_r();
void vbowl_pen_hi_w(u8 data);
void vbowl_link_0_w(u16 data);
void vbowl_link_1_w(u16 data);
void vbowl_link_2_w(u16 data);
void vbowl_link_3_w(u16 data);
void lhb_okibank_w(u8 data);
void sound_irq(int state);
TIMER_DEVICE_CALLBACK_MEMBER(lev5_timer_irq_cb);
TIMER_DEVICE_CALLBACK_MEMBER(lhb_timer_irq_cb);
TIMER_DEVICE_CALLBACK_MEMBER(lev3_timer_irq_cb);
u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void screen_vblank_vbowl(int state);
INTERRUPT_GEN_MEMBER(lhb_vblank_irq);
void wlcc_decrypt();
void lhb_decrypt();
void drgnwrld_type3_decrypt();
void drgnwrld_type2_decrypt();
void drgnwrld_type1_decrypt();
void drgnwrldv40k_decrypt();
void lhb2_decrypt();
void nkishusp_decrypt();
void vbowl_decrypt();
void vbowlhk_decrypt();
void dbc_decrypt();
void ryukobou_decrypt();
void lhb2_gfx_decrypt();
void vbowl_gfx_decrypt();
void drgnwrld_gfx_decrypt();
void prot_mem_range_set();
void drgnwrld_mem(address_map &map);
void drgnwrld_igs012_mem(address_map &map);
void lhb_mem(address_map &map);
void lhb2_mem(address_map &map);
void nkishusp_mem(address_map &map);
void vbowl_mem(address_map &map);
void vbowlhk_mem(address_map &map);
void wlcc_mem(address_map &map);
void xymg_mem(address_map &map);
};
/***************************************************************************
Video
There are 8 non scrolling layers as big as the screen (512 x 256).
Each layer has 256 colors and its own palette.
There are 8 priority codes with RAM associated to each (8 x 256 values).
For each screen position, to determine which pixel to display, the video
chip associates a bit to the opacity of that pixel for each layer
(1 = transparent) to form an address into the selected priority RAM.
The value at that address (0-7) is the topmost layer.
***************************************************************************/
void igs011_state::igs011_priority_w(offs_t offset, u16 data, u16 mem_mask)
{
COMBINE_DATA(&m_priority);
// logerror("%06x: priority = %02x\n", m_maincpu->pc(), m_priority);
if (data & ~0x7)
logerror("%06x: warning, unknown bits written to priority = %02x\n", m_maincpu->pc(), m_priority);
}
void igs011_state::video_start()
{
for (int i = 0; i < 8; i++)
{
m_layer[i] = std::make_unique<u8[]>(512 * 256);
save_pointer(NAME(m_layer[i]), 512 * 256, i);
}
m_lhb2_pen_hi = 0;
save_item(NAME(m_priority));
save_item(NAME(m_lhb2_pen_hi));
save_item(NAME(m_blitter.x));
save_item(NAME(m_blitter.y));
save_item(NAME(m_blitter.w));
save_item(NAME(m_blitter.h));
save_item(NAME(m_blitter.gfx_lo));
save_item(NAME(m_blitter.gfx_hi));
save_item(NAME(m_blitter.depth));
save_item(NAME(m_blitter.pen));
save_item(NAME(m_blitter.flags));
}
u32 igs011_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
#ifdef MAME_DEBUG
int layer_enable = -1;
#endif
#ifdef MAME_DEBUG
if (machine().input().code_pressed(KEYCODE_Z))
{
int mask = 0;
if (machine().input().code_pressed(KEYCODE_Q)) mask |= 0x01;
if (machine().input().code_pressed(KEYCODE_W)) mask |= 0x02;
if (machine().input().code_pressed(KEYCODE_E)) mask |= 0x04;
if (machine().input().code_pressed(KEYCODE_R)) mask |= 0x08;
if (machine().input().code_pressed(KEYCODE_A)) mask |= 0x10;
if (machine().input().code_pressed(KEYCODE_S)) mask |= 0x20;
if (machine().input().code_pressed(KEYCODE_D)) mask |= 0x40;
if (machine().input().code_pressed(KEYCODE_F)) mask |= 0x80;
if (mask) layer_enable &= mask;
}
#endif
u16 *pri_ram = &m_priority_ram[(m_priority & 7) * 512/2];
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
{
for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
{
int scr_addr = x + y * 512;
int pri_addr = 0xff;
int l;
for (l = 0; l < 8; l++)
{
if ( (m_layer[l][scr_addr] != 0xff)
#ifdef MAME_DEBUG
&& (layer_enable & (1 << l))
#endif
)
pri_addr &= ~(1 << l);
}
l = pri_ram[pri_addr] & 7;
#ifdef MAME_DEBUG
if ((layer_enable != -1) && (pri_addr == 0xff))
bitmap.pix(y, x) = m_palette->black_pen();
else
#endif
bitmap.pix(y, x) = m_layer[l][scr_addr] | (l << 8);
}
}
return 0;
}
/***************************************************************************
In addition to the blitter, the CPU can also read from and write to
the framebuffers for the 8 layers, seen as 0x100000 bytes in memory.
The first half contains layers 0-3. Layers 4-7 are in the other half.
The layers are interleaved:
- bytes 0x00000-0x00003 contain the 1st pixel of layer 0,1,2,3
- bytes 0x00004-0x00007 contain the 2nd pixel of layer 0,1,2,3
...
- bytes 0x80000-0x80003 contain the 1st pixel of layer 4,5,6,7
- bytes 0x80004-0x80007 contain the 2nd pixel of layer 4,5,6,7
and so on.
***************************************************************************/
u16 igs011_state::igs011_layers_r(offs_t offset)
{
int layer0 = ((offset & (0x80000/2)) ? 4 : 0) + ((offset & 1) ? 0 : 2);
u8 *l0 = m_layer[layer0].get();
u8 *l1 = m_layer[layer0+1].get();
offset >>= 1;
offset &= 0x1ffff;
return (l0[offset] << 8) | l1[offset];
}
void igs011_state::igs011_layers_w(offs_t offset, u16 data, u16 mem_mask)
{
u16 word;
int layer0 = ((offset & (0x80000/2)) ? 4 : 0) + ((offset & 1) ? 0 : 2);
u8 *l0 = m_layer[layer0].get();
u8 *l1 = m_layer[layer0+1].get();
offset >>= 1;
offset &= 0x1ffff;
word = (l0[offset] << 8) | l1[offset];
COMBINE_DATA(&word);
l0[offset] = word >> 8;
l1[offset] = word;
}
/***************************************************************************
Blitter
***************************************************************************/
void igs011_state::igs011_blit_x_w(offs_t offset, u16 data, u16 mem_mask)
{
struct blitter_t &blitter = m_blitter;
COMBINE_DATA(&blitter.x);
}
void igs011_state::igs011_blit_y_w(offs_t offset, u16 data, u16 mem_mask)
{
struct blitter_t &blitter = m_blitter;
COMBINE_DATA(&blitter.y);
}
void igs011_state::igs011_blit_gfx_lo_w(offs_t offset, u16 data, u16 mem_mask)
{
struct blitter_t &blitter = m_blitter;
COMBINE_DATA(&blitter.gfx_lo);
}
void igs011_state::igs011_blit_gfx_hi_w(offs_t offset, u16 data, u16 mem_mask)
{
struct blitter_t &blitter = m_blitter;
COMBINE_DATA(&blitter.gfx_hi);
}
void igs011_state::igs011_blit_w_w(offs_t offset, u16 data, u16 mem_mask)
{
struct blitter_t &blitter = m_blitter;
COMBINE_DATA(&blitter.w);
}
void igs011_state::igs011_blit_h_w(offs_t offset, u16 data, u16 mem_mask)
{
struct blitter_t &blitter = m_blitter;
COMBINE_DATA(&blitter.h);
}
void igs011_state::igs011_blit_depth_w(offs_t offset, u16 data, u16 mem_mask)
{
struct blitter_t &blitter = m_blitter;
COMBINE_DATA(&blitter.depth);
}
void igs011_state::igs011_blit_pen_w(offs_t offset, u16 data, u16 mem_mask)
{
struct blitter_t &blitter = m_blitter;
COMBINE_DATA(&blitter.pen);
}
void igs011_state::igs011_blit_flags_w(offs_t offset, u16 data, u16 mem_mask)
{
struct blitter_t &blitter = m_blitter;
int xend, xinc;
int yend, yinc;
u8 trans_pen, clear_pen;
u8 pen = 0;
const rectangle &clip = m_screen->visible_area();
COMBINE_DATA(&blitter.flags);
LOGMASKED(LOG_BLITTER, "%06x: blit x %03x, y %03x, w %03x, h %03x, gfx %03x%04x, depth %02x, pen %02x, flags %03x\n", m_maincpu->pc(),
blitter.x,blitter.y,blitter.w,blitter.h,blitter.gfx_hi,blitter.gfx_lo,blitter.depth,blitter.pen,blitter.flags);
u8 *dest = m_layer[blitter.flags & 0x0007].get();
const bool opaque = !(blitter.flags & 0x0008);
const bool clear = blitter.flags & 0x0010;
const bool flipx = blitter.flags & 0x0020;
const bool flipy = blitter.flags & 0x0040;
if (!(blitter.flags & 0x0400))
return;
u8 pen_hi = (m_lhb2_pen_hi & 0x07) << 5;
// pixel address
u32 z = blitter.gfx_lo + (blitter.gfx_hi << 16);
// what were they smoking???
const bool depth4 = !((blitter.flags & 0x7) < (4 - (blitter.depth & 0x7))) ||
(z & 0x800000); // see lhb2
z &= 0x7fffff;
if (depth4)
{
z *= 2;
if (m_gfx2 && (blitter.gfx_hi & 0x80)) trans_pen = 0x1f; // lhb2
else trans_pen = 0x0f;
clear_pen = blitter.pen | 0xf0;
}
else
{
if (m_gfx2) trans_pen = 0x1f; // vbowl
else trans_pen = 0xff;
clear_pen = blitter.pen;
}
int xstart = (blitter.x & 0x1ff) - (blitter.x & 0x200);
int ystart = (blitter.y & 0x0ff) - (blitter.y & 0x100);
if (flipx) { xend = xstart - (blitter.w & 0x1ff) - 1; xinc = -1; }
else { xend = xstart + (blitter.w & 0x1ff) + 1; xinc = 1; }
if (flipy) { yend = ystart - (blitter.h & 0x0ff) - 1; yinc = -1; }
else { yend = ystart + (blitter.h & 0x0ff) + 1; yinc = 1; }
for (int y = ystart; y != yend; y += yinc)
{
for (int x = xstart; x != xend; x += xinc)
{
// fetch the pixel
if (!clear)
{
if (depth4) pen = (m_gfx[(z/2)%m_gfx.length()] >> ((z&1)?4:0)) & 0x0f;
else pen = m_gfx[z%m_gfx.length()];
if (m_gfx2)
{
pen &= 0x0f;
if (m_gfx2[(z/8)%m_gfx2.length()] & (1 << (z & 7)))
pen |= 0x10;
}
}
// plot it
if (clip.contains(x, y))
{
if (clear) dest[x + y * 512] = clear_pen;
else if (pen != trans_pen) dest[x + y * 512] = pen | pen_hi;
else if (opaque) dest[x + y * 512] = 0xff;
}
z++;
}
}
#ifdef MAME_DEBUG
#if 1
if (machine().input().code_pressed(KEYCODE_Z))
{ char buf[20];
sprintf(buf, "%02X%02X",blitter.depth,blitter.flags&0xff);
// ui_draw_text(buf, blitter.x, blitter.y); // crashes mame!
}
#endif
#endif
}
/***************************************************************************
Common functions
***************************************************************************/
void igs011_state::machine_start()
{
m_prot1_addr = 0;
m_lhb_irq_enable = 0;
save_item(NAME(m_igs_dips_sel));
save_item(NAME(m_igs_input_sel));
save_item(NAME(m_igs_hopper));
save_item(NAME(m_prot1));
save_item(NAME(m_prot1_swap));
save_item(NAME(m_prot1_addr));
save_item(NAME(m_prot2));
save_item(NAME(m_igs012_prot));
save_item(NAME(m_igs012_prot_swap));
save_item(NAME(m_igs012_prot_mode));
save_item(NAME(m_igs003_reg));
save_item(NAME(m_lhb_irq_enable));
save_item(NAME(m_igs003_prot_hold));
save_item(NAME(m_igs003_prot_x));
save_item(NAME(m_igs003_prot_y));
save_item(NAME(m_igs003_prot_z));
save_item(NAME(m_igs003_prot_h1));
save_item(NAME(m_igs003_prot_h2));
}
// Inputs
int igs011_state::igs_hopper_r()
{
return (m_igs_hopper && ((m_screen->frame_number()/5)&1)) ? 0x0000 : 0x0001;
}
void igs011_state::igs_dips_w(offs_t offset, u16 data, u16 mem_mask)
{
COMBINE_DATA(&m_igs_dips_sel);
}
template<unsigned Num>
u16 igs011_state::igs_dips_r()
{
u16 ret=0;
for (int i = 0; i < Num; i++)
if ((~m_igs_dips_sel) & (1 << i))
ret = m_io_dsw[i]->read();
// 0x0100 is blitter busy
return (ret & 0xff) | 0x0000;
}
// Games have 3 to 5 dips
/***************************************************************************
Code Decryption
***************************************************************************/
void igs011_state::wlcc_decrypt()
{
u16 *src = (u16 *) (m_maincpu_region->base());
int rom_size = 0x80000;
for (int i=0; i<rom_size/2; i++)
{
u16 x = src[i];
if ((i & 0x2000) == 0x0000 || (i & 0x0004) == 0x0000 || (i & 0x0090) == 0x0000)
x ^= 0x0004;
if ((i & 0x0100) == 0x0100 || (i & 0x0040) == 0x0040 || (i & 0x0012) == 0x0012)
x ^= 0x0020;
if ((i & 0x2400) == 0x0000 || (i & 0x4100) == 0x4100 || ((i & 0x2000) == 0x2000 && (i & 0x0c00) != 0x0000))
x ^= 0x0200;
if ((x & 0x0024) == 0x0004 || (x & 0x0024) == 0x0020)
x ^= 0x0024;
src[i] = x;
}
}
void igs011_state::lhb_decrypt()
{
u16 *src = (u16 *) (m_maincpu_region->base());
int rom_size = 0x80000;
for (int i=0; i<rom_size/2; i++)
{
u16 x = src[i];
if ((i & 0x1100) != 0x0100)
x ^= 0x0200;
if ((i & 0x0150) != 0x0000 && (i & 0x0152) != 0x0010)
x ^= 0x0004;
if ((i & 0x2084) != 0x2084 && (i & 0x2094) != 0x2014)
x ^= 0x0020;
src[i] = x;
}
}
void igs011_state::drgnwrld_type3_decrypt()
{
u16 *src = (u16 *) (m_maincpu_region->base());
int rom_size = 0x80000;
for (int i=0; i<rom_size/2; i++)
{
u16 x = src[i];
if ((i & 0x2000) == 0x0000 || (i & 0x0004) == 0x0000 || (i & 0x0090) == 0x0000)
x ^= 0x0004;
if ((i & 0x0100) == 0x0100 || (i & 0x0040) == 0x0040 || (i & 0x0012) == 0x0012)
x ^= 0x0020;
if ((((i & 0x1000) == 0x1000) ^ ((i & 0x0100) == 0x0100))
|| (i & 0x0880) == 0x0800 || (i & 0x0240) == 0x0240)
x ^= 0x0200;
if ((x & 0x0024) == 0x0004 || (x & 0x0024) == 0x0020)
x ^= 0x0024;
src[i] = x;
}
}
void igs011_state::drgnwrld_type2_decrypt()
{
u16 *src = (u16 *) (m_maincpu_region->base());
int rom_size = 0x80000;
for (int i=0; i<rom_size/2; i++)
{
u16 x = src[i];
if (((i & 0x000090) == 0x000000) || ((i & 0x002004) != 0x002004))
x ^= 0x0004;
if ((((i & 0x000050) == 0x000000) || ((i & 0x000142) != 0x000000)) && ((i & 0x000150) != 0x000000))
x ^= 0x0020;
if (((i & 0x004280) == 0x004000) || ((i & 0x004080) == 0x000000))
x ^= 0x0200;
if ((i & 0x0011a0) != 0x001000)
x ^= 0x0200;
if ((i & 0x000180) == 0x000100)
x ^= 0x0200;
if ((x & 0x0024) == 0x0020 || (x & 0x0024) == 0x0004)
x ^= 0x0024;
src[i] = x;
}
}
void igs011_state::drgnwrld_type1_decrypt()
{
u16 *src = (u16 *) (m_maincpu_region->base());
int rom_size = 0x80000;
for (int i=0; i<rom_size/2; i++)
{
u16 x = src[i];
if ((i & 0x2000) == 0x0000 || (i & 0x0004) == 0x0000 || (i & 0x0090) == 0x0000)
x ^= 0x0004;
if ((i & 0x0100) == 0x0100 || (i & 0x0040) == 0x0040 || (i & 0x0012) == 0x0012)
x ^= 0x0020;
/*
if ((((i & 0x1000) == 0x1000) ^ ((i & 0x0100) == 0x0100))
|| (i & 0x0880) == 0x0800 || (i & 0x0240) == 0x0240)
x ^= 0x0200;
*/
if ((x & 0x0024) == 0x0004 || (x & 0x0024) == 0x0020)
x ^= 0x0024;
src[i] = x;
}
}
void igs011_state::drgnwrldv40k_decrypt()
{
drgnwrld_type1_decrypt();
u16 *src = (u16 *) (m_maincpu_region->base());
int rom_size = 0x80000;
for (int i = 0; i < rom_size / 2; i++)
{
u16 x = src[i];
if ((i & 0x0800) != 0x0800)
x ^= 0x0200;
if (((i & 0x3a00) == 0x0a00) ^ ((i & 0x3a00) == 0x2a00))
x ^= 0x0200;
if (((i & 0x3ae0) == 0x0860) ^ ((i & 0x3ae0) == 0x2860))
x ^= 0x0200;
if (((i & 0x1c00) == 0x1800) ^ ((i & 0x1e00) == 0x1e00))
x ^= 0x0200;
if ((i & 0x1ee0) == 0x1c60)
x ^= 0x0200;
src[i] = x;
}
}
void igs011_state::lhb2_decrypt()
{
int rom_size = 0x80000;
u16 *src = (u16 *) (m_maincpu_region->base());
std::vector<u16> result_data(rom_size/2);
for (int i=0; i<rom_size/2; i++)
{
u16 x = src[i];
if ((i & 0x0054) != 0x0000 && (i & 0x0056) != 0x0010)
x ^= 0x0004;
if ((i & 0x0204) == 0x0000)
x ^= 0x0008;
if ((i & 0x3080) != 0x3080 && (i & 0x3090) != 0x3010)
x ^= 0x0020;
int j = bitswap<24>(i, 23,22,21,20,19,18,17,16,15,14,13, 8, 11,10, 9, 2, 7,6,5,4,3, 12, 1,0);
result_data[j] = x;
}
memcpy(src,&result_data[0],rom_size);
}
// xor similar to ryukobou (both sets are Japan), address scrambling from lhb2
void igs011_state::nkishusp_decrypt()
{
int rom_size = 0x80000;
u16 *src = (u16 *) (m_maincpu_region->base());
std::vector<u16> result_data(rom_size/2);
for (int i=0; i<rom_size/2; i++)
{
u16 x = src[i];
// lhb2 address scrambling
int j = bitswap<24>(i, 23,22,21,20,19,18,17,16,15,14,13, 8, 11,10, 9, 2, 7,6,5,4,3, 12, 1,0);
// ryukobou xor:
// if ((j & 0x00100) && (j & 0x00400))
// x ^= 0x0200;
if (!(j & 0x00004) || !(j & 0x02000) || (!(j & 0x00080) && !(j & 0x00010)))
x ^= 0x0020;
if ((j & 0x00100) || (j & 0x00040) || ((j & 0x00010)&&(j & 0x00002)))
x ^= 0x00004;
// additional xor:
if (!(j & 0x4000) && (j & 0x1000) && (j & 0x00200))
x ^= 0x0008;
result_data[j] = x;
}
memcpy(src,&result_data[0],rom_size);
}
void igs011_state::vbowl_decrypt()
{
u16 *src = (u16 *) (m_maincpu_region->base());
int rom_size = 0x80000;
for (int i=0; i<rom_size/2; i++)
{
u16 x = src[i];
if ((i & 0x4100) == 0x0100)
x ^= 0x0200;
if ((i & 0x4000) == 0x4000 && (i & 0x0300) != 0x0100)
x ^= 0x0200;
if ((i & 0x5700) == 0x5100)
x ^= 0x0200;
if ((i & 0x5500) == 0x1000)
x ^= 0x0200;
if ((i & 0x0140) != 0x0000 || (i & 0x0012) == 0x0012)
x ^= 0x0004;
if ((i & 0x2004) != 0x2004 || (i & 0x0090) == 0x0000)
x ^= 0x0020;
src[i] = x;
}
}
void igs011_state::vbowlhk_decrypt()
{
vbowl_decrypt();
u16 *src = (u16 *) (m_maincpu_region->base());
int rom_size = 0x80000;
for (int i=0; i<rom_size/2; i++)
{
u16 x = src[i];
// 00000-07fff, 2000 off, 800 off, 400 off, 200 on (2xx, 3xx)
if ((i & 0xd700) == 0x0100)
x ^= 0x0200;
// 00000-07fff, 800 on, 400 off, 200 on (axx, bxx)
if ((i & 0xc700) == 0x0500)
x ^= 0x0200;
// 08000-0ffff, 2000 off, 800 off, 200 off (0xx, 1xx, 4xx, 5xx)
if ((i & 0xd500) == 0x4000)
x ^= 0x0200;
// 08000-0ffff, 800 on, 200 off (8xx, 9xx, cxx, dxx)
if ((i & 0xc500) == 0x4400)
x ^= 0x0200;
// 10000-17fff, 2000 off, 200 off (0xx, 1xx, 4xx, 5xx, 8xx, 9xx, cxx, dxx)
if ((i & 0xd100) == 0x8000)
x ^= 0x0200;
// 10000-17fff, 2000 on, 800 on, 400 off, 200 on (axx, bxx)
if ((i & 0xd700) == 0x9500)
x ^= 0x0200;
// 18000-1ffff, 2000 off, 400 off, 200 on (2xx, 3xx, axx, bxx)
if ((i & 0xd300) == 0xc100)
x ^= 0x0200;
// 18000-1ffff, 2000 on, 800 on, 200 off (8xx, 9xx, cxx, dxx)
if ((i & 0xd500) == 0xd400)
x ^= 0x0200;
src[i] = x;
}
}
void igs011_state::dbc_decrypt()
{
u16 *src = (u16 *) (m_maincpu_region->base());
int rom_size = 0x80000;
for (int i=0; i<rom_size/2; i++)
{
u16 x = src[i];