1 // FinalBurn Neo Sega System C/C2 driver module
2 // Based on MAME driver by David Haywood and Aaron Giles
3
4 // System C/C2 vdp note:
5 // System C mixes the raw data from the sprite & other layers externally
6 // Because of this the sprite:sprite masking (x == 0) feature, internal to the
7 // 315-5313 vdp, is not used. When properly implemented and coming from the
8 // rgb output (using internal VDP mixer), The beach and Metal Factory levels
9 // will have sprites with incorrect masking due to the game hiding sprites
10 // with x == 0.
11
12 #include "tiles_generic.h"
13 #include "m68000_intf.h"
14 #include "burn_ym2612.h"
15 #include "upd7759.h"
16 #include "sn76496.h"
17 #include "burn_pal.h"
18 #include "burn_gun.h" // for dial (BurnTrackball)
19
20 static UINT8 *AllMem;
21 static UINT8 *AllRam;
22 static UINT8 *RamEnd;
23 static UINT8 *MemEnd;
24 static UINT8 *Drv68KROM;
25 static UINT8 *DrvSndROM;
26 static UINT8 *Drv68KRAM;
27 static UINT8 *DrvPalRAM;
28
29 static UINT32 *DrvPalette;
30 static UINT8 DrvRecalc;
31
32 static INT32 nExtraCycles[1];
33
34 static INT32 sound_rom_length = 0;
35 static UINT8 (*protection_read_cb)(UINT8);
36
37 static INT32 prot_write_buf = 0;
38 static INT32 prot_read_buf = 0;
39
40 static INT32 enable_display = 0;
41
42 static INT32 alt_palette_mode = 0;
43 static INT32 palette_bank = 0;
44 static INT32 bg_palbase = 0;
45 static INT32 sp_palbase = 0;
46
47 static UINT8 output_latch[8];
48 static UINT8 dir = 0;
49 static UINT8 dir_override = 0;
50 static UINT8 iocnt = 0;
51
52 static INT32 sound_bank = 0;
53
54 static INT32 irq6_line;
55 static INT32 irq4_counter;
56 static UINT16 SegaC2BgPalLookup[4];
57 static UINT16 SegaC2SpPalLookup[4];
58
59 static UINT8 DrvInputs[8];
60 static UINT8 DrvDips[4];
61 static UINT8 DrvJoy1[8];
62 static UINT8 DrvJoy2[8];
63 static UINT8 DrvJoy3[8];
64 static UINT8 DrvReset;
65
66 static INT16 Analog[2];
67
68 static INT32 is_wwmarine = 0;
69 static INT32 is_tfrceacb = 0;
70 static INT32 is_ribbit = 0;
71
72 static INT32 has_dial = 0;
73
74 struct PicoVideo {
75 UINT8 reg[0x20];
76 UINT32 command; // 32-bit Command
77 UINT8 pending; // 1 if waiting for second half of 32-bit command
78 UINT8 type; // Command type (v/c/vsram read/write)
79 UINT16 addr; // Read/Write address
80 UINT8 addr_u; // bit16 of .addr (for 128k)
81 INT32 status; // Status bits
82 UINT8 pending_ints; // pending interrupts: ??VH????
83 INT8 lwrite_cnt; // VDP write count during active display line
84 UINT16 v_counter; // V-counter
85 INT32 h_mask;
86 INT32 field; // for interlace mode 2. -dink
87 INT32 rotate;
88 INT32 debug_p; // debug port
89 INT32 rendstatus; // status of vdp renderer
90 };
91
92 #define LF_PLANE_1 (1 << 0)
93 #define LF_SH (1 << 1) // must be = 2
94 #define LF_FORCE (1 << 2)
95
96 #define SPRL_HAVE_HI 0x80 // have hi priority sprites
97 #define SPRL_HAVE_LO 0x40 // *lo*
98 #define SPRL_MAY_HAVE_OP 0x20 // may have operator sprites on the line
99 #define SPRL_LO_ABOVE_HI 0x10 // low priority sprites may be on top of hi
100
101 #define PVD_KILL_A (1 << 0)
102 #define PVD_KILL_B (1 << 1)
103 #define PVD_KILL_S_LO (1 << 2)
104 #define PVD_KILL_S_HI (1 << 3)
105 #define PVD_KILL_32X (1 << 4)
106 #define PVD_FORCE_A (1 << 5)
107 #define PVD_FORCE_B (1 << 6)
108 #define PVD_FORCE_S (1 << 7)
109
110 #define PDRAW_SPRITES_MOVED (1<<0) // (asm)
111 #define PDRAW_WND_DIFF_PRIO (1<<1) // not all window tiles use same priority
112 #define PDRAW_INTERLACE (1<<3)
113 #define PDRAW_DIRTY_SPRITES (1<<4) // (asm)
114 #define PDRAW_SONIC_MODE (1<<5) // mid-frame palette changes for 8bit renderer
115 #define PDRAW_PLANE_HI_PRIO (1<<6) // have layer with all hi prio tiles (mk3)
116 #define PDRAW_SHHI_DONE (1<<7) // layer sh/hi already processed
117 #define PDRAW_32_COLS (1<<8) // 32 column mode
118
119 #define MAX_LINE_SPRITES 29
120
121 static UINT8 HighLnSpr[240][3 + MAX_LINE_SPRITES]; // sprite_count, ^flags, tile_count, [spritep]...
122
123 struct TileStrip
124 {
125 INT32 nametab; // Position in VRAM of name table (for this tile line)
126 INT32 line; // Line number in pixels 0x000-0x3ff within the virtual tilemap
127 INT32 hscroll; // Horizontal scroll value in pixels for the line
128 INT32 xmask; // X-Mask (0x1f - 0x7f) for horizontal wraparound in the tilemap
129 INT32 *hc; // cache for high tile codes and their positions
130 INT32 cells; // cells (tiles) to draw (32 col mode doesn't need to update whole 320)
131 };
132
133 static UINT16 *RamPal;
134 static UINT16 *RamVid;
135 static UINT16 *RamSVid;
136 static struct PicoVideo *RamVReg;
137
138 static UINT16 *HighCol;
139 static UINT16 *HighColFull;
140
141 static INT32 *HighCacheA;
142 static INT32 *HighCacheB;
143 static INT32 *HighPreSpr;
144
145 static INT32 Scanline = 0;
146 static INT32 line_base_cycles;
147
148 static INT32 Hardware = 0x00; // japan-ntsc
149 static INT32 dma_xfers = 0; // vdp dma
150 static INT32 BlankedLine = 0;
151 static INT32 interlacemode2 = 0;
152
153 #define SekCyclesLine() ( (SekTotalCycles() - line_base_cycles) )
154
155 static struct BurnInputInfo SegaC2_3ButtonInputList[] = {
156 {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" },
157 {"P1 Start", BIT_DIGITAL, DrvJoy3 + 4, "p1 start" },
158 {"P1 Up", BIT_DIGITAL, DrvJoy1 + 5, "p1 up" },
159 {"P1 Down", BIT_DIGITAL, DrvJoy1 + 4, "p1 down" },
160 {"P1 Left", BIT_DIGITAL, DrvJoy1 + 7, "p1 left" },
161 {"P1 Right", BIT_DIGITAL, DrvJoy1 + 6, "p1 right" },
162 {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 1" },
163 {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 2" },
164 {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 3" },
165
166 {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" },
167 {"P2 Start", BIT_DIGITAL, DrvJoy3 + 5, "p2 start" },
168 {"P2 Up", BIT_DIGITAL, DrvJoy2 + 5, "p2 up" },
169 {"P2 Down", BIT_DIGITAL, DrvJoy2 + 4, "p2 down" },
170 {"P2 Left", BIT_DIGITAL, DrvJoy2 + 7, "p2 left" },
171 {"P2 Right", BIT_DIGITAL, DrvJoy2 + 6, "p2 right" },
172 {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 0, "p2 fire 1" },
173 {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 1, "p2 fire 2" },
174 {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 2, "p2 fire 3" },
175
176 {"Reset", BIT_DIGITAL, &DrvReset, "reset" },
177 {"Service Mode", BIT_DIGITAL, DrvJoy3 + 2, "diag" },
178 {"Service", BIT_DIGITAL, DrvJoy3 + 3, "service" },
179 {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" },
180 {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" },
181 };
182
183 STDINPUTINFO(SegaC2_3Button)
184
185 static struct BurnInputInfo SegaC2_2ButtonInputList[] = {
186 {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" },
187 {"P1 Start", BIT_DIGITAL, DrvJoy3 + 4, "p1 start" },
188 {"P1 Up", BIT_DIGITAL, DrvJoy1 + 5, "p1 up" },
189 {"P1 Down", BIT_DIGITAL, DrvJoy1 + 4, "p1 down" },
190 {"P1 Left", BIT_DIGITAL, DrvJoy1 + 7, "p1 left" },
191 {"P1 Right", BIT_DIGITAL, DrvJoy1 + 6, "p1 right" },
192 {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 1" },
193 {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 2" },
194
195
196 {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" },
197 {"P2 Start", BIT_DIGITAL, DrvJoy3 + 5, "p2 start" },
198 {"P2 Up", BIT_DIGITAL, DrvJoy2 + 5, "p2 up" },
199 {"P2 Down", BIT_DIGITAL, DrvJoy2 + 4, "p2 down" },
200 {"P2 Left", BIT_DIGITAL, DrvJoy2 + 7, "p2 left" },
201 {"P2 Right", BIT_DIGITAL, DrvJoy2 + 6, "p2 right" },
202 {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 0, "p2 fire 1" },
203 {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 1, "p2 fire 2" },
204
205 {"Reset", BIT_DIGITAL, &DrvReset, "reset" },
206 {"Service Mode", BIT_DIGITAL, DrvJoy3 + 2, "diag" },
207 {"Service", BIT_DIGITAL, DrvJoy3 + 3, "service" },
208 {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" },
209 {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" },
210 };
211
212 STDINPUTINFO(SegaC2_2Button)
213
214 static struct BurnInputInfo SegaC2_1ButtonInputList[] = {
215 {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" },
216 {"P1 Start", BIT_DIGITAL, DrvJoy3 + 4, "p1 start" },
217 {"P1 Up", BIT_DIGITAL, DrvJoy1 + 5, "p1 up" },
218 {"P1 Down", BIT_DIGITAL, DrvJoy1 + 4, "p1 down" },
219 {"P1 Left", BIT_DIGITAL, DrvJoy1 + 7, "p1 left" },
220 {"P1 Right", BIT_DIGITAL, DrvJoy1 + 6, "p1 right" },
221 {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 1" },
222
223 {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" },
224 {"P2 Start", BIT_DIGITAL, DrvJoy3 + 5, "p2 start" },
225 {"P2 Up", BIT_DIGITAL, DrvJoy2 + 5, "p2 up" },
226 {"P2 Down", BIT_DIGITAL, DrvJoy2 + 4, "p2 down" },
227 {"P2 Left", BIT_DIGITAL, DrvJoy2 + 7, "p2 left" },
228 {"P2 Right", BIT_DIGITAL, DrvJoy2 + 6, "p2 right" },
229 {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 0, "p2 fire 1" },
230
231 {"Reset", BIT_DIGITAL, &DrvReset, "reset" },
232 {"Service Mode", BIT_DIGITAL, DrvJoy3 + 2, "diag" },
233 {"Service", BIT_DIGITAL, DrvJoy3 + 3, "service" },
234 {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" },
235 {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" },
236 };
237
238 STDINPUTINFO(SegaC2_1Button)
239
240 static struct BurnInputInfo RibbitInputList[] = { // Look Ma! No buttons!
241 {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" },
242 {"P1 Start", BIT_DIGITAL, DrvJoy3 + 4, "p1 start" },
243 {"P1 Up", BIT_DIGITAL, DrvJoy1 + 5, "p1 up" },
244 {"P1 Down", BIT_DIGITAL, DrvJoy1 + 4, "p1 down" },
245 {"P1 Left", BIT_DIGITAL, DrvJoy1 + 7, "p1 left" },
246 {"P1 Right", BIT_DIGITAL, DrvJoy1 + 6, "p1 right" },
247
248 {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" },
249 {"P2 Start", BIT_DIGITAL, DrvJoy3 + 5, "p2 start" },
250 {"P2 Up", BIT_DIGITAL, DrvJoy2 + 5, "p2 up" },
251 {"P2 Down", BIT_DIGITAL, DrvJoy2 + 4, "p2 down" },
252 {"P2 Left", BIT_DIGITAL, DrvJoy2 + 7, "p2 left" },
253 {"P2 Right", BIT_DIGITAL, DrvJoy2 + 6, "p2 right" },
254
255 {"Reset", BIT_DIGITAL, &DrvReset, "reset" },
256 {"Service Mode", BIT_DIGITAL, DrvJoy3 + 2, "diag" },
257 {"Service", BIT_DIGITAL, DrvJoy3 + 3, "service" },
258 {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" },
259 {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" },
260 };
261
262 STDINPUTINFO(Ribbit)
263
264 #define A(a, b, c, d) {a, b, (UINT8*)(c), d}
265 static struct BurnInputInfo TwinsquaInputList[] = {
266 {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" },
267 {"P1 Start", BIT_DIGITAL, DrvJoy3 + 4, "p1 start" },
268 {"P1 Button 1", BIT_DIGITAL, DrvJoy3 + 6, "p1 fire 1" },
269 A("P1 Dial", BIT_ANALOG_REL, &Analog[0], "p1 x-axis"),
270
271 {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" },
272 {"P2 Start", BIT_DIGITAL, DrvJoy3 + 5, "p2 start" },
273 {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 7, "p2 fire 1" },
274 A("P2 Dial", BIT_ANALOG_REL, &Analog[1], "p2 x-axis"),
275
276 {"Reset", BIT_DIGITAL, &DrvReset, "reset" },
277 {"Service Mode", BIT_DIGITAL, DrvJoy3 + 2, "diag" },
278 {"Service", BIT_DIGITAL, DrvJoy3 + 3, "service" },
279 {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" },
280 {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" },
281 };
282 #undef A
283 STDINPUTINFO(Twinsqua)
284
285 static struct BurnInputInfo SoniccarInputList[] = {
286 {"Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" },
287 {"Lt Stick Left", BIT_DIGITAL, DrvJoy1 + 5, "p1 left" },
288 {"Lt Stick Right", BIT_DIGITAL, DrvJoy1 + 4, "p1 right" },
289 {"Rt Stick Left", BIT_DIGITAL, DrvJoy1 + 7, "p2 left" },
290 {"Rt Stick Right", BIT_DIGITAL, DrvJoy1 + 6, "p2 right" },
291 {"Button 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 1" },
292 {"Button 2", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 2" },
293 {"Button 3", BIT_DIGITAL, DrvJoy3 + 4, "p1 fire 3" },
294 {"Button 4", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 4" },
295
296 {"Reset", BIT_DIGITAL, &DrvReset, "reset" },
297 {"Service Mode", BIT_DIGITAL, DrvJoy3 + 2, "diag" },
298 {"Service", BIT_DIGITAL, DrvJoy3 + 3, "service" },
299 {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" },
300 {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" },
301 };
302
303 STDINPUTINFO(Soniccar)
304
305 static struct BurnInputInfo OopartsInputList[] = {
306 {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" },
307 {"P1 Start", BIT_DIGITAL, DrvJoy3 + 4, "p1 start" },
308 {"P1 Up", BIT_DIGITAL, DrvJoy1 + 5, "p1 up" },
309 {"P1 Down", BIT_DIGITAL, DrvJoy1 + 4, "p1 down" },
310 {"P1 Left", BIT_DIGITAL, DrvJoy1 + 7, "p1 left" },
311 {"P1 Right", BIT_DIGITAL, DrvJoy1 + 6, "p1 right" },
312 {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 1" },
313 {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 2" },
314 {"P1 Button 3", BIT_DIGITAL, DrvJoy3 + 6, "p1 fire 3" },
315
316 {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" },
317 {"P2 Start", BIT_DIGITAL, DrvJoy3 + 5, "p2 start" },
318 {"P2 Up", BIT_DIGITAL, DrvJoy2 + 5, "p2 up" },
319 {"P2 Down", BIT_DIGITAL, DrvJoy2 + 4, "p2 down" },
320 {"P2 Left", BIT_DIGITAL, DrvJoy2 + 7, "p2 left" },
321 {"P2 Right", BIT_DIGITAL, DrvJoy2 + 6, "p2 right" },
322 {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 0, "p2 fire 1" },
323 {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 1, "p2 fire 2" },
324 {"P2 Button 3", BIT_DIGITAL, DrvJoy3 + 7, "p2 fire 3" },
325
326 {"Reset", BIT_DIGITAL, &DrvReset, "reset" },
327 {"Service Mode", BIT_DIGITAL, DrvJoy3 + 2, "diag" },
328 {"Service", BIT_DIGITAL, DrvJoy3 + 3, "service" },
329 {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" },
330 {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" },
331 };
332
333 STDINPUTINFO(Ooparts)
334
335 static struct BurnInputInfo WwmarineInputList[] = {
336 {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" },
337 {"P1 Left", BIT_DIGITAL, DrvJoy1 + 6, "p1 left" },
338 {"P1 Right", BIT_DIGITAL, DrvJoy1 + 7, "p1 right" },
339 {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 1" },
340 {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 2" },
341 {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 3" },
342
343 {"Reset", BIT_DIGITAL, &DrvReset, "reset" },
344 {"Service Mode", BIT_DIGITAL, DrvJoy3 + 2, "diag" },
345 {"Service", BIT_DIGITAL, DrvJoy3 + 3, "service" },
346 {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" },
347 {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" },
348 };
349
350 STDINPUTINFO(Wwmarine)
351
352 static struct BurnInputInfo SonicfgtInputList[] = {
353 {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" },
354 {"P1 Left", BIT_DIGITAL, DrvJoy1 + 7, "p1 left" },
355 {"P1 Right", BIT_DIGITAL, DrvJoy1 + 6, "p1 right" },
356 {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 1" },
357 {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 2" },
358 {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 3" },
359
360 {"Reset", BIT_DIGITAL, &DrvReset, "reset" },
361 {"Service Mode", BIT_DIGITAL, DrvJoy3 + 2, "diag" },
362 {"Service", BIT_DIGITAL, DrvJoy3 + 3, "service" },
363 {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" },
364 {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" },
365 };
366
367 STDINPUTINFO(Sonicfgt)
368
369
370
371 #define coinage_dips(_num) \
372 {0 , 0xfe, 0 , 16, "Coin A" }, \
373 {_num, 0x01, 0x0f, 0x07, "4 Coins 1 Credits" }, \
374 {_num, 0x01, 0x0f, 0x08, "3 Coins 1 Credits" }, \
375 {_num, 0x01, 0x0f, 0x09, "2 Coins 1 Credits" }, \
376 {_num, 0x01, 0x0f, 0x05, "2 Coins/1 Credit, 5/3, 6/4" }, \
377 {_num, 0x01, 0x0f, 0x04, "2 Coins/1 Credit, 4/3" }, \
378 {_num, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, \
379 {_num, 0x01, 0x0f, 0x03, "1 Coin/1 Credit, 5/6" }, \
380 {_num, 0x01, 0x0f, 0x02, "1 Coin/1 Credit, 4/5" }, \
381 {_num, 0x01, 0x0f, 0x01, "1 Coin/1 Credit, 2/3" }, \
382 {_num, 0x01, 0x0f, 0x06, "2 Coins 3 Credits" }, \
383 {_num, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, \
384 {_num, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, \
385 {_num, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, \
386 {_num, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, \
387 {_num, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, \
388 {_num, 0x01, 0x0f, 0x00, "Free Play (if Coin B too) or 1/1" }, \
389 \
390 {0 , 0xfe, 0 , 16, "Coin B" }, \
391 {_num, 0x01, 0xf0, 0x70, "4 Coins 1 Credits" }, \
392 {_num, 0x01, 0xf0, 0x80, "3 Coins 1 Credits" }, \
393 {_num, 0x01, 0xf0, 0x90, "2 Coins 1 Credits" }, \
394 {_num, 0x01, 0xf0, 0x50, "2 Coins/1 Credit, 5/3, 6/4" }, \
395 {_num, 0x01, 0xf0, 0x40, "2 Coins/1 Credit, 4/3" }, \
396 {_num, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, \
397 {_num, 0x01, 0xf0, 0x30, "1 Coin/1 Credit, 5/6" }, \
398 {_num, 0x01, 0xf0, 0x20, "1 Coin/1 Credit, 4/5" }, \
399 {_num, 0x01, 0xf0, 0x10, "1 Coin/1 Credit, 2/3" }, \
400 {_num, 0x01, 0xf0, 0x60, "2 Coins 3 Credits" }, \
401 {_num, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, \
402 {_num, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, \
403 {_num, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, \
404 {_num, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, \
405 {_num, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, \
406 {_num, 0x01, 0xf0, 0x00, "Free Play (if Coin A too) or 1/1" },
407
408
409 static struct BurnDIPInfo BloxeedcDIPList[]=
410 {
411 {0x11, 0xff, 0xff, 0xff, NULL },
412 {0x12, 0xff, 0xff, 0x77, NULL },
413
414 coinage_dips(0x11)
415
416 {0 , 0xfe, 0 , 4, "Credits to Start (VS)" },
417 {0x12, 0x01, 0x01, 0x00, "1" },
418 {0x12, 0x01, 0x01, 0x01, "2" },
419 {0x12, 0x01, 0x01, 0x00, "2" },
420 {0x12, 0x01, 0x01, 0x01, "4" },
421
422 {0 , 0xfe, 0 , 2, "Credits to Start (Normal)" },
423 {0x12, 0x01, 0x02, 0x02, "1" },
424 {0x12, 0x01, 0x02, 0x00, "2" },
425
426 {0 , 0xfe, 0 , 2, "Demo Sounds" },
427 {0x12, 0x01, 0x08, 0x08, "Off" },
428 {0x12, 0x01, 0x08, 0x00, "On" },
429
430 {0 , 0xfe, 0 , 4, "Difficulty" },
431 {0x12, 0x01, 0x30, 0x20, "Easy" },
432 {0x12, 0x01, 0x30, 0x30, "Normal" },
433 {0x12, 0x01, 0x30, 0x10, "Hard" },
434 {0x12, 0x01, 0x30, 0x00, "Hardest" },
435
436 {0 , 0xfe, 0 , 2, "High Speed Mode" },
437 {0x12, 0x01, 0x80, 0x00, "Off" },
438 {0x12, 0x01, 0x80, 0x80, "On" },
439 };
440
441 STDDIPINFO(Bloxeedc)
442
443 static struct BurnDIPInfo BloxeeduDIPList[]=
444 {
445 {0x11, 0xff, 0xff, 0xff, NULL },
446 {0x12, 0xff, 0xff, 0x77, NULL },
447
448 coinage_dips(0x11)
449
450 {0 , 0xfe, 0 , 4, "Credits to Start (Normal/VS)" },
451 {0x12, 0x01, 0x03, 0x01, "1 / 1" },
452 {0x12, 0x01, 0x03, 0x03, "1 / 2" },
453 {0x12, 0x01, 0x03, 0x02, "1 / 2" },
454 {0x12, 0x01, 0x03, 0x00, "2 / 4" },
455
456 {0 , 0xfe, 0 , 2, "Demo Sounds" },
457 {0x12, 0x01, 0x08, 0x08, "Off" },
458 {0x12, 0x01, 0x08, 0x00, "On" },
459
460 {0 , 0xfe, 0 , 4, "Difficulty" },
461 {0x12, 0x01, 0x30, 0x20, "Easy" },
462 {0x12, 0x01, 0x30, 0x30, "Normal" },
463 {0x12, 0x01, 0x30, 0x10, "Hard" },
464 {0x12, 0x01, 0x30, 0x00, "Hardest" },
465
466 {0 , 0xfe, 0 , 2, "High Speed Mode" },
467 {0x12, 0x01, 0x80, 0x00, "Off" },
468 {0x12, 0x01, 0x80, 0x80, "On" },
469 };
470
471 STDDIPINFO(Bloxeedu)
472
473 static struct BurnDIPInfo ColumnsDIPList[]=
474 {
475 {0x11, 0xff, 0xff, 0xff, NULL },
476 {0x12, 0xff, 0xff, 0xfd, NULL },
477
478 coinage_dips(0x11)
479
480 {0 , 0xfe, 0 , 2, "Demo Sounds" },
481 {0x12, 0x01, 0x02, 0x02, "Off" },
482 {0x12, 0x01, 0x02, 0x00, "On" },
483
484 {0 , 0xfe, 0 , 4, "Difficulty" },
485 {0x12, 0x01, 0x30, 0x00, "Easiest" },
486 {0x12, 0x01, 0x30, 0x10, "Easy" },
487 {0x12, 0x01, 0x30, 0x30, "Normal" },
488 {0x12, 0x01, 0x30, 0x20, "Hard" },
489 };
490
491 STDDIPINFO(Columns)
492
493 static struct BurnDIPInfo Columns2DIPList[]=
494 {
495 {0x11, 0xff, 0xff, 0xff, NULL },
496 {0x12, 0xff, 0xff, 0xfd, NULL },
497
498 coinage_dips(0x11)
499
500 {0 , 0xfe, 0 , 2, "Cabinet" },
501 {0x12, 0x01, 0x01, 0x01, "Upright" },
502 {0x12, 0x01, 0x01, 0x00, "Cocktail" },
503
504 {0 , 0xfe, 0 , 2, "Demo Sounds" },
505 {0x12, 0x01, 0x02, 0x02, "Off" },
506 {0x12, 0x01, 0x02, 0x00, "On" },
507
508 {0 , 0xfe, 0 , 4, "VS. Mode Credits/Match" },
509 {0x12, 0x01, 0x0c, 0x0c, "1" },
510 {0x12, 0x01, 0x0c, 0x08, "2" },
511 {0x12, 0x01, 0x0c, 0x04, "3" },
512 {0x12, 0x01, 0x0c, 0x00, "4" },
513
514 {0 , 0xfe, 0 , 4, "Flash Mode Difficulty" },
515 {0x12, 0x01, 0x30, 0x20, "Easy" },
516 {0x12, 0x01, 0x30, 0x30, "Normal" },
517 {0x12, 0x01, 0x30, 0x10, "Hard" },
518 {0x12, 0x01, 0x30, 0x00, "Hardest" },
519 };
520
521 STDDIPINFO(Columns2)
522
523 static struct BurnDIPInfo TfrceacDIPList[]=
524 {
525 {0x15, 0xff, 0xff, 0xff, NULL },
526 {0x16, 0xff, 0xff, 0xfd, NULL },
527
528 coinage_dips(0x15)
529
530 {0 , 0xfe, 0 , 2, "Credits to Start" },
531 {0x16, 0x01, 0x01, 0x01, "1" },
532 {0x16, 0x01, 0x01, 0x00, "2" },
533
534 {0 , 0xfe, 0 , 2, "Demo Sounds" },
535 {0x16, 0x01, 0x02, 0x02, "Off" },
536 {0x16, 0x01, 0x02, 0x00, "On" },
537
538 {0 , 0xfe, 0 , 4, "Lives" },
539 {0x16, 0x01, 0x0c, 0x00, "2" },
540 {0x16, 0x01, 0x0c, 0x0c, "3" },
541 {0x16, 0x01, 0x0c, 0x08, "4" },
542 {0x16, 0x01, 0x0c, 0x04, "5" },
543
544 {0 , 0xfe, 0 , 4, "Bonus Life" },
545 {0x16, 0x01, 0x30, 0x10, "10k, 70k, 150k" },
546 {0x16, 0x01, 0x30, 0x30, "20k, 100k, 200k" },
547 {0x16, 0x01, 0x30, 0x20, "40k, 150k, 300k" },
548 {0x16, 0x01, 0x30, 0x00, "None" },
549
550 {0 , 0xfe, 0 , 4, "Difficulty" },
551 {0x16, 0x01, 0xc0, 0x80, "Easy" },
552 {0x16, 0x01, 0xc0, 0xc0, "Medium" },
553 {0x16, 0x01, 0xc0, 0x40, "Hard" },
554 {0x16, 0x01, 0xc0, 0x00, "Hardest" },
555 };
556
557 STDDIPINFO(Tfrceac)
558
559 static struct BurnDIPInfo BorenchDIPList[]=
560 {
561 {0x13, 0xff, 0xff, 0xff, NULL },
562 {0x14, 0xff, 0xff, 0xfd, NULL },
563
564 coinage_dips(0x13)
565
566 {0 , 0xfe, 0 , 2, "Credits to Start" },
567 {0x14, 0x01, 0x01, 0x01, "1" },
568 {0x14, 0x01, 0x01, 0x00, "2" },
569
570 {0 , 0xfe, 0 , 2, "Demo Sounds" },
571 {0x14, 0x01, 0x02, 0x02, "Off" },
572 {0x14, 0x01, 0x02, 0x00, "On" },
573
574 {0 , 0xfe, 0 , 4, "Lives 1P Mode" },
575 {0x14, 0x01, 0x0c, 0x00, "1" },
576 {0x14, 0x01, 0x0c, 0x0c, "2" },
577 {0x14, 0x01, 0x0c, 0x08, "3" },
578 {0x14, 0x01, 0x0c, 0x04, "4" },
579
580 {0 , 0xfe, 0 , 4, "Lives 2P Mode" },
581 {0x14, 0x01, 0x30, 0x00, "2" },
582 {0x14, 0x01, 0x30, 0x30, "3" },
583 {0x14, 0x01, 0x30, 0x20, "4" },
584 {0x14, 0x01, 0x30, 0x10, "5" },
585
586 {0 , 0xfe, 0 , 4, "Difficulty" },
587 {0x14, 0x01, 0xc0, 0x80, "Easy" },
588 {0x14, 0x01, 0xc0, 0xc0, "Medium" },
589 {0x14, 0x01, 0xc0, 0x40, "Hard" },
590 {0x14, 0x01, 0xc0, 0x00, "Hardest" },
591 };
592
593 STDDIPINFO(Borench)
594
595 static struct BurnDIPInfo StkclmnsDIPList[]=
596 {
597 {0x13, 0xff, 0xff, 0xff, NULL },
598 {0x14, 0xff, 0xff, 0xfd, NULL },
599
600 coinage_dips(0x13)
601
602 {0 , 0xfe, 0 , 4, "Difficulty" },
603 {0x14, 0x01, 0x03, 0x02, "Easy" },
604 {0x14, 0x01, 0x03, 0x03, "Medium" },
605 {0x14, 0x01, 0x03, 0x01, "Hard" },
606 {0x14, 0x01, 0x03, 0x00, "Hardest" },
607
608 {0 , 0xfe, 0 , 2, "Demo Sounds" },
609 {0x14, 0x01, 0x02, 0x02, "Off" },
610 {0x14, 0x01, 0x02, 0x00, "On" },
611
612 {0 , 0xfe, 0 , 2, "Match Mode Prices" },
613 {0x14, 0x01, 0x0c, 0x08, "1" },
614 {0x14, 0x01, 0x0c, 0x09, "2" },
615 };
616
617 STDDIPINFO(Stkclmns)
618
619 static struct BurnDIPInfo RibbitDIPList[]=
620 {
621 {0x0f, 0xff, 0xff, 0xff, NULL },
622 {0x10, 0xff, 0xff, 0xf5, NULL },
623
624 coinage_dips(0xf)
625
626 {0 , 0xfe, 0 , 2, "Credits to Start" },
627 {0x10, 0x01, 0x01, 0x01, "1" },
628 {0x10, 0x01, 0x01, 0x00, "2" },
629
630 {0 , 0xfe, 0 , 2, "Demo Sounds" },
631 {0x10, 0x01, 0x02, 0x02, "Off" },
632 {0x10, 0x01, 0x02, 0x00, "On" },
633
634 {0 , 0xfe, 0 , 4, "Lives" },
635 {0x10, 0x01, 0x0c, 0x08, "1" },
636 {0x10, 0x01, 0x0c, 0x0c, "2" },
637 {0x10, 0x01, 0x0c, 0x04, "3" },
638 {0x10, 0x01, 0x0c, 0x00, "5" },
639
640 {0 , 0xfe, 0 , 4, "Difficulty" },
641 {0x10, 0x01, 0x30, 0x20, "Easy" },
642 {0x10, 0x01, 0x30, 0x30, "Normal" },
643 {0x10, 0x01, 0x30, 0x10, "Hard" },
644 {0x10, 0x01, 0x30, 0x00, "Hardest" },
645 };
646
647 STDDIPINFO(Ribbit)
648
649 static struct BurnDIPInfo RibbitjDIPList[]=
650 {
651 {0x0f, 0xff, 0xff, 0xff, NULL },
652 {0x10, 0xff, 0xff, 0xf5, NULL },
653
654 coinage_dips(0xf)
655
656 {0 , 0xfe, 0 , 2, "Credits to Start" },
657 {0x10, 0x01, 0x01, 0x01, "1" },
658 {0x10, 0x01, 0x01, 0x00, "2" },
659
660 {0 , 0xfe, 0 , 2, "Demo Sounds" },
661 {0x10, 0x01, 0x02, 0x02, "Off" },
662 {0x10, 0x01, 0x02, 0x00, "On" },
663
664 {0 , 0xfe, 0 , 4, "Lives" },
665 {0x10, 0x01, 0x0c, 0x04, "1" },
666 {0x10, 0x01, 0x0c, 0x08, "2" },
667 {0x10, 0x01, 0x0c, 0x0c, "3" },
668 {0x10, 0x01, 0x0c, 0x00, "5" },
669
670 {0 , 0xfe, 0 , 4, "Difficulty" },
671 {0x10, 0x01, 0x30, 0x20, "Easy" },
672 {0x10, 0x01, 0x30, 0x30, "Normal" },
673 {0x10, 0x01, 0x30, 0x10, "Hard" },
674 {0x10, 0x01, 0x30, 0x00, "Hardest" },
675 };
676
677 STDDIPINFO(Ribbitj)
678
679
680 static struct BurnDIPInfo TwinsquaDIPList[]=
681 {
682 {0x0b, 0xff, 0xff, 0xff, NULL },
683 {0x0c, 0xff, 0xff, 0xfd, NULL },
684
685 coinage_dips(0x0b)
686
687 {0 , 0xfe, 0 , 2, "Credits to Start" },
688 {0x0c, 0x01, 0x01, 0x01, "1" },
689 {0x0c, 0x01, 0x01, 0x00, "2" },
690
691 {0 , 0xfe, 0 , 2, "Demo Sounds" },
692 {0x0c, 0x01, 0x02, 0x02, "Off" },
693 {0x0c, 0x01, 0x02, 0x00, "On" },
694
695 {0 , 0xfe, 0 , 2, "Buy In" },
696 {0x0c, 0x01, 0x04, 0x04, "Off" },
697 {0x0c, 0x01, 0x04, 0x00, "On" },
698
699 {0 , 0xfe, 0 , 4, "Difficulty" },
700 {0x0c, 0x01, 0x18, 0x10, "Easy" },
701 {0x0c, 0x01, 0x18, 0x18, "Medium" },
702 {0x0c, 0x01, 0x18, 0x08, "Hard" },
703 {0x0c, 0x01, 0x18, 0x00, "Hardest" },
704
705 {0 , 0xfe, 0 , 2, "Seat Type" },
706 {0x0c, 0x01, 0x20, 0x20, "Normal" },
707 {0x0c, 0x01, 0x20, 0x00, "Moving" },
708 };
709
710 STDDIPINFO(Twinsqua)
711
712 static struct BurnDIPInfo SoniccarDIPList[]=
713 {
714 {0x0c, 0xff, 0xff, 0xff, NULL },
715 {0x0d, 0xff, 0xff, 0xff, NULL },
716
717 coinage_dips(0x0c)
718
719 {0 , 0xfe, 0 , 4, "Demo Sound Interval" },
720 {0x0d, 0x01, 0x03, 0x00, "Off" },
721 {0x0d, 0x01, 0x03, 0x01, "Every 4 Minutes" },
722 {0x0d, 0x01, 0x03, 0x02, "Every 2 Minutes" },
723 {0x0d, 0x01, 0x03, 0x03, "On" },
724
725 {0 , 0xfe, 0 , 2, "Lighting Time" },
726 {0x0d, 0x01, 0x04, 0x04, "Advertise & Playtime" },
727 {0x0d, 0x01, 0x04, 0x00, "Playtime Only" },
728
729 {0 , 0xfe, 0 , 2, "Light" },
730 {0x0d, 0x01, 0x08, 0x00, "Off" },
731 {0x0d, 0x01, 0x08, 0x08, "On" },
732
733 {0 , 0xfe, 0 , 2, "Screen Display" },
734 {0x0d, 0x01, 0x10, 0x10, "Insert 100-400 Yen" },
735 {0x0d, 0x01, 0x10, 0x00, "Insert Money" },
736 };
737
738 STDDIPINFO(Soniccar)
739
740 static struct BurnDIPInfo SsonicbrDIPList[]=
741 {
742 {0x11, 0xff, 0xff, 0xff, NULL },
743 {0x12, 0xff, 0xff, 0xff, NULL },
744
745 coinage_dips(0x11)
746
747 {0 , 0xfe, 0 , 2, "Demo Sounds" },
748 {0x12, 0x01, 0x01, 0x01, "On" },
749 {0x12, 0x01, 0x01, 0x00, "Off" },
750
751 {0 , 0xfe, 0 , 4, "Difficulty" },
752 {0x12, 0x01, 0x06, 0x04, "Easy" },
753 {0x12, 0x01, 0x06, 0x06, "Medium" },
754 {0x12, 0x01, 0x06, 0x02, "Hard" },
755 {0x12, 0x01, 0x06, 0x00, "Hardest" },
756 };
757
758 STDDIPINFO(Ssonicbr)
759
760 static struct BurnDIPInfo OopartsDIPList[]=
761 {
762 {0x15, 0xff, 0xff, 0xff, NULL },
763 {0x16, 0xff, 0xff, 0xfe, NULL },
764
765 coinage_dips(0x15)
766
767 {0 , 0xfe, 0 , 2, "Demo Sounds" },
768 {0x16, 0x01, 0x01, 0x01, "Off" },
769 {0x16, 0x01, 0x01, 0x00, "On" },
770
771 {0 , 0xfe, 0 , 4, "Lives" },
772 {0x16, 0x01, 0x06, 0x04, "2" },
773 {0x16, 0x01, 0x06, 0x06, "3" },
774 {0x16, 0x01, 0x06, 0x02, "4" },
775 {0x16, 0x01, 0x06, 0x00, "5" },
776
777 {0 , 0xfe, 0 , 4, "Difficulty" },
778 {0x16, 0x01, 0x18, 0x10, "Easy" },
779 {0x16, 0x01, 0x18, 0x18, "Medium" },
780 {0x16, 0x01, 0x18, 0x08, "Hard" },
781 {0x16, 0x01, 0x18, 0x00, "Hardest" },
782
783 {0 , 0xfe, 0 , 4, "Region" },
784 {0x16, 0x01, 0x60, 0x60, "Japan" },
785 {0x16, 0x01, 0x60, 0x40, "USA" },
786 {0x16, 0x01, 0x60, 0x20, "Export" },
787 {0x16, 0x01, 0x60, 0x00, "Export" },
788 };
789
790 STDDIPINFO(Ooparts)
791
792 static struct BurnDIPInfo PuyoDIPList[]=
793 {
794 {0x11, 0xff, 0xff, 0xff, NULL },
795 {0x12, 0xff, 0xff, 0xfd, NULL },
796
797 coinage_dips(0x11)
798
799 {0 , 0xfe, 0 , 2, "Demo Sounds" },
800 {0x12, 0x01, 0x02, 0x02, "Off" },
801 {0x12, 0x01, 0x02, 0x00, "On" },
802
803 {0 , 0xfe, 0 , 2, "VS. Mode Credits/Match" },
804 {0x12, 0x01, 0x04, 0x04, "1" },
805 {0x12, 0x01, 0x04, 0x00, "3" },
806
807 {0 , 0xfe, 0 , 4, "1P Mode Difficulty" },
808 {0x12, 0x01, 0x18, 0x10, "Easy" },
809 {0x12, 0x01, 0x18, 0x18, "Medium" },
810 {0x12, 0x01, 0x18, 0x08, "Hard" },
811 {0x12, 0x01, 0x18, 0x00, "Hardest" },
812
813 {0 , 0xfe, 0 , 2, "Moving Seat" },
814 {0x12, 0x01, 0x80, 0x80, "No Use" },
815 {0x12, 0x01, 0x80, 0x00, "In Use" },
816 };
817
818 STDDIPINFO(Puyo)
819
820 static struct BurnDIPInfo IchirDIPList[]=
821 {
822 {0x11, 0xff, 0xff, 0xff, NULL },
823 {0x12, 0xff, 0xff, 0xfe, NULL },
824
825 coinage_dips(0x11)
826
827 {0 , 0xfe, 0 , 2, "Demo Sounds" },
828 {0x12, 0x01, 0x01, 0x01, "Off" },
829 {0x12, 0x01, 0x01, 0x00, "On" },
830
831 {0 , 0xfe, 0 , 4, "Difficulty" },
832 {0x12, 0x01, 0x06, 0x04, "Easy" },
833 {0x12, 0x01, 0x06, 0x06, "Medium" },
834 {0x12, 0x01, 0x06, 0x02, "Hard" },
835 {0x12, 0x01, 0x06, 0x00, "Hardest" },
836 };
837
838 STDDIPINFO(Ichir)
839
840 static struct BurnDIPInfo WwmarineDIPList[]=
841 {
842 {0x09, 0xff, 0xff, 0xff, NULL },
843 {0x0a, 0xff, 0xff, 0xfc, NULL },
844
845 coinage_dips(0x09)
846
847 {0 , 0xfe, 0 , 4, "Demo Sound Interval" },
848 {0x0a, 0x01, 0x03, 0x00, "Off" },
849 {0x0a, 0x01, 0x03, 0x01, "Every 3 Demo Cycles" },
850 {0x0a, 0x01, 0x03, 0x02, "Every 2 Demo Cycles" },
851 {0x0a, 0x01, 0x03, 0x03, "On" },
852
853 {0 , 0xfe, 0 , 2, "Capsule Mode" },
854 {0x0a, 0x01, 0x04, 0x00, "Off" },
855 {0x0a, 0x01, 0x04, 0x04, "On" },
856
857 {0 , 0xfe, 0 , 2, "Credit Mode" },
858 {0x0a, 0x01, 0x10, 0x10, "Off" },
859 {0x0a, 0x01, 0x10, 0x00, "On" },
860 };
861
862 STDDIPINFO(Wwmarine)
863
864 static struct BurnDIPInfo SonicfgtDIPList[]=
865 {
866 {0x09, 0xff, 0xff, 0xff, NULL },
867 {0x0a, 0xff, 0xff, 0xff, NULL },
868
869 coinage_dips(0x09)
870
871 {0 , 0xfe, 0 , 2, "Credit Mode" },
872 {0x0a, 0x01, 0x01, 0x01, "Off" },
873 {0x0a, 0x01, 0x01, 0x00, "On" },
874 };
875
876 STDDIPINFO(Sonicfgt)
877
878 static struct BurnDIPInfo PotopotoDIPList[]=
879 {
880 {0x11, 0xff, 0xff, 0xff, NULL },
881 {0x12, 0xff, 0xff, 0xfd, NULL },
882
883 coinage_dips(0x11)
884
885 {0 , 0xfe, 0 , 2, "Credits to Start" },
886 {0x12, 0x01, 0x01, 0x01, "1" },
887 {0x12, 0x01, 0x01, 0x00, "2" },
888
889 {0 , 0xfe, 0 , 2, "Demo Sounds" },
890 {0x12, 0x01, 0x02, 0x02, "Off" },
891 {0x12, 0x01, 0x02, 0x00, "On" },
892
893 {0 , 0xfe, 0 , 2, "Coin Chute Type" },
894 {0x12, 0x01, 0x04, 0x04, "Common" },
895 {0x12, 0x01, 0x04, 0x00, "Individual" },
896
897 {0 , 0xfe, 0 , 2, "Credits to Continue" },
898 {0x12, 0x01, 0x08, 0x08, "1" },
899 {0x12, 0x01, 0x08, 0x00, "2" },
900
901 {0 , 0xfe, 0 , 2, "Buy-In" },
902 {0x12, 0x01, 0x10, 0x10, "No" },
903 {0x12, 0x01, 0x10, 0x00, "Yes" },
904
905 {0 , 0xfe, 0 , 4, "Difficulty" },
906 {0x12, 0x01, 0x60, 0x40, "Easy" },
907 {0x12, 0x01, 0x60, 0x60, "Medium" },
908 {0x12, 0x01, 0x60, 0x20, "Hard" },
909 {0x12, 0x01, 0x60, 0x00, "Hardest" },
910
911 {0 , 0xfe, 0 , 2, "Moving Seat" },
912 {0x12, 0x01, 0x80, 0x80, "No Use" },
913 {0x12, 0x01, 0x80, 0x00, "In Use" },
914 };
915
916 STDDIPINFO(Potopoto)
917
918 static struct BurnDIPInfo Puyopuy2DIPList[]=
919 {
920 {0x13, 0xff, 0xff, 0xff, NULL },
921 {0x14, 0xff, 0xff, 0xfd, NULL },
922
923 coinage_dips(0x13)
924
925 {0 , 0xfe, 0 , 2, "Rannyu Off Button" },
926 {0x14, 0x01, 0x01, 0x01, "Use" },
927 {0x14, 0x01, 0x01, 0x00, "No Use" },
928
929 {0 , 0xfe, 0 , 2, "Demo Sounds" },
930 {0x14, 0x01, 0x02, 0x02, "Off" },
931 {0x14, 0x01, 0x02, 0x00, "On" },
932
933 {0 , 0xfe, 0 , 2, "Turn Direction" },
934 {0x14, 0x01, 0x04, 0x04, "1:Right 2:Left" },
935 {0x14, 0x01, 0x04, 0x00, "1:Left 2:Right" },
936
937 {0 , 0xfe, 0 , 4, "Difficulty" },
938 {0x14, 0x01, 0x18, 0x10, "Easy" },
939 {0x14, 0x01, 0x18, 0x18, "Medium" },
940 {0x14, 0x01, 0x18, 0x08, "Hard" },
941 {0x14, 0x01, 0x18, 0x00, "Hardest" },
942
943 {0 , 0xfe, 0 , 4, "VS Mode Match/1 Play" },
944 {0x14, 0x01, 0x60, 0x60, "1" },
945 {0x14, 0x01, 0x60, 0x40, "2" },
946 {0x14, 0x01, 0x60, 0x20, "3" },
947 {0x14, 0x01, 0x60, 0x00, "4" },
948
949 {0 , 0xfe, 0 , 2, "Battle Start credit" },
950 {0x14, 0x01, 0x80, 0x00, "1" },
951 {0x14, 0x01, 0x80, 0x80, "2" },
952 };
953
954 STDDIPINFO(Puyopuy2)
955
956 static struct BurnDIPInfo ZunkyouDIPList[]=
957 {
958 {0x13, 0xff, 0xff, 0xff, NULL },
959 {0x14, 0xff, 0xff, 0xef, NULL },
960
961 coinage_dips(0x13)
962
963 {0 , 0xfe, 0 , 2, "Game Difficulty 1" },
964 {0x14, 0x01, 0x01, 0x01, "Medium" },
965 {0x14, 0x01, 0x01, 0x00, "Hard" },
966
967 {0 , 0xfe, 0 , 2, "Game Difficulty 2" },
968 {0x14, 0x01, 0x02, 0x02, "Medium" },
969 {0x14, 0x01, 0x02, 0x00, "Hard" },
970
971 {0 , 0xfe, 0 , 4, "Lives" },
972 {0x14, 0x01, 0x0c, 0x08, "1" },
973 {0x14, 0x01, 0x0c, 0x04, "2" },
974 {0x14, 0x01, 0x0c, 0x0c, "3" },
975 {0x14, 0x01, 0x0c, 0x00, "5" },
976
977 {0 , 0xfe, 0 , 2, "Demo Sounds" },
978 {0x14, 0x01, 0x10, 0x10, "Off" },
979 {0x14, 0x01, 0x10, 0x00, "On" },
980 };
981
982 STDDIPINFO(Zunkyou)
983
984 static struct BurnDIPInfo HeadonchDIPList[]=
985 {
986 {0x11, 0xff, 0xff, 0xff, NULL },
987 {0x12, 0xff, 0xff, 0xfe, NULL },
988
989 coinage_dips(0x11)
990
991 {0 , 0xfe, 0 , 2, "Demo Sounds" },
992 {0x12, 0x01, 0x01, 0x01, "Off" },
993 {0x12, 0x01, 0x01, 0x00, "On" },
994
995 {0 , 0xfe, 0 , 4, "Difficulty" },
996 {0x12, 0x01, 0x06, 0x04, "Easy" },
997 {0x12, 0x01, 0x06, 0x06, "Medium" },
998 {0x12, 0x01, 0x06, 0x02, "Hard" },
999 {0x12, 0x01, 0x06, 0x00, "Hardest" },
1000
1001 {0 , 0xfe, 0 , 4, "Lives" },
1002 {0x12, 0x01, 0x18, 0x10, "2" },
1003 {0x12, 0x01, 0x18, 0x18, "3" },
1004 {0x12, 0x01, 0x18, 0x08, "4" },
1005 {0x12, 0x01, 0x18, 0x00, "5" },
1006 };
1007
STDDIPINFO(Headonch)1008 STDDIPINFO(Headonch)
1009
1010 static UINT16 palette_read(UINT16 offset)
1011 {
1012 offset = (offset >> 1) & 0x1ff;
1013 UINT16 *ram = (UINT16*)DrvPalRAM;
1014
1015 if (alt_palette_mode)
1016 offset = ((offset << 1) & 0x100) | ((offset << 2) & 0x80) | ((~offset >> 2) & 0x40) | ((offset >> 1) & 0x20) | (offset & 0x1f);
1017
1018 return ram[offset + palette_bank * 0x200];
1019 }
1020
palette_update(UINT16 offset)1021 static void palette_update(UINT16 offset)
1022 {
1023 UINT16 *ram = (UINT16*)DrvPalRAM;
1024
1025 INT32 data = ram[offset];
1026
1027 INT32 r = ((data << 1) & 0x1e) | ((data >> 12) & 0x01);
1028 INT32 g = ((data >> 3) & 0x1e) | ((data >> 13) & 0x01);
1029 INT32 b = ((data >> 7) & 0x1e) | ((data >> 14) & 0x01);
1030 DrvPalette[offset + 0x0000] = BurnHighCol(pal5bit(r), pal5bit(g), pal5bit(b), 0);
1031
1032 INT32 tmpr = r >> 1;
1033 INT32 tmpg = g >> 1;
1034 INT32 tmpb = b >> 1;
1035
1036 DrvPalette[offset + 0x0800] = BurnHighCol(pal5bit(tmpr), pal5bit(tmpg), pal5bit(tmpb), 0);
1037 DrvPalette[offset + 0x1800] = BurnHighCol(pal5bit(tmpr), pal5bit(tmpg), pal5bit(tmpb), 0); // shadow + hilight = shadow?
1038
1039 tmpr = tmpr | 0x10;
1040 tmpg = tmpg | 0x10;
1041 tmpb = tmpb | 0x10;
1042
1043 DrvPalette[offset + 0x1000] = BurnHighCol(pal5bit(tmpr), pal5bit(tmpg), pal5bit(tmpb), 0);
1044 }
1045
palette_write(UINT16 offset,UINT16 data,UINT16 mem_mask)1046 static void palette_write(UINT16 offset, UINT16 data, UINT16 mem_mask)
1047 {
1048 offset = (offset >> 1) & 0x1ff;
1049
1050 if (alt_palette_mode)
1051 offset = ((offset << 1) & 0x100) | ((offset << 2) & 0x80) | ((~offset >> 2) & 0x40) | ((offset >> 1) & 0x20) | (offset & 0x1f);
1052 offset += palette_bank * 0x200;
1053
1054 UINT16 *ram = (UINT16*)DrvPalRAM;
1055
1056 ram[offset] = (ram[offset] & ~mem_mask) | (data & mem_mask);
1057
1058 palette_update(offset);
1059 }
1060
recompute_palette_tables()1061 static void recompute_palette_tables()
1062 {
1063 for (INT32 i = 0; i < 4; i++)
1064 {
1065 INT32 bgpal = 0x000 + bg_palbase * 0x40 + i * 0x10;
1066 INT32 sppal = 0x100 + sp_palbase * 0x40 + i * 0x10;
1067
1068 if (!alt_palette_mode)
1069 {
1070 SegaC2BgPalLookup[i] = 0x200 * palette_bank + bgpal;
1071 SegaC2SpPalLookup[i] = 0x200 * palette_bank + sppal;
1072 }
1073 else
1074 {
1075 SegaC2BgPalLookup[i] = 0x200 * palette_bank + ((bgpal << 1) & 0x180) + ((~bgpal >> 2) & 0x40) + (bgpal & 0x30);
1076 SegaC2SpPalLookup[i] = 0x200 * palette_bank + ((~sppal << 2) & 0x100) + ((sppal << 2) & 0x80) + ((~sppal >> 2) & 0x40) + ((sppal >> 2) & 0x20) + (sppal & 0x10);
1077 }
1078 }
1079 }
1080
protection_write(UINT8 data)1081 static void protection_write(UINT8 data)
1082 {
1083 if (is_tfrceacb) return;
1084
1085 INT32 new_sp_palbase = (data >> 2) & 3;
1086 INT32 new_bg_palbase = data & 3;
1087 INT32 table_index = (prot_write_buf << 4) | prot_read_buf;
1088
1089 prot_write_buf = data & 0x0f;
1090 prot_read_buf = protection_read_cb(table_index);
1091
1092 if (new_sp_palbase != sp_palbase || new_bg_palbase != bg_palbase)
1093 {
1094 sp_palbase = new_sp_palbase;
1095 bg_palbase = new_bg_palbase;
1096 //bprintf(0, _T("sp %x bg %x palbases. (scanline: %d\tframe: %d)\n"), sp_palbase, bg_palbase, Scanline, nCurrentFrame);
1097 recompute_palette_tables();
1098 }
1099 }
1100
io_porth_write(UINT8 data)1101 static void io_porth_write(UINT8 data)
1102 {
1103 INT32 newbank = data & 3;
1104 if (newbank != palette_bank)
1105 {
1106 //bprintf(0, _T("palette bank: %x (scanline: %d\tframe: %d)\n"), newbank, Scanline, nCurrentFrame);
1107 palette_bank = newbank;
1108 recompute_palette_tables();
1109 }
1110 if (sound_rom_length)
1111 {
1112 sound_bank = (data >> 2) & (((sound_rom_length) / 0x20000) - 1);
1113 memcpy (DrvSndROM + 0x80000, DrvSndROM + (sound_bank * 0x20000), 0x20000);
1114 }
1115 }
1116
sega_315_5296_read(UINT8 offset)1117 static UINT8 sega_315_5296_read(UINT8 offset)
1118 {
1119 if (offset <= 7) {
1120 if (dir & dir_override & (1 << offset)) {
1121 return output_latch[offset];
1122 }
1123
1124 if (offset == 2) {
1125 if (sound_rom_length == 0) return 0xff;
1126 return UPD7759BusyRead(0) ? 0xff : 0xbf;
1127 }
1128
1129 return DrvInputs[offset];
1130 }
1131 if (offset <= 0x0b)
1132 {
1133 char *s = "SEGA";
1134 return s[offset - 8];
1135 }
1136 if (offset & 1) {
1137 return dir;
1138 } else {
1139 return iocnt;
1140 }
1141
1142 return 0xff;
1143 }
1144
sega_315_5296_write(UINT8 offset,UINT8 data)1145 void sega_315_5296_write(UINT8 offset, UINT8 data)
1146 {
1147 offset &= 0x3f;
1148 if (offset <= 0x07) {
1149 if (dir & (1 << offset)) {
1150 // if (offset == 0x03) return; // port D (coin counters)
1151 if (offset == 0x07) io_porth_write(data);
1152 }
1153 output_latch[offset] = data;
1154 return;
1155 }
1156 if (offset == 0x0e) {
1157 // for (INT32 i = 0; i < 3; i++) out_cnt_callback[i]((data >> i) & 1);
1158 if (sound_rom_length) {
1159 UPD7759ResetWrite(0, (data >> 1) & 1); // cnt1
1160 }
1161 iocnt = data;
1162 return;
1163 }
1164 if (offset == 0x0f) {
1165 for (INT32 i = 0; i < 8; i++) {
1166 if ((dir ^ data) & (1 << i)) {
1167 // if (i == 0x03) continue; // port A (coin counters)
1168 if (i == 0x07) io_porth_write((data & (1 << i)) ? output_latch[i] : 0);
1169 }
1170 }
1171 dir = data;
1172 return;
1173 }
1174 }
1175
1176 //---------------------------------------------------------------
1177 // Megadrive Video Port Read Write
1178 //---------------------------------------------------------------
1179
VideoWrite128(UINT32 a,UINT16 d)1180 static void VideoWrite128(UINT32 a, UINT16 d)
1181 {
1182 a = ((a & 2) >> 1) | ((a & 0x400) >> 9) | (a & 0x3FC) | ((a & 0x1F800) >> 1);
1183 ((UINT8 *)RamVid)[a] = d;
1184 }
1185
GetDmaLength()1186 static INT32 GetDmaLength()
1187 {
1188 INT32 len = 0;
1189 // 16-bit words to transfer:
1190 len = RamVReg->reg[0x13];
1191 len |= RamVReg->reg[0x14]<<8;
1192 // Charles MacDonald:
1193 len = ((len - 1) & 0xffff) + 1;
1194 return len;
1195 }
1196
1197 // dma2vram settings are just hacks to unglitch Legend of Galahad (needs <= 104 to work)
1198 // same for Outrunners (92-121, when active is set to 24)
1199 // 96 is VR hack
1200 static const INT32 dma_timings[] = {
1201 167, 167, 166, 83, // vblank: 32cell: dma2vram dma2[vs|c]ram vram_fill vram_copy
1202 103, 205, 204, 102, // vblank: 40cell:
1203 16, 16, 15, 8, // active: 32cell:
1204 24, 18, 17, 9 // ...
1205 };
1206
1207 static const INT32 dma_bsycles[] = {
1208 (488<<8)/167, (488<<8)/167, (488<<8)/166, (488<<8)/83,
1209 (488<<8)/103, (488<<8)/233, (488<<8)/204, (488<<8)/102,
1210 (488<<8)/16, (488<<8)/16, (488<<8)/15, (488<<8)/8,
1211 (488<<8)/24, (488<<8)/18, (488<<8)/17, (488<<8)/9
1212 };
1213
CheckDMA(void)1214 static UINT32 CheckDMA(void)
1215 {
1216 INT32 burn = 0, xfers_can, dma_op = RamVReg->reg[0x17]>>6; // see gens for 00 and 01 modes
1217 INT32 xfers = dma_xfers;
1218 INT32 dma_op1;
1219
1220 if(!(dma_op&2)) dma_op = (RamVReg->type == 1) ? 0 : 1; // setting dma_timings offset here according to Gens
1221 dma_op1 = dma_op;
1222 if(RamVReg->reg[12] & 1) dma_op |= 4; // 40 cell mode?
1223 if(!(RamVReg->status&8)&&(RamVReg->reg[1]&0x40)) dma_op|=8; // active display?
1224 xfers_can = dma_timings[dma_op];
1225
1226 if(xfers <= xfers_can)
1227 {
1228 if(dma_op&2) RamVReg->status&=~2; // dma no longer busy
1229 else {
1230 burn = xfers * dma_bsycles[dma_op] >> 8; // have to be approximate because can't afford division..
1231 }
1232 dma_xfers = 0;
1233 } else {
1234 if(!(dma_op&2)) burn = 488;
1235 dma_xfers -= xfers_can;
1236 }
1237
1238 //elprintf(EL_VDPDMA, "~Dma %i op=%i can=%i burn=%i [%i]", Pico.m.dma_xfers, dma_op1, xfers_can, burn, SekCyclesDone());
1239 //dprintf("~aim: %i, cnt: %i", SekCycleAim, SekCycleCnt);
1240 //bprintf(0, _T("burn[%d]"), burn);
1241 return burn;
1242 }
1243
DMABURN()1244 static INT32 DMABURN() { // add cycles to the 68k cpu
1245 if (dma_xfers) {
1246 return CheckDMA();
1247 } else return 0;
1248 }
1249
DmaSlow(INT32 len)1250 static void DmaSlow(INT32 len)
1251 {
1252 UINT16 *pd=0, *pdend, *r;
1253 UINT32 a = RamVReg->addr, a2, d;
1254 UINT8 inc = RamVReg->reg[0xf];
1255 UINT32 source;
1256 UINT32 fromrom = 0;
1257
1258 source = RamVReg->reg[0x15] << 1;
1259 source |= RamVReg->reg[0x16] << 9;
1260 source |= RamVReg->reg[0x17] << 17;
1261
1262 //dprintf("DmaSlow[%i] %06x->%04x len %i inc=%i blank %i [%i|%i]", Pico.video.type, source, a, len, inc,
1263 // (Pico.video.status&8)||!(Pico.video.reg[1]&0x40), Pico.m.scanline, SekCyclesDone());
1264
1265 dma_xfers += len;
1266
1267 INT32 dmab = CheckDMA();
1268 m68k_ICount -= dmab;
1269
1270 #ifdef CYCDBUG
1271 // bprintf(0, _T("dma @ ln %d cyc %d, burnt: %d.\n"), Scanline, SekCyclesLine(), dmab);
1272 #endif
1273 //SekCyclesBurnRun(dmab);
1274
1275 const INT32 RomSize = 0x200000;
1276
1277 if ((source & 0xe00000) == 0xe00000) { // RAM
1278 pd = (UINT16 *)(Drv68KRAM + (source & 0xfffe));
1279 pdend = (UINT16 *)(Drv68KRAM + 0x10000);
1280 } else if( source < RomSize) { // ROM
1281 fromrom = 1;
1282 source &= ~1;
1283 pd = (UINT16 *)(Drv68KROM + source);
1284 pdend = (UINT16 *)(Drv68KROM + RomSize);
1285 } else return; // Invalid source address
1286
1287 // overflow protection, might break something..
1288 if (len > pdend - pd) {
1289 len = pdend - pd;
1290 //bprintf(0, _T("DmaSlow() overflow(!).\n"));
1291 }
1292
1293 switch ( RamVReg->type ) {
1294 case 1: // vram
1295 r = RamVid;
1296 for(; len; len--) {
1297 d = *pd++;
1298 if(a&1) d=(d<<8)|(d>>8);
1299 r[a>>1] = (UINT16)d; // will drop the upper bits
1300 // AutoIncrement
1301 a = (UINT16)(a+inc);
1302 // didn't src overlap?
1303 //if(pd >= pdend) pd -= 0x8000; // should be good for RAM, bad for ROM
1304 }
1305
1306 RamVReg->rendstatus |= PDRAW_DIRTY_SPRITES;
1307 break;
1308
1309 case 3: // cram
1310 //dprintf("DmaSlow[%i] %06x->%04x len %i inc=%i blank %i [%i|%i]", Pico.video.type, source, a, len, inc,
1311 // (Pico.video.status&8)||!(Pico.video.reg[1]&0x40), Pico.m.scanline, SekCyclesDone());
1312 for(a2 = a&0x7f; len; len--) {
1313 d = *pd++;
1314 //CalcCol( a2>>1, BURN_ENDIAN_SWAP_INT16(d) );
1315 //pd++;
1316 // AutoIncrement
1317 a2+=inc;
1318 // didn't src overlap?
1319 //if(pd >= pdend) pd-=0x8000;
1320 // good dest?
1321 if(a2 >= 0x80) break; // Todds Adventures in Slime World / Andre Agassi tennis
1322 }
1323 a = (a&0xff00) | a2;
1324 break;
1325
1326 case 5: // vsram[a&0x003f]=d;
1327 r = RamSVid;
1328 for(a2=a&0x7f; len; len--) {
1329 d = *pd++;
1330 r[a2>>1] = (UINT16)d;
1331 // AutoIncrement
1332 a2+=inc;
1333 // didn't src overlap?
1334 //if(pd >= pdend) pd-=0x8000;
1335 // good dest?
1336 if(a2 >= 0x80) break;
1337 }
1338 a=(a&0xff00)|a2;
1339 break;
1340
1341 case 0x81: // vram 128k
1342 a |= RamVReg->addr_u << 16;
1343 for(; len; len--)
1344 {
1345 VideoWrite128(a, *pd++);
1346 // AutoIncrement
1347 a = (a + inc) & 0x1ffff;
1348 }
1349 RamVReg->addr_u = a >> 16;
1350 break;
1351
1352 }
1353 // remember addr
1354 RamVReg->reg[0x13] = RamVReg->reg[0x14] = 0; // Dino Dini's Soccer (E) (by Haze)
1355 RamVReg->addr = (UINT16)a;
1356 }
1357
DmaCopy(INT32 len)1358 static void DmaCopy(INT32 len)
1359 {
1360 UINT8 * vr = (UINT8 *) RamVid;
1361 UINT8 * vrs;
1362 UINT16 a = RamVReg->addr;
1363 UINT8 inc = RamVReg->reg[0xf];
1364 INT32 source;
1365
1366 //dprintf("DmaCopy len %i [%i|%i]", len, Pico.m.scanline, SekCyclesDone());
1367
1368 RamVReg->status |= 2; // dma busy
1369 dma_xfers += len;
1370
1371 source = RamVReg->reg[0x15];
1372 source |= RamVReg->reg[0x16]<<8;
1373 vrs = vr + source;
1374
1375 if (source+len > 0x10000)
1376 len = 0x10000 - source; // clip??
1377
1378 for(;len;len--) {
1379 vr[a] = *vrs++;
1380 // AutoIncrement
1381 a = (UINT16)(a + inc);
1382 }
1383 // remember addr
1384 RamVReg->addr = a;
1385 RamVReg->reg[0x13] = RamVReg->reg[0x14] = 0; // Dino Dini's Soccer (E) (by Haze)
1386 RamVReg->rendstatus |= PDRAW_DIRTY_SPRITES;
1387 }
1388
DmaFill(INT32 data)1389 static void DmaFill(INT32 data)
1390 {
1391 INT32 len = GetDmaLength();
1392 UINT8 *vr = (UINT8 *) RamVid;
1393 UINT8 high = (UINT8) (data >> 8);
1394 UINT16 a = RamVReg->addr;
1395 UINT8 inc = RamVReg->reg[0xf];
1396
1397 //dprintf("DmaFill len %i inc %i [%i|%i]", len, inc, Pico.m.scanline, SekCyclesDone());
1398
1399 // from Charles MacDonald's genvdp.txt:
1400 // Write lower byte to address specified
1401 RamVReg->status |= 2; // dma busy
1402 dma_xfers += len;
1403 vr[a] = (UINT8) data;
1404 a = (UINT16)(a+inc);
1405
1406 if(!inc) len=1;
1407
1408 for(;len;len--) {
1409 // Write upper byte to adjacent address
1410 // (here we are byteswapped, so address is already 'adjacent')
1411 vr[a] = high;
1412 // Increment address register
1413 a = (UINT16)(a+inc);
1414 }
1415 // remember addr
1416 RamVReg->addr = a;
1417 // update length
1418 RamVReg->reg[0x13] = RamVReg->reg[0x14] = 0; // Dino Dini's Soccer (E) (by Haze)
1419
1420 RamVReg->rendstatus |= PDRAW_DIRTY_SPRITES;
1421 }
1422
CommandChange()1423 static void CommandChange()
1424 {
1425 //struct PicoVideo *pvid=&Pico.video;
1426 UINT32 cmd = RamVReg->command;
1427 UINT32 addr = 0;
1428
1429 // Get type of transfer 0xc0000030 (v/c/vsram read/write)
1430 RamVReg->type = (UINT8)(((cmd >> 2) & 0xc) | (cmd >> 30));
1431 if (RamVReg->type == 1) { // vram
1432 RamVReg->type |= RamVReg->reg[1] & 0x80; // 128k
1433 }
1434
1435 // Get address 0x3fff0003
1436 addr = (cmd >> 16) & 0x3fff;
1437 addr |= (cmd << 14) & 0xc000;
1438 RamVReg->addr = (UINT16)addr;
1439 RamVReg->addr_u = (UINT8)((cmd >> 2) & 1);
1440
1441 //dprintf("addr set: %04x", addr);
1442
1443 // Check for dma:
1444 if (cmd & 0x80) {
1445 // Command DMA
1446 if ((RamVReg->reg[1] & 0x10) == 0) return; // DMA not enabled
1447 INT32 len = GetDmaLength();
1448 switch ( RamVReg->reg[0x17]>>6 ) {
1449 case 0x00:
1450 case 0x01:
1451 DmaSlow(len); // 68000 to VDP
1452 break;
1453 case 0x03:
1454 DmaCopy(len); // VRAM Copy
1455 break;
1456 case 0x02: // DMA Fill Flag ???
1457 default:
1458 ;//bprintf(PRINT_NORMAL, _T("Video Command DMA Unknown %02x len %d\n"), RamVReg->reg[0x17]>>6, len);
1459 }
1460 }
1461 }
1462
1463 // H-counter table for hvcounter reads in 40col mode
1464 // based on Gens code
1465 static const UINT8 hcounts_40[] = {
1466 0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,
1467 0x0e,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x13,0x14,
1468 0x14,0x15,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,
1469 0x1b,0x1b,0x1c,0x1c,0x1d,0x1d,0x1d,0x1e,0x1e,0x1f,0x1f,0x20,0x20,0x20,0x21,0x21,
1470 0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x25,0x25,0x25,0x26,0x26,0x27,0x27,0x28,0x28,
1471 0x28,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2c,0x2c,0x2d,0x2d,0x2d,0x2e,0x2e,0x2f,
1472 0x2f,0x30,0x30,0x30,0x31,0x31,0x32,0x32,0x32,0x33,0x33,0x34,0x34,0x35,0x35,0x35,
1473 0x36,0x36,0x37,0x37,0x38,0x38,0x38,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,0x3c,0x3c,
1474 0x3d,0x3d,0x3d,0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x41,0x41,0x42,0x42,0x42,0x43,
1475 0x43,0x44,0x44,0x45,0x45,0x45,0x46,0x46,0x47,0x47,0x47,0x48,0x48,0x49,0x49,0x4a,
1476 0x4a,0x4a,0x4b,0x4b,0x4c,0x4c,0x4d,0x4d,0x4d,0x4e,0x4e,0x4f,0x4f,0x4f,0x50,0x50,
1477 0x51,0x51,0x52,0x52,0x52,0x53,0x53,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x57,0x57,
1478 0x57,0x58,0x58,0x59,0x59,0x5a,0x5a,0x5a,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,0x5e,
1479 0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x61,0x61,0x62,0x62,0x62,0x63,0x63,0x64,0x64,0x64,
1480 0x65,0x65,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b,
1481 0x6c,0x6c,0x6c,0x6d,0x6d,0x6e,0x6e,0x6f,0x6f,0x6f,0x70,0x70,0x71,0x71,0x71,0x72,
1482 0x72,0x73,0x73,0x74,0x74,0x74,0x75,0x75,0x76,0x76,0x77,0x77,0x77,0x78,0x78,0x79,
1483 0x79,0x79,0x7a,0x7a,0x7b,0x7b,0x7c,0x7c,0x7c,0x7d,0x7d,0x7e,0x7e,0x7f,0x7f,0x7f,
1484 0x80,0x80,0x81,0x81,0x81,0x82,0x82,0x83,0x83,0x84,0x84,0x84,0x85,0x85,0x86,0x86,
1485 0x86,0x87,0x87,0x88,0x88,0x89,0x89,0x89,0x8a,0x8a,0x8b,0x8b,0x8c,0x8c,0x8c,0x8d,
1486 0x8d,0x8e,0x8e,0x8e,0x8f,0x8f,0x90,0x90,0x91,0x91,0x91,0x92,0x92,0x93,0x93,0x94,
1487 0x94,0x94,0x95,0x95,0x96,0x96,0x96,0x97,0x97,0x98,0x98,0x99,0x99,0x99,0x9a,0x9a,
1488 0x9b,0x9b,0x9b,0x9c,0x9c,0x9d,0x9d,0x9e,0x9e,0x9e,0x9f,0x9f,0xa0,0xa0,0xa1,0xa1,
1489 0xa1,0xa2,0xa2,0xa3,0xa3,0xa3,0xa4,0xa4,0xa5,0xa5,0xa6,0xa6,0xa6,0xa7,0xa7,0xa8,
1490 0xa8,0xa9,0xa9,0xa9,0xaa,0xaa,0xab,0xab,0xab,0xac,0xac,0xad,0xad,0xae,0xae,0xae,
1491 0xaf,0xaf,0xb0,0xb0,0xe4,0xe4,0xe4,0xe5,0xe5,0xe6,0xe6,0xe6,0xe7,0xe7,0xe8,0xe8,
1492 0xe9,0xe9,0xe9,0xea,0xea,0xeb,0xeb,0xeb,0xec,0xec,0xed,0xed,0xee,0xee,0xee,0xef,
1493 0xef,0xf0,0xf0,0xf1,0xf1,0xf1,0xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf5,0xf5,0xf6,
1494 0xf6,0xf6,0xf7,0xf7,0xf8,0xf8,0xf9,0xf9,0xf9,0xfa,0xfa,0xfb,0xfb,0xfb,0xfc,0xfc,
1495 0xfd,0xfd,0xfe,0xfe,0xfe,0xff,0xff,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,
1496 0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x0a,
1497 0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x10,
1498 };
1499
1500 // H-counter table for hvcounter reads in 32col mode
1501 static const UINT8 hcounts_32[] = {
1502 0x05,0x05,0x05,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x09,0x0a,0x0a,
1503 0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x0f,0x10,
1504 0x10,0x10,0x11,0x11,0x11,0x12,0x12,0x12,0x13,0x13,0x13,0x14,0x14,0x14,0x15,0x15,
1505 0x15,0x16,0x16,0x17,0x17,0x17,0x18,0x18,0x18,0x19,0x19,0x19,0x1a,0x1a,0x1a,0x1b,
1506 0x1b,0x1b,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1e,0x1e,0x1f,0x1f,0x1f,0x20,0x20,0x20,
1507 0x21,0x21,0x21,0x22,0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x24,0x25,0x25,0x26,0x26,
1508 0x26,0x27,0x27,0x27,0x28,0x28,0x28,0x29,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2b,
1509 0x2c,0x2c,0x2c,0x2d,0x2d,0x2e,0x2e,0x2e,0x2f,0x2f,0x2f,0x30,0x30,0x30,0x31,0x31,
1510 0x31,0x32,0x32,0x32,0x33,0x33,0x33,0x34,0x34,0x34,0x35,0x35,0x36,0x36,0x36,0x37,
1511 0x37,0x37,0x38,0x38,0x38,0x39,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,0x3b,0x3c,0x3c,
1512 0x3d,0x3d,0x3d,0x3e,0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x40,0x41,0x41,0x41,0x42,
1513 0x42,0x42,0x43,0x43,0x43,0x44,0x44,0x45,0x45,0x45,0x46,0x46,0x46,0x47,0x47,0x47,
1514 0x48,0x48,0x48,0x49,0x49,0x49,0x4a,0x4a,0x4a,0x4b,0x4b,0x4b,0x4c,0x4c,0x4d,0x4d,
1515 0x4d,0x4e,0x4e,0x4e,0x4f,0x4f,0x4f,0x50,0x50,0x50,0x51,0x51,0x51,0x52,0x52,0x52,
1516 0x53,0x53,0x53,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x56,0x57,0x57,0x57,0x58,0x58,
1517 0x58,0x59,0x59,0x59,0x5a,0x5a,0x5a,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x5e,
1518 0x5e,0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x60,0x61,0x61,0x61,0x62,0x62,0x62,0x63,0x63,
1519 0x64,0x64,0x64,0x65,0x65,0x65,0x66,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x68,0x69,
1520 0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b,0x6c,0x6c,0x6c,0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,
1521 0x6f,0x6f,0x6f,0x70,0x70,0x70,0x71,0x71,0x71,0x72,0x72,0x72,0x73,0x73,0x74,0x74,
1522 0x74,0x75,0x75,0x75,0x76,0x76,0x76,0x77,0x77,0x77,0x78,0x78,0x78,0x79,0x79,0x79,
1523 0x7a,0x7a,0x7b,0x7b,0x7b,0x7c,0x7c,0x7c,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f,
1524 0x7f,0x80,0x80,0x80,0x81,0x81,0x81,0x82,0x82,0x83,0x83,0x83,0x84,0x84,0x84,0x85,
1525 0x85,0x85,0x86,0x86,0x86,0x87,0x87,0x87,0x88,0x88,0x88,0x89,0x89,0x89,0x8a,0x8a,
1526 0x8b,0x8b,0x8b,0x8c,0x8c,0x8c,0x8d,0x8d,0x8d,0x8e,0x8e,0x8e,0x8f,0x8f,0x8f,0x90,
1527 0x90,0x90,0x91,0x91,0xe8,0xe8,0xe8,0xe9,0xe9,0xe9,0xea,0xea,0xea,0xeb,0xeb,0xeb,
1528 0xec,0xec,0xec,0xed,0xed,0xed,0xee,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf0,0xf1,0xf1,
1529 0xf1,0xf2,0xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf4,0xf5,0xf5,0xf5,0xf6,0xf6,0xf6,
1530 0xf7,0xf7,0xf8,0xf8,0xf8,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfb,0xfb,0xfb,0xfc,0xfc,
1531 0xfc,0xfd,0xfd,0xfd,0xfe,0xfe,0xfe,0xff,0xff,0x00,0x00,0x00,0x01,0x01,0x01,0x02,
1532 0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x06,0x07,0x07,0x07,
1533 0x08,0x08,0x08,0x09,0x09,0x09,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0d,
1534 };
1535
MegadriveVideoReadWord(UINT32 sekAddress)1536 static UINT16 __fastcall MegadriveVideoReadWord(UINT32 sekAddress)
1537 {
1538 if (sekAddress > 0xC0001F)
1539 bprintf(PRINT_NORMAL, _T("Video Attempt to read word value of location %x\n"), sekAddress);
1540
1541 UINT16 res = 0;
1542
1543 switch (sekAddress & 0x1c) {
1544 case 0x00: // data
1545 switch (RamVReg->type) {
1546 case 0: res = BURN_ENDIAN_SWAP_INT16(RamVid [(RamVReg->addr >> 1) & 0x7fff]); break;
1547 case 4: res = BURN_ENDIAN_SWAP_INT16(RamSVid[(RamVReg->addr >> 1) & 0x003f]); break;
1548 case 8: res = BURN_ENDIAN_SWAP_INT16(RamPal [(RamVReg->addr >> 1) & 0x003f]); break;
1549 }
1550 RamVReg->addr += RamVReg->reg[0xf];
1551 break;
1552
1553 case 0x04: // command
1554 {
1555 UINT16 d = RamVReg->status;
1556 if (SekCyclesLine() >= (328) && SekCyclesLine() <= (460))
1557 d|=0x0004; // H-Blank (Sonic3 vs)
1558
1559 d |= ((RamVReg->reg[1]&0x40)^0x40) >> 3; // set V-Blank if display is disabled
1560 d |= (RamVReg->pending_ints&0x20)<<2; // V-int pending?
1561 if (d&0x100) RamVReg->status&=~0x100; // FIFO no longer full
1562 d |= (nCurrentFrame&1) ? 0x10 : 0x00;
1563
1564 RamVReg->pending = 0; // ctrl port reads clear write-pending flag (Charles MacDonald)
1565 return d;
1566 }
1567 break;
1568 case 0x08: // H-counter info
1569 {
1570 UINT32 d;
1571
1572 d = (SekCyclesLine()) & 0x1ff; // FIXME
1573
1574 if (RamVReg->reg[12]&1)
1575 d = hcounts_40[d];
1576 else d = hcounts_32[d];
1577
1578 //elprintf(EL_HVCNT, "hv: %02x %02x (%i) @ %06x", d, Pico.video.v_counter, SekCyclesDone(), SekPc);
1579 return d | (RamVReg->v_counter << 8);
1580 }
1581 break;
1582
1583 default:
1584 bprintf(PRINT_NORMAL, _T("Video Attempt to read word value of location %x, %x\n"), sekAddress, sekAddress & 0x1c);
1585 break;
1586 }
1587
1588 return res;
1589 }
1590
MegadriveVideoReadByte(UINT32 sekAddress)1591 static UINT8 __fastcall MegadriveVideoReadByte(UINT32 sekAddress)
1592 {
1593 // bprintf(PRINT_NORMAL, _T("Video Attempt to read byte value of location %x\n"), sekAddress);
1594 UINT16 res = MegadriveVideoReadWord(sekAddress & ~1);
1595 if ((sekAddress&1)==0) res >>= 8;
1596 return res & 0xff;
1597 }
1598
MegadriveVideoWriteWord(UINT32 sekAddress,UINT16 wordValue)1599 static void __fastcall MegadriveVideoWriteWord(UINT32 sekAddress, UINT16 wordValue)
1600 {
1601 if (sekAddress > 0xC0001F)
1602 bprintf(PRINT_NORMAL, _T("Video Attempt to write word value %x to location %x\n"), wordValue, sekAddress);
1603
1604 switch (sekAddress & 0x1c) {
1605 case 0x00: // data
1606 if (RamVReg->pending) {
1607 CommandChange();
1608 RamVReg->pending = 0;
1609 }
1610 if ((RamVReg->command & 0x80) && (RamVReg->reg[1]&0x10) && (RamVReg->reg[0x17]>>6)==2) {
1611
1612 DmaFill(wordValue);
1613
1614 } else {
1615
1616 // FIFO
1617 // preliminary FIFO emulation for Chaos Engine, The (E)
1618 if (!(RamVReg->status&8) && (RamVReg->reg[1]&0x40)) // active display?
1619 {
1620 RamVReg->status&=~0x200; // FIFO no longer empty
1621 RamVReg->lwrite_cnt++;
1622 if (RamVReg->lwrite_cnt >= 4) RamVReg->status|=0x100; // FIFO full
1623 if (RamVReg->lwrite_cnt > 4) {
1624 //SekRunAdjust(0-80);
1625 //SekIdle(80);
1626 //SekCyclesBurnRun(32);
1627 }
1628 //elprintf(EL_ASVDP, "VDP data write: %04x [%06x] {%i} #%i @ %06x", d, Pico.video.addr,
1629 // Pico.video.type, pvid->lwrite_cnt, SekPc);
1630 }
1631
1632 //UINT32 a=Pico.video.addr;
1633 switch (RamVReg->type) {
1634 case 1:
1635 // If address is odd, bytes are swapped (which game needs this?)
1636 // williams arcade greatest hits -dink
1637 if (RamVReg->addr & 1) {
1638 //bprintf(PRINT_NORMAL, _T("Video address is odd, bytes are swapped!!!\n"));
1639 wordValue = (wordValue<<8)|(wordValue>>8);
1640 }
1641 RamVid[(RamVReg->addr >> 1) & 0x7fff] = BURN_ENDIAN_SWAP_INT16(wordValue);
1642 RamVReg->rendstatus |= PDRAW_DIRTY_SPRITES;
1643 break;
1644 case 3:
1645 //Pico.m.dirtyPal = 1;
1646 //dprintf("w[%i] @ %04x, inc=%i [%i|%i]", Pico.video.type, a, Pico.video.reg[0xf], Pico.m.scanline, SekCyclesDone());
1647 //CalcCol((RamVReg->addr >> 1) & 0x003f, wordValue); // no cram in C2
1648 break;
1649 case 5:
1650 RamSVid[(RamVReg->addr >> 1) & 0x003f] = BURN_ENDIAN_SWAP_INT16(wordValue);
1651 break;
1652 case 0x81: {
1653 UINT32 a = RamVReg->addr | (RamVReg->addr_u << 16);
1654 VideoWrite128(a, wordValue);
1655 break;
1656 }
1657 }
1658 //dprintf("w[%i] @ %04x, inc=%i [%i|%i]", Pico.video.type, a, Pico.video.reg[0xf], Pico.m.scanline, SekCyclesDone());
1659 //AutoIncrement();
1660 RamVReg->addr += RamVReg->reg[0xf];
1661 }
1662 return;
1663
1664 case 0x04: // command
1665 if(RamVReg->pending) {
1666 // Low word of command:
1667 RamVReg->command &= 0xffff0000;
1668 RamVReg->command |= wordValue;
1669 RamVReg->pending = 0;
1670 CommandChange();
1671 } else {
1672 if((wordValue & 0xc000) == 0x8000) {
1673 INT32 num = (wordValue >> 8) & 0x1f;
1674 RamVReg->type = 0; // register writes clear command (else no Sega logo in Golden Axe II)
1675 if (num > 0x0a && !(RamVReg->reg[1] & 4)) {
1676 //bprintf(0, _T("%02x written to reg %02x in SMS mode @ %06x"), d, num, SekGetPC(-1));
1677 return;
1678 }
1679
1680 // Blank last line
1681 if (num == 1 && !(wordValue&0x40) && SekCyclesLine() <= (488-390)) {
1682 BlankedLine = 1;
1683 }
1684
1685 UINT8 oldreg = RamVReg->reg[num];
1686 RamVReg->reg[num] = wordValue & 0xff;
1687
1688 // update IRQ level (Lemmings, Wiz 'n' Liz intro, ... )
1689 // may break if done improperly:
1690 // International Superstar Soccer Deluxe (crash), Street Racer (logos), Burning Force (gfx), Fatal Rewind (hang), Sesame Street Counting Cafe
1691 if(num < 2 && !SekShouldInterrupt()) {
1692
1693 INT32 irq = 0;
1694 INT32 lines = (RamVReg->reg[1] & 0x20) | (RamVReg->reg[0] & 0x10);
1695 INT32 pints = (RamVReg->pending_ints&lines);
1696 if (pints & 0x20) irq = 6;
1697 else if (pints & 0x10) irq = 4;
1698
1699 if (pints) {
1700 SekSetVIRQLine(irq, CPU_IRQSTATUS_ACK);
1701 } else {
1702 if (irq != 0) SekSetVIRQLine(irq, CPU_IRQSTATUS_NONE);
1703 }
1704 }
1705
1706 if (num == 5) if (RamVReg->reg[num]^oldreg) RamVReg->rendstatus |= PDRAW_SPRITES_MOVED;
1707
1708 if (num == 11) {
1709 const UINT8 h_msks[4] = { 0x00, 0x07, 0xf8, 0xff };
1710 RamVReg->h_mask = h_msks[RamVReg->reg[11] & 3];
1711 }
1712 } else {
1713 // High word of command:
1714 RamVReg->command &= 0x0000ffff;
1715 RamVReg->command |= wordValue << 16;
1716 RamVReg->pending = 1;
1717 }
1718 }
1719 return;
1720
1721 case 0x10:
1722 case 0x14:
1723 // PSG Sound
1724 //bprintf(PRINT_NORMAL, _T("PSG Attempt to write word value %04x to location %08x\n"), wordValue, sekAddress);
1725 SN76496Write(0, wordValue & 0xFF);
1726 return;
1727
1728 }
1729 bprintf(0, _T("vdp unmapped write %X %X\n"), sekAddress, wordValue);
1730 }
1731
MegadriveVideoWriteByte(UINT32 sekAddress,UINT8 byteValue)1732 static void __fastcall MegadriveVideoWriteByte(UINT32 sekAddress, UINT8 byteValue)
1733 {
1734 //bprintf(PRINT_NORMAL, _T("Video Attempt to write byte value %x to location %x\n"), byteValue, sekAddress);
1735 MegadriveVideoWriteWord(sekAddress, (byteValue << 8) | byteValue);
1736 }
1737
segac2_main_write_word(UINT32 address,UINT16 data)1738 static void __fastcall segac2_main_write_word(UINT32 address, UINT16 data)
1739 {
1740 if ((address & 0xec0200) == 0x800000) {
1741 protection_write(data);
1742 return;
1743 }
1744
1745 if ((address & 0xec0200) == 0x800200) {
1746 enable_display = ~data & 1;
1747 if (!(data & 2)) prot_write_buf = prot_read_buf = 0;
1748 alt_palette_mode = ((~data & 4) >> 2);
1749 //bprintf(0, _T("alt_pallette_mode: %x disp_en %x (scanline: %d\tframe: %d)\n"), alt_palette_mode, enable_display, Scanline, nCurrentFrame);
1750 recompute_palette_tables();
1751 return;
1752 }
1753
1754 if ((address & 0xec0100) == 0x840000) {
1755 sega_315_5296_write((address & 0x1f) >> 1, data);
1756 return;
1757 }
1758
1759 if ((address & 0xec0100) == 0x840100) {
1760 BurnYM3438Write(0, (address >> 1) & 3, data);
1761 return;
1762 }
1763
1764 if ((address & 0xec0100) == 0x880000) {
1765 if (sound_rom_length) {
1766 UPD7759PortWrite(0, data & 0xff);
1767 UPD7759StartWrite(0, 0);
1768 UPD7759StartWrite(0, 1);
1769 }
1770 return;
1771 }
1772
1773 if ((address & 0xec0100) == 0x880100) {
1774 // coin counters, other functions?
1775 return;
1776 }
1777
1778 if ((address & 0xec0000) == 0x8c0000) {
1779 //bprintf(0, _T("pal_w %x %x (scanline: %d\tframe: %d)\n"), address, data, Scanline, nCurrentFrame);
1780 palette_write(address & 0xfff, data, 0xffff);
1781 return;
1782 }
1783
1784 if ((address & 0xe70000) == 0xc00000) {
1785 MegadriveVideoWriteWord(address & 0x1f, data);
1786 return;
1787 }
1788 bprintf(0, _T("ww %x %x\n"), address, data);
1789 }
1790
segac2_main_write_byte(UINT32 address,UINT8 data)1791 static void __fastcall segac2_main_write_byte(UINT32 address, UINT8 data)
1792 {
1793 if ((address & 0xec0201) == 0x800001) {
1794 protection_write(data);
1795 return;
1796 }
1797
1798 if ((address & 0xec0201) == 0x800201) {
1799 enable_display = ~data & 1;
1800 if (!(data & 2)) prot_write_buf = prot_read_buf = 0;
1801 alt_palette_mode = ((~data & 4) >> 2);
1802 //bprintf(0, _T("alt_pallette_mode.b: %x disp_en %x (scanline: %d\tframe: %d)\n"), alt_palette_mode, enable_display, Scanline, nCurrentFrame);
1803 recompute_palette_tables();
1804 return;
1805 }
1806
1807 if ((address & 0xec0101) == 0x840001) {
1808 sega_315_5296_write((address & 0x1f) >> 1, data);
1809 return;
1810 }
1811
1812 if ((address & 0xec0101) == 0x840101) {
1813 BurnYM3438Write(0, (address >> 1) & 3, data);
1814 return;
1815 }
1816
1817 if ((address & 0xec0101) == 0x880001) {
1818 if (sound_rom_length) {
1819 UPD7759PortWrite(0, data);
1820 UPD7759StartWrite(0, 0);
1821 UPD7759StartWrite(0, 1);
1822 }
1823 return;
1824 }
1825
1826 if ((address & 0xec0100) == 0x880100) {
1827 // coin counters, other functions?
1828 return;
1829 }
1830
1831 if ((address & 0xec0000) == 0x8c0000) {
1832 //bprintf(0, _T("pal_w.b %x %x (scanline: %d\tframe: %d)\n"), address, data, Scanline, nCurrentFrame);
1833 palette_write(address & 0xfff, data << ((~address & 1) * 8), 0xff << ((~address & 1) * 8));
1834 return;
1835 }
1836
1837 if ((address & 0xe70000) == 0xc00000) {
1838 MegadriveVideoWriteByte(address & 0x1f, data);
1839 return;
1840 }
1841
1842 if (address > 0x1fffff) { // puyopuy2 writes to romspace a lot
1843 bprintf(0, _T("wb %x %x\n"), address, data);
1844 }
1845 }
1846
segac2_main_read_word(UINT32 address)1847 static UINT16 __fastcall segac2_main_read_word(UINT32 address)
1848 {
1849 if ((address & 0xec0200) == 0x800000) {
1850 return prot_read_buf | 0xf0;
1851 }
1852
1853 if ((address & 0xec0100) == 0x840000) {
1854 return sega_315_5296_read((address & 0x1f) >> 1);
1855 }
1856
1857 if ((address & 0xec0100) == 0x840100) {
1858 return BurnYM3438Read(0, (address >> 1) & 3);
1859 }
1860
1861 if ((address & 0xec0000) == 0x8c0000) {
1862 return palette_read(address & 0x3ff);
1863 }
1864
1865 if ((address & 0xe70000) == 0xc00000) {
1866 return MegadriveVideoReadWord(address & 0x1f);
1867 }
1868
1869 bprintf(0, _T("rw %x\n"), address);
1870
1871 return 0;
1872 }
1873
segac2_main_read_byte(UINT32 address)1874 static UINT8 __fastcall segac2_main_read_byte(UINT32 address)
1875 {
1876 if ((address & 0xec0200) == 0x800000) {
1877 return prot_read_buf | 0xf0;
1878 }
1879
1880 if ((address & 0xec0101) == 0x840001) {
1881 return sega_315_5296_read((address & 0x1f) >> 1);
1882 }
1883
1884 if ((address & 0xec0101) == 0x840101) {
1885 return BurnYM3438Read(0, (address >> 1) & 3);
1886 }
1887
1888 if ((address & 0xec0101) == 0x880101) {
1889 // nop? (puyopuy2)
1890 return 0;
1891 }
1892
1893 if ((address & 0xec0201) == 0x800201) {
1894 // nop? (puyopuy2)
1895 return 0;
1896 }
1897
1898 if ((address & 0xec0000) == 0x8c0000) {
1899 return palette_read(address & 0x3ff) >> ((~address & 1) * 8);
1900 }
1901
1902 if ((address & 0xe70000) == 0xc00000) {
1903 return MegadriveVideoReadByte(address & 0x1f);
1904 }
1905
1906 bprintf(0, _T("rb %x\n"), address);
1907
1908 return 0;
1909 }
1910
DrvFMIRQHandler(INT32,INT32 state)1911 inline static void DrvFMIRQHandler(INT32, INT32 state)
1912 {
1913 SekSetVIRQLine(2, state ? CPU_IRQSTATUS_ACK : CPU_IRQSTATUS_NONE);
1914 }
1915
segac2_irq_callback(INT32 irqline)1916 static INT32 __fastcall segac2_irq_callback(INT32 irqline)
1917 {
1918 if (irqline == 4) {
1919 RamVReg->pending_ints &= ~0x10;
1920 SekSetVIRQLine(irqline, CPU_IRQSTATUS_NONE);
1921 }
1922 if (irqline == 6) {
1923 RamVReg->pending_ints &= ~0x20;
1924 SekSetVIRQLine(irqline, CPU_IRQSTATUS_NONE);
1925 }
1926
1927 return (0x60 + irqline * 4) / 4; // vector address
1928 }
1929
DrvDoReset()1930 static INT32 DrvDoReset()
1931 {
1932 memset (AllRam, 0, RamEnd - AllRam);
1933
1934 SekOpen(0);
1935 SekReset();
1936 BurnYM3438Reset();
1937 if (sound_rom_length) UPD7759Reset();
1938 SekClose();
1939
1940 prot_write_buf = 0;
1941 prot_read_buf = 0;
1942 enable_display = 0;
1943 alt_palette_mode = 0;
1944 palette_bank = 0;
1945 bg_palbase = 0;
1946 sp_palbase = 0;
1947
1948 // I/O chip
1949 memset (output_latch, 0, sizeof(output_latch));
1950 dir = 0;
1951 iocnt = 0;
1952 io_porth_write(0);
1953
1954 SegaC2BgPalLookup[0] = 0x00;
1955 SegaC2BgPalLookup[1] = 0x10;
1956 SegaC2BgPalLookup[2] = 0x20;
1957 SegaC2BgPalLookup[3] = 0x30;
1958
1959 SegaC2SpPalLookup[0] = 0x00;
1960 SegaC2SpPalLookup[1] = 0x10;
1961 SegaC2SpPalLookup[2] = 0x20;
1962 SegaC2SpPalLookup[3] = 0x30;
1963
1964 irq4_counter = -1;
1965 irq6_line = 224;
1966
1967 // default VDP register values (based on Fusion)
1968 memset(RamVReg, 0, sizeof(struct PicoVideo));
1969 RamVReg->reg[0x00] = 0x04;
1970 RamVReg->reg[0x01] = 0x04;
1971 RamVReg->reg[0x0c] = 0x81;
1972 RamVReg->reg[0x0f] = 0x02;
1973 RamVReg->status = 0x3408 | 0; // 'always set' bits | vblank | collision | pal
1974 RamVReg->rotate = 0;
1975 dma_xfers = 0;
1976 Scanline = 0;
1977 RamVReg->rendstatus = 0;
1978 interlacemode2 = 0;
1979
1980 nExtraCycles[0] = 0;
1981
1982 return 0;
1983 }
1984
MemIndex()1985 static INT32 MemIndex()
1986 {
1987 UINT8 *Next; Next = AllMem;
1988
1989 Drv68KROM = Next; Next += 0x200000;
1990
1991 DrvSndROM = Next; Next += 0x0a0000;
1992
1993 DrvPalette = (UINT32*)Next; Next += 0x3001 * sizeof(UINT32); // +1 for black
1994
1995 AllRam = Next;
1996
1997 Drv68KRAM = Next; Next += 0x010000;
1998 DrvPalRAM = Next; Next += 0x001000;
1999
2000 // picodrive vdp stuff
2001 RamPal = (UINT16 *) Next; Next += 0x000040 * sizeof(UINT16);
2002 RamSVid = (UINT16 *) Next; Next += 0x000040 * sizeof(UINT16); // VSRam
2003 RamVid = (UINT16 *) Next; Next += 0x010000 * sizeof(UINT16); // Video Ram
2004 RamVReg = (struct PicoVideo *)Next; Next += sizeof(struct PicoVideo);
2005
2006 RamEnd = Next;
2007
2008 HighColFull = (UINT16*) Next; Next += ((8 + 320 + 8) * ((240 + 1) * 2)) * sizeof(UINT16);
2009
2010 HighCacheA = (INT32 *) Next; Next += (41+1) * sizeof(INT32); // caches for high layers
2011 HighCacheB = (INT32 *) Next; Next += (41+1) * sizeof(INT32);
2012 HighPreSpr = (INT32 *) Next; Next += (80*2+1) * sizeof(INT32); // slightly preprocessed sprites
2013
2014 MemEnd = Next;
2015
2016 return 0;
2017 }
2018
SegaC2Init(UINT8 (* prot_read_cb)(UINT8))2019 static INT32 SegaC2Init(UINT8 (*prot_read_cb)(UINT8))
2020 {
2021 BurnAllocMemIndex();
2022
2023 {
2024 char* pRomName;
2025 struct BurnRomInfo ri;
2026 UINT8 *pLoad = Drv68KROM;
2027 UINT8 *sLoad = DrvSndROM;
2028
2029 for (INT32 i = 0; !BurnDrvGetRomName(&pRomName, i, 0); i++)
2030 {
2031 BurnDrvGetRomInfo(&ri, i);
2032
2033 if ((ri.nType & BRF_PRG) && (ri.nType & 0x03) == 1) // everyone else
2034 {
2035 if (BurnLoadRom(pLoad + 1, i+0, 2)) return 1;
2036 if (BurnLoadRom(pLoad + 0, i+1, 2)) return 1;
2037 pLoad += 0x100000;
2038 i++;
2039 continue;
2040 }
2041
2042 if ((ri.nType & BRF_PRG) && (ri.nType & 0x03) == 3) // Bloxeed is weird
2043 {
2044 if (BurnLoadRom(pLoad + 1, i+0, 2)) return 1;
2045 if (BurnLoadRom(pLoad + 0, i+1, 2)) return 1;
2046 pLoad += (ri.nLen * 2);
2047 i++;
2048 continue;
2049 }
2050
2051 if ((ri.nType & BRF_SND) && (ri.nType & 0x03) == 2)
2052 {
2053 if (BurnLoadRom(sLoad, i, 1)) return 1;
2054 sLoad += ri.nLen;
2055 sound_rom_length += ri.nLen;
2056 continue;
2057 }
2058 }
2059
2060 memcpy (DrvSndROM + 0x80000, DrvSndROM, 0x20000);
2061 }
2062
2063 bprintf (0, _T("soundlen: %5.5x\n"), sound_rom_length);
2064
2065 protection_read_cb = prot_read_cb;
2066
2067 SekInit(0, 0x68000);
2068 SekOpen(0);
2069 SekSetIrqCallback(segac2_irq_callback);
2070 SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, MAP_ROM);
2071 for (INT32 i = 0; i < 0x200000; i += 0x10000) {
2072 SekMapMemory(Drv68KRAM, 0xe00000 + i, 0xe0ffff + i, MAP_RAM);
2073 }
2074 SekSetWriteWordHandler(0, segac2_main_write_word);
2075 SekSetWriteByteHandler(0, segac2_main_write_byte);
2076 SekSetReadWordHandler(0, segac2_main_read_word);
2077 SekSetReadByteHandler(0, segac2_main_read_byte);
2078 SekClose();
2079
2080 BurnYM3438Init(1, 53693175 / 7, &DrvFMIRQHandler, 0);
2081 BurnTimerAttachNull(53693175 / 6);
2082 BurnYM3438SetAllRoutes(0, 0.40, BURN_SND_ROUTE_BOTH);
2083
2084 SN76496Init(0, 53693175 / 15, 0);
2085 SN76496SetBuffered(SekTotalCycles, 53693175 / 6);
2086 SN76496SetRoute(0, 0.35, BURN_SND_ROUTE_BOTH);
2087
2088 if (sound_rom_length)
2089 {
2090 UPD7759Init(0, UPD7759_STANDARD_CLOCK, DrvSndROM + 0x80000);
2091 UPD7759SetRoute(0, 0.35, BURN_SND_ROUTE_BOTH);
2092 UPD7759SetSyncCallback(0, SekTotalCycles, 53693175 / 6);
2093 }
2094
2095 GenericTilesInit();
2096
2097 if (has_dial) BurnTrackballInit(2); // twinsqua
2098
2099 // I/O Chip
2100 dir_override = 0xff;
2101
2102 DrvDoReset();
2103
2104 return 0;
2105 }
2106
DrvExit()2107 static INT32 DrvExit()
2108 {
2109 GenericTilesExit();
2110
2111 BurnYM3438Exit();
2112 SN76496Exit();
2113 if (sound_rom_length) UPD7759Exit();
2114 SekExit();
2115
2116 BurnFreeMemIndex();
2117
2118 if (has_dial) BurnTrackballExit();
2119 has_dial = 0;
2120
2121 sound_rom_length = 0;
2122
2123 is_wwmarine = 0;
2124 is_tfrceacb = 0;
2125 is_ribbit = 0;
2126
2127 return 0;
2128 }
2129
2130 //---------------------------------------------------------------
2131 // Megadrive Draw
2132 //---------------------------------------------------------------
2133
2134 #define TileNormMaker_(pix_func) \
2135 { \
2136 unsigned int t; \
2137 \
2138 t = (pack&0x0000f000)>>12; pix_func(0); \
2139 t = (pack&0x00000f00)>> 8; pix_func(1); \
2140 t = (pack&0x000000f0)>> 4; pix_func(2); \
2141 t = (pack&0x0000000f) ; pix_func(3); \
2142 t = (pack&0xf0000000)>>28; pix_func(4); \
2143 t = (pack&0x0f000000)>>24; pix_func(5); \
2144 t = (pack&0x00f00000)>>20; pix_func(6); \
2145 t = (pack&0x000f0000)>>16; pix_func(7); \
2146 }
2147
2148 #define TileFlipMaker_(pix_func) \
2149 { \
2150 unsigned int t; \
2151 \
2152 t = (pack&0x000f0000)>>16; pix_func(0); \
2153 t = (pack&0x00f00000)>>20; pix_func(1); \
2154 t = (pack&0x0f000000)>>24; pix_func(2); \
2155 t = (pack&0xf0000000)>>28; pix_func(3); \
2156 t = (pack&0x0000000f) ; pix_func(4); \
2157 t = (pack&0x000000f0)>> 4; pix_func(5); \
2158 t = (pack&0x00000f00)>> 8; pix_func(6); \
2159 t = (pack&0x0000f000)>>12; pix_func(7); \
2160 }
2161
2162 #define TileNormMaker(funcname, pix_func) \
2163 static void funcname(UINT16 *pd, unsigned int pack, int pal) \
2164 TileNormMaker_(pix_func)
2165
2166 #define TileFlipMaker(funcname, pix_func) \
2167 static void funcname(UINT16 *pd, unsigned int pack, int pal) \
2168 TileFlipMaker_(pix_func)
2169
2170 #define TileNormMakerAS(funcname, pix_func) \
2171 static void funcname(UINT16 *pd, unsigned char *mb, unsigned int pack, int pal) \
2172 TileNormMaker_(pix_func)
2173
2174 #define TileFlipMakerAS(funcname, pix_func) \
2175 static void funcname(UINT16 *pd, unsigned char *mb, unsigned int pack, int pal) \
2176 TileFlipMaker_(pix_func)
2177
2178 #define pix_just_write(x) \
2179 if (t) pd[x]=pal|t
2180
TileNormMaker(TileNorm,pix_just_write)2181 TileNormMaker(TileNorm,pix_just_write)
2182 TileFlipMaker(TileFlip,pix_just_write)
2183
2184 // draw a sprite pixel, process operator colors
2185 #define pix_sh(x) \
2186 if (!t); \
2187 else if (t>=0xe) pd[x]=(pd[x]&0x3f)|(t<<6); /* c0 shadow, 80 hilight */ \
2188 else pd[x]=pal|t
2189
2190 TileNormMaker(TileNormSH, pix_sh)
2191 TileFlipMaker(TileFlipSH, pix_sh)
2192
2193 // draw a sprite pixel, mark operator colors
2194 #define pix_sh_markop(x) \
2195 if (!t); \
2196 else if (t>=0xe) pd[x]|=0x80; \
2197 else pd[x]=pal|t
2198
2199 TileNormMaker(TileNormSH_markop, pix_sh_markop)
2200 TileFlipMaker(TileFlipSH_markop, pix_sh_markop)
2201
2202 // process operator pixels only, apply only on low pri tiles and other op pixels
2203 #define pix_sh_onlyop(x) \
2204 if (t>=0xe && (pd[x]&0xc0)) \
2205 pd[x]=(pd[x]&0x3f)|(t<<6); /* c0 shadow, 80 hilight */ \
2206
2207 TileNormMaker(TileNormSH_onlyop_lp, pix_sh_onlyop)
2208 TileFlipMaker(TileFlipSH_onlyop_lp, pix_sh_onlyop)
2209
2210 // draw a sprite pixel (AS)
2211 #define pix_as(x) \
2212 if (t & mb[x]) mb[x] = 0, pd[x] = pal | t
2213
2214 TileNormMakerAS(TileNormAS, pix_as)
2215 TileFlipMakerAS(TileFlipAS, pix_as)
2216
2217 // draw a sprite pixel, process operator colors (AS)
2218 #define pix_sh_as(x) \
2219 if (t & mb[x]) { \
2220 mb[x] = 0; \
2221 if (t>=0xe) pd[x]=(pd[x]&0x3f)|(t<<6); /* c0 shadow, 80 hilight */ \
2222 else pd[x] = pal | t; \
2223 }
2224
2225 TileNormMakerAS(TileNormSH_AS, pix_sh_as)
2226 TileFlipMakerAS(TileFlipSH_AS, pix_sh_as)
2227
2228 #define pix_sh_as_onlyop(x) \
2229 if (t & mb[x]) { \
2230 mb[x] = 0; \
2231 pix_sh_onlyop(x); \
2232 }
2233
2234 TileNormMakerAS(TileNormSH_AS_onlyop_lp, pix_sh_as_onlyop)
2235 TileFlipMakerAS(TileFlipSH_AS_onlyop_lp, pix_sh_as_onlyop)
2236
2237 // mark pixel as sprite pixel (AS)
2238 #define pix_sh_as_onlymark(x) \
2239 if (t) mb[x] = 0
2240
2241 TileNormMakerAS(TileNormAS_onlymark, pix_sh_as_onlymark)
2242 TileFlipMakerAS(TileFlipAS_onlymark, pix_sh_as_onlymark)
2243
2244 // forced both layer draw (through debug reg)
2245 #define pix_and(x) \
2246 pd[x] = (pd[x] & 0xc0) | (pd[x] & (pal | t))
2247
2248 TileNormMaker(TileNorm_and, pix_and)
2249 TileFlipMaker(TileFlip_and, pix_and)
2250
2251 // --------------------------------------------
2252
2253
2254 static void DrawStrip(struct TileStrip *ts, int lflags, int cellskip)
2255 {
2256 UINT16 *pd = HighCol;
2257 int tilex,dx,ty,code=0,addr=0,cells;
2258 int oldcode=-1,blank=-1; // The tile we know is blank
2259 int pal=0,sh;
2260
2261 // Draw tiles across screen:
2262 sh = (lflags & LF_SH) << 5; // 0x40
2263 tilex=((-ts->hscroll)>>3)+cellskip;
2264 ty=(ts->line&7)<<1; // Y-Offset into tile
2265 dx=((ts->hscroll-1)&7)+1;
2266 cells = ts->cells - cellskip;
2267 if(dx != 8) cells++; // have hscroll, need to draw 1 cell more
2268 dx+=cellskip<<3;
2269
2270 for (; cells > 0; dx+=8, tilex++, cells--)
2271 {
2272 unsigned int pack;
2273
2274 code = RamVid[ts->nametab + (tilex & ts->xmask)];
2275 if (code == blank)
2276 continue;
2277 if ((code >> 15) | (lflags & LF_FORCE)) { // high priority tile
2278 int cval = code | (dx<<16) | (ty<<25);
2279 if(code&0x1000) cval^=7<<26;
2280 *ts->hc++ = cval; // cache it
2281 continue;
2282 }
2283
2284 if (code!=oldcode) {
2285 oldcode = code;
2286 // Get tile address/2:
2287 addr=(code&0x7ff)<<4;
2288 addr+=ty;
2289 if (code&0x1000) addr^=0xe; // Y-flip
2290
2291 pal=((code>>9)&0x30)|sh;
2292 }
2293
2294 pack = *(unsigned int *)(RamVid + addr);
2295 if (!pack) {
2296 blank = code;
2297 continue;
2298 }
2299
2300 if (~nBurnLayer & 4) return;
2301
2302 if (code & 0x0800) TileFlip(pd + dx, pack, pal);
2303 else TileNorm(pd + dx, pack, pal);
2304 }
2305
2306 // terminate the cache list
2307 *ts->hc = 0;
2308 // if oldcode wasn't changed, it means all layer is hi priority
2309 if (oldcode == -1) RamVReg->rendstatus |= PDRAW_PLANE_HI_PRIO;
2310 }
2311
DrawStripVSRam(struct TileStrip * ts,int plane_sh,int cellskip)2312 static void DrawStripVSRam(struct TileStrip *ts, int plane_sh, int cellskip)
2313 {
2314 UINT16 *pd = HighCol;
2315 int tilex,dx,code=0,addr=0,cell=0;
2316 int oldcode=-1,blank=-1; // The tile we know is blank
2317 int pal=0,scan=Scanline;
2318
2319 // Draw tiles across screen:
2320 tilex=(-ts->hscroll)>>3;
2321 dx=((ts->hscroll-1)&7)+1;
2322 if (ts->hscroll & 0x0f) {
2323 int adj = ((ts->hscroll ^ dx) >> 3) & 1;
2324 cell -= adj + 1;
2325 ts->cells -= adj;
2326 }
2327 cell+=cellskip;
2328 tilex+=cellskip;
2329 dx+=cellskip<<3;
2330
2331 for (; cell < ts->cells; dx+=8,tilex++,cell++)
2332 {
2333 int nametabadd, ty;
2334 unsigned int pack;
2335
2336 //if((cell&1)==0)
2337 {
2338 int line,vscroll;
2339 vscroll=RamSVid[(plane_sh&1)+(cell&~1)];
2340
2341 // Find the line in the name table
2342 line=(vscroll+scan)&ts->line&0xffff; // ts->line is really ymask ..
2343 nametabadd=(line>>3)<<(ts->line>>24); // .. and shift[width]
2344 ty=(line&7)<<1; // Y-Offset into tile
2345 }
2346
2347 code=RamVid[ts->nametab+nametabadd+(tilex&ts->xmask)];
2348 if (code==blank) continue;
2349 if (code>>15) { // high priority tile
2350 int cval = code | (dx<<16) | (ty<<25);
2351 if(code&0x1000) cval^=7<<26;
2352 *ts->hc++ = cval; // cache it
2353 continue;
2354 }
2355
2356 if (code!=oldcode) {
2357 oldcode = code;
2358 // Get tile address/2:
2359 addr=(code&0x7ff)<<4;
2360 if (code&0x1000) addr+=14-ty; else addr+=ty; // Y-flip
2361
2362 pal=((code>>9)&0x30)|((plane_sh<<5)&0x40);
2363 }
2364
2365 pack = *(unsigned int *)(RamVid + addr);
2366 if (!pack) {
2367 blank = code;
2368 continue;
2369 }
2370
2371 if (~nBurnLayer & 2) return;
2372
2373 if (code & 0x0800) TileFlip(pd + dx, pack, pal);
2374 else TileNorm(pd + dx, pack, pal);
2375 }
2376
2377 // terminate the cache list
2378 *ts->hc = 0;
2379 if (oldcode == -1) RamVReg->rendstatus |= PDRAW_PLANE_HI_PRIO;
2380 }
2381
DrawStripInterlace(struct TileStrip * ts)2382 void DrawStripInterlace(struct TileStrip *ts)
2383 {
2384 UINT16 *pd = HighCol;
2385 int tilex=0,dx=0,ty=0,code=0,addr=0,cells;
2386 int oldcode=-1,blank=-1; // The tile we know is blank
2387 int pal=0;
2388
2389 // Draw tiles across screen:
2390 tilex=(-ts->hscroll)>>3;
2391 ty=(ts->line&15)<<1; // Y-Offset into tile
2392 dx=((ts->hscroll-1)&7)+1;
2393 cells = ts->cells;
2394 if(dx != 8) cells++; // have hscroll, need to draw 1 cell more
2395
2396 for (; cells; dx+=8,tilex++,cells--)
2397 {
2398 unsigned int pack;
2399
2400 code = RamVid[ts->nametab + (tilex & ts->xmask)];
2401 if (code==blank) continue;
2402 if (code>>15) { // high priority tile
2403 int cval = (code&0xfc00) | (dx<<16) | (ty<<25);
2404 cval|=(code&0x3ff)<<1;
2405 if(code&0x1000) cval^=0xf<<26;
2406 *ts->hc++ = cval; // cache it
2407 continue;
2408 }
2409
2410 if (code!=oldcode) {
2411 oldcode = code;
2412 // Get tile address/2:
2413 addr=(code&0x7ff)<<5;
2414 if (code&0x1000) addr+=30-ty; else addr+=ty; // Y-flip
2415
2416 // pal=Pico.cram+((code>>9)&0x30);
2417 pal=((code>>9)&0x30);
2418 }
2419
2420 pack = *(unsigned int *)(RamVid + addr);
2421 if (!pack) {
2422 blank = code;
2423 continue;
2424 }
2425
2426 if (code & 0x0800) TileFlip(pd + dx, pack, pal);
2427 else TileNorm(pd + dx, pack, pal);
2428 }
2429
2430 // terminate the cache list
2431 *ts->hc = 0;
2432 }
2433
2434 // --------------------------------------------
2435
2436
DrawLayer(int plane_sh,int * hcache,int cellskip,int maxcells)2437 static void DrawLayer(int plane_sh, int *hcache, int cellskip, int maxcells)
2438 {
2439 const char shift[4]={5,6,5,7}; // 32,64 or 128 sized tilemaps (2 is invalid)
2440 const unsigned char h_masks[4] = { 0x00, 0x07, 0xf8, 0xff };
2441 struct TileStrip ts;
2442 int width, height, ymask;
2443 int vscroll, htab;
2444
2445 ts.hc=hcache;
2446 ts.cells=maxcells;
2447
2448 // Work out the TileStrip to draw
2449
2450 // Work out the name table size: 32 64 or 128 tiles (0-3)
2451 width=RamVReg->reg[16];
2452 height=(width>>4)&3; width&=3;
2453
2454 ts.xmask=(1<<shift[width])-1; // X Mask in tiles (0x1f-0x7f)
2455 ymask=(height<<8)|0xff; // Y Mask in pixels
2456 switch (width) {
2457 case 1: ymask &= 0x1ff; break;
2458 case 2: ymask = 0x007; break;
2459 case 3: ymask = 0x0ff; break;
2460 }
2461
2462 // Find name table:
2463 if (plane_sh&1) ts.nametab=(RamVReg->reg[4]&0x07)<<12; // B
2464 else ts.nametab=(RamVReg->reg[2]&0x38)<< 9; // A
2465
2466 htab=RamVReg->reg[13]<<9; // Horizontal scroll table address
2467 htab+=(Scanline&h_masks[RamVReg->reg[11]&3])<<1; // Point to line (masked)
2468 htab+=plane_sh&1; // A or B
2469
2470 // Get horizontal scroll value, will be masked later
2471 ts.hscroll = RamVid[htab & 0x7fff];
2472
2473 if((RamVReg->reg[12]&6) == 6) {
2474 // interlace mode 2
2475 vscroll = RamSVid[plane_sh & 1]; // Get vertical scroll value
2476
2477 // Find the line in the name table
2478 ts.line=(vscroll+(Scanline<<1))&((ymask<<1)|1);
2479 ts.nametab+=(ts.line>>4)<<shift[width];
2480
2481 DrawStripInterlace(&ts);
2482 } else if( RamVReg->reg[11]&4) {
2483 // shit, we have 2-cell column based vscroll
2484 // luckily this doesn't happen too often
2485 ts.line=ymask|(shift[width]<<24); // save some stuff instead of line
2486 DrawStripVSRam(&ts, plane_sh, cellskip);
2487 } else {
2488 vscroll = RamSVid[plane_sh & 1]; // Get vertical scroll value
2489
2490 // Find the line in the name table
2491 ts.line=(vscroll+Scanline)&ymask;
2492 ts.nametab+=(ts.line>>3)<<shift[width];
2493
2494 DrawStrip(&ts, plane_sh, cellskip);
2495 }
2496 }
2497
2498 // --------------------------------------------
2499
2500 // tstart & tend are tile pair numbers
DrawWindow(int tstart,int tend,int prio,int sh)2501 static void DrawWindow(int tstart, int tend, int prio, int sh)
2502 {
2503 UINT16 *pd = HighCol;
2504 int tilex,ty,nametab,code=0;
2505 int blank=-1; // The tile we know is blank
2506
2507 if (~nSpriteEnable & 0x10) return;
2508
2509 // Find name table line:
2510 if (RamVReg->reg[12]&1)
2511 {
2512 nametab=(RamVReg->reg[3]&0x3c)<<9; // 40-cell mode
2513 nametab+=(Scanline>>3)<<6;
2514 }
2515 else
2516 {
2517 nametab=(RamVReg->reg[3]&0x3e)<<9; // 32-cell mode
2518 nametab+=(Scanline>>3)<<5;
2519 }
2520
2521 tilex=tstart<<1;
2522
2523 if (!(RamVReg->rendstatus & PDRAW_WND_DIFF_PRIO)) {
2524 // check the first tile code
2525 code = RamVid[nametab + tilex];
2526 // if the whole window uses same priority (what is often the case), we may be able to skip this field
2527 if ((code>>15) != prio) return;
2528 }
2529
2530 tend<<=1;
2531 ty=(Scanline&7)<<1; // Y-Offset into tile
2532
2533 // Draw tiles across screen:
2534 if (!sh)
2535 {
2536 for (; tilex < tend; tilex++)
2537 {
2538 unsigned int pack;
2539 int dx, addr;
2540 int pal;
2541
2542 code = RamVid[nametab + tilex];
2543 if (code==blank) continue;
2544 if ((code>>15) != prio) {
2545 RamVReg->rendstatus |= PDRAW_WND_DIFF_PRIO;
2546 continue;
2547 }
2548
2549 // Get tile address/2:
2550 addr=(code&0x7ff)<<4;
2551 if (code&0x1000) addr+=14-ty; else addr+=ty; // Y-flip
2552
2553 pack = *(unsigned int *)(RamVid + addr);
2554 if (!pack) {
2555 blank = code;
2556 continue;
2557 }
2558
2559 pal = ((code >> 9) & 0x30);
2560 dx = 8 + (tilex << 3);
2561
2562 if (code & 0x0800) TileFlip(pd + dx, pack, pal);
2563 else TileNorm(pd + dx, pack, pal);
2564 }
2565 }
2566 else
2567 {
2568 for (; tilex < tend; tilex++)
2569 {
2570 unsigned int pack;
2571 int dx, addr;
2572 int pal;
2573
2574 code = RamVid[nametab + tilex];
2575 if(code==blank) continue;
2576 if((code>>15) != prio) {
2577 RamVReg->rendstatus |= PDRAW_WND_DIFF_PRIO;
2578 continue;
2579 }
2580
2581 pal=((code>>9)&0x30);
2582
2583 if (prio) {
2584 UINT16 *zb = (UINT16 *)(HighCol+8+(tilex<<3));
2585 *zb &= 0x00bf; zb++;
2586 *zb &= 0x00bf; zb++;
2587 *zb &= 0x00bf; zb++;
2588 *zb &= 0x00bf; zb++;
2589 *zb &= 0x00bf; zb++;
2590 *zb &= 0x00bf; zb++;
2591 *zb &= 0x00bf; zb++;
2592 *zb &= 0x00bf; zb++;
2593 } else {
2594 pal |= 0x40;
2595 }
2596
2597 // Get tile address/2:
2598 addr=(code&0x7ff)<<4;
2599 if (code&0x1000) addr+=14-ty; else addr+=ty; // Y-flip
2600
2601 pack = *(unsigned int *)(RamVid + addr);
2602 if (!pack) {
2603 blank = code;
2604 continue;
2605 }
2606
2607 dx = 8 + (tilex << 3);
2608
2609 if (code & 0x0800) TileFlip(pd + dx, pack, pal);
2610 else TileNorm(pd + dx, pack, pal);
2611 }
2612 }
2613 }
2614
2615 // --------------------------------------------
2616
DrawTilesFromCacheShPrep(void)2617 static void DrawTilesFromCacheShPrep(void)
2618 {
2619 // as some layer has covered whole line with hi priority tiles,
2620 // we can process whole line and then act as if sh/hi mode was off,
2621 // but leave lo pri op sprite markers alone
2622 int c = 320;
2623 UINT16 *zb = (UINT16 *)(HighCol+8);
2624 RamVReg->rendstatus |= PDRAW_SHHI_DONE;
2625 while (c--)
2626 {
2627 *zb++ &= 0x80bf; // dink maybe 0x80bf ?
2628 }
2629 }
2630
DrawTilesFromCache(int * hc,int sh,int rlim)2631 static void DrawTilesFromCache(int *hc, int sh, int rlim)
2632 {
2633 UINT16 *pd = HighCol;
2634 int code, addr, dx;
2635 unsigned int pack;
2636 int pal;
2637
2638 // *ts->hc++ = code | (dx<<16) | (ty<<25); // cache it
2639
2640 if (~nBurnLayer & 1) return;
2641
2642 if (sh && (RamVReg->rendstatus & (PDRAW_SHHI_DONE|PDRAW_PLANE_HI_PRIO)))
2643 {
2644 if (!(RamVReg->rendstatus & PDRAW_SHHI_DONE))
2645 DrawTilesFromCacheShPrep();
2646 sh = 0;
2647 }
2648
2649 if (!sh)
2650 {
2651 if (~nSpriteEnable & 0x40) return;
2652 short blank=-1; // The tile we know is blank
2653 while ((code=*hc++)) {
2654 if (!(code & 0x8000) || (short)code == blank)
2655 continue;
2656 // Get tile address/2:
2657 addr = (code & 0x7ff) << 4;
2658 addr += code >> 25; // y offset into tile
2659
2660 pack = *(unsigned int *)(RamVid + addr);
2661 if (!pack) {
2662 blank = (short)code;
2663 continue;
2664 }
2665
2666 dx = (code >> 16) & 0x1ff;
2667 pal = ((code >> 9) & 0x30);
2668 if (rlim-dx < 0)
2669 goto last_cut_tile;
2670
2671 if (code & 0x0800) TileFlip(pd + dx, pack, pal);
2672 else TileNorm(pd + dx, pack, pal);
2673 }
2674 }
2675 else
2676 {
2677 if (~nSpriteEnable & 0x80) return;
2678 while ((code=*hc++)) {
2679 UINT16 *zb;
2680
2681 // Get tile address/2:
2682 addr=(code&0x7ff)<<4;
2683 addr+=(unsigned int)code>>25; // y offset into tile
2684 dx=(code>>16)&0x1ff;
2685 zb = HighCol+dx;
2686 *zb++ &= 0x00bf; *zb++ &= 0x00bf; *zb++ &= 0x00bf; *zb++ &= 0x00bf;
2687 *zb++ &= 0x00bf; *zb++ &= 0x00bf; *zb++ &= 0x00bf; *zb++ &= 0x00bf;
2688
2689 pack = *(unsigned int *)(RamVid + addr);
2690 if (!pack)
2691 continue;
2692
2693 pal = ((code >> 9) & 0x30);
2694 if (rlim - dx < 0)
2695 goto last_cut_tile;
2696
2697 if (code & 0x0800) TileFlip(pd + dx, pack, pal);
2698 else TileNorm(pd + dx, pack, pal);
2699 }
2700 }
2701 return;
2702
2703 last_cut_tile:
2704 // for vertical window cutoff
2705 {
2706 unsigned int t;
2707
2708 pd += dx;
2709 if (code&0x0800)
2710 {
2711 switch (rlim-dx+8)
2712 {
2713 case 7: t=pack&0x00000f00; if (t) pd[6]=(pal|(t>> 8)); // "break" is left out intentionally
2714 case 6: t=pack&0x000000f0; if (t) pd[5]=(pal|(t>> 4));
2715 case 5: t=pack&0x0000000f; if (t) pd[4]=(pal|(t ));
2716 case 4: t=pack&0xf0000000; if (t) pd[3]=(pal|(t>>28));
2717 case 3: t=pack&0x0f000000; if (t) pd[2]=(pal|(t>>24));
2718 case 2: t=pack&0x00f00000; if (t) pd[1]=(pal|(t>>20));
2719 case 1: t=pack&0x000f0000; if (t) pd[0]=(pal|(t>>16));
2720 default: break;
2721 }
2722 }
2723 else
2724 {
2725 switch (rlim-dx+8)
2726 {
2727 case 7: t=pack&0x00f00000; if (t) pd[6]=(pal|(t>>20));
2728 case 6: t=pack&0x0f000000; if (t) pd[5]=(pal|(t>>24));
2729 case 5: t=pack&0xf0000000; if (t) pd[4]=(pal|(t>>28));
2730 case 4: t=pack&0x0000000f; if (t) pd[3]=(pal|(t ));
2731 case 3: t=pack&0x000000f0; if (t) pd[2]=(pal|(t>> 4));
2732 case 2: t=pack&0x00000f00; if (t) pd[1]=(pal|(t>> 8));
2733 case 1: t=pack&0x0000f000; if (t) pd[0]=(pal|(t>>12));
2734 default: break;
2735 }
2736 }
2737 }
2738 }
2739
2740 // Index + 0 : hhhhvvvv ab--hhvv yyyyyyyy yyyyyyyy // a: offscreen h, b: offs. v, h: horiz. size
2741 // Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8
2742
DrawSprite(int * sprite,int sh)2743 static void DrawSprite(int *sprite, int sh)
2744 {
2745 void (*fTileFunc)(UINT16 *pd, unsigned int pack, int pal);
2746 UINT16 *pd = HighCol;
2747 int width=0,height=0;
2748 int row=0,code=0;
2749 int pal;
2750 int tile=0,delta=0;
2751 int sx, sy;
2752
2753 if (~nSpriteEnable & 0x01) return;
2754
2755 // parse the sprite data
2756 sy=sprite[0];
2757 code=sprite[1];
2758 sx=code>>16; // X
2759 width=sy>>28;
2760 height=(sy>>24)&7; // Width and height in tiles
2761 sy=(sy<<16)>>16; // Y
2762
2763 row=Scanline-sy; // Row of the sprite we are on
2764
2765 if (code&0x1000) row=(height<<3)-1-row; // Flip Y
2766
2767 tile=code + (row>>3); // Tile number increases going down
2768 delta=height; // Delta to increase tile by going right
2769 if (code&0x0800) { tile+=delta*(width-1); delta=-delta; } // Flip X
2770
2771 tile &= 0x7ff; tile<<=4; tile+=(row&7)<<1; // Tile address
2772 delta<<=4; // Delta of address
2773
2774 pal=(code>>9)&0x30;
2775 pal|=(sh<<6)|0x8000; // 0x8000 = c2 sprite (dink)
2776
2777 if (sh && (code&0x6000) == 0x6000) {
2778 if(code&0x0800) fTileFunc=TileFlipSH_markop;
2779 else fTileFunc=TileNormSH_markop;
2780 } else {
2781 if(code&0x0800) fTileFunc=TileFlip;
2782 else fTileFunc=TileNorm;
2783 }
2784
2785 for (; width; width--,sx+=8,tile+=delta)
2786 {
2787 unsigned int pack;
2788
2789 if(sx<=0) continue;
2790 if(sx>=328) break; // Offscreen
2791
2792 pack = *(unsigned int *)(RamVid + (tile & 0x7fff));
2793 fTileFunc(pd + sx, pack, pal);
2794 }
2795 }
2796
DrawTilesFromCacheForced(const int * hc)2797 static void DrawTilesFromCacheForced(const int *hc)
2798 {
2799 UINT16 *pd = HighCol;
2800 int code, addr, dx;
2801 unsigned int pack;
2802 int pal;
2803
2804 // *ts->hc++ = code | (dx<<16) | (ty<<25);
2805 while ((code = *hc++)) {
2806 // Get tile address/2:
2807 addr = (code & 0x7ff) << 4;
2808 addr += (code >> 25) & 0x0e; // y offset into tile
2809
2810 dx = (code >> 16) & 0x1ff;
2811 pal = ((code >> 9) & 0x30);
2812 pack = *(unsigned int *)(RamVid + addr);
2813
2814 if (code & 0x0800) TileFlip_and(pd + dx, pack, pal);
2815 else TileNorm_and(pd + dx, pack, pal);
2816 }
2817 }
2818
2819
2820
DrawSpriteInterlace(unsigned int * sprite)2821 static void DrawSpriteInterlace(unsigned int *sprite)
2822 {
2823 UINT16 *pd = HighCol;
2824 int width=0,height=0;
2825 int row=0,code=0;
2826 int pal;
2827 int tile=0,delta=0;
2828 int sx, sy;
2829
2830 if (~nSpriteEnable & 0x02) return;
2831
2832 // parse the sprite data
2833 sy=sprite[0];
2834 height=sy>>24;
2835 sy=(sy&0x3ff)-0x100; // Y
2836 width=(height>>2)&3; height&=3;
2837 width++; height++; // Width and height in tiles
2838
2839 row=(Scanline<<1)-sy; // Row of the sprite we are on
2840
2841 code=sprite[1];
2842 sx=((code>>16)&0x1ff)-0x78; // X
2843
2844 if (code&0x1000) row^=(16<<height)-1; // Flip Y
2845
2846 tile=code&0x3ff; // Tile number
2847 tile+=row>>4; // Tile number increases going down
2848 delta=height; // Delta to increase tile by going right
2849 if (code&0x0800) { tile+=delta*(width-1); delta=-delta; } // Flip X
2850
2851 tile<<=5; tile+=(row&15)<<1; // Tile address
2852
2853 delta<<=5; // Delta of address
2854 pal=((code>>9)&0x30)|0x8000; // Get palette pointer
2855
2856 for (; width; width--,sx+=8,tile+=delta)
2857 {
2858 unsigned int pack;
2859
2860 if(sx<=0) continue;
2861 if(sx>=328) break; // Offscreen
2862
2863 pack = *(unsigned int *)(RamVid + (tile & 0x7fff));
2864 if (code & 0x0800) TileFlip(pd + sx, pack, pal);
2865 else TileNorm(pd + sx, pack, pal);
2866 }
2867 }
2868
2869
DrawAllSpritesInterlace(int pri,int sh)2870 static void DrawAllSpritesInterlace(int pri, int sh)
2871 {
2872 int i,u,table,link=0,sline=(Scanline<<1)+RamVReg->field;;
2873 unsigned int *sprites[80]; // Sprite index
2874
2875 table=RamVReg->reg[5]&0x7f;
2876 if (RamVReg->reg[12]&1) table&=0x7e; // Lowest bit 0 in 40-cell mode
2877 table<<=8; // Get sprite table address/2
2878
2879 for (i=u=0; u < 80 && i < 21; u++)
2880 {
2881 unsigned int *sprite;
2882 int code, sx, sy, height;
2883
2884 sprite=(unsigned int *)(RamVid+((table+(link<<2))&0x7ffc)); // Find sprite
2885
2886 // get sprite info
2887 code = sprite[0];
2888 sx = sprite[1];
2889 if(((sx>>15)&1) != pri) goto nextsprite; // wrong priority sprite
2890
2891 // check if it is on this line
2892 sy = (code&0x3ff)-0x100;
2893 height = (((code>>24)&3)+1)<<4;
2894 if(sline < sy || sline >= sy+height) goto nextsprite; // no
2895
2896 // check if sprite is not hidden offscreen
2897 sx = (sx>>16)&0x1ff;
2898 sx -= 0x78; // Get X coordinate + 8
2899 if(sx <= -8*3 || sx >= 328) goto nextsprite;
2900
2901 // sprite is good, save it's pointer
2902 sprites[i++]=sprite;
2903
2904 nextsprite:
2905 // Find next sprite
2906 link=(code>>16)&0x7f;
2907 if(!link) break; // End of sprites
2908 }
2909
2910 // Go through sprites backwards:
2911 for (i-- ;i>=0; i--)
2912 DrawSpriteInterlace(sprites[i]);
2913 }
2914
2915
2916 /*
2917 * s/h drawing: lo_layers|40, lo_sprites|40 && mark_op,
2918 * hi_layers&=~40, hi_sprites
2919 *
2920 * Index + 0 : hhhhvvvv ----hhvv yyyyyyyy yyyyyyyy // v, h: vert./horiz. size
2921 * Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8
2922 */
DrawSpritesSHi(unsigned char * sprited)2923 static void DrawSpritesSHi(unsigned char *sprited)
2924 {
2925 void (*fTileFunc)(UINT16 *pd, unsigned int pack, int pal);
2926 UINT16 *pd = HighCol;
2927 unsigned char *p;
2928 int cnt;
2929
2930 if (~nSpriteEnable & 0x04) return;
2931
2932 cnt = sprited[0] & 0x7f;
2933 if (cnt == 0) return;
2934
2935 p = &sprited[3];
2936
2937 // Go through sprites backwards:
2938 for (cnt--; cnt >= 0; cnt--)
2939 {
2940 int *sprite, code, pal, tile, sx, sy;
2941 int offs, delta, width, height, row;
2942
2943 offs = (p[cnt] & 0x7f) * 2;
2944 sprite = HighPreSpr + offs;
2945 code = sprite[1];
2946 pal = (code>>9)&0x30;
2947
2948 if (pal == 0x30)
2949 {
2950 if (code & 0x8000) // hi priority
2951 {
2952 if (code&0x800) fTileFunc=TileFlipSH;
2953 else fTileFunc=TileNormSH;
2954 } else {
2955 if (code&0x800) fTileFunc=TileFlipSH_onlyop_lp;
2956 else fTileFunc=TileNormSH_onlyop_lp;
2957 }
2958 } else {
2959 if (!(code & 0x8000)) continue; // non-operator low sprite, already drawn
2960 if (code&0x800) fTileFunc=TileFlip;
2961 else fTileFunc=TileNorm;
2962 }
2963
2964 // parse remaining sprite data
2965 sy=sprite[0];
2966 sx=code>>16; // X
2967 width=sy>>28;
2968 height=(sy>>24)&7; // Width and height in tiles
2969 sy=(sy<<16)>>16; // Y
2970
2971 row=Scanline-sy; // Row of the sprite we are on
2972
2973 if (code&0x1000) row=(height<<3)-1-row; // Flip Y
2974
2975 tile=code + (row>>3); // Tile number increases going down
2976 delta=height; // Delta to increase tile by going right
2977 if (code&0x0800) { tile+=delta*(width-1); delta=-delta; } // Flip X
2978
2979 tile &= 0x7ff; tile<<=4; tile+=(row&7)<<1; // Tile address
2980 delta<<=4; // Delta of address
2981
2982 for (; width; width--,sx+=8,tile+=delta)
2983 {
2984 unsigned int pack;
2985
2986 if(sx<=0) continue;
2987 if(sx>=328) break; // Offscreen
2988
2989 pack = *(unsigned int *)(RamVid + (tile & 0x7fff));
2990 fTileFunc(pd + sx, pack, pal|0x8000);
2991 }
2992 }
2993 }
2994
DrawSpritesHiAS(unsigned char * sprited,int sh)2995 static void DrawSpritesHiAS(unsigned char *sprited, int sh)
2996 {
2997 void (*fTileFunc)(UINT16 *pd, unsigned char *mb,
2998 unsigned int pack, int pal);
2999 UINT16 *pd = HighCol;
3000 unsigned char mb[8+320+8];
3001 unsigned char *p;
3002 int entry, cnt;
3003
3004 if (~nSpriteEnable & 0x08) return;
3005
3006 cnt = sprited[0] & 0x7f;
3007 if (cnt == 0) return;
3008
3009 memset(mb, 0xff, sizeof(mb));
3010 p = &sprited[3];
3011
3012 // Go through sprites:
3013 for (entry = 0; entry < cnt; entry++)
3014 {
3015 int *sprite, code, pal, tile, sx, sy;
3016 int offs, delta, width, height, row;
3017
3018 offs = (p[entry] & 0x7f) * 2;
3019 sprite = HighPreSpr + offs;
3020 code = sprite[1];
3021 pal = (code>>9)&0x30;
3022
3023 if (sh && pal == 0x30)
3024 {
3025 if (code & 0x8000) // hi priority
3026 {
3027 if (code&0x800) fTileFunc = TileFlipSH_AS;
3028 else fTileFunc = TileNormSH_AS;
3029 } else {
3030 if (code&0x800) fTileFunc = TileFlipSH_AS_onlyop_lp;
3031 else fTileFunc = TileNormSH_AS_onlyop_lp;
3032 }
3033 } else {
3034 if (code & 0x8000) // hi priority
3035 {
3036 if (code&0x800) fTileFunc = TileFlipAS;
3037 else fTileFunc = TileNormAS;
3038 } else {
3039 if (code&0x800) fTileFunc = TileFlipAS_onlymark;
3040 else fTileFunc = TileNormAS_onlymark;
3041 }
3042 }
3043
3044 // parse remaining sprite data
3045 sy=sprite[0];
3046 sx=code>>16; // X
3047 width=sy>>28;
3048 height=(sy>>24)&7; // Width and height in tiles
3049 sy=(sy<<16)>>16; // Y
3050
3051 row=Scanline-sy; // Row of the sprite we are on
3052
3053 if (code&0x1000) row=(height<<3)-1-row; // Flip Y
3054
3055 tile=code + (row>>3); // Tile number increases going down
3056 delta=height; // Delta to increase tile by going right
3057 if (code&0x0800) { tile+=delta*(width-1); delta=-delta; } // Flip X
3058
3059 tile &= 0x7ff; tile<<=4; tile+=(row&7)<<1; // Tile address
3060 delta<<=4; // Delta of address
3061
3062 for (; width; width--,sx+=8,tile+=delta)
3063 {
3064 unsigned int pack;
3065
3066 if(sx<=0) continue;
3067 if(sx>=328) break; // Offscreen
3068
3069 pack = *(unsigned int *)(RamVid + (tile & 0x7fff));
3070 fTileFunc(pd + sx, mb + sx, pack, pal|0x8000);
3071 }
3072 }
3073 }
3074
3075
3076 // Index + 0 : ----hhvv -lllllll -------y yyyyyyyy
3077 // Index + 4 : -------x xxxxxxxx pccvhnnn nnnnnnnn
3078 // v
3079 // Index + 0 : hhhhvvvv ----hhvv yyyyyyyy yyyyyyyy // v, h: vert./horiz. size
3080 // Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8
3081
PrepareSprites(int full)3082 static void PrepareSprites(int full)
3083 {
3084 int u,link=0,sh;
3085 int table=0;
3086 int *pd = HighPreSpr;
3087 int max_lines = 224, max_sprites = 80, max_width = 328;
3088 int max_line_sprites = 20; // 20 sprites, 40 tiles
3089
3090 if (!(RamVReg->reg[12]&1))
3091 max_sprites = 64, max_line_sprites = 16, max_width = 264;
3092 if (0) //PicoIn.opt & POPT_DIS_SPRITE_LIM)
3093 max_line_sprites = MAX_LINE_SPRITES;
3094
3095 if (RamVReg->reg[1]&8) max_lines = 240;
3096 sh = RamVReg->reg[0xC]&8; // shadow/hilight?
3097
3098 table=RamVReg->reg[5]&0x7f;
3099 if (RamVReg->reg[12]&1) table&=0x7e; // Lowest bit 0 in 40-cell mode
3100 table<<=8; // Get sprite table address/2
3101
3102 if (!full)
3103 {
3104 int pack;
3105 // updates: tilecode, sx
3106 for (u=0; u < max_sprites && (pack = *pd); u++, pd+=2)
3107 {
3108 unsigned int *sprite;
3109 int code2, sx, sy, height;
3110
3111 sprite=(unsigned int *)(RamVid+((table+(link<<2))&0x7ffc)); // Find sprite
3112
3113 // parse sprite info
3114 code2 = sprite[1];
3115 sx = (code2>>16)&0x1ff;
3116 sx -= 0x78; // Get X coordinate + 8
3117 sy = (pack << 16) >> 16;
3118 height = (pack >> 24) & 0xf;
3119
3120 if (sy < max_lines &&
3121 sy + (height<<3) > Scanline && // sprite onscreen (y)?
3122 (sx > -24 || sx < max_width)) // onscreen x
3123 {
3124 int y = (sy >= Scanline) ? sy : Scanline;
3125 int entry = ((pd - HighPreSpr) / 2) | ((code2>>8)&0x80);
3126 for (; y < sy + (height<<3) && y < max_lines; y++)
3127 {
3128 int i, cnt;
3129 cnt = HighLnSpr[y][0] & 0x7f;
3130 if (cnt >= max_line_sprites) continue; // sprite limit?
3131
3132 for (i = 0; i < cnt; i++)
3133 if (((HighLnSpr[y][3+i] ^ entry) & 0x7f) == 0) goto found;
3134
3135 // this sprite was previously missing
3136 HighLnSpr[y][3+cnt] = entry;
3137 HighLnSpr[y][0] = cnt + 1;
3138 found:;
3139 if (entry & 0x80)
3140 HighLnSpr[y][1] |= SPRL_HAVE_HI;
3141 else HighLnSpr[y][1] |= SPRL_HAVE_LO;
3142 }
3143 }
3144
3145 code2 &= ~0xfe000000;
3146 code2 -= 0x00780000; // Get X coordinate + 8 in upper 16 bits
3147 pd[1] = code2;
3148
3149 // Find next sprite
3150 link=(sprite[0]>>16)&0x7f;
3151 if (!link) break; // End of sprites
3152 }
3153 }
3154 else
3155 {
3156 for (u = 0; u < max_lines; u++)
3157 *((int *)&HighLnSpr[u][0]) = 0;
3158
3159 for (u = 0; u < max_sprites; u++)
3160 {
3161 unsigned int *sprite;
3162 int code, code2, sx, sy, hv, height, width;
3163
3164 sprite=(unsigned int *)(RamVid+((table+(link<<2))&0x7ffc)); // Find sprite
3165
3166 // parse sprite info
3167 code = sprite[0];
3168 sy = (code&0x1ff)-0x80;
3169 hv = (code>>24)&0xf;
3170 height = (hv&3)+1;
3171
3172 width = (hv>>2)+1;
3173 code2 = sprite[1];
3174 sx = (code2>>16)&0x1ff;
3175 sx -= 0x78; // Get X coordinate + 8
3176
3177 if (sy < max_lines && sy + (height<<3) > Scanline) // sprite onscreen (y)?
3178 {
3179 int entry, y, sx_min, onscr_x, maybe_op = 0;
3180
3181 sx_min = 8-(width<<3);
3182 onscr_x = sx_min < sx && sx < max_width;
3183 if (sh && (code2 & 0x6000) == 0x6000)
3184 maybe_op = SPRL_MAY_HAVE_OP;
3185
3186 entry = ((pd - HighPreSpr) / 2) | ((code2>>8)&0x80);
3187 y = (sy >= Scanline) ? sy : Scanline;
3188 for (; y < sy + (height<<3) && y < max_lines; y++)
3189 {
3190 unsigned char *p = &HighLnSpr[y][0];
3191 int cnt = p[0];
3192 if (cnt >= max_line_sprites) continue; // sprite limit?
3193
3194 if (p[2] >= max_line_sprites*2) { // tile limit?
3195 p[0] |= 0x80;
3196 continue;
3197 }
3198 p[2] += width;
3199
3200 if (sx == -0x78) {
3201 if (sy == -1 && is_ribbit) continue; // ribbit: bad sprite:sprite masking on the beach level
3202
3203 //bprintf(0, _T("masked @ %d,%d (x,y)\twidth,height %x,%x\tcnt/pri %x %x\tScanline %d\ty %d\n"), sx, sy, width,height, cnt,(entry & 0x80), Scanline, y);
3204
3205 if (cnt > 0)
3206 p[0] |= 0x80; // masked, no more sprites for this line
3207 continue;
3208 }
3209 // must keep the first sprite even if it's offscreen, for masking
3210 if (cnt > 0 && !onscr_x) continue; // offscreen x
3211
3212 p[3+cnt] = entry;
3213 p[0] = cnt + 1;
3214 p[1] |= (entry & 0x80) ? SPRL_HAVE_HI : SPRL_HAVE_LO;
3215 p[1] |= maybe_op; // there might be op sprites on this line
3216 if (cnt > 0 && (code2 & 0x8000) && !(p[3+cnt-1]&0x80))
3217 p[1] |= SPRL_LO_ABOVE_HI;
3218 }
3219 }
3220
3221 *pd++ = (width<<28)|(height<<24)|(hv<<16)|((unsigned short)sy);
3222 *pd++ = (sx<<16)|((unsigned short)code2);
3223
3224 // Find next sprite
3225 link=(code>>16)&0x7f;
3226 if (!link) break; // End of sprites
3227 }
3228 *pd = 0;
3229
3230 #if 0
3231 for (u = 0; u < max_lines; u++)
3232 {
3233 int y;
3234 printf("c%03i: %2i, %2i: ", u, HighLnSpr[u][0] & 0x7f, HighLnSpr[u][2]);
3235 for (y = 0; y < HighLnSpr[u][0] & 0x7f; y++)
3236 printf(" %i", HighLnSpr[u][y+3]);
3237 printf("\n");
3238 }
3239 #endif
3240 }
3241 }
3242
DrawAllSprites(unsigned char * sprited,int prio,int sh)3243 static void DrawAllSprites(unsigned char *sprited, int prio, int sh)
3244 {
3245 unsigned char *p;
3246 int cnt;
3247
3248 cnt = sprited[0] & 0x7f;
3249 if (cnt == 0) return;
3250
3251 p = &sprited[3];
3252
3253 // Go through sprites backwards:
3254 for (cnt--; cnt >= 0; cnt--)
3255 {
3256 int offs;
3257 if ((p[cnt] >> 7) != prio) continue;
3258 offs = (p[cnt]&0x7f) * 2;
3259 DrawSprite(HighPreSpr + offs, sh);
3260 }
3261 }
3262
3263
3264 // --------------------------------------------
3265
BackFill(INT32 reg7,INT32 sh)3266 static void BackFill(INT32 reg7, INT32 sh)
3267 {
3268 // Start with a blank scanline (background colour):
3269 UINT16 *pd = (UINT16 *)(HighCol+8);
3270 UINT16 *end= (UINT16 *)(HighCol+8+320);
3271 UINT16 back = (reg7 & 0x3f) | (sh<<6);
3272 back |= back<<8;
3273 do { pd[0]=pd[1]=back; pd+=2; } while (pd < end);
3274 }
3275
3276
DrawDisplay(int sh)3277 static int DrawDisplay(int sh)
3278 {
3279 unsigned char *sprited = &HighLnSpr[Scanline][0];
3280 int win=0, edge=0, hvwind=0, lflags;
3281 int maxw, maxcells;
3282
3283 if (RamVReg->rendstatus & (PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES)) {
3284 // elprintf(EL_STATUS, "PrepareSprites(%i)", (est->rendstatus>>4)&1);
3285 PrepareSprites(RamVReg->rendstatus & PDRAW_DIRTY_SPRITES);
3286 RamVReg->rendstatus &= ~(PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES);
3287 }
3288
3289 RamVReg->rendstatus &= ~(PDRAW_SHHI_DONE|PDRAW_PLANE_HI_PRIO);
3290
3291 if (RamVReg->reg[12]&1) {
3292 maxw = 328; maxcells = 40;
3293 } else {
3294 maxw = 264; maxcells = 32;
3295 }
3296
3297 // Find out if the window is on this line:
3298 win=RamVReg->reg[0x12];
3299 edge=(win&0x1f)<<3;
3300
3301 if (win&0x80) { if (Scanline>=edge) hvwind=1; }
3302 else { if (Scanline< edge) hvwind=1; }
3303
3304 if (!hvwind) // we might have a vertical window here
3305 {
3306 win=RamVReg->reg[0x11];
3307 edge=win&0x1f;
3308 if (win&0x80) {
3309 if (!edge) hvwind=1;
3310 else if(edge < (maxcells>>1)) hvwind=2;
3311 } else {
3312 if (!edge);
3313 else if(edge < (maxcells>>1)) hvwind=2;
3314 else hvwind=1;
3315 }
3316 }
3317
3318 // if (hvwind) bprintf(0, _T("we have window! %x\n"), hvwind);
3319
3320 /* - layer B low - */
3321 if (!(RamVReg->debug_p & PVD_KILL_B)) {
3322 lflags = LF_PLANE_1 | (sh << 1);
3323 if (RamVReg->debug_p & PVD_FORCE_B)
3324 lflags |= LF_FORCE;
3325 DrawLayer(lflags, HighCacheB, 0, maxcells);
3326 }
3327 /* - layer A low - */
3328 lflags = 0 | (sh << 1);
3329 if (RamVReg->debug_p & PVD_FORCE_A)
3330 lflags |= LF_FORCE;
3331 if (RamVReg->debug_p & PVD_KILL_A)
3332 ;
3333 else if (hvwind == 1)
3334 DrawWindow(0, maxcells>>1, 0, sh);
3335 else if (hvwind == 2) {
3336 DrawLayer(lflags, HighCacheA, (win&0x80) ? 0 : edge<<1, (win&0x80) ? edge<<1 : maxcells);
3337 DrawWindow( (win&0x80) ? edge : 0, (win&0x80) ? maxcells>>1 : edge, 0, sh);
3338 }
3339 else
3340 DrawLayer(lflags, HighCacheA, 0, maxcells);
3341 /* - sprites low - */
3342 if (RamVReg->debug_p & PVD_KILL_S_LO)
3343 ;
3344 else if (RamVReg->rendstatus & PDRAW_INTERLACE)
3345 DrawAllSpritesInterlace(0, sh);
3346 else if (sprited[1] & SPRL_HAVE_LO)
3347 DrawAllSprites(sprited, 0, sh);
3348
3349 /* - layer B hi - */
3350 if (!(RamVReg->debug_p & PVD_KILL_B) && HighCacheB[0])
3351 DrawTilesFromCache(HighCacheB, sh, maxw);
3352 /* - layer A hi - */
3353 if (RamVReg->debug_p & PVD_KILL_A)
3354 ;
3355 else if (hvwind == 1)
3356 DrawWindow(0, maxcells>>1, 1, sh);
3357 else if (hvwind == 2) {
3358 if (HighCacheA[0])
3359 DrawTilesFromCache(HighCacheA, sh, (win&0x80) ? edge<<4 : maxw);
3360 DrawWindow((win&0x80) ? edge : 0, (win&0x80) ? maxcells>>1 : edge, 1, sh);
3361 } else
3362 if (HighCacheA[0])
3363 DrawTilesFromCache(HighCacheA, sh, maxw);
3364 /* - sprites hi - */
3365 if (RamVReg->debug_p & PVD_KILL_S_HI)
3366 ;
3367 else if (RamVReg->rendstatus & PDRAW_INTERLACE)
3368 DrawAllSpritesInterlace(1, sh);
3369 // have sprites without layer pri bit ontop of sprites with that bit
3370 else if ((sprited[1] & 0xd0) == 0xd0 && 1)// (PicoIn.opt & POPT_ACC_SPRITES))
3371 DrawSpritesHiAS(sprited, sh);
3372 else if (sh && (sprited[1] & SPRL_MAY_HAVE_OP))
3373 DrawSpritesSHi(sprited);
3374 else if (sprited[1] & SPRL_HAVE_HI)
3375 DrawAllSprites(sprited, 1, 0);
3376
3377 if (RamVReg->debug_p & PVD_FORCE_B)
3378 DrawTilesFromCacheForced(HighCacheB);
3379 else if (RamVReg->debug_p & PVD_FORCE_A)
3380 DrawTilesFromCacheForced(HighCacheA);
3381
3382 #if 0
3383 {
3384 int *c, a, b;
3385 for (a = 0, c = HighCacheA; *c; c++, a++);
3386 for (b = 0, c = HighCacheB; *c; c++, b++);
3387 printf("%i:%03i: a=%i, b=%i\n", Pico.m.frame_count,
3388 Scanline, a, b);
3389 }
3390 #endif
3391
3392 return 0;
3393 }
3394
SetHighCol(INT32 line)3395 static void SetHighCol(INT32 line)
3396 {
3397 INT32 offset = (~RamVReg->reg[1] & 8) ? 8 : 0;
3398
3399 HighCol = HighColFull + ( (offset + line) * (8 + 320 + 8) );
3400 }
3401
PicoFrameStart()3402 static void PicoFrameStart()
3403 {
3404 // prepare to do this frame
3405 RamVReg->status &= ~0x0020; // mask collision bit
3406
3407 INT32 offs = 8, lines = 224;
3408
3409 // prepare to do this frame
3410 RamVReg->rendstatus = 0;
3411 if ((RamVReg->reg[12] & 6) == 6)
3412 RamVReg->rendstatus |= PDRAW_INTERLACE; // interlace mode
3413 if (!(RamVReg->reg[12] & 1))
3414 RamVReg->rendstatus |= PDRAW_32_COLS;
3415 if (RamVReg->reg[1] & 8) {
3416 offs = 0;
3417 lines = 240;
3418 }
3419
3420 Scanline = 0;
3421 BlankedLine = 0;
3422
3423 interlacemode2 = ((RamVReg->reg[12] & (4|2)) == (4|2));
3424
3425 SetHighCol(0); // start rendering here
3426
3427 PrepareSprites(1);
3428
3429 RamVReg->status &= ~0x88; // clear V-Int, come out of vblank
3430 RamVReg->v_counter = 0;
3431 }
3432
fix_palette(UINT8 * dest8,INT32 DestXY,UINT16 * psrc)3433 static void fix_palette(UINT8 *dest8, INT32 DestXY, UINT16 *psrc)
3434 {
3435 UINT16 *dest16 = (UINT16*)dest8 + DestXY;
3436 UINT32 *dest32 = (UINT32*)dest8 + DestXY;
3437 dest8 += DestXY;
3438
3439 for (INT32 x = 0; x < nScreenWidth; x++)
3440 {
3441 UINT16 src = psrc[x];
3442 UINT16 *pPalLUT = (src & 0x8000) ? SegaC2SpPalLookup : SegaC2BgPalLookup;
3443 UINT32 destrgb = 0;
3444
3445 switch (src & 0xc0)
3446 {
3447 case 0x00:
3448 destrgb = DrvPalette[(src & 0x0f) | pPalLUT[(src & 0x30) >> 4] | 0x0000];
3449 break;
3450
3451 case 0x40:
3452 case 0xc0:
3453 destrgb = DrvPalette[(src & 0x0f) | pPalLUT[(src & 0x30) >> 4] | 0x0800];
3454 break;
3455
3456 case 0x80:
3457 destrgb = DrvPalette[(src & 0x0f) | pPalLUT[(src & 0x30) >> 4] | 0x1000];
3458 break;
3459 }
3460
3461 switch (nBurnBpp) {
3462 case 4: dest32[x] = destrgb; break;
3463 case 3: dest8[x*3 + 0] = destrgb; dest8[x*3 + 1] = destrgb >> 8; dest8[x*3 + 2] = destrgb >> 16; break;
3464 case 2: dest16[x] = destrgb; break;
3465 }
3466 }
3467 }
3468
PicoLine(INT32 y)3469 static INT32 PicoLine(INT32 y)
3470 {
3471 INT32 lines_vis = 224;
3472 if (RamVReg->reg[1]&8) lines_vis = 240;
3473 INT32 vcnt_wrap = 0;
3474
3475 irq6_line = lines_vis;
3476
3477 // handle fifo and vcounter zoop
3478 RamVReg->v_counter = y;
3479 if (y < lines_vis) {
3480 // VDP FIFO
3481 RamVReg->lwrite_cnt -= 12;
3482 if (RamVReg->lwrite_cnt <= 0) {
3483 RamVReg->lwrite_cnt=0;
3484 RamVReg->status|=0x200;
3485 }
3486 if ((RamVReg->reg[12]&6) == 6) { // interlace mode 2
3487 RamVReg->v_counter <<= 1;
3488 RamVReg->v_counter |= RamVReg->v_counter >> 8;
3489 RamVReg->v_counter &= 0xff;
3490 }
3491 } else if (y == lines_vis) {
3492 vcnt_wrap = (Hardware & 0x40) ? 0x103 : 0xEB; // based on Gens, TODO: verify
3493 if ((RamVReg->reg[12]&6) == 6) RamVReg->v_counter = 0xc1;
3494 // VDP FIFO
3495 RamVReg->lwrite_cnt = 0;
3496 RamVReg->status |= 0x200;
3497
3498 return 0; // ---- don't draw ----
3499 } else if (y > lines_vis) {
3500 if (y >= vcnt_wrap)
3501 RamVReg->v_counter -= (Hardware & 0x40) ? 313 : 262;//(Hardware & 0x40) ? 56 : 6;
3502 if ((RamVReg->reg[12]&6) == 6)
3503 RamVReg->v_counter = (RamVReg->v_counter << 1) | 1;
3504 RamVReg->v_counter &= 0xff;
3505
3506 return 0; // ---- don't draw ----
3507 }
3508
3509 INT32 sh = (RamVReg->reg[0xC] & 8)>>3; // shadow/hilight?
3510
3511 BackFill(RamVReg->reg[7], sh);
3512
3513 INT32 offset = (~RamVReg->reg[1] & 8) ? 8 : 0;
3514
3515 if (BlankedLine && Scanline > 0 && !interlacemode2) // blank last line stuff
3516 {
3517 { // copy blanked line to previous line
3518 // UINT16 *pDest = LineBuf + ((Scanline-1) * 320) + ((interlacemode2 & RamVReg->field) * 240 * 320);
3519 // UINT16 *pSrc = HighColFull + (Scanline + offset + ((interlacemode2 & RamVReg->field) * 240))*(8+320+8) + 8;
3520
3521 // memcpy(pDest, pSrc, 320 * sizeof(UINT16));
3522 }
3523 }
3524 BlankedLine = 0;
3525
3526 if (RamVReg->reg[1] & 0x40)
3527 DrawDisplay(sh);
3528
3529 {
3530 SetHighCol(Scanline + 1); // Set-up pointer to next line to be rendered to (see: PicoFrameStart();)
3531
3532 { // copy current line to linebuf, for mid-screen palette changes (referred to as SONIC rendering mode, for water & etc.)
3533 UINT32 DestXY = (Scanline * nScreenWidth) + ((interlacemode2 & RamVReg->field) * 240 * 320);
3534 UINT16 *pSrc = HighColFull + (Scanline + offset + ((interlacemode2 & RamVReg->field) * 240))*(8+320+8) + 8;
3535
3536 if (pBurnDraw) fix_palette(pBurnDraw, DestXY, pSrc);
3537 }
3538 }
3539
3540 return 0;
3541 }
3542
DrvDrawBegin()3543 static void DrvDrawBegin() // run in-frame
3544 {
3545 if (DrvRecalc) {
3546 for (INT32 i = 0; i < 0x800; i++) {
3547 palette_update(i);
3548 }
3549 DrvPalette[0x3000] = 0; // black
3550 DrvRecalc = 0;
3551 }
3552 }
3553
DrvDrawEnd()3554 static void DrvDrawEnd()
3555 {
3556 if (!enable_display) {
3557 BurnTransferClear(0x3000);
3558 BurnTransferCopy(DrvPalette);
3559 }
3560 }
3561
DrvDraw()3562 static INT32 DrvDraw() // called when paused for redraw or mode change
3563 {
3564 DrvDrawBegin();
3565
3566 INT32 offset = (~RamVReg->reg[1] & 8) ? 8 : 0;
3567
3568 for (INT32 i = 0; i < nScreenHeight; i++)
3569 {
3570 UINT32 DestXY = (i * nScreenWidth) + ((interlacemode2 & RamVReg->field) * 240 * 320);
3571 UINT16 *pSrc = HighColFull + (i + offset + ((interlacemode2 & RamVReg->field) * 240))*(8+320+8) + 8;
3572
3573 if (pBurnDraw) fix_palette(pBurnDraw, DestXY, pSrc);
3574 }
3575
3576 DrvDrawEnd();
3577
3578 return 0;
3579 }
3580
DrvFrame()3581 static INT32 DrvFrame()
3582 {
3583 if (DrvReset) {
3584 DrvDoReset();
3585 }
3586
3587 SekNewFrame();
3588 NullNewFrame();
3589
3590 {
3591 memset (DrvInputs, 0xff, sizeof(DrvInputs));
3592
3593 for (INT32 i = 0; i < 8; i++) {
3594 DrvInputs[0] ^= (DrvJoy1[i] & 1) << i;
3595 DrvInputs[1] ^= (DrvJoy2[i] & 1) << i;
3596 DrvInputs[4] ^= (DrvJoy3[i] & 1) << i;
3597 }
3598 DrvInputs[5] = DrvDips[0];
3599 DrvInputs[6] = DrvDips[1];
3600
3601 if (is_wwmarine) {
3602 DrvInputs[0] |= (nCurrentFrame & 1) * 0xc0; // l/r pulsed by digital steering wheel
3603 }
3604
3605 if (has_dial) {
3606 BurnTrackballConfig(0, AXIS_NORMAL, AXIS_NORMAL);
3607 BurnTrackballFrame(0, Analog[0], Analog[1], 1, 0x1f);
3608 BurnTrackballUpdate(0);
3609 DrvInputs[0] = BurnTrackballRead(0, 0);
3610 DrvInputs[1] = BurnTrackballRead(0, 1);
3611 }
3612 }
3613
3614 if (pBurnDraw) DrvDrawBegin(); // re-calc palette if necessary
3615
3616 PicoFrameStart();
3617
3618 INT32 nInterleave = 262;
3619 INT32 nCyclesTotal[2] = { (INT32)(53693175 / 6 / 59.922745), (INT32)(53693175 / 6 / 59.922745) };
3620 INT32 nCyclesDone[2] = { 0, 0 };
3621
3622 SekOpen(0);
3623 SekIdle(nExtraCycles[0]);
3624
3625 irq4_counter = RamVReg->reg[0x0a];
3626
3627 for (INT32 i = 0; i < nInterleave; i++)
3628 {
3629 Scanline = i;
3630 line_base_cycles = SekTotalCycles();
3631
3632 SekIdle(DMABURN());
3633
3634 CPU_RUN_SYNCINT(0, Sek);
3635 CPU_RUN_TIMER(1); // nullcpu for fm timer (we can't have the fm timer breaking Sek execution)
3636
3637 PicoLine(Scanline); // draw & blit line
3638
3639 if (Scanline <= 224) {
3640 irq4_counter--;
3641 if (irq4_counter < 0) {
3642 irq4_counter = RamVReg->reg[0x0a];
3643 RamVReg->pending_ints |= 0x10;
3644 if (RamVReg->reg[0x00] & 0x10) {
3645 SekSetVIRQLine(4, CPU_IRQSTATUS_ACK);
3646 }
3647 }
3648 }
3649 if (Scanline == irq6_line) {
3650 RamVReg->status |= 0x08; // V-Int
3651 RamVReg->pending_ints |= 0x20;
3652 SekRun(68); // this is called "v-int lag" on megadrive
3653 SekSetVIRQLine(6, CPU_IRQSTATUS_ACK); // irq hooked to z80_irq (vdp), not the usual vdp vblank line!
3654
3655 if (pBurnDraw) DrvDrawEnd();
3656 }
3657 }
3658
3659 if (pBurnSoundOut) {
3660 BurnYM3438Update(pBurnSoundOut, nBurnSoundLen);
3661 if (sound_rom_length) {
3662 UPD7759Render(pBurnSoundOut, nBurnSoundLen);
3663 }
3664 }
3665
3666 nExtraCycles[0] = SekTotalCycles() - nCyclesTotal[0];
3667
3668 SekClose();
3669
3670 return 0;
3671 }
3672
DrvScan(INT32 nAction,INT32 * pnMin)3673 static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
3674 {
3675 struct BurnArea ba;
3676
3677 if (pnMin != NULL) {
3678 *pnMin = 0x029709;
3679 }
3680
3681 if (nAction & ACB_MEMORY_RAM) {
3682 memset(&ba, 0, sizeof(ba));
3683 ba.Data = AllRam;
3684 ba.nLen = RamEnd-AllRam;
3685 ba.szName = "All Ram";
3686 BurnAcb(&ba);
3687 }
3688
3689 if (nAction & ACB_DRIVER_DATA) {
3690 SekScan(nAction);
3691
3692 BurnYM3438Scan(nAction, pnMin);
3693 if (sound_rom_length) UPD7759Scan(nAction, pnMin);
3694 SN76496Scan(nAction, pnMin);
3695
3696 if (has_dial) BurnTrackballScan();
3697
3698 SCAN_VAR(prot_write_buf);
3699 SCAN_VAR(prot_read_buf);
3700 SCAN_VAR(enable_display);
3701 SCAN_VAR(alt_palette_mode);
3702 SCAN_VAR(palette_bank);
3703 SCAN_VAR(bg_palbase);
3704 SCAN_VAR(sp_palbase);
3705 SCAN_VAR(output_latch);
3706 SCAN_VAR(dir);
3707 SCAN_VAR(iocnt);
3708 SCAN_VAR(sound_bank);
3709 SCAN_VAR(irq6_line);
3710 SCAN_VAR(irq4_counter);
3711 SCAN_VAR(SegaC2BgPalLookup);
3712 SCAN_VAR(SegaC2SpPalLookup);
3713
3714 SCAN_VAR(Hardware);
3715 SCAN_VAR(dma_xfers);
3716 SCAN_VAR(BlankedLine);
3717 SCAN_VAR(interlacemode2);
3718
3719 SCAN_VAR(nExtraCycles);
3720 }
3721
3722 if (nAction & ACB_WRITE) {
3723 recompute_palette_tables();
3724
3725 if (sound_rom_length) {
3726 memcpy (DrvSndROM + 0x80000, DrvSndROM + (sound_bank * 0x20000), 0x20000);
3727 }
3728 }
3729
3730 return 0;
3731 }
3732
3733
3734 // Bloxeed (World, C System)
3735
3736 static struct BurnRomInfo bloxeedcRomDesc[] = {
3737 { "epr-12908.ic32", 0x20000, 0xfc77cb91, 3 | BRF_PRG | BRF_ESS }, // 0 68K Code
3738 { "epr-12907.ic31", 0x20000, 0xe5fcbac6, 3 | BRF_PRG | BRF_ESS }, // 1
3739 { "epr-12993.ic34", 0x20000, 0x487bc8fc, 3 | BRF_PRG | BRF_ESS }, // 2
3740 { "epr-12992.ic33", 0x20000, 0x19b0084c, 3 | BRF_PRG | BRF_ESS }, // 3
3741 };
3742
3743 STD_ROM_PICK(bloxeedc)
STD_ROM_FN(bloxeedc)3744 STD_ROM_FN(bloxeedc)
3745
3746 static UINT8 no_protection_callback(UINT8 in)
3747 {
3748 return 0;
3749 }
3750
NoProtectionInit()3751 static INT32 NoProtectionInit()
3752 {
3753 return SegaC2Init(no_protection_callback);
3754 }
3755
3756 struct BurnDriver BurnDrvBloxeedc = {
3757 "bloxeedc", "bloxeed", NULL, NULL, "1989",
3758 "Bloxeed (World, C System)\0", NULL, "Sega / Elorg", "C",
3759 NULL, NULL, NULL, NULL,
3760 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
3761 NULL, bloxeedcRomInfo, bloxeedcRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, BloxeedcDIPInfo,
3762 NoProtectionInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
3763 320, 224, 4, 3
3764 };
3765
3766
3767 // Bloxeed (US, C System, Rev A)
3768
3769 static struct BurnRomInfo bloxeeduRomDesc[] = {
3770 { "epr-12997a.ic32", 0x20000, 0x23655bc9, 3 | BRF_PRG | BRF_ESS }, // 0 68K Code
3771 { "epr-12996a.ic31", 0x20000, 0x83c83f0c, 3 | BRF_PRG | BRF_ESS }, // 1
3772 { "epr-12993.ic34", 0x20000, 0x487bc8fc, 3 | BRF_PRG | BRF_ESS }, // 2
3773 { "epr-12992.ic33", 0x20000, 0x19b0084c, 3 | BRF_PRG | BRF_ESS }, // 3
3774
3775 { "315-5393.ic24", 0x00001, 0x00000000, 0 | BRF_NODUMP | BRF_OPT }, // 4 pals
3776 { "315-5394.ic25", 0x00001, 0x00000000, 0 | BRF_NODUMP | BRF_OPT }, // 5
3777 { "315-5395.ic26", 0x00001, 0x00000000, 0 | BRF_NODUMP | BRF_OPT }, // 6
3778 { "317-0140.ic27", 0x00001, 0x00000000, 0 | BRF_NODUMP | BRF_OPT }, // 7
3779 };
3780
3781 STD_ROM_PICK(bloxeedu)
3782 STD_ROM_FN(bloxeedu)
3783
3784 struct BurnDriver BurnDrvBloxeedu = {
3785 "bloxeedu", "bloxeed", NULL, NULL, "1989",
3786 "Bloxeed (US, C System, Rev A)\0", NULL, "Sega / Elorg", "C",
3787 NULL, NULL, NULL, NULL,
3788 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
3789 NULL, bloxeeduRomInfo, bloxeeduRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, BloxeeduDIPInfo,
3790 NoProtectionInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
3791 320, 224, 4, 3
3792 };
3793
3794
3795 // Columns (World)
3796
3797 static struct BurnRomInfo columnsRomDesc[] = {
3798 { "epr-13114.ic32", 0x20000, 0xff78f740, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
3799 { "epr-13113.ic31", 0x20000, 0x9a426d9b, 1 | BRF_PRG | BRF_ESS }, // 1
3800 };
3801
3802 STD_ROM_PICK(columns)
STD_ROM_FN(columns)3803 STD_ROM_FN(columns)
3804
3805 static UINT8 columns_protection_callback(UINT8 in)
3806 {
3807 static const UINT8 prot_lut_table[0x100] = {
3808 0x02, 0x00, 0x0a, 0x04, 0x01, 0x03, 0x09, 0x07, 0x06, 0x04, 0x0e, 0x00, 0x05, 0x07, 0x0d, 0x03,
3809 0x02, 0x00, 0x0a, 0x04, 0x01, 0x03, 0x09, 0x07, 0x06, 0x04, 0x0e, 0x00, 0x05, 0x07, 0x0d, 0x03,
3810 0x02, 0x00, 0x0a, 0x04, 0x01, 0x03, 0x09, 0x07, 0x06, 0x04, 0x0e, 0x00, 0x05, 0x07, 0x0d, 0x03,
3811 0x0a, 0x08, 0x02, 0x04, 0x09, 0x0b, 0x01, 0x07, 0x0e, 0x0c, 0x06, 0x00, 0x0d, 0x0f, 0x05, 0x03,
3812 0x02, 0x00, 0x0a, 0x04, 0x01, 0x03, 0x09, 0x07, 0x06, 0x04, 0x0e, 0x00, 0x05, 0x07, 0x0d, 0x03,
3813 0x07, 0x05, 0x0f, 0x05, 0x04, 0x06, 0x0c, 0x06, 0x03, 0x01, 0x0b, 0x01, 0x00, 0x02, 0x08, 0x02,
3814 0x02, 0x00, 0x0a, 0x04, 0x01, 0x03, 0x09, 0x07, 0x06, 0x04, 0x0e, 0x00, 0x05, 0x07, 0x0d, 0x03,
3815 0x0f, 0x0d, 0x07, 0x05, 0x0c, 0x0e, 0x04, 0x06, 0x0b, 0x09, 0x03, 0x01, 0x08, 0x0a, 0x00, 0x02,
3816 0x0b, 0x08, 0x03, 0x04, 0x08, 0x0b, 0x00, 0x07, 0x0f, 0x0c, 0x07, 0x00, 0x0c, 0x0f, 0x04, 0x03,
3817 0x0b, 0x08, 0x03, 0x04, 0x08, 0x0b, 0x00, 0x07, 0x0f, 0x0c, 0x07, 0x00, 0x0c, 0x0f, 0x04, 0x03,
3818 0x09, 0x0a, 0x01, 0x06, 0x08, 0x0b, 0x00, 0x07, 0x0d, 0x0e, 0x05, 0x02, 0x0c, 0x0f, 0x04, 0x03,
3819 0x09, 0x0a, 0x01, 0x06, 0x08, 0x0b, 0x00, 0x07, 0x0d, 0x0e, 0x05, 0x02, 0x0c, 0x0f, 0x04, 0x03,
3820 0x03, 0x00, 0x0b, 0x04, 0x00, 0x03, 0x08, 0x07, 0x07, 0x04, 0x0f, 0x00, 0x04, 0x07, 0x0c, 0x03,
3821 0x07, 0x05, 0x0f, 0x05, 0x04, 0x06, 0x0c, 0x06, 0x03, 0x01, 0x0b, 0x01, 0x00, 0x02, 0x08, 0x02,
3822 0x03, 0x00, 0x0b, 0x04, 0x00, 0x03, 0x08, 0x07, 0x07, 0x04, 0x0f, 0x00, 0x04, 0x07, 0x0c, 0x03,
3823 0x0f, 0x0d, 0x07, 0x05, 0x0c, 0x0e, 0x04, 0x06, 0x0b, 0x09, 0x03, 0x01, 0x08, 0x0a, 0x00, 0x02
3824 };
3825
3826 return prot_lut_table[in];
3827 }
3828
ColumnsInit()3829 static INT32 ColumnsInit()
3830 {
3831 return SegaC2Init(columns_protection_callback);
3832 }
3833
3834 struct BurnDriver BurnDrvColumns = {
3835 "columns", NULL, NULL, NULL, "1990",
3836 "Columns (World)\0", NULL, "Sega", "C",
3837 NULL, NULL, NULL, NULL,
3838 BDF_GAME_WORKING, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
3839 NULL, columnsRomInfo, columnsRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, ColumnsDIPInfo,
3840 ColumnsInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
3841 320, 224, 4, 3
3842 };
3843
3844
3845 // Columns (US, cocktail, Rev A)
3846
3847 static struct BurnRomInfo columnsuRomDesc[] = {
3848 { "epr-13116a.ic32", 0x20000, 0xa0284b16, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
3849 { "epr-13115a.ic31", 0x20000, 0xe37496f3, 1 | BRF_PRG | BRF_ESS }, // 1
3850 };
3851
3852 STD_ROM_PICK(columnsu)
3853 STD_ROM_FN(columnsu)
3854
3855 struct BurnDriver BurnDrvColumnsu = {
3856 "columnsu", "columns", NULL, NULL, "1990",
3857 "Columns (US, cocktail, Rev A)\0", NULL, "Sega", "C",
3858 NULL, NULL, NULL, NULL,
3859 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
3860 NULL, columnsuRomInfo, columnsuRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, ColumnsDIPInfo,
3861 ColumnsInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
3862 320, 224, 4, 3
3863 };
3864
3865
3866 // Columns (Japan)
3867
3868 static struct BurnRomInfo columnsjRomDesc[] = {
3869 { "epr-13112.ic32", 0x20000, 0xbae6e53e, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
3870 { "epr-13111.ic31", 0x20000, 0xaa5ccd6d, 1 | BRF_PRG | BRF_ESS }, // 1
3871 };
3872
3873 STD_ROM_PICK(columnsj)
3874 STD_ROM_FN(columnsj)
3875
3876 struct BurnDriver BurnDrvColumnsj = {
3877 "columnsj", "columns", NULL, NULL, "1990",
3878 "Columns (Japan)\0", NULL, "Sega", "C",
3879 NULL, NULL, NULL, NULL,
3880 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
3881 NULL, columnsjRomInfo, columnsjRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, ColumnsDIPInfo,
3882 ColumnsInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
3883 320, 224, 4, 3
3884 };
3885
3886
3887 // Columns II: The Voyage Through Time (World)
3888
3889 static struct BurnRomInfo columns2RomDesc[] = {
3890 { "epr-13363.ic32", 0x20000, 0xc99e4ffd, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
3891 { "epr-13362.ic31", 0x20000, 0x394e2419, 1 | BRF_PRG | BRF_ESS }, // 1
3892 };
3893
3894 STD_ROM_PICK(columns2)
STD_ROM_FN(columns2)3895 STD_ROM_FN(columns2)
3896
3897 static UINT8 columns2_protection_callback(UINT8 in)
3898 {
3899 static const UINT8 prot_lut_table[0x100] = {
3900 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x00, 0x0c,
3901 0x08, 0x08, 0x09, 0x0d, 0x09, 0x09, 0x08, 0x04, 0x0c, 0x0e, 0x0d, 0x0b, 0x09, 0x0b, 0x08, 0x06,
3902 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x04, 0x0c,
3903 0x0d, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x04, 0x09, 0x0b, 0x09, 0x0b, 0x0c, 0x0e, 0x0c, 0x06,
3904 0x02, 0x02, 0x03, 0x07, 0x03, 0x03, 0x02, 0x0e, 0x02, 0x02, 0x03, 0x07, 0x03, 0x03, 0x02, 0x0e,
3905 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x06, 0x0e, 0x02, 0x00, 0x03, 0x01, 0x07, 0x05, 0x06, 0x0c,
3906 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x06, 0x0e, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x06, 0x0e,
3907 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, 0x0e, 0x03, 0x01, 0x03, 0x01, 0x06, 0x04, 0x06, 0x0c,
3908 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x00, 0x0c,
3909 0x08, 0x08, 0x09, 0x0d, 0x09, 0x09, 0x08, 0x04, 0x0c, 0x0e, 0x0d, 0x0b, 0x09, 0x0b, 0x08, 0x06,
3910 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x06, 0x0e, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x06, 0x0e,
3911 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x06, 0x0b, 0x09, 0x0b, 0x09, 0x0e, 0x0c, 0x0e, 0x04,
3912 0x0a, 0x0a, 0x0b, 0x0f, 0x0b, 0x0b, 0x0a, 0x06, 0x0a, 0x0a, 0x0b, 0x0f, 0x0b, 0x0b, 0x0a, 0x06,
3913 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x06, 0x0a, 0x08, 0x0b, 0x09, 0x0f, 0x0d, 0x0e, 0x04,
3914 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x06, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x06,
3915 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x06, 0x0b, 0x09, 0x0b, 0x09, 0x0e, 0x0c, 0x0e, 0x04
3916 };
3917
3918 return prot_lut_table[in];
3919 }
3920
Columns2Init()3921 static INT32 Columns2Init()
3922 {
3923 return SegaC2Init(columns2_protection_callback);
3924 }
3925
3926 struct BurnDriver BurnDrvColumns2 = {
3927 "columns2", NULL, NULL, NULL, "1990",
3928 "Columns II: The Voyage Through Time (World)\0", NULL, "Sega", "C",
3929 NULL, NULL, NULL, NULL,
3930 BDF_GAME_WORKING, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
3931 NULL, columns2RomInfo, columns2RomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, Columns2DIPInfo,
3932 Columns2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
3933 320, 224, 4, 3
3934 };
3935
3936
3937 // Columns II: The Voyage Through Time (Japan)
3938
3939 static struct BurnRomInfo column2jRomDesc[] = {
3940 { "epr-13361.ic32", 0x20000, 0xb54b5f12, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
3941 { "epr-13360.ic31", 0x20000, 0xa59b1d4f, 1 | BRF_PRG | BRF_ESS }, // 1
3942 };
3943
3944 STD_ROM_PICK(column2j)
3945 STD_ROM_FN(column2j)
3946
3947 struct BurnDriver BurnDrvColumn2j = {
3948 "column2j", "columns2", NULL, NULL, "1990",
3949 "Columns II: The Voyage Through Time (Japan)\0", NULL, "Sega", "C",
3950 NULL, NULL, NULL, NULL,
3951 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
3952 NULL, column2jRomInfo, column2jRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, Columns2DIPInfo,
3953 Columns2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
3954 320, 224, 4, 3
3955 };
3956
3957
3958 // Thunder Force AC
3959
3960 static struct BurnRomInfo tfrceacRomDesc[] = {
3961 { "epr-13675.ic32", 0x40000, 0x95ecf202, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
3962 { "epr-13674.ic31", 0x40000, 0xe63d7f1a, 1 | BRF_PRG | BRF_ESS }, // 1
3963 { "epr-13659.ic34", 0x40000, 0x29f23461, 1 | BRF_PRG | BRF_ESS }, // 2
3964 { "epr-13658.ic33", 0x40000, 0x9e23734f, 1 | BRF_PRG | BRF_ESS }, // 3
3965
3966 { "epr-13655.ic4", 0x40000, 0xe09961f6, 2 | BRF_SND }, // 4 UPD Samples
3967 };
3968
3969 STD_ROM_PICK(tfrceac)
STD_ROM_FN(tfrceac)3970 STD_ROM_FN(tfrceac)
3971
3972 static UINT8 tfrceac_protection_callback(UINT8 in)
3973 {
3974 static const UINT8 prot_lut_table[0x100] = {
3975 0x03, 0x0a, 0x03, 0x0a, 0x06, 0x0f, 0x06, 0x0f, 0x03, 0x08, 0x03, 0x08, 0x06, 0x0d, 0x06, 0x0d,
3976 0x03, 0x0a, 0x03, 0x0a, 0x06, 0x0f, 0x06, 0x0f, 0x02, 0x08, 0x02, 0x08, 0x07, 0x0d, 0x07, 0x0d,
3977 0x03, 0x0a, 0x03, 0x0a, 0x06, 0x0f, 0x06, 0x0f, 0x03, 0x08, 0x03, 0x08, 0x06, 0x0d, 0x06, 0x0d,
3978 0x03, 0x0a, 0x03, 0x0a, 0x06, 0x0f, 0x06, 0x0f, 0x02, 0x08, 0x02, 0x08, 0x07, 0x0d, 0x07, 0x0d,
3979 0x07, 0x0e, 0x03, 0x0a, 0x02, 0x0b, 0x06, 0x0f, 0x07, 0x0c, 0x03, 0x08, 0x02, 0x09, 0x06, 0x0d,
3980 0x07, 0x0e, 0x0b, 0x02, 0x02, 0x0b, 0x0e, 0x07, 0x06, 0x0c, 0x0a, 0x00, 0x03, 0x09, 0x0f, 0x05,
3981 0x07, 0x0e, 0x03, 0x0a, 0x02, 0x0b, 0x06, 0x0f, 0x07, 0x0c, 0x03, 0x08, 0x02, 0x09, 0x06, 0x0d,
3982 0x07, 0x0e, 0x0b, 0x02, 0x02, 0x0b, 0x0e, 0x07, 0x06, 0x0c, 0x0a, 0x00, 0x03, 0x09, 0x0f, 0x05,
3983 0x03, 0x0b, 0x03, 0x0b, 0x06, 0x0e, 0x06, 0x0e, 0x03, 0x09, 0x03, 0x09, 0x06, 0x0c, 0x06, 0x0c,
3984 0x05, 0x0d, 0x0d, 0x05, 0x00, 0x08, 0x08, 0x00, 0x04, 0x0e, 0x0c, 0x06, 0x01, 0x0b, 0x09, 0x03,
3985 0x03, 0x0b, 0x03, 0x0b, 0x06, 0x0e, 0x06, 0x0e, 0x03, 0x09, 0x03, 0x09, 0x06, 0x0c, 0x06, 0x0c,
3986 0x03, 0x0b, 0x0b, 0x03, 0x06, 0x0e, 0x0e, 0x06, 0x02, 0x08, 0x0a, 0x00, 0x07, 0x0d, 0x0f, 0x05,
3987 0x05, 0x0d, 0x01, 0x09, 0x00, 0x08, 0x04, 0x0c, 0x05, 0x0d, 0x01, 0x09, 0x00, 0x08, 0x04, 0x0c,
3988 0x07, 0x0f, 0x0f, 0x07, 0x02, 0x0a, 0x0a, 0x02, 0x06, 0x0e, 0x0e, 0x06, 0x03, 0x0b, 0x0b, 0x03,
3989 0x05, 0x0d, 0x01, 0x09, 0x00, 0x08, 0x04, 0x0c, 0x05, 0x0d, 0x01, 0x09, 0x00, 0x08, 0x04, 0x0c,
3990 0x05, 0x0d, 0x09, 0x01, 0x00, 0x08, 0x0c, 0x04, 0x04, 0x0c, 0x08, 0x00, 0x01, 0x09, 0x0d, 0x05,
3991 };
3992
3993 return prot_lut_table[in];
3994 }
3995
TfrceacInit()3996 static INT32 TfrceacInit()
3997 {
3998 return SegaC2Init(tfrceac_protection_callback);
3999 }
4000
4001 struct BurnDriver BurnDrvTfrceac = {
4002 "tfrceac", NULL, NULL, NULL, "1990",
4003 "Thunder Force AC\0", NULL, "Technosoft / Sega", "C2",
4004 NULL, NULL, NULL, NULL,
4005 BDF_GAME_WORKING, 1, HARDWARE_SEGA_MISC, GBF_HORSHOOT, 0,
4006 NULL, tfrceacRomInfo, tfrceacRomName, NULL, NULL, NULL, NULL, SegaC2_3ButtonInputInfo, TfrceacDIPInfo,
4007 TfrceacInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4008 320, 224, 4, 3
4009 };
4010
4011
4012 // Thunder Force AC (Japan)
4013
4014 static struct BurnRomInfo tfrceacjRomDesc[] = {
4015 { "epr-13657.ic32", 0x40000, 0xa0f38ffd, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4016 { "epr-13656.ic31", 0x40000, 0xb9438d1e, 1 | BRF_PRG | BRF_ESS }, // 1
4017 { "epr-13659.ic34", 0x40000, 0x29f23461, 1 | BRF_PRG | BRF_ESS }, // 2
4018 { "epr-13658.ic33", 0x40000, 0x9e23734f, 1 | BRF_PRG | BRF_ESS }, // 3
4019
4020 { "epr-13655.ic4", 0x40000, 0xe09961f6, 2 | BRF_SND }, // 4 UPD Samples
4021 };
4022
4023 STD_ROM_PICK(tfrceacj)
4024 STD_ROM_FN(tfrceacj)
4025
4026 struct BurnDriver BurnDrvTfrceacj = {
4027 "tfrceacj", "tfrceac", NULL, NULL, "1990",
4028 "Thunder Force AC (Japan)\0", NULL, "Technosoft / Sega", "C2",
4029 NULL, NULL, NULL, NULL,
4030 BDF_GAME_WORKING | BDF_CLONE, 1, HARDWARE_SEGA_MISC, GBF_HORSHOOT, 0,
4031 NULL, tfrceacjRomInfo, tfrceacjRomName, NULL, NULL, NULL, NULL, SegaC2_3ButtonInputInfo, TfrceacDIPInfo,
4032 TfrceacInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4033 320, 224, 4, 3
4034 };
4035
4036
4037 // Thunder Force AC (Japan, prototype, bootleg)
4038
4039 static struct BurnRomInfo tfrceacjpbRomDesc[] = {
4040 { "ic32_t.f.ac_075f.ic32", 0x40000, 0x2167dd93, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4041 { "ic31_t.f.ac_0d26.id31", 0x40000, 0xebf02bba, 1 | BRF_PRG | BRF_ESS }, // 1
4042 { "ic34_t.f.ac_549d.ic34", 0x40000, 0x902ad2ec, 1 | BRF_PRG | BRF_ESS }, // 2
4043 { "ic33_t.f.ac_d131.ic33", 0x40000, 0xb162219d, 1 | BRF_PRG | BRF_ESS }, // 3
4044 };
4045
4046 STD_ROM_PICK(tfrceacjpb)
STD_ROM_FN(tfrceacjpb)4047 STD_ROM_FN(tfrceacjpb)
4048
4049 static INT32 TfrceacjpbInit()
4050 {
4051 INT32 rc = SegaC2Init(tfrceac_protection_callback);
4052 dir_override = 0xf; // issue w/io chip
4053
4054 return rc;
4055 }
4056
4057 struct BurnDriver BurnDrvTfrceacjpb = {
4058 "tfrceacjpb", "tfrceac", NULL, NULL, "1990",
4059 "Thunder Force AC (Japan, prototype, bootleg)\0", NULL, "Technosoft / Sega", "C2",
4060 NULL, NULL, NULL, NULL,
4061 BDF_GAME_WORKING | BDF_CLONE | BDF_PROTOTYPE | BDF_BOOTLEG, 1, HARDWARE_SEGA_MISC, GBF_HORSHOOT, 0,
4062 NULL, tfrceacjpbRomInfo, tfrceacjpbRomName, NULL, NULL, NULL, NULL, SegaC2_3ButtonInputInfo, TfrceacDIPInfo,
4063 TfrceacjpbInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4064 320, 224, 4, 3
4065 };
4066
4067
4068 // Thunder Force AC (bootleg)
4069
4070 static struct BurnRomInfo tfrceacbRomDesc[] = {
4071 { "4.bin", 0x40000, 0xeba059d3, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4072 { "3.bin", 0x40000, 0x3e5dc542, 1 | BRF_PRG | BRF_ESS }, // 1
4073 { "epr-13659.ic34", 0x40000, 0x29f23461, 1 | BRF_PRG | BRF_ESS }, // 2
4074 { "epr-13658.ic33", 0x40000, 0x9e23734f, 1 | BRF_PRG | BRF_ESS }, // 3
4075
4076 { "epr-13655.ic4", 0x40000, 0xe09961f6, 2 | BRF_SND }, // 4 UPD Samples
4077 };
4078
4079 STD_ROM_PICK(tfrceacb)
STD_ROM_FN(tfrceacb)4080 STD_ROM_FN(tfrceacb)
4081
4082 static INT32 TfrceacbInit()
4083 {
4084 is_tfrceacb = 1;
4085
4086 return SegaC2Init(no_protection_callback);
4087 }
4088
4089 struct BurnDriver BurnDrvTfrceacb = {
4090 "tfrceacb", "tfrceac", NULL, NULL, "1990",
4091 "Thunder Force AC (bootleg)\0", NULL, "bootleg", "C2",
4092 NULL, NULL, NULL, NULL,
4093 BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 1, HARDWARE_SEGA_MISC, GBF_HORSHOOT, 0,
4094 NULL, tfrceacbRomInfo, tfrceacbRomName, NULL, NULL, NULL, NULL, SegaC2_3ButtonInputInfo, TfrceacDIPInfo,
4095 TfrceacbInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4096 320, 224, 4, 3
4097 };
4098
4099
4100 // Borench (set 1)
4101
4102 static struct BurnRomInfo borenchRomDesc[] = {
4103 { "ic32.bin", 0x40000, 0x2c54457d, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4104 { "ic31.bin", 0x40000, 0xb46445fc, 1 | BRF_PRG | BRF_ESS }, // 1
4105
4106 { "epr-13587.ic4", 0x20000, 0x62b85e56, 2 | BRF_SND }, // 2 UPD Samples
4107 };
4108
4109 STD_ROM_PICK(borench)
STD_ROM_FN(borench)4110 STD_ROM_FN(borench)
4111
4112 static UINT8 borench_protection_callback(UINT8 in)
4113 {
4114 static const UINT8 prot_lut_table[0x100] = {
4115 0x01, 0x02, 0x0f, 0x0e, 0x05, 0x06, 0x0b, 0x0a, 0x05, 0x06, 0x0b, 0x0a, 0x05, 0x06, 0x0b, 0x0a,
4116 0x00, 0x00, 0x0a, 0x0a, 0x04, 0x04, 0x0e, 0x0e, 0x0c, 0x0c, 0x0e, 0x0e, 0x0c, 0x0c, 0x0e, 0x0e,
4117 0x01, 0x03, 0x0f, 0x0f, 0x05, 0x07, 0x0b, 0x0b, 0x07, 0x05, 0x09, 0x09, 0x05, 0x07, 0x0b, 0x0b,
4118 0x01, 0x01, 0x0b, 0x0b, 0x05, 0x05, 0x0f, 0x0f, 0x0f, 0x0f, 0x0d, 0x0d, 0x0d, 0x0d, 0x0f, 0x0f,
4119 0x01, 0x02, 0x0b, 0x0a, 0x05, 0x06, 0x0f, 0x0e, 0x05, 0x06, 0x0f, 0x0e, 0x05, 0x06, 0x0f, 0x0e,
4120 0x00, 0x00, 0x0a, 0x0a, 0x04, 0x04, 0x0e, 0x0e, 0x0c, 0x0c, 0x0e, 0x0e, 0x0c, 0x0c, 0x0e, 0x0e,
4121 0x09, 0x03, 0x03, 0x0b, 0x0d, 0x07, 0x07, 0x0f, 0x0f, 0x05, 0x05, 0x0d, 0x0d, 0x07, 0x07, 0x0f,
4122 0x09, 0x01, 0x03, 0x0b, 0x0d, 0x05, 0x07, 0x0f, 0x07, 0x0f, 0x05, 0x0d, 0x05, 0x0d, 0x07, 0x0f,
4123 0x01, 0x02, 0x0f, 0x0e, 0x05, 0x06, 0x0b, 0x0a, 0x05, 0x06, 0x0b, 0x0a, 0x05, 0x06, 0x0a, 0x0b,
4124 0x00, 0x00, 0x0a, 0x0a, 0x04, 0x04, 0x0e, 0x0e, 0x0c, 0x0c, 0x0e, 0x0e, 0x0c, 0x0c, 0x0f, 0x0f,
4125 0x0d, 0x07, 0x03, 0x0b, 0x0d, 0x07, 0x03, 0x0b, 0x0f, 0x05, 0x01, 0x09, 0x0d, 0x07, 0x02, 0x0a,
4126 0x0d, 0x05, 0x07, 0x0f, 0x0d, 0x05, 0x07, 0x0f, 0x07, 0x0f, 0x05, 0x0d, 0x05, 0x0d, 0x06, 0x0e,
4127 0x01, 0x02, 0x0b, 0x0a, 0x05, 0x06, 0x0f, 0x0e, 0x05, 0x06, 0x0f, 0x0e, 0x05, 0x06, 0x0e, 0x0f,
4128 0x00, 0x00, 0x0a, 0x0a, 0x04, 0x04, 0x0e, 0x0e, 0x0c, 0x0c, 0x0e, 0x0e, 0x0c, 0x0c, 0x0f, 0x0f,
4129 0x0d, 0x07, 0x07, 0x0f, 0x0d, 0x07, 0x07, 0x0f, 0x0f, 0x05, 0x05, 0x0d, 0x0d, 0x07, 0x06, 0x0e,
4130 0x0d, 0x05, 0x07, 0x0f, 0x0d, 0x05, 0x07, 0x0f, 0x07, 0x0f, 0x05, 0x0d, 0x05, 0x0d, 0x06, 0x0e
4131 };
4132
4133 return prot_lut_table[in];
4134 }
4135
BorenchInit()4136 static INT32 BorenchInit()
4137 {
4138 return SegaC2Init(borench_protection_callback);
4139 }
4140
4141 struct BurnDriver BurnDrvBorench = {
4142 "borench", NULL, NULL, NULL, "1990",
4143 "Borench (set 1)\0", NULL, "Sega", "C2",
4144 NULL, NULL, NULL, NULL,
4145 BDF_GAME_WORKING, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
4146 NULL, borenchRomInfo, borenchRomName, NULL, NULL, NULL, NULL, SegaC2_2ButtonInputInfo, BorenchDIPInfo,
4147 BorenchInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4148 320, 224, 4, 3
4149 };
4150
4151
4152 // Borench (set 2)
4153
4154 static struct BurnRomInfo borenchaRomDesc[] = {
4155 { "epr-13591.ic32", 0x40000, 0x7851078b, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4156 { "epr-13590.ic31", 0x40000, 0x01bc6fe6, 1 | BRF_PRG | BRF_ESS }, // 1
4157
4158 { "epr-13587.ic4", 0x20000, 0x62b85e56, 2 | BRF_SND }, // 2 UPD Samples
4159 };
4160
4161 STD_ROM_PICK(borencha)
4162 STD_ROM_FN(borencha)
4163
4164 struct BurnDriver BurnDrvBorencha = {
4165 "borencha", "borench", NULL, NULL, "1990",
4166 "Borench (set 2)\0", NULL, "Sega", "C2",
4167 NULL, NULL, NULL, NULL,
4168 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
4169 NULL, borenchaRomInfo, borenchaRomName, NULL, NULL, NULL, NULL, SegaC2_2ButtonInputInfo, BorenchDIPInfo,
4170 BorenchInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4171 320, 224, 4, 3
4172 };
4173
4174
4175 // Borench (Japan)
4176
4177 static struct BurnRomInfo borenchjRomDesc[] = {
4178 { "epr-13586.ic32", 0x40000, 0x62d7f8e8, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4179 { "epr-13585.ic31", 0x40000, 0x087b9704, 1 | BRF_PRG | BRF_ESS }, // 1
4180
4181 { "epr-13587.ic4", 0x20000, 0x62b85e56, 2 | BRF_SND }, // 2 UPD Samples
4182 };
4183
4184 STD_ROM_PICK(borenchj)
4185 STD_ROM_FN(borenchj)
4186
4187 struct BurnDriver BurnDrvBorenchj = {
4188 "borenchj", "borench", NULL, NULL, "1990",
4189 "Borench (Japan)\0", NULL, "Sega", "C2",
4190 NULL, NULL, NULL, NULL,
4191 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
4192 NULL, borenchjRomInfo, borenchjRomName, NULL, NULL, NULL, NULL, SegaC2_2ButtonInputInfo, BorenchDIPInfo,
4193 BorenchInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4194 320, 224, 4, 3
4195 };
4196
4197
4198 // Ribbit!
4199
4200 static struct BurnRomInfo ribbitRomDesc[] = {
4201 { "epr-13833.ic32", 0x40000, 0x5347f8ce, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4202 { "epr-13832.ic31", 0x40000, 0x889c42c2, 1 | BRF_PRG | BRF_ESS }, // 1
4203 { "epr-13838.ic34", 0x80000, 0xa5d62ac3, 1 | BRF_PRG | BRF_ESS }, // 2
4204 { "epr-13837.ic33", 0x80000, 0x434de159, 1 | BRF_PRG | BRF_ESS }, // 3
4205
4206 { "epr-13834.ic4", 0x20000, 0xab0c1833, 2 | BRF_SND }, // 4 UPD Samples
4207 };
4208
4209 STD_ROM_PICK(ribbit)
STD_ROM_FN(ribbit)4210 STD_ROM_FN(ribbit)
4211 #include "bitswap.h"
4212 static UINT8 ribbit_protection_callback(UINT8 in)
4213 {
4214 static const UINT8 prot_lut_table[0x100] = {
4215 0x0f, 0x0f, 0x0b, 0x0b, 0x07, 0x07, 0x03, 0x0b, 0x0f, 0x0f, 0x0b, 0x0f, 0x07, 0x07, 0x03, 0x0f,
4216 0x0f, 0x0e, 0x0b, 0x0a, 0x0f, 0x0e, 0x0b, 0x0a, 0x0f, 0x0e, 0x0b, 0x0e, 0x0f, 0x0e, 0x0b, 0x0e,
4217 0x0e, 0x0e, 0x08, 0x08, 0x06, 0x06, 0x01, 0x09, 0x0f, 0x0f, 0x09, 0x0d, 0x07, 0x07, 0x01, 0x0d,
4218 0x0e, 0x0f, 0x08, 0x09, 0x0e, 0x0f, 0x09, 0x08, 0x0f, 0x0e, 0x09, 0x0c, 0x0f, 0x0e, 0x09, 0x0c,
4219 0x0d, 0x0f, 0x09, 0x0b, 0x05, 0x07, 0x01, 0x0b, 0x05, 0x07, 0x01, 0x07, 0x0f, 0x0f, 0x0b, 0x07,
4220 0x0d, 0x0e, 0x09, 0x0a, 0x0d, 0x0e, 0x09, 0x0a, 0x05, 0x06, 0x01, 0x06, 0x07, 0x06, 0x03, 0x06,
4221 0x0c, 0x0e, 0x0a, 0x08, 0x04, 0x06, 0x03, 0x09, 0x05, 0x07, 0x03, 0x05, 0x0f, 0x0f, 0x09, 0x05,
4222 0x0c, 0x0f, 0x0a, 0x09, 0x0c, 0x0f, 0x0b, 0x08, 0x05, 0x06, 0x03, 0x04, 0x07, 0x06, 0x01, 0x04,
4223 0x0f, 0x0f, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x0b, 0x0f, 0x0f, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x0b,
4224 0x0f, 0x0e, 0x0f, 0x0e, 0x0b, 0x0a, 0x0b, 0x0a, 0x0f, 0x0e, 0x0f, 0x0e, 0x0b, 0x0a, 0x0b, 0x0a,
4225 0x0e, 0x0e, 0x0c, 0x0c, 0x02, 0x02, 0x01, 0x09, 0x0f, 0x0f, 0x0d, 0x0d, 0x03, 0x03, 0x01, 0x09,
4226 0x0e, 0x0f, 0x0c, 0x0d, 0x0a, 0x0b, 0x09, 0x08, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
4227 0x0d, 0x0f, 0x0d, 0x0f, 0x01, 0x03, 0x01, 0x0b, 0x05, 0x07, 0x05, 0x07, 0x0b, 0x0b, 0x0b, 0x03,
4228 0x0d, 0x0e, 0x0d, 0x0e, 0x09, 0x0a, 0x09, 0x0a, 0x05, 0x06, 0x05, 0x06, 0x03, 0x02, 0x03, 0x02,
4229 0x0c, 0x0e, 0x0e, 0x0c, 0x00, 0x02, 0x03, 0x09, 0x05, 0x07, 0x07, 0x05, 0x0b, 0x0b, 0x09, 0x01,
4230 0x0c, 0x0f, 0x0e, 0x0d, 0x08, 0x0b, 0x0b, 0x08, 0x05, 0x06, 0x07, 0x04, 0x03, 0x02, 0x01, 0x00,
4231 };
4232
4233 return prot_lut_table[in];
4234 }
4235
RibbitInit()4236 static INT32 RibbitInit()
4237 {
4238 is_ribbit = 1;
4239
4240 INT32 rc = SegaC2Init(ribbit_protection_callback);
4241
4242 if (!rc) {
4243 memmove(Drv68KROM + 0x80000, Drv68KROM + 0x00000, 0x80000);
4244 UPD7759SetStartDelay(0, 250);
4245 }
4246
4247 return rc;
4248 }
4249
4250 struct BurnDriver BurnDrvRibbit = {
4251 "ribbit", NULL, NULL, NULL, "1991",
4252 "Ribbit!\0", NULL, "Sega", "C2",
4253 NULL, NULL, NULL, NULL,
4254 BDF_GAME_WORKING, 2, HARDWARE_SEGA_MISC, GBF_ACTION, 0,
4255 NULL, ribbitRomInfo, ribbitRomName, NULL, NULL, NULL, NULL, RibbitInputInfo, RibbitDIPInfo,
4256 RibbitInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4257 320, 224, 4, 3
4258 };
4259
4260
4261 // Ribbit! (Japan)
4262
4263 static struct BurnRomInfo ribbitjRomDesc[] = {
4264 { "epr-13836.ic32", 0x40000, 0x21f222e2, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4265 { "epr-13835.ic31", 0x40000, 0x1c4b291a, 1 | BRF_PRG | BRF_ESS }, // 1
4266 { "epr-13838.ic34", 0x80000, 0xa5d62ac3, 1 | BRF_PRG | BRF_ESS }, // 2
4267 { "epr-13837.ic33", 0x80000, 0x434de159, 1 | BRF_PRG | BRF_ESS }, // 3
4268
4269 { "epr-13834.ic4", 0x20000, 0xab0c1833, 2 | BRF_SND }, // 4 UPD Samples
4270 };
4271
4272 STD_ROM_PICK(ribbitj)
4273 STD_ROM_FN(ribbitj)
4274
4275 struct BurnDriver BurnDrvRibbitj = {
4276 "ribbitj", "ribbit", NULL, NULL, "1991",
4277 "Ribbit! (Japan)\0", NULL, "Sega", "C2",
4278 NULL, NULL, NULL, NULL,
4279 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_MISC, GBF_ACTION, 0,
4280 NULL, ribbitjRomInfo, ribbitjRomName, NULL, NULL, NULL, NULL, RibbitInputInfo, RibbitjDIPInfo,
4281 RibbitInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4282 320, 224, 4, 3
4283 };
4284
4285
4286 // Twin Squash
4287
4288 static struct BurnRomInfo twinsquaRomDesc[] = {
4289 { "epr-14657.ic32", 0x40000, 0xbecbb1a1, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4290 { "epr-14656.ic31", 0x40000, 0x411906e7, 1 | BRF_PRG | BRF_ESS }, // 1
4291
4292 { "epr-14588.ic4", 0x20000, 0x5a9b6881, 2 | BRF_SND }, // 2 UPD Samples
4293 };
4294
4295 STD_ROM_PICK(twinsqua)
STD_ROM_FN(twinsqua)4296 STD_ROM_FN(twinsqua)
4297
4298 static UINT8 twinsqua_protection_callback(UINT8 in)
4299 {
4300 static const UINT8 prot_lut_table[0x100] = {
4301 0x0b, 0x0b, 0x03, 0x03, 0x0a, 0x0a, 0x02, 0x02, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e,
4302 0x0a, 0x08, 0x02, 0x00, 0x0b, 0x0b, 0x03, 0x03, 0x0f, 0x0d, 0x07, 0x05, 0x0e, 0x0e, 0x06, 0x06,
4303 0x0b, 0x0b, 0x03, 0x03, 0x0b, 0x0b, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
4304 0x0a, 0x08, 0x02, 0x00, 0x0a, 0x0a, 0x02, 0x02, 0x0b, 0x09, 0x03, 0x01, 0x0b, 0x0b, 0x03, 0x03,
4305 0x03, 0x03, 0x0b, 0x0b, 0x02, 0x02, 0x0a, 0x0a, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e,
4306 0x02, 0x02, 0x0a, 0x0a, 0x03, 0x01, 0x0b, 0x09, 0x07, 0x07, 0x0f, 0x0f, 0x06, 0x04, 0x0e, 0x0c,
4307 0x03, 0x03, 0x0b, 0x0b, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
4308 0x02, 0x02, 0x0a, 0x0a, 0x02, 0x00, 0x0a, 0x08, 0x03, 0x03, 0x0b, 0x0b, 0x03, 0x01, 0x0b, 0x09,
4309 0x0b, 0x0b, 0x03, 0x03, 0x0a, 0x0a, 0x02, 0x02, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e,
4310 0x0e, 0x0c, 0x06, 0x04, 0x0f, 0x0f, 0x07, 0x07, 0x0b, 0x09, 0x03, 0x01, 0x0a, 0x0a, 0x02, 0x02,
4311 0x0b, 0x0b, 0x03, 0x03, 0x0b, 0x0b, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
4312 0x0e, 0x0c, 0x06, 0x04, 0x0e, 0x0e, 0x06, 0x06, 0x0f, 0x0d, 0x07, 0x05, 0x0f, 0x0f, 0x07, 0x07,
4313 0x03, 0x03, 0x0b, 0x0b, 0x02, 0x02, 0x0a, 0x0a, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e,
4314 0x06, 0x06, 0x0e, 0x0e, 0x07, 0x05, 0x0f, 0x0d, 0x03, 0x03, 0x0b, 0x0b, 0x02, 0x00, 0x0a, 0x08,
4315 0x03, 0x03, 0x0b, 0x0b, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
4316 0x06, 0x06, 0x0e, 0x0e, 0x06, 0x04, 0x0e, 0x0c, 0x07, 0x07, 0x0f, 0x0f, 0x07, 0x05, 0x0f, 0x0d
4317 };
4318
4319 return prot_lut_table[in];
4320 }
4321
TwinsquaInit()4322 static INT32 TwinsquaInit()
4323 {
4324 has_dial = 1;
4325
4326 return SegaC2Init(twinsqua_protection_callback);
4327 }
4328
4329 struct BurnDriver BurnDrvTwinsqua = {
4330 "twinsqua", NULL, NULL, NULL, "1991",
4331 "Twin Squash\0", NULL, "Sega", "C2",
4332 NULL, NULL, NULL, NULL,
4333 BDF_GAME_WORKING, 2, HARDWARE_SEGA_MISC, GBF_BREAKOUT, 0,
4334 NULL, twinsquaRomInfo, twinsquaRomName, NULL, NULL, NULL, NULL, TwinsquaInputInfo, TwinsquaDIPInfo,
4335 TwinsquaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4336 320, 224, 4, 3
4337 };
4338
4339
4340 // Waku Waku Sonic Patrol Car
4341
4342 static struct BurnRomInfo soniccarRomDesc[] = {
4343 { "epr-14369.ic32", 0x40000, 0x2ea4c9a3, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4344 { "epr-14395.ic31", 0x40000, 0x39622e18, 1 | BRF_PRG | BRF_ESS }, // 1
4345
4346 { "epr-14394.ic4", 0x40000, 0x476e30dd, 2 | BRF_SND }, // 2 UPD Samples
4347 };
4348
4349 STD_ROM_PICK(soniccar)
4350 STD_ROM_FN(soniccar)
4351
4352 struct BurnDriver BurnDrvSoniccar = {
4353 "soniccar", NULL, NULL, NULL, "1991",
4354 "Waku Waku Sonic Patrol Car\0", NULL, "Sega", "C2",
4355 NULL, NULL, NULL, NULL,
4356 BDF_GAME_WORKING, 1, HARDWARE_SEGA_MISC, GBF_ACTION, 0,
4357 NULL, soniccarRomInfo, soniccarRomName, NULL, NULL, NULL, NULL, SoniccarInputInfo, SoniccarDIPInfo,
4358 NoProtectionInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4359 320, 224, 4, 3
4360 };
4361
4362
4363 // SegaSonic Bros. (prototype, hack)
4364
4365 static struct BurnRomInfo ssonicbrRomDesc[] = {
4366 { "ssonicbr.ic32", 0x40000, 0xcf254ecd, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4367 { "ssonicbr.ic31", 0x40000, 0x03709746, 1 | BRF_PRG | BRF_ESS }, // 1
4368
4369 { "ssonicbr.ic4", 0x20000, 0x78e56a51, 2 | BRF_SND }, // 2 UPD Samples
4370 };
4371
4372 STD_ROM_PICK(ssonicbr)
4373 STD_ROM_FN(ssonicbr)
4374
4375 struct BurnDriver BurnDrvSsonicbr = {
4376 "ssonicbr", NULL, NULL, NULL, "1992",
4377 "SegaSonic Bros. (prototype, hack)\0", NULL, "hack", "C2",
4378 NULL, NULL, NULL, NULL,
4379 BDF_GAME_WORKING | BDF_PROTOTYPE | BDF_HACK, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
4380 NULL, ssonicbrRomInfo, ssonicbrRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, SsonicbrDIPInfo,
4381 NoProtectionInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4382 320, 224, 4, 3
4383 };
4384
4385
4386 // OOPArts (prototype, joystick hack)
4387
4388 static struct BurnRomInfo oopartsRomDesc[] = {
4389 { "ooparts.ic32", 0x80000, 0x8dcf2940, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4390 { "ooparts.ic31", 0x80000, 0x35381899, 1 | BRF_PRG | BRF_ESS }, // 1
4391 { "ooparts.ic34", 0x80000, 0x7192ac29, 1 | BRF_PRG | BRF_ESS }, // 2
4392 { "ooparts.ic33", 0x80000, 0x42755dc2, 1 | BRF_PRG | BRF_ESS }, // 3
4393
4394 { "epr-13655.ic4", 0x40000, 0xe09961f6, 2 | BRF_SND }, // 4 UPD Samples
4395 };
4396
4397 STD_ROM_PICK(ooparts)
4398 STD_ROM_FN(ooparts)
4399
4400 struct BurnDriver BurnDrvOoparts = {
4401 "ooparts", NULL, NULL, NULL, "1992",
4402 "OOPArts (prototype, joystick hack)\0", NULL, "hack", "C2",
4403 NULL, NULL, NULL, NULL,
4404 BDF_GAME_WORKING | BDF_PROTOTYPE | BDF_HACK | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_MISC, GBF_BREAKOUT, 0,
4405 NULL, oopartsRomInfo, oopartsRomName, NULL, NULL, NULL, NULL, OopartsInputInfo, OopartsDIPInfo,
4406 NoProtectionInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4407 224, 320, 3, 4
4408 };
4409
4410
4411 // Puyo Puyo (World)
4412
4413 static struct BurnRomInfo puyoRomDesc[] = {
4414 { "epr-15198.ic32", 0x20000, 0x9610d80c, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4415 { "epr-15197.ic31", 0x20000, 0x7b1f3229, 1 | BRF_PRG | BRF_ESS }, // 1
4416 { "epr-15200.ic34", 0x20000, 0x0a0692e5, 1 | BRF_PRG | BRF_ESS }, // 2
4417 { "epr-15199.ic33", 0x20000, 0x353109b8, 1 | BRF_PRG | BRF_ESS }, // 3
4418
4419 { "epr-15196.ic4", 0x20000, 0x79112b3b, 2 | BRF_SND }, // 4 UPD Samples
4420 };
4421
4422 STD_ROM_PICK(puyo)
STD_ROM_FN(puyo)4423 STD_ROM_FN(puyo)
4424
4425 static UINT8 puyo_protection_callback(UINT8 in)
4426 {
4427 static const UINT8 prot_lut_table[0x100] = {
4428 0x03, 0x03, 0x0a, 0x0a, 0x05, 0x05, 0x0c, 0x0c, 0x03, 0x03, 0x0a, 0x0a, 0x05, 0x05, 0x0c, 0x0c,
4429 0x0b, 0x0a, 0x02, 0x02, 0x0f, 0x0e, 0x06, 0x06, 0x0b, 0x0a, 0x02, 0x02, 0x0f, 0x0e, 0x06, 0x06,
4430 0x07, 0x07, 0x0e, 0x0e, 0x05, 0x05, 0x0c, 0x0c, 0x05, 0x05, 0x0c, 0x0c, 0x07, 0x07, 0x0e, 0x0e,
4431 0x0f, 0x0e, 0x06, 0x06, 0x0f, 0x0e, 0x06, 0x06, 0x0d, 0x0c, 0x04, 0x04, 0x0d, 0x0c, 0x04, 0x04,
4432 0x03, 0x03, 0x0a, 0x0a, 0x07, 0x07, 0x0e, 0x0e, 0x07, 0x07, 0x0a, 0x0a, 0x03, 0x03, 0x0e, 0x0e,
4433 0x0b, 0x0a, 0x02, 0x02, 0x0f, 0x0e, 0x06, 0x06, 0x0f, 0x0e, 0x02, 0x02, 0x0b, 0x0a, 0x06, 0x06,
4434 0x07, 0x07, 0x0e, 0x0e, 0x07, 0x07, 0x0e, 0x0e, 0x01, 0x01, 0x0c, 0x0c, 0x01, 0x01, 0x0c, 0x0c,
4435 0x0f, 0x0e, 0x06, 0x06, 0x0f, 0x0e, 0x06, 0x06, 0x09, 0x08, 0x04, 0x04, 0x09, 0x08, 0x04, 0x04,
4436 0x02, 0x02, 0x0b, 0x0b, 0x04, 0x04, 0x0d, 0x0d, 0x03, 0x0b, 0x0a, 0x02, 0x05, 0x0d, 0x0c, 0x04,
4437 0x0a, 0x0b, 0x03, 0x03, 0x0e, 0x0f, 0x07, 0x07, 0x0b, 0x0a, 0x02, 0x02, 0x0f, 0x0e, 0x06, 0x06,
4438 0x06, 0x06, 0x0f, 0x0f, 0x04, 0x04, 0x0d, 0x0d, 0x05, 0x0d, 0x0c, 0x04, 0x07, 0x0f, 0x0e, 0x06,
4439 0x0e, 0x0f, 0x07, 0x07, 0x0e, 0x0f, 0x07, 0x07, 0x0d, 0x0c, 0x04, 0x04, 0x0d, 0x0c, 0x04, 0x04,
4440 0x02, 0x02, 0x0b, 0x0b, 0x06, 0x06, 0x0f, 0x0f, 0x07, 0x0f, 0x0a, 0x02, 0x03, 0x0b, 0x0e, 0x06,
4441 0x0a, 0x0b, 0x03, 0x03, 0x0e, 0x0f, 0x07, 0x07, 0x0f, 0x0e, 0x02, 0x02, 0x0b, 0x0a, 0x06, 0x06,
4442 0x06, 0x06, 0x0f, 0x0f, 0x06, 0x06, 0x0f, 0x0f, 0x01, 0x09, 0x0c, 0x04, 0x01, 0x09, 0x0c, 0x04,
4443 0x0e, 0x0f, 0x07, 0x07, 0x0e, 0x0f, 0x07, 0x07, 0x09, 0x08, 0x04, 0x04, 0x09, 0x08, 0x04, 0x04,
4444 };
4445
4446 return prot_lut_table[in];
4447 }
4448
PuyoInit()4449 static INT32 PuyoInit()
4450 {
4451 return SegaC2Init(puyo_protection_callback);
4452 }
4453
4454 struct BurnDriver BurnDrvPuyo = {
4455 "puyo", NULL, NULL, NULL, "1992",
4456 "Puyo Puyo (World)\0", NULL, "Compile / Sega", "C2",
4457 NULL, NULL, NULL, NULL,
4458 BDF_GAME_WORKING, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
4459 NULL, puyoRomInfo, puyoRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, PuyoDIPInfo,
4460 PuyoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4461 320, 224, 4, 3
4462 };
4463
4464
4465 // Puyo Puyo (Japan, Rev B)
4466
4467 static struct BurnRomInfo puyojRomDesc[] = {
4468 { "epr-15036b.ic32", 0x20000, 0x5310ca1b, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4469 { "epr-15035b.ic31", 0x20000, 0xbc62e400, 1 | BRF_PRG | BRF_ESS }, // 1
4470 { "epr-15038.ic34", 0x20000, 0x3b9eea0c, 1 | BRF_PRG | BRF_ESS }, // 2
4471 { "epr-15037.ic33", 0x20000, 0xbe2f7974, 1 | BRF_PRG | BRF_ESS }, // 3
4472
4473 { "epr-15034.ic4", 0x20000, 0x5688213b, 2 | BRF_SND }, // 4 UPD Samples
4474
4475 { "315-5452.ic24", 0x00001, 0x00000000, 0 | BRF_NODUMP | BRF_OPT }, // 5 pals
4476 { "315-5394.ic25", 0x00001, 0x00000000, 0 | BRF_NODUMP | BRF_OPT }, // 6
4477 { "315-5395.ic26", 0x00001, 0x00000000, 0 | BRF_NODUMP | BRF_OPT }, // 7
4478 { "317-0203.ic27", 0x00001, 0x00000000, 0 | BRF_NODUMP | BRF_OPT }, // 8
4479 };
4480
4481 STD_ROM_PICK(puyoj)
4482 STD_ROM_FN(puyoj)
4483
4484 struct BurnDriver BurnDrvPuyoj = {
4485 "puyoj", "puyo", NULL, NULL, "1992",
4486 "Puyo Puyo (Japan, Rev B)\0", NULL, "Compile / Sega", "C2",
4487 NULL, NULL, NULL, NULL,
4488 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
4489 NULL, puyojRomInfo, puyojRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, PuyoDIPInfo,
4490 PuyoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4491 320, 224, 4, 3
4492 };
4493
4494
4495 // Puyo Puyo (Japan, Rev A)
4496
4497 static struct BurnRomInfo puyojaRomDesc[] = {
4498 { "epr-15036a.ic32", 0x20000, 0x61b35257, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4499 { "epr-15035a.ic31", 0x20000, 0xdfebb6d9, 1 | BRF_PRG | BRF_ESS }, // 1
4500 { "epr-15038.ic34", 0x20000, 0x3b9eea0c, 1 | BRF_PRG | BRF_ESS }, // 2
4501 { "epr-15037.ic33", 0x20000, 0xbe2f7974, 1 | BRF_PRG | BRF_ESS }, // 3
4502
4503 { "epr-15034.ic4", 0x20000, 0x5688213b, 2 | BRF_SND }, // 4 UPD Samples
4504
4505 { "315-5452.ic24", 0x00001, 0x00000000, 0 | BRF_NODUMP | BRF_OPT }, // 5 pals
4506 { "315-5394.ic25", 0x00001, 0x00000000, 0 | BRF_NODUMP | BRF_OPT }, // 6
4507 { "315-5395.ic26", 0x00001, 0x00000000, 0 | BRF_NODUMP | BRF_OPT }, // 7
4508 { "317-0203.ic27", 0x00001, 0x00000000, 0 | BRF_NODUMP | BRF_OPT }, // 8
4509 };
4510
4511 STD_ROM_PICK(puyoja)
4512 STD_ROM_FN(puyoja)
4513
4514 struct BurnDriver BurnDrvPuyoja = {
4515 "puyoja", "puyo", NULL, NULL, "1992",
4516 "Puyo Puyo (Japan, Rev A)\0", NULL, "Compile / Sega", "C2",
4517 NULL, NULL, NULL, NULL,
4518 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
4519 NULL, puyojaRomInfo, puyojaRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, PuyoDIPInfo,
4520 PuyoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4521 320, 224, 4, 3
4522 };
4523
4524
4525 // Puyo Puyo (World, bootleg)
4526
4527 static struct BurnRomInfo puyoblRomDesc[] = {
4528 { "puyopuyb.4bo", 0x20000, 0x89ea4d33, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4529 { "puyopuyb.3bo", 0x20000, 0xc002e545, 1 | BRF_PRG | BRF_ESS }, // 1
4530 { "puyopuyb.6bo", 0x20000, 0x0a0692e5, 1 | BRF_PRG | BRF_ESS }, // 2
4531 { "puyopuyb.5bo", 0x20000, 0x353109b8, 1 | BRF_PRG | BRF_ESS }, // 3
4532
4533 { "puyopuyb.abo", 0x20000, 0x79112b3b, 2 | BRF_SND }, // 4 UPD Samples
4534 };
4535
4536 STD_ROM_PICK(puyobl)
4537 STD_ROM_FN(puyobl)
4538
4539 struct BurnDriver BurnDrvPuyobl = {
4540 "puyobl", "puyo", NULL, NULL, "1992",
4541 "Puyo Puyo (World, bootleg)\0", NULL, "bootleg", "C2",
4542 NULL, NULL, NULL, NULL,
4543 BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
4544 NULL, puyoblRomInfo, puyoblRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, PuyoDIPInfo,
4545 PuyoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4546 320, 224, 4, 3
4547 };
4548
4549
4550 // Puzzle & Action: Tant-R (Japan)
4551
4552 static struct BurnRomInfo tantrRomDesc[] = {
4553 { "epr-15614.ic32", 0x80000, 0x557782bc, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4554 { "epr-15613.ic31", 0x80000, 0x14bbb235, 1 | BRF_PRG | BRF_ESS }, // 1
4555 { "mpr-15616.ic34", 0x80000, 0x17b80202, 1 | BRF_PRG | BRF_ESS }, // 2
4556 { "mpr-15615.ic33", 0x80000, 0x36a88bd4, 1 | BRF_PRG | BRF_ESS }, // 3
4557
4558 { "epr-15617.ic4", 0x40000, 0x338324a1, 2 | BRF_SND }, // 4 UPD Samples
4559 };
4560
4561 STD_ROM_PICK(tantr)
STD_ROM_FN(tantr)4562 STD_ROM_FN(tantr)
4563
4564 static UINT8 tantr_protection_callback(UINT8 in)
4565 {
4566 static const UINT8 prot_lut_table[0x100] = {
4567 0x09, 0x01, 0x0d, 0x0d, 0x0d, 0x01, 0x09, 0x0d, 0x09, 0x01, 0x0d, 0x0d, 0x0d, 0x01, 0x09, 0x0d,
4568 0x0d, 0x04, 0x0d, 0x0c, 0x09, 0x04, 0x09, 0x0c, 0x0f, 0x06, 0x0f, 0x0e, 0x0b, 0x06, 0x0b, 0x0e,
4569 0x09, 0x01, 0x0b, 0x0b, 0x0d, 0x01, 0x0f, 0x0b, 0x09, 0x01, 0x0b, 0x0b, 0x0d, 0x01, 0x0f, 0x0b,
4570 0x0d, 0x04, 0x0f, 0x0e, 0x09, 0x04, 0x0b, 0x0e, 0x0f, 0x06, 0x0f, 0x0e, 0x0b, 0x06, 0x0b, 0x0e,
4571 0x08, 0x00, 0x0c, 0x0c, 0x0e, 0x02, 0x0a, 0x0e, 0x08, 0x08, 0x0c, 0x0c, 0x0e, 0x0a, 0x0a, 0x0e,
4572 0x0c, 0x05, 0x0c, 0x0d, 0x0a, 0x07, 0x0a, 0x0f, 0x0e, 0x0f, 0x0e, 0x0f, 0x08, 0x0d, 0x08, 0x0d,
4573 0x09, 0x01, 0x0b, 0x0b, 0x0f, 0x03, 0x0d, 0x09, 0x09, 0x09, 0x0b, 0x0b, 0x0f, 0x0b, 0x0d, 0x09,
4574 0x0d, 0x04, 0x0f, 0x0e, 0x0b, 0x06, 0x09, 0x0c, 0x0f, 0x0e, 0x0f, 0x0e, 0x09, 0x0c, 0x09, 0x0c,
4575 0x05, 0x0d, 0x05, 0x05, 0x09, 0x05, 0x09, 0x0d, 0x05, 0x0d, 0x05, 0x05, 0x09, 0x05, 0x09, 0x0d,
4576 0x05, 0x0c, 0x05, 0x04, 0x09, 0x04, 0x09, 0x0c, 0x07, 0x0e, 0x07, 0x06, 0x0b, 0x06, 0x0b, 0x0e,
4577 0x05, 0x0d, 0x07, 0x07, 0x09, 0x05, 0x0b, 0x0f, 0x05, 0x0d, 0x07, 0x07, 0x09, 0x05, 0x0b, 0x0f,
4578 0x05, 0x0c, 0x07, 0x06, 0x09, 0x04, 0x0b, 0x0e, 0x07, 0x0e, 0x07, 0x06, 0x0b, 0x06, 0x0b, 0x0e,
4579 0x05, 0x0d, 0x05, 0x05, 0x0b, 0x07, 0x0b, 0x0f, 0x04, 0x04, 0x04, 0x04, 0x0a, 0x0e, 0x0a, 0x0e,
4580 0x05, 0x0c, 0x05, 0x04, 0x0b, 0x06, 0x0b, 0x0e, 0x06, 0x07, 0x06, 0x07, 0x08, 0x0d, 0x08, 0x0d,
4581 0x05, 0x0d, 0x07, 0x07, 0x0b, 0x07, 0x09, 0x0d, 0x05, 0x05, 0x07, 0x07, 0x0b, 0x0f, 0x09, 0x0d,
4582 0x05, 0x0c, 0x07, 0x06, 0x0b, 0x06, 0x09, 0x0c, 0x07, 0x06, 0x07, 0x06, 0x09, 0x0c, 0x09, 0x0c,
4583 };
4584
4585 return prot_lut_table[in];
4586 }
4587
TantrInit()4588 static INT32 TantrInit()
4589 {
4590 return SegaC2Init(tantr_protection_callback);
4591 }
4592
4593 struct BurnDriver BurnDrvTantr = {
4594 "tantr", NULL, NULL, NULL, "1992",
4595 "Puzzle & Action: Tant-R (Japan)\0", NULL, "Sega", "C2",
4596 NULL, NULL, NULL, NULL,
4597 BDF_GAME_WORKING, 2, HARDWARE_SEGA_MISC, GBF_MINIGAMES | GBF_PUZZLE, 0,
4598 NULL, tantrRomInfo, tantrRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, IchirDIPInfo,
4599 TantrInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4600 320, 224, 4, 3
4601 };
4602
4603
4604 // Puzzle & Action: Tant-R (Korea)
4605
4606 static struct BurnRomInfo tantrkorRomDesc[] = {
4607 { "mpr-15592b.ic32", 0x80000, 0x7efe26b3, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4608 { "mpr-15592b.ic31", 0x80000, 0xaf5a860f, 1 | BRF_PRG | BRF_ESS }, // 1
4609 { "mpr-15992b.ic34", 0x80000, 0x6282a5d4, 1 | BRF_PRG | BRF_ESS }, // 2
4610 { "mpr-15592b.ic33", 0x80000, 0x82d78413, 1 | BRF_PRG | BRF_ESS }, // 3
4611
4612 { "epr-15617.ic4", 0x40000, 0x338324a1, 2 | BRF_SND }, // 4 UPD Samples
4613 };
4614
4615 STD_ROM_PICK(tantrkor)
STD_ROM_FN(tantrkor)4616 STD_ROM_FN(tantrkor)
4617
4618 static UINT8 tantrkor_protection_callback(UINT8 in)
4619 {
4620 static const UINT8 prot_lut_table[0x100] = {
4621 0x08, 0x00, 0x09, 0x03, 0x01, 0x01, 0x00, 0x02, 0x0c, 0x04, 0x0d, 0x07, 0x05, 0x05, 0x04, 0x06,
4622 0x0d, 0x05, 0x08, 0x02, 0x05, 0x05, 0x00, 0x02, 0x09, 0x01, 0x0c, 0x06, 0x01, 0x01, 0x04, 0x06,
4623 0x00, 0x08, 0x01, 0x0b, 0x09, 0x09, 0x08, 0x0a, 0x04, 0x0c, 0x05, 0x0f, 0x0d, 0x0d, 0x0c, 0x0e,
4624 0x05, 0x0d, 0x00, 0x0a, 0x0d, 0x0d, 0x08, 0x0a, 0x01, 0x09, 0x04, 0x0e, 0x09, 0x09, 0x0c, 0x0e,
4625 0x0c, 0x04, 0x0d, 0x07, 0x07, 0x07, 0x06, 0x04, 0x0c, 0x04, 0x0d, 0x07, 0x07, 0x07, 0x06, 0x04,
4626 0x09, 0x01, 0x0c, 0x06, 0x03, 0x03, 0x06, 0x04, 0x09, 0x01, 0x0c, 0x06, 0x03, 0x03, 0x06, 0x04,
4627 0x0c, 0x04, 0x0d, 0x07, 0x07, 0x07, 0x06, 0x04, 0x0c, 0x04, 0x0d, 0x07, 0x07, 0x07, 0x06, 0x04,
4628 0x09, 0x01, 0x0c, 0x06, 0x03, 0x03, 0x06, 0x04, 0x09, 0x01, 0x0c, 0x06, 0x03, 0x03, 0x06, 0x04,
4629 0x09, 0x01, 0x09, 0x03, 0x00, 0x00, 0x00, 0x02, 0x0d, 0x05, 0x0d, 0x07, 0x04, 0x04, 0x04, 0x06,
4630 0x0c, 0x04, 0x08, 0x02, 0x04, 0x04, 0x00, 0x02, 0x08, 0x00, 0x0c, 0x06, 0x00, 0x00, 0x04, 0x06,
4631 0x01, 0x09, 0x01, 0x0b, 0x08, 0x08, 0x08, 0x0a, 0x05, 0x0d, 0x05, 0x0f, 0x0c, 0x0c, 0x0c, 0x0e,
4632 0x04, 0x0c, 0x00, 0x0a, 0x0c, 0x0c, 0x08, 0x0a, 0x00, 0x08, 0x04, 0x0e, 0x08, 0x08, 0x0c, 0x0e,
4633 0x0d, 0x05, 0x0d, 0x07, 0x06, 0x06, 0x06, 0x04, 0x0d, 0x05, 0x0d, 0x07, 0x06, 0x06, 0x06, 0x04,
4634 0x08, 0x00, 0x0c, 0x06, 0x02, 0x02, 0x06, 0x04, 0x08, 0x00, 0x0c, 0x06, 0x02, 0x02, 0x06, 0x04,
4635 0x0d, 0x05, 0x0d, 0x07, 0x06, 0x06, 0x06, 0x04, 0x0d, 0x05, 0x0d, 0x07, 0x06, 0x06, 0x06, 0x04,
4636 0x08, 0x00, 0x0c, 0x06, 0x02, 0x02, 0x06, 0x04, 0x08, 0x00, 0x0c, 0x06, 0x02, 0x02, 0x06, 0x04
4637 };
4638
4639 return prot_lut_table[in];
4640 }
4641
TantrkorInit()4642 static INT32 TantrkorInit()
4643 {
4644 return SegaC2Init(tantrkor_protection_callback);
4645 }
4646
4647 struct BurnDriver BurnDrvTantrkor = {
4648 "tantrkor", "tantr", NULL, NULL, "1993",
4649 "Puzzle & Action: Tant-R (Korea)\0", NULL, "Sega", "C2",
4650 NULL, NULL, NULL, NULL,
4651 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_MISC, GBF_MINIGAMES | GBF_PUZZLE, 0,
4652 NULL, tantrkorRomInfo, tantrkorRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, IchirDIPInfo,
4653 TantrkorInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4654 320, 224, 4, 3
4655 };
4656
4657
4658 // Puzzle & Action: Tant-R (Japan) (bootleg set 1)
4659
4660 static struct BurnRomInfo tantrblRomDesc[] = {
4661 { "pa_e10.bin", 0x80000, 0x6c3f711f, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4662 { "pa_f10.bin", 0x80000, 0x75526786, 1 | BRF_PRG | BRF_ESS }, // 1
4663 { "mpr-15616.ic34", 0x80000, 0x17b80202, 1 | BRF_PRG | BRF_ESS }, // 2
4664 { "mpr-15615.ic33", 0x80000, 0x36a88bd4, 1 | BRF_PRG | BRF_ESS }, // 3
4665
4666 { "pa_e03.bin", 0x20000, 0x72918c58, 2 | BRF_SND }, // 4 UPD Samples
4667 { "pa_e02.bin", 0x20000, 0x4e85b2a3, 2 | BRF_SND }, // 5
4668 };
4669
4670 STD_ROM_PICK(tantrbl)
4671 STD_ROM_FN(tantrbl)
4672
4673 struct BurnDriver BurnDrvTantrbl = {
4674 "tantrbl", "tantr", NULL, NULL, "1992",
4675 "Puzzle & Action: Tant-R (Japan) (bootleg set 1)\0", NULL, "bootleg", "C2",
4676 NULL, NULL, NULL, NULL,
4677 BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_MISC, GBF_MINIGAMES | GBF_PUZZLE, 0,
4678 NULL, tantrblRomInfo, tantrblRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, IchirDIPInfo,
4679 NoProtectionInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4680 320, 224, 4, 3
4681 };
4682
4683
4684 // Puzzle & Action: Tant-R (Japan) (bootleg set 2)
4685
4686 static struct BurnRomInfo tantrbl2RomDesc[] = {
4687 { "trb2_2.32", 0x80000, 0x8fc99c48, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4688 { "trb2_1.31", 0x80000, 0xc318d00d, 1 | BRF_PRG | BRF_ESS }, // 1
4689 { "mpr-15616.ic34", 0x80000, 0x17b80202, 1 | BRF_PRG | BRF_ESS }, // 2
4690 { "mpr-15615.ic33", 0x80000, 0x36a88bd4, 1 | BRF_PRG | BRF_ESS }, // 3
4691 };
4692
4693 STD_ROM_PICK(tantrbl2)
4694 STD_ROM_FN(tantrbl2)
4695
4696 struct BurnDriver BurnDrvTantrbl2 = {
4697 "tantrbl2", "tantr", NULL, NULL, "1994",
4698 "Puzzle & Action: Tant-R (Japan) (bootleg set 2)\0", NULL, "bootleg", "C2",
4699 NULL, NULL, NULL, NULL,
4700 BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_MISC, GBF_MINIGAMES | GBF_PUZZLE, 0,
4701 NULL, tantrbl2RomInfo, tantrbl2RomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, IchirDIPInfo,
4702 TantrInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4703 320, 224, 4, 3
4704 };
4705
4706
4707 // Puzzle & Action: Tant-R (Japan) (bootleg set 3)
4708
4709 static struct BurnRomInfo tantrbl3RomDesc[] = {
4710 { "2.u29", 0x80000, 0xfaecb7b1, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4711 { "1.u28", 0x80000, 0x3304556d, 1 | BRF_PRG | BRF_ESS }, // 1
4712 { "4.u31", 0x80000, 0x17b80202, 1 | BRF_PRG | BRF_ESS }, // 2
4713 { "3.u30", 0x80000, 0x36a88bd4, 1 | BRF_PRG | BRF_ESS }, // 3
4714 };
4715
4716 STD_ROM_PICK(tantrbl3)
4717 STD_ROM_FN(tantrbl3)
4718
4719 struct BurnDriver BurnDrvTantrbl3 = {
4720 "tantrbl3", "tantr", NULL, NULL, "1994",
4721 "Puzzle & Action: Tant-R (Japan) (bootleg set 3)\0", NULL, "bootleg", "C2",
4722 NULL, NULL, NULL, NULL,
4723 BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_MISC, GBF_MINIGAMES | GBF_PUZZLE, 0,
4724 NULL, tantrbl3RomInfo, tantrbl3RomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, IchirDIPInfo,
4725 TantrInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4726 320, 224, 4, 3
4727 };
4728
4729
4730 // Puzzle & Action: Tant-R (Japan) (bootleg set 4)
4731
4732 static struct BurnRomInfo tantrbl4RomDesc[] = {
4733 { "a.bin", 0x80000, 0x25cafec2, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4734 { "b.bin", 0x80000, 0x8cf5ffd5, 1 | BRF_PRG | BRF_ESS }, // 1
4735 { "d.bin", 0x80000, 0x17b80202, 1 | BRF_PRG | BRF_ESS }, // 2
4736 { "c.bin", 0x80000, 0x36a88bd4, 1 | BRF_PRG | BRF_ESS }, // 3
4737
4738 { "2.bin", 0x20000, 0x72918c58, 2 | BRF_SND }, // 4 UPD Samples
4739 { "1.bin", 0x20000, 0x4e85b2a3, 2 | BRF_SND }, // 5
4740 };
4741
4742 STD_ROM_PICK(tantrbl4)
4743 STD_ROM_FN(tantrbl4)
4744
4745 struct BurnDriver BurnDrvTantrbl4 = {
4746 "tantrbl4", "tantr", NULL, NULL, "1992",
4747 "Puzzle & Action: Tant-R (Japan) (bootleg set 4)\0", NULL, "bootleg", "C2",
4748 NULL, NULL, NULL, NULL,
4749 BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_MISC, GBF_MINIGAMES | GBF_PUZZLE, 0,
4750 NULL, tantrbl4RomInfo, tantrbl4RomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, IchirDIPInfo,
4751 NoProtectionInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4752 320, 224, 4, 3
4753 };
4754
4755
4756 // Waku Waku Marine
4757
4758 static struct BurnRomInfo wwmarineRomDesc[] = {
4759 { "epr-15097.ic32", 0x40000, 0x1223a77a, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4760 { "epr-15096.ic31", 0x40000, 0x1b833932, 1 | BRF_PRG | BRF_ESS }, // 1
4761
4762 { "epr-15095.ic4", 0x40000, 0xdf13755b, 2 | BRF_SND }, // 2 UPD Samples
4763 };
4764
4765 STD_ROM_PICK(wwmarine)
STD_ROM_FN(wwmarine)4766 STD_ROM_FN(wwmarine)
4767
4768 static INT32 WwmarineInit()
4769 {
4770 is_wwmarine = 1;
4771 return NoProtectionInit();
4772 }
4773
4774 struct BurnDriver BurnDrvWwmarine = {
4775 "wwmarine", NULL, NULL, NULL, "1992",
4776 "Waku Waku Marine\0", NULL, "Sega", "C2",
4777 NULL, NULL, NULL, NULL,
4778 BDF_GAME_WORKING, 1, HARDWARE_SEGA_MISC, GBF_MISC, 0,
4779 NULL, wwmarineRomInfo, wwmarineRomName, NULL, NULL, NULL, NULL, WwmarineInputInfo, WwmarineDIPInfo,
4780 WwmarineInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4781 320, 224, 4, 3
4782 };
4783
4784
4785 // SegaSonic Cosmo Fighter
4786
4787 static struct BurnRomInfo sonicfgtRomDesc[] = {
4788 { "epr-16001.ic32", 0x40000, 0x8ed1dc11, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4789 { "epr-16000.ic31", 0x40000, 0x1440caec, 1 | BRF_PRG | BRF_ESS }, // 1
4790 { "epr-16003.ic34", 0x40000, 0x8933e91c, 1 | BRF_PRG | BRF_ESS }, // 2
4791 { "epr-16002.ic33", 0x40000, 0x0ae979cd, 1 | BRF_PRG | BRF_ESS }, // 3
4792
4793 { "epr-16004.ic4", 0x40000, 0xe87e8433, 2 | BRF_SND }, // 4 UPD Samples
4794 };
4795
4796 STD_ROM_PICK(sonicfgt)
4797 STD_ROM_FN(sonicfgt)
4798
4799 struct BurnDriver BurnDrvSonicfgt = {
4800 "sonicfgt", NULL, NULL, NULL, "1993",
4801 "SegaSonic Cosmo Fighter\0", NULL, "Sega", "C2",
4802 NULL, NULL, NULL, NULL,
4803 BDF_GAME_WORKING, 1, HARDWARE_SEGA_MISC, GBF_VERSHOOT, 0,
4804 NULL, sonicfgtRomInfo, sonicfgtRomName, NULL, NULL, NULL, NULL, SonicfgtInputInfo, SonicfgtDIPInfo,
4805 NoProtectionInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4806 320, 224, 4, 3
4807 };
4808
4809
4810
4811 // Poto Poto (Japan, Rev A)
4812
4813 static struct BurnRomInfo potopotoRomDesc[] = {
4814 { "epr-16662a.ic32", 0x40000, 0xbbd305d6, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4815 { "epr-16661a.ic31", 0x40000, 0x5a7d14f4, 1 | BRF_PRG | BRF_ESS }, // 1
4816
4817 { "epr-16660.ic4", 0x40000, 0x8251c61c, 2 | BRF_SND }, // 2 UPD Samples
4818 };
4819
4820 STD_ROM_PICK(potopoto)
STD_ROM_FN(potopoto)4821 STD_ROM_FN(potopoto)
4822
4823 static UINT8 potopoto_protection_callback(UINT8 in)
4824 {
4825 static const UINT8 prot_lut_table[0x100] = {
4826 0x0b, 0x03, 0x03, 0x0b, 0x0a, 0x02, 0x02, 0x0a, 0x0a, 0x02, 0x03, 0x0b, 0x0b, 0x03, 0x02, 0x0a,
4827 0x0a, 0x02, 0x02, 0x0a, 0x0a, 0x02, 0x02, 0x0a, 0x0b, 0x03, 0x02, 0x0a, 0x0b, 0x03, 0x02, 0x0a,
4828 0x0b, 0x01, 0x03, 0x09, 0x0a, 0x00, 0x02, 0x08, 0x0a, 0x00, 0x03, 0x09, 0x0b, 0x01, 0x02, 0x08,
4829 0x0a, 0x00, 0x02, 0x08, 0x0a, 0x00, 0x02, 0x08, 0x0b, 0x01, 0x02, 0x08, 0x0b, 0x01, 0x02, 0x08,
4830 0x03, 0x0f, 0x03, 0x0f, 0x02, 0x0e, 0x02, 0x0e, 0x02, 0x0e, 0x03, 0x0f, 0x03, 0x0f, 0x02, 0x0e,
4831 0x02, 0x0e, 0x02, 0x0e, 0x02, 0x0e, 0x02, 0x0e, 0x03, 0x0f, 0x02, 0x0e, 0x03, 0x0f, 0x02, 0x0e,
4832 0x03, 0x0d, 0x03, 0x0d, 0x02, 0x0c, 0x02, 0x0c, 0x02, 0x0c, 0x03, 0x0d, 0x03, 0x0d, 0x02, 0x0c,
4833 0x02, 0x0c, 0x02, 0x0c, 0x02, 0x0c, 0x02, 0x0c, 0x03, 0x0d, 0x02, 0x0c, 0x03, 0x0d, 0x02, 0x0c,
4834 0x0d, 0x0d, 0x01, 0x01, 0x0e, 0x0e, 0x02, 0x02, 0x0c, 0x0c, 0x01, 0x01, 0x0f, 0x0f, 0x02, 0x02,
4835 0x0c, 0x0c, 0x00, 0x00, 0x0e, 0x0e, 0x02, 0x02, 0x0d, 0x0d, 0x00, 0x00, 0x0f, 0x0f, 0x02, 0x02,
4836 0x0d, 0x0f, 0x01, 0x03, 0x0e, 0x0c, 0x02, 0x00, 0x0c, 0x0e, 0x01, 0x03, 0x0f, 0x0d, 0x02, 0x00,
4837 0x0c, 0x0e, 0x00, 0x02, 0x0e, 0x0c, 0x02, 0x00, 0x0d, 0x0f, 0x00, 0x02, 0x0f, 0x0d, 0x02, 0x00,
4838 0x05, 0x01, 0x01, 0x05, 0x06, 0x02, 0x02, 0x06, 0x04, 0x00, 0x01, 0x05, 0x07, 0x03, 0x02, 0x06,
4839 0x04, 0x00, 0x00, 0x04, 0x06, 0x02, 0x02, 0x06, 0x05, 0x01, 0x00, 0x04, 0x07, 0x03, 0x02, 0x06,
4840 0x05, 0x03, 0x01, 0x07, 0x06, 0x00, 0x02, 0x04, 0x04, 0x02, 0x01, 0x07, 0x07, 0x01, 0x02, 0x04,
4841 0x04, 0x02, 0x00, 0x06, 0x06, 0x00, 0x02, 0x04, 0x05, 0x03, 0x00, 0x06, 0x07, 0x01, 0x02, 0x04
4842 };
4843
4844 return prot_lut_table[in];
4845 }
4846
PotopotoInit()4847 static INT32 PotopotoInit()
4848 {
4849 return SegaC2Init(potopoto_protection_callback);
4850 }
4851
4852 struct BurnDriver BurnDrvPotopoto = {
4853 "potopoto", NULL, NULL, NULL, "1994",
4854 "Poto Poto (Japan, Rev A)\0", NULL, "Sega", "C2",
4855 NULL, NULL, NULL, NULL,
4856 BDF_GAME_WORKING, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
4857 NULL, potopotoRomInfo, potopotoRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, PotopotoDIPInfo,
4858 PotopotoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4859 320, 224, 4, 3
4860 };
4861
4862
4863
4864 // Stack Columns (World)
4865
4866 static struct BurnRomInfo stkclmnsRomDesc[] = {
4867 { "epr-16874.ic32", 0x80000, 0xd78a871c, 1 | BRF_PRG | BRF_ESS }, // 0 maincpu
4868 { "epr-16873.ic31", 0x80000, 0x1def1da4, 1 | BRF_PRG | BRF_ESS }, // 1
4869 { "mpr-16797.ic34", 0x80000, 0xb28e9bd5, 1 | BRF_PRG | BRF_ESS }, // 2
4870 { "mpr-16796.ic33", 0x80000, 0xec7de52d, 1 | BRF_PRG | BRF_ESS }, // 3
4871
4872 { "epr-16793.ic4", 0x20000, 0xebb2d057, 2 | BRF_SND }, // 4 upd
4873 };
4874
4875 STD_ROM_PICK(stkclmns)
STD_ROM_FN(stkclmns)4876 STD_ROM_FN(stkclmns)
4877
4878 static UINT8 stkclmns_protection_callback(UINT8 in)
4879 {
4880 static const UINT8 prot_lut_table[0x100] = {
4881 0x01, 0x0d, 0x05, 0x09, 0x01, 0x0d, 0x05, 0x09, 0x00, 0x0c, 0x05, 0x09, 0x00, 0x0c, 0x05, 0x09,
4882 0x01, 0x0d, 0x05, 0x09, 0x00, 0x0c, 0x04, 0x08, 0x00, 0x0c, 0x05, 0x09, 0x01, 0x0d, 0x04, 0x08,
4883 0x01, 0x0f, 0x05, 0x0b, 0x01, 0x0f, 0x05, 0x0b, 0x00, 0x0e, 0x05, 0x0b, 0x00, 0x0e, 0x05, 0x0b,
4884 0x01, 0x0f, 0x05, 0x0b, 0x00, 0x0e, 0x04, 0x0a, 0x00, 0x0e, 0x05, 0x0b, 0x01, 0x0f, 0x04, 0x0a,
4885 0x09, 0x01, 0x05, 0x0d, 0x09, 0x01, 0x05, 0x0d, 0x08, 0x00, 0x05, 0x0d, 0x08, 0x00, 0x05, 0x0d,
4886 0x09, 0x01, 0x05, 0x0d, 0x08, 0x00, 0x04, 0x0c, 0x08, 0x00, 0x05, 0x0d, 0x09, 0x01, 0x04, 0x0c,
4887 0x09, 0x03, 0x05, 0x0f, 0x09, 0x03, 0x05, 0x0f, 0x08, 0x02, 0x05, 0x0f, 0x08, 0x02, 0x05, 0x0f,
4888 0x09, 0x03, 0x05, 0x0f, 0x08, 0x02, 0x04, 0x0e, 0x08, 0x02, 0x05, 0x0f, 0x09, 0x03, 0x04, 0x0e,
4889 0x01, 0x05, 0x01, 0x05, 0x03, 0x07, 0x03, 0x07, 0x00, 0x04, 0x01, 0x05, 0x02, 0x06, 0x03, 0x07,
4890 0x01, 0x05, 0x01, 0x05, 0x02, 0x06, 0x02, 0x06, 0x00, 0x04, 0x01, 0x05, 0x03, 0x07, 0x02, 0x06,
4891 0x01, 0x07, 0x01, 0x07, 0x03, 0x05, 0x03, 0x05, 0x00, 0x06, 0x01, 0x07, 0x02, 0x04, 0x03, 0x05,
4892 0x01, 0x07, 0x01, 0x07, 0x02, 0x04, 0x02, 0x04, 0x00, 0x06, 0x01, 0x07, 0x03, 0x05, 0x02, 0x04,
4893 0x09, 0x09, 0x01, 0x01, 0x0b, 0x0b, 0x03, 0x03, 0x08, 0x08, 0x01, 0x01, 0x0a, 0x0a, 0x03, 0x03,
4894 0x09, 0x09, 0x01, 0x01, 0x0a, 0x0a, 0x02, 0x02, 0x08, 0x08, 0x01, 0x01, 0x0b, 0x0b, 0x02, 0x02,
4895 0x09, 0x0b, 0x01, 0x03, 0x0b, 0x09, 0x03, 0x01, 0x08, 0x0a, 0x01, 0x03, 0x0a, 0x08, 0x03, 0x01,
4896 0x09, 0x0b, 0x01, 0x03, 0x0a, 0x08, 0x02, 0x00, 0x08, 0x0a, 0x01, 0x03, 0x0b, 0x09, 0x02, 0x00
4897 };
4898
4899 return prot_lut_table[in];
4900 }
4901
StkclmnsInit()4902 static INT32 StkclmnsInit()
4903 {
4904 return SegaC2Init(stkclmns_protection_callback);
4905 }
4906
4907 struct BurnDriver BurnDrvStkclmns = {
4908 "stkclmns", NULL, NULL, NULL, "1994",
4909 "Stack Columns (World)\0", NULL, "Sega", "C2",
4910 NULL, NULL, NULL, NULL,
4911 BDF_GAME_WORKING, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
4912 NULL, stkclmnsRomInfo, stkclmnsRomName, NULL, NULL, NULL, NULL, SegaC2_2ButtonInputInfo, StkclmnsDIPInfo,
4913 StkclmnsInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4914 320, 224, 4, 3
4915 };
4916
4917
4918 // Stack Columns (Japan)
4919
4920 static struct BurnRomInfo stkclmnsjRomDesc[] = {
4921 { "epr-16795.ic32", 0x80000, 0xb478fd02, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4922 { "epr-16794.ic31", 0x80000, 0x6d0e8c56, 1 | BRF_PRG | BRF_ESS }, // 1
4923 { "mpr-16797.ic34", 0x80000, 0xb28e9bd5, 1 | BRF_PRG | BRF_ESS }, // 2
4924 { "mpr-16796.ic33", 0x80000, 0xec7de52d, 1 | BRF_PRG | BRF_ESS }, // 3
4925
4926 { "epr-16793.ic4", 0x20000, 0xebb2d057, 2 | BRF_SND }, // 4 UPD Samples
4927 };
4928
4929 STD_ROM_PICK(stkclmnsj)
STD_ROM_FN(stkclmnsj)4930 STD_ROM_FN(stkclmnsj)
4931
4932 static UINT8 stkclmnsj_protection_callback(UINT8 in)
4933 {
4934 static const UINT8 prot_lut_table[0x100] = {
4935 0x0c, 0x0c, 0x08, 0x08, 0x0c, 0x0c, 0x08, 0x08, 0x0c, 0x0c, 0x08, 0x08, 0x0c, 0x0c, 0x08, 0x08,
4936 0x0c, 0x0c, 0x09, 0x09, 0x0c, 0x0c, 0x09, 0x09, 0x0c, 0x0c, 0x09, 0x09, 0x0c, 0x0c, 0x09, 0x09,
4937 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09,
4938 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08,
4939 0x0a, 0x0a, 0x0e, 0x0e, 0x08, 0x08, 0x0c, 0x0c, 0x0e, 0x0e, 0x0a, 0x0a, 0x0c, 0x0c, 0x08, 0x08,
4940 0x0a, 0x0a, 0x0f, 0x0f, 0x08, 0x08, 0x0d, 0x0d, 0x0e, 0x0e, 0x0b, 0x0b, 0x0c, 0x0c, 0x09, 0x09,
4941 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09,
4942 0x06, 0x06, 0x07, 0x07, 0x05, 0x05, 0x04, 0x04, 0x0a, 0x0a, 0x0b, 0x0b, 0x09, 0x09, 0x08, 0x08,
4943 0x0e, 0x0e, 0x0a, 0x0a, 0x0e, 0x0e, 0x0a, 0x0a, 0x0e, 0x0e, 0x0a, 0x0a, 0x0e, 0x0e, 0x0a, 0x0a,
4944 0x0e, 0x0e, 0x0b, 0x0b, 0x0e, 0x0e, 0x0b, 0x0b, 0x0e, 0x0e, 0x0b, 0x0b, 0x0e, 0x0e, 0x0b, 0x0b,
4945 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09,
4946 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08,
4947 0x00, 0x00, 0x04, 0x04, 0x02, 0x02, 0x06, 0x06, 0x04, 0x04, 0x00, 0x00, 0x06, 0x06, 0x02, 0x02,
4948 0x00, 0x00, 0x05, 0x05, 0x02, 0x02, 0x07, 0x07, 0x04, 0x04, 0x01, 0x01, 0x06, 0x06, 0x03, 0x03,
4949 0x0e, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
4950 0x0e, 0x0e, 0x0f, 0x0f, 0x0d, 0x0d, 0x0c, 0x0c, 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00
4951 };
4952
4953 return prot_lut_table[in];
4954 }
4955
StkclmnsjInit()4956 static INT32 StkclmnsjInit()
4957 {
4958 return SegaC2Init(stkclmnsj_protection_callback);
4959 }
4960
4961 struct BurnDriver BurnDrvStkclmnsj = {
4962 "stkclmnsj", "stkclmns", NULL, NULL, "1994",
4963 "Stack Columns (Japan)\0", NULL, "Sega", "C2",
4964 NULL, NULL, NULL, NULL,
4965 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
4966 NULL, stkclmnsjRomInfo, stkclmnsjRomName, NULL, NULL, NULL, NULL, SegaC2_2ButtonInputInfo, StkclmnsDIPInfo,
4967 StkclmnsjInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
4968 320, 224, 4, 3
4969 };
4970
4971
4972 // Puzzle & Action: Ichidant-R (World)
4973
4974 static struct BurnRomInfo ichirRomDesc[] = {
4975 { "pa2_32.bin", 0x80000, 0x7ba0c025, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
4976 { "pa2_31.bin", 0x80000, 0x5f86e5cc, 1 | BRF_PRG | BRF_ESS }, // 1
4977 { "epr-16888.ic34", 0x80000, 0x85d73722, 1 | BRF_PRG | BRF_ESS }, // 2
4978 { "epr-16887.ic33", 0x80000, 0xbc3bbf25, 1 | BRF_PRG | BRF_ESS }, // 3
4979
4980 { "pa2_02.bin", 0x80000, 0xfc7b0da5, 2 | BRF_SND }, // 4 UPD Samples
4981 };
4982
4983 STD_ROM_PICK(ichir)
STD_ROM_FN(ichir)4984 STD_ROM_FN(ichir)
4985
4986 static UINT8 ichir_protection_callback(UINT8 in)
4987 {
4988 static const UINT8 prot_lut_table[0x100] = {
4989 0x04, 0x0c, 0x04, 0x0c, 0x04, 0x0c, 0x04, 0x0c, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08,
4990 0x05, 0x0d, 0x05, 0x0d, 0x04, 0x0c, 0x04, 0x0c, 0x01, 0x09, 0x01, 0x09, 0x00, 0x08, 0x00, 0x08,
4991 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02,
4992 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
4993 0x00, 0x08, 0x02, 0x0a, 0x00, 0x08, 0x02, 0x0a, 0x00, 0x08, 0x02, 0x0a, 0x00, 0x08, 0x02, 0x0a,
4994 0x01, 0x09, 0x03, 0x0b, 0x00, 0x08, 0x02, 0x0a, 0x01, 0x09, 0x03, 0x0b, 0x00, 0x08, 0x02, 0x0a,
4995 0x07, 0x07, 0x05, 0x05, 0x06, 0x06, 0x04, 0x04, 0x03, 0x03, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00,
4996 0x06, 0x06, 0x04, 0x04, 0x06, 0x06, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
4997 0x06, 0x0e, 0x06, 0x0e, 0x06, 0x0e, 0x06, 0x0e, 0x02, 0x0a, 0x02, 0x0a, 0x02, 0x0a, 0x02, 0x0a,
4998 0x07, 0x0f, 0x07, 0x0f, 0x06, 0x0e, 0x06, 0x0e, 0x03, 0x0b, 0x03, 0x0b, 0x02, 0x0a, 0x02, 0x0a,
4999 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a,
5000 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
5001 0x02, 0x0a, 0x00, 0x08, 0x02, 0x0a, 0x00, 0x08, 0x02, 0x0a, 0x00, 0x08, 0x02, 0x0a, 0x00, 0x08,
5002 0x03, 0x0b, 0x01, 0x09, 0x02, 0x0a, 0x00, 0x08, 0x03, 0x0b, 0x01, 0x09, 0x02, 0x0a, 0x00, 0x08,
5003 0x0f, 0x0f, 0x0d, 0x0d, 0x0e, 0x0e, 0x0c, 0x0c, 0x0b, 0x0b, 0x09, 0x09, 0x0a, 0x0a, 0x08, 0x08,
5004 0x0e, 0x0e, 0x0c, 0x0c, 0x0e, 0x0e, 0x0c, 0x0c, 0x0a, 0x0a, 0x08, 0x08, 0x0a, 0x0a, 0x08, 0x08
5005 };
5006
5007 return prot_lut_table[in];
5008 }
5009
IchirInit()5010 static INT32 IchirInit()
5011 {
5012 return SegaC2Init(ichir_protection_callback);
5013 }
5014
5015 struct BurnDriver BurnDrvIchir = {
5016 "ichir", NULL, NULL, NULL, "1994",
5017 "Puzzle & Action: Ichidant-R (World)\0", NULL, "Sega", "C2",
5018 NULL, NULL, NULL, NULL,
5019 BDF_GAME_WORKING, 2, HARDWARE_SEGA_MISC, GBF_MINIGAMES | GBF_PUZZLE, 0,
5020 NULL, ichirRomInfo, ichirRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, IchirDIPInfo,
5021 IchirInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
5022 320, 224, 4, 3
5023 };
5024
5025
5026 // Puzzle & Action: Ichidant-R (Korea)
5027
5028 static struct BurnRomInfo ichirkRomDesc[] = {
5029 { "epr_ichi.32", 0x80000, 0x804dea11, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
5030 { "epr_ichi.31", 0x80000, 0x92452353, 1 | BRF_PRG | BRF_ESS }, // 1
5031 { "epr-16888.ic34", 0x80000, 0x85d73722, 1 | BRF_PRG | BRF_ESS }, // 2
5032 { "epr-16887.ic33", 0x80000, 0xbc3bbf25, 1 | BRF_PRG | BRF_ESS }, // 3
5033
5034 { "pa2_02.bin", 0x80000, 0xfc7b0da5, 2 | BRF_SND }, // 4 UPD Samples
5035 };
5036
5037 STD_ROM_PICK(ichirk)
STD_ROM_FN(ichirk)5038 STD_ROM_FN(ichirk)
5039
5040 static UINT8 ichirk_protection_callback(UINT8 in)
5041 {
5042 static const UINT8 prot_lut_table[0x100] = {
5043 0x04, 0x04, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x04, 0x04,
5044 0x05, 0x05, 0x01, 0x01, 0x04, 0x04, 0x00, 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00, 0x04, 0x04,
5045 0x05, 0x05, 0x08, 0x08, 0x05, 0x05, 0x08, 0x08, 0x05, 0x05, 0x08, 0x08, 0x05, 0x05, 0x08, 0x08,
5046 0x06, 0x06, 0x0b, 0x0b, 0x07, 0x07, 0x0a, 0x0a, 0x06, 0x06, 0x0b, 0x0b, 0x07, 0x07, 0x0a, 0x0a,
5047 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06, 0x04, 0x06,
5048 0x01, 0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x02, 0x05, 0x07, 0x05, 0x07, 0x04, 0x06, 0x04, 0x06,
5049 0x01, 0x03, 0x08, 0x0a, 0x01, 0x03, 0x08, 0x0a, 0x01, 0x03, 0x08, 0x0a, 0x01, 0x03, 0x08, 0x0a,
5050 0x02, 0x00, 0x0b, 0x09, 0x03, 0x01, 0x0a, 0x08, 0x02, 0x00, 0x0b, 0x09, 0x03, 0x01, 0x0a, 0x08,
5051 0x04, 0x04, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x04, 0x04,
5052 0x05, 0x05, 0x01, 0x01, 0x04, 0x04, 0x00, 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00, 0x04, 0x04,
5053 0x05, 0x05, 0x08, 0x08, 0x05, 0x05, 0x08, 0x08, 0x05, 0x05, 0x08, 0x08, 0x05, 0x05, 0x08, 0x08,
5054 0x06, 0x06, 0x0b, 0x0b, 0x07, 0x07, 0x0a, 0x0a, 0x06, 0x06, 0x0b, 0x0b, 0x07, 0x07, 0x0a, 0x0a,
5055 0x08, 0x0a, 0x08, 0x0a, 0x08, 0x0a, 0x08, 0x0a, 0x0c, 0x0e, 0x0c, 0x0e, 0x0c, 0x0e, 0x0c, 0x0e,
5056 0x09, 0x0b, 0x09, 0x0b, 0x08, 0x0a, 0x08, 0x0a, 0x0d, 0x0f, 0x0d, 0x0f, 0x0c, 0x0e, 0x0c, 0x0e,
5057 0x09, 0x0b, 0x00, 0x02, 0x09, 0x0b, 0x00, 0x02, 0x09, 0x0b, 0x00, 0x02, 0x09, 0x0b, 0x00, 0x02,
5058 0x0a, 0x08, 0x03, 0x01, 0x0b, 0x09, 0x02, 0x00, 0x0a, 0x08, 0x03, 0x01, 0x0b, 0x09, 0x02, 0x00,
5059 };
5060
5061 return prot_lut_table[in];
5062 }
5063
IchirkInit()5064 static INT32 IchirkInit()
5065 {
5066 return SegaC2Init(ichirk_protection_callback);
5067 }
5068
5069 struct BurnDriver BurnDrvIchirk = {
5070 "ichirk", "ichir", NULL, NULL, "1994",
5071 "Puzzle & Action: Ichidant-R (Korea)\0", NULL, "Sega", "C2",
5072 NULL, NULL, NULL, NULL,
5073 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_MISC, GBF_MINIGAMES | GBF_PUZZLE, 0,
5074 NULL, ichirkRomInfo, ichirkRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, IchirDIPInfo,
5075 IchirkInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
5076 320, 224, 4, 3
5077 };
5078
5079
5080 // Puzzle & Action: Ichidant-R (Japan)
5081
5082 static struct BurnRomInfo ichirjRomDesc[] = {
5083 { "epr-16886.ic32", 0x80000, 0x38208e28, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
5084 { "epr-16885.ic31", 0x80000, 0x1ce4e837, 1 | BRF_PRG | BRF_ESS }, // 1
5085 { "epr-16888.ic34", 0x80000, 0x85d73722, 1 | BRF_PRG | BRF_ESS }, // 2
5086 { "epr-16887.ic33", 0x80000, 0xbc3bbf25, 1 | BRF_PRG | BRF_ESS }, // 3
5087
5088 { "epr-16884.ic4", 0x80000, 0xfd9dcdd6, 2 | BRF_SND }, // 4 UPD Samples
5089 };
5090
5091 STD_ROM_PICK(ichirj)
STD_ROM_FN(ichirj)5092 STD_ROM_FN(ichirj)
5093
5094 static UINT8 ichirj_protection_callback(UINT8 in)
5095 {
5096 static const UINT8 prot_lut_table[0x100] = {
5097 0x05, 0x05, 0x01, 0x01, 0x06, 0x06, 0x02, 0x02, 0x05, 0x05, 0x01, 0x01, 0x06, 0x06, 0x02, 0x02,
5098 0x05, 0x05, 0x01, 0x01, 0x07, 0x07, 0x03, 0x03, 0x05, 0x05, 0x01, 0x01, 0x07, 0x07, 0x03, 0x03,
5099 0x08, 0x08, 0x00, 0x00, 0x0a, 0x0a, 0x02, 0x02, 0x08, 0x08, 0x00, 0x00, 0x0a, 0x0a, 0x02, 0x02,
5100 0x08, 0x08, 0x00, 0x00, 0x0b, 0x0b, 0x03, 0x03, 0x08, 0x08, 0x00, 0x00, 0x0b, 0x0b, 0x03, 0x03,
5101 0x01, 0x01, 0x05, 0x05, 0x00, 0x00, 0x04, 0x04, 0x05, 0x05, 0x01, 0x01, 0x04, 0x04, 0x00, 0x00,
5102 0x01, 0x01, 0x05, 0x05, 0x01, 0x01, 0x05, 0x05, 0x05, 0x05, 0x01, 0x01, 0x05, 0x05, 0x01, 0x01,
5103 0x0c, 0x0c, 0x04, 0x04, 0x0c, 0x0c, 0x04, 0x04, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,
5104 0x0c, 0x0c, 0x04, 0x04, 0x0d, 0x0d, 0x05, 0x05, 0x08, 0x08, 0x00, 0x00, 0x09, 0x09, 0x01, 0x01,
5105 0x0d, 0x0d, 0x09, 0x09, 0x0e, 0x0e, 0x0a, 0x0a, 0x0d, 0x0d, 0x09, 0x09, 0x0e, 0x0e, 0x0a, 0x0a,
5106 0x0d, 0x0d, 0x09, 0x09, 0x0f, 0x0f, 0x0b, 0x0b, 0x0d, 0x0d, 0x09, 0x09, 0x0f, 0x0f, 0x0b, 0x0b,
5107 0x0a, 0x0a, 0x02, 0x02, 0x08, 0x08, 0x00, 0x00, 0x0a, 0x0a, 0x02, 0x02, 0x08, 0x08, 0x00, 0x00,
5108 0x0a, 0x0a, 0x02, 0x02, 0x09, 0x09, 0x01, 0x01, 0x0a, 0x0a, 0x02, 0x02, 0x09, 0x09, 0x01, 0x01,
5109 0x09, 0x09, 0x0d, 0x0d, 0x08, 0x08, 0x0c, 0x0c, 0x0d, 0x0d, 0x09, 0x09, 0x0c, 0x0c, 0x08, 0x08,
5110 0x09, 0x09, 0x0d, 0x0d, 0x09, 0x09, 0x0d, 0x0d, 0x0d, 0x0d, 0x09, 0x09, 0x0d, 0x0d, 0x09, 0x09,
5111 0x0e, 0x0e, 0x06, 0x06, 0x0e, 0x0e, 0x06, 0x06, 0x0a, 0x0a, 0x02, 0x02, 0x0a, 0x0a, 0x02, 0x02,
5112 0x0e, 0x0e, 0x06, 0x06, 0x0f, 0x0f, 0x07, 0x07, 0x0a, 0x0a, 0x02, 0x02, 0x0b, 0x0b, 0x03, 0x03,
5113 };
5114
5115 return prot_lut_table[in];
5116 }
5117
IchirjInit()5118 static INT32 IchirjInit()
5119 {
5120 return SegaC2Init(ichirj_protection_callback);
5121 }
5122
5123 struct BurnDriver BurnDrvIchirj = {
5124 "ichirj", "ichir", NULL, NULL, "1994",
5125 "Puzzle & Action: Ichidant-R (Japan)\0", NULL, "Sega", "C2",
5126 NULL, NULL, NULL, NULL,
5127 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_MISC, GBF_MINIGAMES | GBF_PUZZLE, 0,
5128 NULL, ichirjRomInfo, ichirjRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, IchirDIPInfo,
5129 IchirjInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
5130 320, 224, 4, 3
5131 };
5132
5133
5134 // Puzzle & Action: Ichidant-R (Japan) (bootleg)
5135
5136 static struct BurnRomInfo ichirjblRomDesc[] = {
5137 { "27c4000.2", 0x80000, 0x5a194f44, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
5138 { "27c4000.1", 0x80000, 0xde209f84, 1 | BRF_PRG | BRF_ESS }, // 1
5139 { "epr-16888", 0x80000, 0x85d73722, 1 | BRF_PRG | BRF_ESS }, // 2
5140 { "epr-16887", 0x80000, 0xbc3bbf25, 1 | BRF_PRG | BRF_ESS }, // 3
5141 };
5142
5143 STD_ROM_PICK(ichirjbl)
5144 STD_ROM_FN(ichirjbl)
5145
5146 struct BurnDriver BurnDrvIchirjbl = {
5147 "ichirjbl", "ichir", NULL, NULL, "1994",
5148 "Puzzle & Action: Ichidant-R (Japan) (bootleg)\0", NULL, "bootleg", "C2",
5149 NULL, NULL, NULL, NULL,
5150 BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_MISC, GBF_MINIGAMES | GBF_PUZZLE, 0,
5151 NULL, ichirjblRomInfo, ichirjblRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, IchirDIPInfo,
5152 IchirInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
5153 320, 224, 4, 3
5154 };
5155
5156
5157 // Puyo Puyo 2 (Japan)
5158
5159 static struct BurnRomInfo puyopuy2RomDesc[] = {
5160 { "epr-17241.ic32", 0x80000, 0x1cad1149, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
5161 { "epr-17240.ic31", 0x80000, 0xbeecf96d, 1 | BRF_PRG | BRF_ESS }, // 1
5162
5163 { "epr-17239.ic4", 0x80000, 0x020ff6ef, 2 | BRF_SND }, // 2 UPD Samples
5164 };
5165
5166 STD_ROM_PICK(puyopuy2)
STD_ROM_FN(puyopuy2)5167 STD_ROM_FN(puyopuy2)
5168
5169 static UINT8 puyopuy2_protection_callback(UINT8 in)
5170 {
5171 static const UINT8 prot_lut_table[0x100] = {
5172 0x00, 0x03, 0x00, 0x03, 0x08, 0x0b, 0x08, 0x0b, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03,
5173 0x0c, 0x0f, 0x04, 0x07, 0x04, 0x07, 0x0c, 0x0f, 0x0c, 0x0f, 0x04, 0x07, 0x0c, 0x0f, 0x04, 0x07,
5174 0x00, 0x03, 0x00, 0x03, 0x08, 0x0b, 0x08, 0x0b, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
5175 0x0c, 0x0f, 0x04, 0x07, 0x04, 0x07, 0x0c, 0x0f, 0x0e, 0x0d, 0x06, 0x05, 0x0e, 0x0d, 0x06, 0x05,
5176 0x04, 0x01, 0x04, 0x01, 0x0c, 0x09, 0x0c, 0x09, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01,
5177 0x09, 0x0c, 0x00, 0x05, 0x01, 0x04, 0x08, 0x0d, 0x09, 0x0c, 0x00, 0x05, 0x09, 0x0c, 0x00, 0x05,
5178 0x04, 0x01, 0x04, 0x01, 0x0c, 0x09, 0x0c, 0x09, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03,
5179 0x09, 0x0c, 0x00, 0x05, 0x01, 0x04, 0x08, 0x0d, 0x0b, 0x0e, 0x02, 0x07, 0x0b, 0x0e, 0x02, 0x07,
5180 0x05, 0x07, 0x05, 0x07, 0x0d, 0x0f, 0x0d, 0x0f, 0x05, 0x07, 0x05, 0x07, 0x05, 0x07, 0x05, 0x07,
5181 0x0d, 0x0f, 0x05, 0x07, 0x05, 0x07, 0x0d, 0x0f, 0x0d, 0x0f, 0x05, 0x07, 0x0d, 0x0f, 0x05, 0x07,
5182 0x05, 0x07, 0x05, 0x07, 0x0d, 0x0f, 0x0d, 0x0f, 0x07, 0x05, 0x07, 0x05, 0x07, 0x05, 0x07, 0x05,
5183 0x0d, 0x0f, 0x05, 0x07, 0x05, 0x07, 0x0d, 0x0f, 0x0f, 0x0d, 0x07, 0x05, 0x0f, 0x0d, 0x07, 0x05,
5184 0x01, 0x05, 0x01, 0x05, 0x09, 0x0d, 0x09, 0x0d, 0x01, 0x05, 0x01, 0x05, 0x01, 0x05, 0x01, 0x05,
5185 0x08, 0x0c, 0x01, 0x05, 0x00, 0x04, 0x09, 0x0d, 0x08, 0x0c, 0x01, 0x05, 0x08, 0x0c, 0x01, 0x05,
5186 0x01, 0x05, 0x01, 0x05, 0x09, 0x0d, 0x09, 0x0d, 0x03, 0x07, 0x03, 0x07, 0x03, 0x07, 0x03, 0x07,
5187 0x08, 0x0c, 0x01, 0x05, 0x00, 0x04, 0x09, 0x0d, 0x0a, 0x0e, 0x03, 0x07, 0x0a, 0x0e, 0x03, 0x07
5188 };
5189
5190 return prot_lut_table[in];
5191 }
5192
Puyopuy2Init()5193 static INT32 Puyopuy2Init()
5194 {
5195 return SegaC2Init(puyopuy2_protection_callback);
5196 }
5197
5198 struct BurnDriver BurnDrvPuyopuy2 = {
5199 "puyopuy2", NULL, NULL, NULL, "1994",
5200 "Puyo Puyo 2 (Japan)\0", NULL, "Compile (Sega license)", "C2",
5201 NULL, NULL, NULL, NULL,
5202 BDF_GAME_WORKING, 2, HARDWARE_SEGA_MISC, GBF_PUZZLE, 0,
5203 NULL, puyopuy2RomInfo, puyopuy2RomName, NULL, NULL, NULL, NULL, SegaC2_2ButtonInputInfo, Puyopuy2DIPInfo,
5204 Puyopuy2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
5205 320, 224, 4, 3
5206 };
5207
5208
5209 // Zunzunkyou no Yabou (Japan)
5210
5211 static struct BurnRomInfo zunkyouRomDesc[] = {
5212 { "epr-16812.ic32", 0x80000, 0xeb088fb0, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
5213 { "epr-16811.ic31", 0x80000, 0x9ac7035b, 1 | BRF_PRG | BRF_ESS }, // 1
5214 { "epr-16814.ic34", 0x80000, 0x821b3b77, 1 | BRF_PRG | BRF_ESS }, // 2
5215 { "epr-16813.ic33", 0x80000, 0x3cba9e8f, 1 | BRF_PRG | BRF_ESS }, // 3
5216
5217 { "epr-16810.ic4", 0x80000, 0xd542f0fe, 2 | BRF_SND }, // 4 UPD Samples
5218 };
5219
5220 STD_ROM_PICK(zunkyou)
STD_ROM_FN(zunkyou)5221 STD_ROM_FN(zunkyou)
5222
5223 static UINT8 zunkyou_protection_callback(UINT8 in)
5224 {
5225 static const UINT8 prot_lut_table[0x100] = {
5226 0x0a, 0x00, 0x0a, 0x00, 0x06, 0x0c, 0x06, 0x0c, 0x08, 0x02, 0x08, 0x02, 0x00, 0x0a, 0x00, 0x0a,
5227 0x0e, 0x0c, 0x0e, 0x0c, 0x02, 0x00, 0x02, 0x00, 0x0e, 0x0c, 0x0e, 0x0c, 0x06, 0x04, 0x06, 0x04,
5228 0x0a, 0x02, 0x0a, 0x02, 0x06, 0x0e, 0x06, 0x0e, 0x08, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x08,
5229 0x0a, 0x0a, 0x0a, 0x0a, 0x06, 0x06, 0x06, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x02, 0x02, 0x02, 0x02,
5230 0x03, 0x09, 0x02, 0x08, 0x07, 0x0d, 0x06, 0x0c, 0x01, 0x0b, 0x00, 0x0a, 0x01, 0x0b, 0x00, 0x0a,
5231 0x07, 0x05, 0x06, 0x04, 0x03, 0x01, 0x02, 0x00, 0x07, 0x05, 0x06, 0x04, 0x07, 0x05, 0x06, 0x04,
5232 0x03, 0x0b, 0x02, 0x0a, 0x07, 0x0f, 0x06, 0x0e, 0x01, 0x09, 0x00, 0x08, 0x01, 0x09, 0x00, 0x08,
5233 0x03, 0x03, 0x02, 0x02, 0x07, 0x07, 0x06, 0x06, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x02, 0x02,
5234 0x0b, 0x01, 0x0b, 0x01, 0x07, 0x0d, 0x07, 0x0d, 0x09, 0x03, 0x09, 0x03, 0x01, 0x0b, 0x01, 0x0b,
5235 0x0f, 0x0d, 0x0f, 0x0d, 0x03, 0x01, 0x03, 0x01, 0x0f, 0x0d, 0x0f, 0x0d, 0x07, 0x05, 0x07, 0x05,
5236 0x0a, 0x02, 0x0a, 0x02, 0x06, 0x0e, 0x06, 0x0e, 0x08, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x08,
5237 0x0a, 0x0a, 0x0a, 0x0a, 0x06, 0x06, 0x06, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x02, 0x02, 0x02, 0x02,
5238 0x02, 0x08, 0x03, 0x09, 0x06, 0x0c, 0x07, 0x0d, 0x00, 0x0a, 0x01, 0x0b, 0x00, 0x0a, 0x01, 0x0b,
5239 0x06, 0x04, 0x07, 0x05, 0x02, 0x00, 0x03, 0x01, 0x06, 0x04, 0x07, 0x05, 0x06, 0x04, 0x07, 0x05,
5240 0x03, 0x0b, 0x02, 0x0a, 0x07, 0x0f, 0x06, 0x0e, 0x01, 0x09, 0x00, 0x08, 0x01, 0x09, 0x00, 0x08,
5241 0x03, 0x03, 0x02, 0x02, 0x07, 0x07, 0x06, 0x06, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x02, 0x02,
5242 };
5243
5244 return prot_lut_table[in];
5245 }
5246
ZunkyouInit()5247 static INT32 ZunkyouInit()
5248 {
5249 return SegaC2Init(zunkyou_protection_callback);
5250 }
5251
5252 struct BurnDriver BurnDrvZunkyou = {
5253 "zunkyou", NULL, NULL, NULL, "1994",
5254 "Zunzunkyou no Yabou (Japan)\0", NULL, "Sega", "C2",
5255 NULL, NULL, NULL, NULL,
5256 BDF_GAME_WORKING, 2, HARDWARE_SEGA_MISC, GBF_VERSHOOT, 0,
5257 NULL, zunkyouRomInfo, zunkyouRomName, NULL, NULL, NULL, NULL, SegaC2_2ButtonInputInfo, ZunkyouDIPInfo,
5258 ZunkyouInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
5259 320, 224, 4, 3
5260 };
5261
5262
5263 // Monita to Rimoko no Head On Channel (prototype, hack)
5264
5265 static struct BurnRomInfo headonchRomDesc[] = {
5266 { "headonch.ic32", 0x80000, 0x091cf538, 1 | BRF_PRG | BRF_ESS }, // 0 maincpu
5267 { "headonch.ic31", 0x80000, 0x91f3b5f1, 1 | BRF_PRG | BRF_ESS }, // 1
5268 { "headonch.ic34", 0x80000, 0xd8dc6323, 1 | BRF_PRG | BRF_ESS }, // 2
5269 { "headonch.ic33", 0x80000, 0x3268e38b, 1 | BRF_PRG | BRF_ESS }, // 3
5270
5271 { "headonch.ic4", 0x40000, 0x90af7301, 2 | BRF_SND }, // 4 upd
5272 };
5273
5274 STD_ROM_PICK(headonch)
5275 STD_ROM_FN(headonch)
5276
5277 struct BurnDriver BurnDrvHeadonch = {
5278 "headonch", NULL, NULL, NULL, "1994",
5279 "Monita to Rimoko no Head On Channel (prototype, hack)\0", NULL, "hack", "C2",
5280 NULL, NULL, NULL, NULL,
5281 BDF_GAME_WORKING | BDF_PROTOTYPE | BDF_HACK, 2, HARDWARE_SEGA_MISC, GBF_MAZE | GBF_ACTION, 0,
5282 NULL, headonchRomInfo, headonchRomName, NULL, NULL, NULL, NULL, SegaC2_1ButtonInputInfo, HeadonchDIPInfo,
5283 NoProtectionInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1800,
5284 320, 224, 4, 3
5285 };
5286
5287
5288 /*
5289 // Soreike! Anpanman Popcorn Koujou (Rev B)
5290
5291 static struct BurnRomInfo anpanmanRomDesc[] = {
5292 { "epr-14804b.ic32", 0x40000, 0x7ce88c49, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
5293 { "epr-14803b.ic31", 0x40000, 0xeb3ca1b9, 1 | BRF_PRG | BRF_ESS }, // 1
5294 { "epr-14806.ic34", 0x40000, 0x40f398db, 1 | BRF_PRG | BRF_ESS }, // 2
5295 { "epr-14805.ic33", 0x40000, 0xf27229ed, 1 | BRF_PRG | BRF_ESS }, // 3
5296
5297 { "epr-14807.ic4", 0x40000, 0x9827549f, 2 | BRF_SND }, // 4 UPD Samples
5298 };
5299
5300 STD_ROM_PICK(anpanman)
5301 STD_ROM_FN(anpanman)
5302
5303 struct BurnDriverD BurnDrvAnpanman = {
5304 "anpanman", NULL, NULL, NULL, "1992",
5305 "Soreike! Anpanman Popcorn Koujou (Rev B)\0", NULL, "Sega", "C2",
5306 NULL, NULL, NULL, NULL,
5307 BDF_GAME_WORKING, 2, HARDWARE_SEGA_MISC, GBF_MISC, 0,
5308 NULL, anpanmanRomInfo, anpanmanRomName, NULL, NULL, NULL, NULL, AnpanmanInputInfo, AnpanmanDIPInfo,
5309 DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0,
5310 320, 224, 4, 3
5311 };
5312
5313
5314 // SegaSonic Popcorn Shop (Rev B)
5315
5316 static struct BurnRomInfo sonicpopRomDesc[] = {
5317 { "epr-14592b.ic32", 0x40000, 0xbac586a1, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
5318 { "epr-15491b.ic31", 0x40000, 0x527106c3, 1 | BRF_PRG | BRF_ESS }, // 1
5319 { "epr-15494.ic34", 0x40000, 0x0520df5e, 1 | BRF_PRG | BRF_ESS }, // 2
5320 { "epr-15493.ic33", 0x40000, 0xd51b3b85, 1 | BRF_PRG | BRF_ESS }, // 3
5321
5322 { "epr-15495.ic4", 0x40000, 0xd3ee4c68, 2 | BRF_SND }, // 4 UPD Samples
5323 };
5324
5325 STD_ROM_PICK(sonicpop)
5326 STD_ROM_FN(sonicpop)
5327
5328 struct BurnDriverD BurnDrvSonicpop = {
5329 "sonicpop", NULL, NULL, NULL, "1993",
5330 "SegaSonic Popcorn Shop (Rev B)\0", NULL, "Sega", "C2",
5331 NULL, NULL, NULL, NULL,
5332 BDF_GAME_WORKING, 2, HARDWARE_SEGA_MISC, GBF_MISC, 0,
5333 NULL, sonicpopRomInfo, sonicpopRomName, NULL, NULL, NULL, NULL, SonicpopInputInfo, SonicpopDIPInfo,
5334 DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0,
5335 320, 224, 4, 3
5336 };
5337
5338
5339 // Print Club (Japan Vol.1)
5340
5341 static struct BurnRomInfo pclubjRomDesc[] = {
5342 { "epr18171.32", 0x80000, 0x6c8eb8e2, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
5343 { "epr18170.31", 0x80000, 0x72c631e6, 1 | BRF_PRG | BRF_ESS }, // 1
5344 { "epr18173.34", 0x80000, 0x9809dc72, 1 | BRF_PRG | BRF_ESS }, // 2
5345 { "epr18172.33", 0x80000, 0xc61d819b, 1 | BRF_PRG | BRF_ESS }, // 3
5346
5347 { "epr18169.4", 0x80000, 0x5c00ccfb, 2 | BRF_SND }, // 4 UPD Samples
5348 };
5349
5350 STD_ROM_PICK(pclubj)
5351 STD_ROM_FN(pclubj)
5352
5353 struct BurnDriver BurnDrvPclubj = {
5354 "pclubj", NULL, NULL, NULL, "1995",
5355 "Print Club (Japan Vol.1)\0", NULL, "Atlus", "C2",
5356 NULL, NULL, NULL, NULL,
5357 0, 2, HARDWARE_SEGA_MISC, GBF_MISC, 0,
5358 NULL, pclubjRomInfo, pclubjRomName, NULL, NULL, NULL, NULL, PclubInputInfo, PclubDIPInfo,
5359 DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0,
5360 320, 224, 4, 3
5361 };
5362
5363
5364 // Print Club (Japan Vol.2)
5365
5366 static struct BurnRomInfo pclubjv2RomDesc[] = {
5367 { "p2jwn.u32", 0x80000, 0xdfc0f7f1, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
5368 { "p2jwn.u31", 0x80000, 0x6ab4c694, 1 | BRF_PRG | BRF_ESS }, // 1
5369 { "p2jwn.u34", 0x80000, 0x854fd456, 1 | BRF_PRG | BRF_ESS }, // 2
5370 { "p2jwn.u33", 0x80000, 0x64428a69, 1 | BRF_PRG | BRF_ESS }, // 3
5371
5372 { "epr18169.4", 0x80000, 0x5c00ccfb, 2 | BRF_SND }, // 4 UPD Samples
5373 };
5374
5375 STD_ROM_PICK(pclubjv2)
5376 STD_ROM_FN(pclubjv2)
5377
5378 struct BurnDriverD BurnDrvPclubjv2 = {
5379 "pclubjv2", NULL, NULL, NULL, "1995",
5380 "Print Club (Japan Vol.2)\0", NULL, "Atlus", "C2",
5381 NULL, NULL, NULL, NULL,
5382 0, 2, HARDWARE_SEGA_MISC, GBF_MISC, 0,
5383 NULL, pclubjv2RomInfo, pclubjv2RomName, NULL, NULL, NULL, NULL, Pclubjv2InputInfo, Pclubjv2DIPInfo,
5384 DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0,
5385 320, 224, 4, 3
5386 };
5387
5388
5389 // Print Club (Japan Vol.4)
5390
5391 static struct BurnRomInfo pclubjv4RomDesc[] = {
5392 { "p4jsm.u32", 0x80000, 0x36ff5f80, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
5393 { "p4jsm.u31", 0x80000, 0xf3c021ad, 1 | BRF_PRG | BRF_ESS }, // 1
5394 { "p4jsm.u34", 0x80000, 0xd0fd4b33, 1 | BRF_PRG | BRF_ESS }, // 2
5395 { "p4jsm.u33", 0x80000, 0xec667875, 1 | BRF_PRG | BRF_ESS }, // 3
5396
5397 { "epr-18169.ic4", 0x80000, 0x5c00ccfb, 2 | BRF_SND }, // 4 UPD Samples
5398 };
5399
5400 STD_ROM_PICK(pclubjv4)
5401 STD_ROM_FN(pclubjv4)
5402
5403 struct BurnDriverD BurnDrvPclubjv4 = {
5404 "pclubjv4", NULL, NULL, NULL, "1996",
5405 "Print Club (Japan Vol.4)\0", NULL, "Atlus", "C2",
5406 NULL, NULL, NULL, NULL,
5407 0, 2, HARDWARE_SEGA_MISC, GBF_MISC, 0,
5408 NULL, pclubjv4RomInfo, pclubjv4RomName, NULL, NULL, NULL, NULL, Pclubjv2InputInfo, Pclubjv2DIPInfo,
5409 DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0,
5410 320, 224, 4, 3
5411 };
5412
5413
5414 // Print Club (Japan Vol.5)
5415
5416 static struct BurnRomInfo pclubjv5RomDesc[] = {
5417 { "p5jat.u32", 0x80000, 0x72220e69, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
5418 { "p5jat.u31", 0x80000, 0x06d83fde, 1 | BRF_PRG | BRF_ESS }, // 1
5419 { "p5jat.u34", 0x80000, 0xb172ab58, 1 | BRF_PRG | BRF_ESS }, // 2
5420 { "p5jat.u33", 0x80000, 0xba38ec50, 1 | BRF_PRG | BRF_ESS }, // 3
5421
5422 { "epr-18169.ic4", 0x80000, 0x5c00ccfb, 2 | BRF_SND }, // 4 UPD Samples
5423 };
5424
5425 STD_ROM_PICK(pclubjv5)
5426 STD_ROM_FN(pclubjv5)
5427
5428 struct BurnDriverD BurnDrvPclubjv5 = {
5429 "pclubjv5", NULL, NULL, NULL, "1996",
5430 "Print Club (Japan Vol.5)\0", NULL, "Atlus", "C2",
5431 NULL, NULL, NULL, NULL,
5432 0, 2, HARDWARE_SEGA_MISC, GBF_MISC, 0,
5433 NULL, pclubjv5RomInfo, pclubjv5RomName, NULL, NULL, NULL, NULL, Pclubjv2InputInfo, Pclubjv2DIPInfo,
5434 DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0,
5435 320, 224, 4, 3
5436 };
5437
5438
5439 // Print Club (Japan Vol.1)
5440
5441 static struct BurnRomInfo pclubRomDesc[] = {
5442 { "epr-ic32.32", 0x80000, 0x3fe9bda7, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code
5443 { "epr-ic31.31", 0x80000, 0x90f994d0, 1 | BRF_PRG | BRF_ESS }, // 1
5444 { "epr-ic34.34", 0x80000, 0x4d1ebb55, 1 | BRF_PRG | BRF_ESS }, // 2
5445 { "epr-ic33.33", 0x80000, 0xbdfdc797, 1 | BRF_PRG | BRF_ESS }, // 3
5446
5447 { "epr-ic4.4", 0x80000, 0x84eed1c4, 2 | BRF_SND }, // 4 UPD Samples
5448 };
5449
5450 STD_ROM_PICK(pclub)
5451 STD_ROM_FN(pclub)
5452
5453 struct BurnDriverD BurnDrvPclub = {
5454 "pclub", NULL, NULL, NULL, "1995",
5455 "Print Club (Japan Vol.1)\0", NULL, "Atlus", "C2",
5456 NULL, NULL, NULL, NULL,
5457 0, 2, HARDWARE_SEGA_MISC, GBF_MISC, 0,
5458 NULL, pclubRomInfo, pclubRomName, NULL, NULL, NULL, NULL, PclubInputInfo, PclubDIPInfo,
5459 DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0,
5460 320, 224, 4, 3
5461 };
5462 */
5463