4
#include "includes/megadriv.h"
8
int megadrive_visible_scanlines;
9
int megadrive_irq6_scanline;
10
int megadrive_z80irq_scanline;
11
int megadrive_imode = 0;
12
int megadriv_framerate;
13
int megadrive_total_scanlines;
14
int megadrive_vblank_flag = 0;
15
int genesis_scanline_counter = 0;
16
int megadrive_irq6_pending = 0;
17
int megadrive_irq4_pending = 0;
19
static int irq4counter;
21
static int megadrive_imode_odd_frame = 0;
23
int segac2_bg_pal_lookup[4];
24
int segac2_sp_pal_lookup[4];
27
int genvdp_use_cram = 0; // c2 uses it's own palette ram
28
int genesis_always_irq6 = 0; // c2 never enables the irq6, different source??
29
int genesis_other_hacks = 0; // misc hacks
33
static UINT8* sprite_renderline;
34
static UINT8* highpri_renderline;
35
static UINT32* video_renderline;
36
UINT16* megadrive_vdp_palette_lookup;
37
UINT16* megadrive_vdp_palette_lookup_sprite; // for C2
38
UINT16* megadrive_vdp_palette_lookup_shadow;
39
UINT16* megadrive_vdp_palette_lookup_highlight;
40
UINT16* megadrive_ram;
41
static UINT8 megadrive_vram_fill_pending = 0;
42
static UINT16 megadrive_vram_fill_length = 0;
43
static int megadrive_sprite_collision = 0;
44
static int megadrive_max_hposition;
45
int megadrive_region_export;
46
int megadrive_region_pal;
51
/* The VDP occupies addresses C00000h to C0001Fh.
53
C00000h - Data port (8=r/w, 16=r/w)
54
C00002h - Data port (mirror)
55
C00004h - Control port (8=r/w, 16=r/w)
56
C00006h - Control port (mirror)
57
C00008h - HV counter (8/16=r/o)
58
C0000Ah - HV counter (mirror)
59
C0000Ch - HV counter (mirror)
60
C0000Eh - HV counter (mirror)
61
C00011h - SN76489 PSG (8=w/o)
62
C00013h - SN76489 PSG (mirror)
63
C00015h - SN76489 PSG (mirror)
64
C00017h - SN76489 PSG (mirror)
67
#define MEGADRIV_VDP_VRAM(address) megadrive_vdp_vram[(address)&0x7fff]
71
static int megadrive_vdp_command_pending; // 2nd half of command pending..
72
static UINT16 megadrive_vdp_command_part1;
73
static UINT16 megadrive_vdp_command_part2;
74
static UINT8 megadrive_vdp_code;
75
static UINT16 megadrive_vdp_address;
76
static UINT16 megadrive_vdp_register[0x20];
77
static UINT16* megadrive_vdp_vram;
78
static UINT16* megadrive_vdp_cram;
79
static UINT16* megadrive_vdp_vsram;
80
/* The VDP keeps a 0x400 byte on-chip cache of the Sprite Attribute Table
81
to speed up processing */
82
static UINT16* megadrive_vdp_internal_sprite_attribute_table;
86
$00 - Mode Set Register No. 1
87
-----------------------------
92
d4 - IE1 (Horizontal interrupt enable)
93
d3 - 1= Invalid display setting
95
d1 - M3 (HV counter latch enable)
100
#define MEGADRIVE_REG0_UNUSED ((megadrive_vdp_register[0x00]&0xc0)>>6)
101
#define MEGADRIVE_REG0_BLANK_LEFT ((megadrive_vdp_register[0x00]&0x20)>>5) // like SMS, not used by any commercial games?
102
#define MEGADRIVE_REG0_IRQ4_ENABLE ((megadrive_vdp_register[0x00]&0x10)>>4)
103
#define MEGADRIVE_REG0_INVALID_MODE ((megadrive_vdp_register[0x00]&0x08)>>3) // invalid display mode, unhandled
104
#define MEGADRIVE_REG0_SPECIAL_PAL ((megadrive_vdp_register[0x00]&0x04)>>2) // strange palette mode, unhandled
105
#define MEGADRIVE_REG0_HVLATCH_ENABLE ((megadrive_vdp_register[0x00]&0x02)>>1) // HV Latch, used by lightgun games
106
#define MEGADRIVE_REG0_DISPLAY_DISABLE ((megadrive_vdp_register[0x00]&0x01)>>0)
110
$01 - Mode Set Register No. 2
111
-----------------------------
113
d7 - TMS9918 / Genesis display select
114
d6 - DISP (Display Enable)
115
d5 - IE0 (Vertical Interrupt Enable)
118
d2 - SMS / Genesis display select
124
#define MEGADRIVE_REG01_TMS9918_SELECT ((megadrive_vdp_register[0x01]&0x80)>>7)
125
#define MEGADRIVE_REG01_DISP_ENABLE ((megadrive_vdp_register[0x01]&0x40)>>6)
126
#define MEGADRIVE_REG01_IRQ6_ENABLE ((megadrive_vdp_register[0x01]&0x20)>>5)
127
#define MEGADRIVE_REG01_DMA_ENABLE ((megadrive_vdp_register[0x01]&0x10)>>4)
128
#define MEGADRIVE_REG01_240_LINE ((megadrive_vdp_register[0x01]&0x08)>>3)
129
#define MEGADRIVE_REG01_SMS_SELECT ((megadrive_vdp_register[0x01]&0x04)>>2)
130
#define MEGADRIVE_REG01_UNUSED ((megadrive_vdp_register[0x01]&0x02)>>1)
131
#define MEGADRIVE_REG01_STRANGE_VIDEO ((megadrive_vdp_register[0x01]&0x01)>>0) // unhandled, does strange things to the display
133
#define MEGADRIVE_REG02_UNUSED1 ((megadrive_vdp_register[0x02]&0xc0)>>6)
134
#define MEGADRIVE_REG02_PATTERN_ADDR_A ((megadrive_vdp_register[0x02]&0x38)>>3)
135
#define MEGADRIVE_REG02_UNUSED2 ((megadrive_vdp_register[0x02]&0x07)>>0)
137
#define MEGADRIVE_REG03_UNUSED1 ((megadrive_vdp_register[0x03]&0xc0)>>6)
138
#define MEGADRIVE_REG03_PATTERN_ADDR_W ((megadrive_vdp_register[0x03]&0x3e)>>1)
139
#define MEGADRIVE_REG03_UNUSED2 ((megadrive_vdp_register[0x03]&0x01)>>0)
141
#define MEGADRIVE_REG04_UNUSED ((megadrive_vdp_register[0x04]&0xf8)>>3)
142
#define MEGADRIVE_REG04_PATTERN_ADDR_B ((megadrive_vdp_register[0x04]&0x07)>>0)
144
#define MEGADRIVE_REG05_UNUSED ((megadrive_vdp_register[0x05]&0x80)>>7)
145
#define MEGADRIVE_REG05_SPRITE_ADDR ((megadrive_vdp_register[0x05]&0x7f)>>0)
149
#define MEGADRIVE_REG07_UNUSED ((megadrive_vdp_register[0x07]&0xc0)>>6)
150
#define MEGADRIVE_REG07_BGCOLOUR ((megadrive_vdp_register[0x07]&0x3f)>>0)
155
#define MEGADRIVE_REG0A_HINT_VALUE ((megadrive_vdp_register[0x0a]&0xff)>>0)
157
#define MEGADRIVE_REG0B_UNUSED ((megadrive_vdp_register[0x0b]&0xf0)>>4)
158
#define MEGADRIVE_REG0B_IRQ2_ENABLE ((megadrive_vdp_register[0x0b]&0x08)>>3)
159
#define MEGADRIVE_REG0B_VSCROLL_MODE ((megadrive_vdp_register[0x0b]&0x04)>>2)
160
#define MEGADRIVE_REG0B_HSCROLL_MODE ((megadrive_vdp_register[0x0b]&0x03)>>0)
162
#define MEGADRIVE_REG0C_RS0 ((megadrive_vdp_register[0x0c]&0x80)>>7)
163
#define MEGADRIVE_REG0C_UNUSED1 ((megadrive_vdp_register[0x0c]&0x40)>>6)
164
#define MEGADRIVE_REG0C_SPECIAL ((megadrive_vdp_register[0x0c]&0x20)>>5)
165
#define MEGADRIVE_REG0C_UNUSED2 ((megadrive_vdp_register[0x0c]&0x10)>>4)
166
#define MEGADRIVE_REG0C_SHADOW_HIGLIGHT ((megadrive_vdp_register[0x0c]&0x08)>>3)
167
#define MEGADRIVE_REG0C_INTERLEAVE ((megadrive_vdp_register[0x0c]&0x06)>>1)
168
#define MEGADRIVE_REG0C_RS1 ((megadrive_vdp_register[0x0c]&0x01)>>0)
170
#define MEGADRIVE_REG0D_UNUSED ((megadrive_vdp_register[0x0d]&0xc0)>>6)
171
#define MEGADRIVE_REG0D_HSCROLL_ADDR ((megadrive_vdp_register[0x0d]&0x3f)>>0)
175
#define MEGADRIVE_REG0F_AUTO_INC ((megadrive_vdp_register[0x0f]&0xff)>>0)
177
#define MEGADRIVE_REG10_UNUSED1 ((megadrive_vdp_register[0x10]&0xc0)>>6)
178
#define MEGADRIVE_REG10_VSCROLL_SIZE ((megadrive_vdp_register[0x10]&0x30)>>4)
179
#define MEGADRIVE_REG10_UNUSED2 ((megadrive_vdp_register[0x10]&0x0c)>>2)
180
#define MEGADRIVE_REG10_HSCROLL_SIZE ((megadrive_vdp_register[0x10]&0x03)>>0)
182
#define MEGADRIVE_REG11_WINDOW_RIGHT ((megadrive_vdp_register[0x11]&0x80)>>7)
183
#define MEGADRIVE_REG11_UNUSED ((megadrive_vdp_register[0x11]&0x60)>>5)
184
#define MEGADRIVE_REG11_WINDOW_HPOS ((megadrive_vdp_register[0x11]&0x1f)>>0)
186
#define MEGADRIVE_REG12_WINDOW_DOWN ((megadrive_vdp_register[0x12]&0x80)>>7)
187
#define MEGADRIVE_REG12_UNUSED ((megadrive_vdp_register[0x12]&0x60)>>5)
188
#define MEGADRIVE_REG12_WINDOW_VPOS ((megadrive_vdp_register[0x12]&0x1f)>>0)
190
#define MEGADRIVE_REG13_DMALENGTH1 ((megadrive_vdp_register[0x13]&0xff)>>0)
192
#define MEGADRIVE_REG14_DMALENGTH2 ((megadrive_vdp_register[0x14]&0xff)>>0)
194
#define MEGADRIVE_REG15_DMASOURCE1 ((megadrive_vdp_register[0x15]&0xff)>>0)
195
#define MEGADRIVE_REG16_DMASOURCE2 ((megadrive_vdp_register[0x16]&0xff)>>0)
197
#define MEGADRIVE_REG17_DMASOURCE3 ((megadrive_vdp_register[0x17]&0xff)>>0)
198
#define MEGADRIVE_REG17_DMATYPE ((megadrive_vdp_register[0x17]&0xc0)>>6)
199
#define MEGADRIVE_REG17_UNUSED ((megadrive_vdp_register[0x17]&0x3f)>>0)
202
static void vdp_vram_write(UINT16 data)
205
UINT16 sprite_base_address = MEGADRIVE_REG0C_RS1?((MEGADRIVE_REG05_SPRITE_ADDR&0x7e)<<9):((MEGADRIVE_REG05_SPRITE_ADDR&0x7f)<<9);
206
int spritetable_size = MEGADRIVE_REG0C_RS1?0x400:0x200;
207
int lowlimit = sprite_base_address;
208
int highlimit = sprite_base_address+spritetable_size;
210
if (megadrive_vdp_address&1)
212
data = ((data&0x00ff)<<8)|((data&0xff00)>>8);
215
MEGADRIV_VDP_VRAM(megadrive_vdp_address>>1) = data;
217
/* The VDP stores an Internal copy of any data written to the Sprite Attribute Table.
218
This data is _NOT_ invalidated when the Sprite Base Address changes, thus allowing
219
for some funky effects, as used by Castlevania Bloodlines Stage 6-3 */
220
if (megadrive_vdp_address>=lowlimit && megadrive_vdp_address<highlimit)
222
// mame_printf_debug("spritebase is %04x-%04x vram address is %04x, write %04x\n",lowlimit, highlimit-1, megadrive_vdp_address, data);
223
megadrive_vdp_internal_sprite_attribute_table[(megadrive_vdp_address&(spritetable_size-1))>>1] = data;
226
megadrive_vdp_address+=MEGADRIVE_REG0F_AUTO_INC;
227
megadrive_vdp_address &= 0xffff;
230
static void vdp_vsram_write(UINT16 data)
232
megadrive_vdp_vsram[(megadrive_vdp_address&0x7e)>>1] = data;
234
//logerror("Wrote to VSRAM addr %04x data %04x\n",megadrive_vdp_address&0xfffe,megadrive_vdp_vsram[megadrive_vdp_address>>1]);
236
megadrive_vdp_address+=MEGADRIVE_REG0F_AUTO_INC;
238
megadrive_vdp_address &=0xffff;
241
static void write_cram_value(running_machine &machine, int offset, int data)
243
megadrive_vdp_cram[offset] = data;
245
//logerror("Wrote to CRAM addr %04x data %04x\n",megadrive_vdp_address&0xfffe,megadrive_vdp_cram[megadrive_vdp_address>>1]);
249
r = ((data >> 1)&0x07);
250
g = ((data >> 5)&0x07);
251
b = ((data >> 9)&0x07);
252
palette_set_color_rgb(machine,offset,pal3bit(r),pal3bit(g),pal3bit(b));
253
megadrive_vdp_palette_lookup[offset] = (b<<2) | (g<<7) | (r<<12);
254
megadrive_vdp_palette_lookup_sprite[offset] = (b<<2) | (g<<7) | (r<<12);
255
megadrive_vdp_palette_lookup_shadow[offset] = (b<<1) | (g<<6) | (r<<11);
256
megadrive_vdp_palette_lookup_highlight[offset] = ((b|0x08)<<1) | ((g|0x08)<<6) | ((r|0x08)<<11);
260
static void vdp_cram_write(running_machine &machine, UINT16 data)
263
offset = (megadrive_vdp_address&0x7e)>>1;
265
write_cram_value(machine, offset,data);
267
megadrive_vdp_address+=MEGADRIVE_REG0F_AUTO_INC;
269
megadrive_vdp_address &=0xffff;
273
static void megadriv_vdp_data_port_w(running_machine &machine, int data)
275
megadrive_vdp_command_pending = 0;
285
// logerror("write to vdp data port %04x with code %04x, write address %04x\n",data, megadrive_vdp_code, megadrive_vdp_address );
287
if (megadrive_vram_fill_pending)
291
megadrive_vdp_address&=0xffff;
293
if (megadrive_vdp_address&1)
295
MEGADRIV_VDP_VRAM((megadrive_vdp_address>>1)) = (MEGADRIV_VDP_VRAM((megadrive_vdp_address>>1))&0xff00) | (data&0x00ff);
299
MEGADRIV_VDP_VRAM((megadrive_vdp_address>>1)) = (MEGADRIV_VDP_VRAM((megadrive_vdp_address>>1))&0x00ff) | ((data&0x00ff)<<8);
303
for (count=0;count<=megadrive_vram_fill_length;count++) // <= for james pond 3
305
if (megadrive_vdp_address&1)
307
MEGADRIV_VDP_VRAM((megadrive_vdp_address>>1)) = (MEGADRIV_VDP_VRAM((megadrive_vdp_address>>1))&0x00ff) | (data&0xff00);
311
MEGADRIV_VDP_VRAM((megadrive_vdp_address>>1)) = (MEGADRIV_VDP_VRAM((megadrive_vdp_address>>1))&0xff00) | ((data&0xff00)>>8);
314
megadrive_vdp_address+=MEGADRIVE_REG0F_AUTO_INC;
315
megadrive_vdp_address&=0xffff;
319
megadrive_vdp_register[0x13] = 0;
320
megadrive_vdp_register[0x14] = 0;
322
// megadrive_vdp_register[0x15] = (source>>1) & 0xff;
323
// megadrive_vdp_register[0x16] = (source>>9) & 0xff;
324
// megadrive_vdp_register[0x17] = (source>>17) & 0xff;
331
switch (megadrive_vdp_code & 0x000f)
334
logerror("Attempting to WRITE to DATA PORT in VRAM READ MODE\n");
338
vdp_vram_write(data);
342
vdp_cram_write(machine, data);
346
logerror("Attempting to WRITE to DATA PORT in VSRAM READ MODE\n");
350
vdp_vsram_write(data);
354
logerror("Attempting to WRITE to DATA PORT in CRAM READ MODE\n");
358
logerror("Attempting to WRITE to DATA PORT in #UNDEFINED# MODE %1x %04x\n",megadrive_vdp_code&0xf, data);
369
static void megadrive_vdp_set_register(running_machine &machine, int regnum, UINT8 value)
371
megadrive_vdp_register[regnum] = value;
373
/* We need special handling for the IRQ enable registers, some games turn
374
off the irqs before they are taken, delaying them until the IRQ is turned
379
//mame_printf_debug("setting reg 0, irq enable is now %d\n",MEGADRIVE_REG0_IRQ4_ENABLE);
381
if (megadrive_irq4_pending)
383
if (MEGADRIVE_REG0_IRQ4_ENABLE)
384
cputag_set_input_line(machine, "maincpu", 4, HOLD_LINE);
386
cputag_set_input_line(machine, "maincpu", 4, CLEAR_LINE);
389
/* ??? Fatal Rewind needs this but I'm not sure it's accurate behavior
390
it causes flickering in roadrash */
391
// megadrive_irq6_pending = 0;
392
// megadrive_irq4_pending = 0;
398
if (megadrive_irq6_pending)
400
if (MEGADRIVE_REG01_IRQ6_ENABLE )
401
cputag_set_input_line(machine, "maincpu", 6, HOLD_LINE);
403
cputag_set_input_line(machine, "maincpu", 6, CLEAR_LINE);
407
// megadrive_irq6_pending = 0;
408
// megadrive_irq4_pending = 0;
413
// if (regnum == 0x0a)
414
// mame_printf_debug("Set HINT Reload Register to %d on scanline %d\n",value, genesis_scanline_counter);
416
// mame_printf_debug("%s: Setting VDP Register #%02x to %02x\n",machine.describe_context(), regnum,value);
419
static void update_megadrive_vdp_code_and_address(void)
421
megadrive_vdp_code = ((megadrive_vdp_command_part1 & 0xc000) >> 14) |
422
((megadrive_vdp_command_part2 & 0x00f0) >> 2);
424
megadrive_vdp_address = ((megadrive_vdp_command_part1 & 0x3fff) >> 0) |
425
((megadrive_vdp_command_part2 & 0x0003) << 14);
428
UINT16 (*vdp_get_word_from_68k_mem)(running_machine &machine, UINT32 source);
430
UINT16 vdp_get_word_from_68k_mem_default(running_machine &machine, UINT32 source)
432
// should we limit the valid areas here?
433
// how does this behave with the segacd etc?
434
// note, the RV bit on 32x is important for this to work, because it causes a normal cart mapping - see tempo
435
address_space *space68k = machine.device<legacy_cpu_device>("maincpu")->space();
437
//printf("vdp_get_word_from_68k_mem_default %08x\n", source);
439
if ( source <= 0x3fffff )
441
if (_svp_cpu != NULL)
443
source -= 2; // the SVP introduces some kind of DMA 'lag', which we have to compensate for, this is obvious even on gfx DMAd from ROM (the Speedometer)
446
// likewise segaCD, at least when reading wordram?
447
// we might need to check what mode we're in here..
448
if (segacd_wordram_mapped)
453
return space68k->read_word(source);
455
else if (( source >= 0xe00000 ) && ( source <= 0xffffff ))
457
return space68k->read_word(source);
461
printf("DMA Read unmapped %06x\n",source);
462
return machine.rand();
468
/* Table from Charles Macdonald
471
DMA Mode Width Display Transfer Count
472
-----------------------------------------------------
473
68K > VDP 32-cell Active 16
477
VRAM Fill 32-cell Active 15
481
VRAM Copy 32-cell Active 8
489
/* Note, In reality this transfer is NOT instant, the 68k isn't paused
490
as the 68k address bus isn't accessed */
492
/* Wani Wani World, James Pond 3, Pirates Gold! */
493
static void megadrive_do_insta_vram_copy(UINT32 source, UINT16 length)
497
for (x=0;x<length;x++)
501
//mame_printf_debug("vram copy length %04x source %04x dest %04x\n",length, source, megadrive_vdp_address );
502
if (source&1) source_byte = MEGADRIV_VDP_VRAM((source&0xffff)>>1)&0x00ff;
503
else source_byte = (MEGADRIV_VDP_VRAM((source&0xffff)>>1)&0xff00)>>8;
505
if (megadrive_vdp_address&1)
507
MEGADRIV_VDP_VRAM((megadrive_vdp_address&0xffff)>>1) = (MEGADRIV_VDP_VRAM((megadrive_vdp_address&0xffff)>>1)&0xff00) | source_byte;
511
MEGADRIV_VDP_VRAM((megadrive_vdp_address&0xffff)>>1) = (MEGADRIV_VDP_VRAM((megadrive_vdp_address&0xffff)>>1)&0x00ff) | (source_byte<<8);
515
megadrive_vdp_address+=MEGADRIVE_REG0F_AUTO_INC;
516
megadrive_vdp_address&=0xffff;
520
/* Instant, but we pause the 68k a bit */
521
static void megadrive_do_insta_68k_to_vram_dma(running_machine &machine, UINT32 source,int length)
525
if (length==0x00) length = 0xffff;
527
/* This is a hack until real DMA timings are implemented */
528
device_spin_until_time(machine.device("maincpu"), attotime::from_nsec(length * 1000 / 3500));
530
for (count = 0;count<(length>>1);count++)
532
vdp_vram_write(vdp_get_word_from_68k_mem(machine, source));
534
if (source>0xffffff) source = 0xe00000;
537
megadrive_vdp_address&=0xffff;
539
megadrive_vdp_register[0x13] = 0;
540
megadrive_vdp_register[0x14] = 0;
542
megadrive_vdp_register[0x15] = (source>>1) & 0xff;
543
megadrive_vdp_register[0x16] = (source>>9) & 0xff;
544
megadrive_vdp_register[0x17] = (source>>17) & 0xff;
548
static void megadrive_do_insta_68k_to_cram_dma(running_machine &machine,UINT32 source,UINT16 length)
552
if (length==0x00) length = 0xffff;
554
for (count = 0;count<(length>>1);count++)
556
//if (megadrive_vdp_address>=0x80) return; // abandon
558
write_cram_value(machine, (megadrive_vdp_address&0x7e)>>1, vdp_get_word_from_68k_mem(machine, source));
561
if (source>0xffffff) source = 0xfe0000;
563
megadrive_vdp_address+=MEGADRIVE_REG0F_AUTO_INC;
564
megadrive_vdp_address&=0xffff;
567
megadrive_vdp_register[0x13] = 0;
568
megadrive_vdp_register[0x14] = 0;
570
megadrive_vdp_register[0x15] = (source>>1) & 0xff;
571
megadrive_vdp_register[0x16] = (source>>9) & 0xff;
572
megadrive_vdp_register[0x17] = (source>>17) & 0xff;
576
static void megadrive_do_insta_68k_to_vsram_dma(running_machine &machine,UINT32 source,UINT16 length)
580
if (length==0x00) length = 0xffff;
582
for (count = 0;count<(length>>1);count++)
584
if (megadrive_vdp_address>=0x80) return; // abandon
586
megadrive_vdp_vsram[(megadrive_vdp_address&0x7e)>>1] = vdp_get_word_from_68k_mem(machine, source);
589
if (source>0xffffff) source = 0xfe0000;
591
megadrive_vdp_address+=MEGADRIVE_REG0F_AUTO_INC;
592
megadrive_vdp_address&=0xffff;
595
megadrive_vdp_register[0x13] = 0;
596
megadrive_vdp_register[0x14] = 0;
598
megadrive_vdp_register[0x15] = (source>>1) & 0xff;
599
megadrive_vdp_register[0x16] = (source>>9) & 0xff;
600
megadrive_vdp_register[0x17] = (source>>17) & 0xff;
603
/* This can be simplified quite a lot.. */
604
static void handle_dma_bits(running_machine &machine)
607
if (megadrive_vdp_code&0x20)
611
source = (MEGADRIVE_REG15_DMASOURCE1 | (MEGADRIVE_REG16_DMASOURCE2<<8) | ((MEGADRIVE_REG17_DMASOURCE3&0xff)<<16))<<1;
612
length = (MEGADRIVE_REG13_DMALENGTH1 | (MEGADRIVE_REG14_DMALENGTH2<<8))<<1;
613
mame_printf_debug("%s 68k DMAtran set source %06x length %04x dest %04x enabled %01x code %02x %02x\n", machine.describe_context(), source, length, megadrive_vdp_address,MEGADRIVE_REG01_DMA_ENABLE, megadrive_vdp_code,MEGADRIVE_REG0F_AUTO_INC);
616
if (megadrive_vdp_code==0x20)
618
mame_printf_debug("DMA bit set 0x20 but invalid??\n");
620
else if (megadrive_vdp_code==0x21 || megadrive_vdp_code==0x31) /* 0x31 used by tecmo cup */
622
if (MEGADRIVE_REG17_DMATYPE==0x0 || MEGADRIVE_REG17_DMATYPE==0x1)
626
source = (MEGADRIVE_REG15_DMASOURCE1 | (MEGADRIVE_REG16_DMASOURCE2<<8) | ((MEGADRIVE_REG17_DMASOURCE3&0x7f)<<16))<<1;
627
length = (MEGADRIVE_REG13_DMALENGTH1 | (MEGADRIVE_REG14_DMALENGTH2<<8))<<1;
629
/* The 68k is frozen during this transfer, it should be safe to throw a few cycles away and do 'instant' DMA because the 68k can't detect it being in progress (can the z80?) */
630
//mame_printf_debug("68k->VRAM DMA transfer source %06x length %04x dest %04x enabled %01x\n", source, length, megadrive_vdp_address,MEGADRIVE_REG01_DMA_ENABLE);
631
if (MEGADRIVE_REG01_DMA_ENABLE) megadrive_do_insta_68k_to_vram_dma(machine,source,length);
634
else if (MEGADRIVE_REG17_DMATYPE==0x2)
636
//mame_printf_debug("vram fill length %02x %02x other regs! %02x %02x %02x(Mode Bits %02x) Enable %02x\n", MEGADRIVE_REG13_DMALENGTH1, MEGADRIVE_REG14_DMALENGTH2, MEGADRIVE_REG15_DMASOURCE1, MEGADRIVE_REG16_DMASOURCE2, MEGADRIVE_REG17_DMASOURCE3, MEGADRIVE_REG17_DMATYPE, MEGADRIVE_REG01_DMA_ENABLE);
637
if (MEGADRIVE_REG01_DMA_ENABLE)
639
megadrive_vram_fill_pending = 1;
640
megadrive_vram_fill_length = (MEGADRIVE_REG13_DMALENGTH1 | (MEGADRIVE_REG14_DMALENGTH2<<8));
643
else if (MEGADRIVE_REG17_DMATYPE==0x3)
647
source = (MEGADRIVE_REG15_DMASOURCE1 | (MEGADRIVE_REG16_DMASOURCE2<<8)); // source (byte offset)
648
length = (MEGADRIVE_REG13_DMALENGTH1 | (MEGADRIVE_REG14_DMALENGTH2<<8)); // length in bytes
649
//mame_printf_debug("setting vram copy mode length registers are %02x %02x other regs! %02x %02x %02x(Mode Bits %02x) Enable %02x\n", MEGADRIVE_REG13_DMALENGTH1, MEGADRIVE_REG14_DMALENGTH2, MEGADRIVE_REG15_DMASOURCE1, MEGADRIVE_REG16_DMASOURCE2, MEGADRIVE_REG17_DMASOURCE3, MEGADRIVE_REG17_DMATYPE, MEGADRIVE_REG01_DMA_ENABLE);
651
if (MEGADRIVE_REG01_DMA_ENABLE) megadrive_do_insta_vram_copy(source, length);
654
else if (megadrive_vdp_code==0x23)
656
if (MEGADRIVE_REG17_DMATYPE==0x0 || MEGADRIVE_REG17_DMATYPE==0x1)
660
source = (MEGADRIVE_REG15_DMASOURCE1 | (MEGADRIVE_REG16_DMASOURCE2<<8) | ((MEGADRIVE_REG17_DMASOURCE3&0x7f)<<16))<<1;
661
length = (MEGADRIVE_REG13_DMALENGTH1 | (MEGADRIVE_REG14_DMALENGTH2<<8))<<1;
663
/* The 68k is frozen during this transfer, it should be safe to throw a few cycles away and do 'instant' DMA because the 68k can't detect it being in progress (can the z80?) */
664
//mame_printf_debug("68k->CRAM DMA transfer source %06x length %04x dest %04x enabled %01x\n", source, length, megadrive_vdp_address,MEGADRIVE_REG01_DMA_ENABLE);
665
if (MEGADRIVE_REG01_DMA_ENABLE) megadrive_do_insta_68k_to_cram_dma(machine,source,length);
667
else if (MEGADRIVE_REG17_DMATYPE==0x2)
669
//mame_printf_debug("vram fill length %02x %02x other regs! %02x %02x %02x(Mode Bits %02x) Enable %02x\n", MEGADRIVE_REG13_DMALENGTH1, MEGADRIVE_REG14_DMALENGTH2, MEGADRIVE_REG15_DMASOURCE1, MEGADRIVE_REG16_DMASOURCE2, MEGADRIVE_REG17_DMASOURCE3, MEGADRIVE_REG17_DMATYPE, MEGADRIVE_REG01_DMA_ENABLE);
670
if (MEGADRIVE_REG01_DMA_ENABLE)
672
megadrive_vram_fill_pending = 1;
673
megadrive_vram_fill_length = (MEGADRIVE_REG13_DMALENGTH1 | (MEGADRIVE_REG14_DMALENGTH2<<8));
676
else if (MEGADRIVE_REG17_DMATYPE==0x3)
678
mame_printf_debug("setting vram copy (INVALID?) mode length registers are %02x %02x other regs! %02x %02x %02x(Mode Bits %02x) Enable %02x\n", MEGADRIVE_REG13_DMALENGTH1, MEGADRIVE_REG14_DMALENGTH2, MEGADRIVE_REG15_DMASOURCE1, MEGADRIVE_REG16_DMASOURCE2, MEGADRIVE_REG17_DMASOURCE3, MEGADRIVE_REG17_DMATYPE, MEGADRIVE_REG01_DMA_ENABLE);
681
else if (megadrive_vdp_code==0x25)
683
if (MEGADRIVE_REG17_DMATYPE==0x0 || MEGADRIVE_REG17_DMATYPE==0x1)
687
source = (MEGADRIVE_REG15_DMASOURCE1 | (MEGADRIVE_REG16_DMASOURCE2<<8) | ((MEGADRIVE_REG17_DMASOURCE3&0x7f)<<16))<<1;
688
length = (MEGADRIVE_REG13_DMALENGTH1 | (MEGADRIVE_REG14_DMALENGTH2<<8))<<1;
690
/* The 68k is frozen during this transfer, it should be safe to throw a few cycles away and do 'instant' DMA because the 68k can't detect it being in progress (can the z80?) */
691
//mame_printf_debug("68k->VSRAM DMA transfer source %06x length %04x dest %04x enabled %01x\n", source, length, megadrive_vdp_address,MEGADRIVE_REG01_DMA_ENABLE);
692
if (MEGADRIVE_REG01_DMA_ENABLE) megadrive_do_insta_68k_to_vsram_dma(machine,source,length);
694
else if (MEGADRIVE_REG17_DMATYPE==0x2)
696
//mame_printf_debug("vram fill length %02x %02x other regs! %02x %02x %02x(Mode Bits %02x) Enable %02x\n", MEGADRIVE_REG13_DMALENGTH1, MEGADRIVE_REG14_DMALENGTH2, MEGADRIVE_REG15_DMASOURCE1, MEGADRIVE_REG16_DMASOURCE2, MEGADRIVE_REG17_DMASOURCE3, MEGADRIVE_REG17_DMATYPE, MEGADRIVE_REG01_DMA_ENABLE);
697
if (MEGADRIVE_REG01_DMA_ENABLE)
699
megadrive_vram_fill_pending = 1;
700
megadrive_vram_fill_length = (MEGADRIVE_REG13_DMALENGTH1 | (MEGADRIVE_REG14_DMALENGTH2<<8));
703
else if (MEGADRIVE_REG17_DMATYPE==0x3)
705
mame_printf_debug("setting vram copy (INVALID?) mode length registers are %02x %02x other regs! %02x %02x %02x(Mode Bits %02x) Enable %02x\n", MEGADRIVE_REG13_DMALENGTH1, MEGADRIVE_REG14_DMALENGTH2, MEGADRIVE_REG15_DMASOURCE1, MEGADRIVE_REG16_DMASOURCE2, MEGADRIVE_REG17_DMASOURCE3, MEGADRIVE_REG17_DMATYPE, MEGADRIVE_REG01_DMA_ENABLE);
708
else if (megadrive_vdp_code==0x30)
710
if (MEGADRIVE_REG17_DMATYPE==0x0)
712
mame_printf_debug("setting vram 68k->vram (INVALID?) mode length registers are %02x %02x other regs! %02x %02x %02x(Mode Bits %02x) Enable %02x\n", MEGADRIVE_REG13_DMALENGTH1, MEGADRIVE_REG14_DMALENGTH2, MEGADRIVE_REG15_DMASOURCE1, MEGADRIVE_REG16_DMASOURCE2, MEGADRIVE_REG17_DMASOURCE3, MEGADRIVE_REG17_DMATYPE, MEGADRIVE_REG01_DMA_ENABLE);
714
else if (MEGADRIVE_REG17_DMATYPE==0x1)
716
mame_printf_debug("setting vram 68k->vram (INVALID?) mode length registers are %02x %02x other regs! %02x %02x %02x(Mode Bits %02x) Enable %02x\n", MEGADRIVE_REG13_DMALENGTH1, MEGADRIVE_REG14_DMALENGTH2, MEGADRIVE_REG15_DMASOURCE1, MEGADRIVE_REG16_DMASOURCE2, MEGADRIVE_REG17_DMASOURCE3, MEGADRIVE_REG17_DMATYPE, MEGADRIVE_REG01_DMA_ENABLE);
718
else if (MEGADRIVE_REG17_DMATYPE==0x2)
720
mame_printf_debug("setting vram fill (INVALID?) mode length registers are %02x %02x other regs! %02x %02x %02x(Mode Bits %02x) Enable %02x\n", MEGADRIVE_REG13_DMALENGTH1, MEGADRIVE_REG14_DMALENGTH2, MEGADRIVE_REG15_DMASOURCE1, MEGADRIVE_REG16_DMASOURCE2, MEGADRIVE_REG17_DMASOURCE3, MEGADRIVE_REG17_DMATYPE, MEGADRIVE_REG01_DMA_ENABLE);
722
else if (MEGADRIVE_REG17_DMATYPE==0x3)
726
source = (MEGADRIVE_REG15_DMASOURCE1 | (MEGADRIVE_REG16_DMASOURCE2<<8)); // source (byte offset)
727
length = (MEGADRIVE_REG13_DMALENGTH1 | (MEGADRIVE_REG14_DMALENGTH2<<8)); // length in bytes
728
//mame_printf_debug("setting vram copy mode length registers are %02x %02x other regs! %02x %02x %02x(Mode Bits %02x) Enable %02x\n", MEGADRIVE_REG13_DMALENGTH1, MEGADRIVE_REG14_DMALENGTH2, MEGADRIVE_REG15_DMASOURCE1, MEGADRIVE_REG16_DMASOURCE2, MEGADRIVE_REG17_DMASOURCE3, MEGADRIVE_REG17_DMATYPE, MEGADRIVE_REG01_DMA_ENABLE);
730
if (MEGADRIVE_REG01_DMA_ENABLE) megadrive_do_insta_vram_copy(source, length);
735
static void megadriv_vdp_ctrl_port_w(running_machine &machine, int data)
737
// logerror("write to vdp control port %04x\n",data);
738
megadrive_vram_fill_pending = 0; // ??
740
if (megadrive_vdp_command_pending)
742
/* 2nd part of 32-bit command */
743
megadrive_vdp_command_pending = 0;
744
megadrive_vdp_command_part2 = data;
746
update_megadrive_vdp_code_and_address();
747
handle_dma_bits(machine);
749
//logerror("VDP Write Part 2 setting Code %02x Address %04x\n",megadrive_vdp_code, megadrive_vdp_address);
754
if ((data & 0xc000) == 0x8000)
755
{ /* Register Setting Command */
756
int regnum = (data & 0x3f00) >> 8;
757
int value = (data & 0x00ff);
759
if (regnum &0x20) mame_printf_debug("reg error\n");
761
megadrive_vdp_set_register(machine, regnum&0x1f,value);
762
megadrive_vdp_code = 0;
763
megadrive_vdp_address = 0;
767
megadrive_vdp_command_pending = 1;
768
megadrive_vdp_command_part1 = data;
769
update_megadrive_vdp_code_and_address();
770
//logerror("VDP Write Part 1 setting Code %02x Address %04x\n",megadrive_vdp_code, megadrive_vdp_address);
776
WRITE16_HANDLER( megadriv_vdp_w )
782
if (!ACCESSING_BITS_8_15)
784
data = (data&0x00ff) | data<<8;
785
// mame_printf_debug("8-bit write VDP data port access, offset %04x data %04x mem_mask %04x\n",offset,data,mem_mask);
787
else if (!ACCESSING_BITS_0_7)
789
data = (data&0xff00) | data>>8;
790
// mame_printf_debug("8-bit write VDP data port access, offset %04x data %04x mem_mask %04x\n",offset,data,mem_mask);
792
megadriv_vdp_data_port_w(space->machine(), data);
797
if ((!ACCESSING_BITS_8_15) || (!ACCESSING_BITS_0_7)) mame_printf_debug("8-bit write VDP control port access, offset %04x data %04x mem_mask %04x\n",offset,data,mem_mask);
798
megadriv_vdp_ctrl_port_w(space->machine(), data);
805
logerror("Attempt to Write to HV counters!!\n");
812
if (ACCESSING_BITS_0_7) sn76496_w(space->machine().device("snsnd"), 0, data & 0xff);
813
//if (ACCESSING_BITS_8_15) sn76496_w(space->machine().device("snsnd"), 0, (data >>8) & 0xff);
817
mame_printf_debug("write to unmapped vdp port\n");
821
static UINT16 vdp_vram_r(void)
823
return MEGADRIV_VDP_VRAM((megadrive_vdp_address&0xfffe)>>1);
826
static UINT16 vdp_vsram_r(void)
828
return megadrive_vdp_vsram[(megadrive_vdp_address&0x7e)>>1];
831
static UINT16 vdp_cram_r(void)
834
return megadrive_vdp_cram[(megadrive_vdp_address&0x7e)>>1];
837
static UINT16 megadriv_vdp_data_port_r(running_machine &machine)
841
//return machine.rand();
843
megadrive_vdp_command_pending = 0;
845
switch (megadrive_vdp_code & 0x000f)
848
retdata = vdp_vram_r();
849
megadrive_vdp_address+=MEGADRIVE_REG0F_AUTO_INC;
850
megadrive_vdp_address&=0xffff;
854
logerror("Attempting to READ from DATA PORT in VRAM WRITE MODE\n");
855
retdata = machine.rand();
859
logerror("Attempting to READ from DATA PORT in CRAM WRITE MODE\n");
860
retdata = machine.rand();
864
retdata = vdp_vsram_r();
865
megadrive_vdp_address+=MEGADRIVE_REG0F_AUTO_INC;
866
megadrive_vdp_address&=0xffff;
870
logerror("Attempting to READ from DATA PORT in VSRAM WRITE MODE\n");
874
retdata = vdp_cram_r();
875
megadrive_vdp_address+=MEGADRIVE_REG0F_AUTO_INC;
876
megadrive_vdp_address&=0xffff;
880
logerror("Attempting to READ from DATA PORT in #UNDEFINED# MODE\n");
881
retdata = machine.rand();
885
// mame_printf_debug("vdp_data_port_r %04x %04x %04x\n",megadrive_vdp_code, megadrive_vdp_address, retdata);
887
// logerror("Read VDP Data Port\n");
940
Pixels H.Cnt Description
941
256 : 00-7F : Active display
942
15 : 80-87 : Right border
943
8 : 87-8B : Right blanking
944
26 : 8B-ED : Horizontal sync
945
2 : ED-EE : Left blanking
946
14 : EE-F5 : Color burst
947
8 : F5-F9 : Left blanking
948
13 : F9-FF : Left border
954
static UINT16 megadriv_vdp_ctrl_port_r(void)
956
/* Battletoads is very fussy about the vblank flag
957
it wants it to be 1. in scanline 224 */
959
/* Double Dragon 2 is very sensitive to hblank timing */
960
/* xperts is very fussy too */
962
/* Game no Kanzume Otokuyou (J) [!] is also fussy
963
- it cares about the bits labeled always 0, always 1.. (!)
966
/* Megalo Mania also fussy - cares about pending flag*/
968
int megadrive_sprite_overflow = 0;
969
int megadrive_odd_frame = megadrive_imode_odd_frame^1;
970
int megadrive_hblank_flag = 0;
971
int megadrive_dma_active = 0;
976
UINT16 hpos = get_hposition();
978
if (hpos>400) megadrive_hblank_flag = 1;
979
if (hpos>460) megadrive_hblank_flag = 0;
981
vblank = megadrive_vblank_flag;
984
if (MEGADRIVE_REG01_DISP_ENABLE==0) vblank = 1;
988
// these aren't *always* 0/1 some of them are open bus return
999
d7 - Vertical interrupt pending
1000
d6 - Sprite overflow on current scan line
1001
d5 - Sprite collision
1004
d3 - Vertical blanking
1005
d2 - Horizontal blanking
1006
d1 - DMA in progress
1010
return (0<<15) | // ALWAYS 0
1011
(0<<14) | // ALWAYS 0
1012
(1<<13) | // ALWAYS 1
1013
(1<<12) | // ALWAYS 1
1014
(0<<11) | // ALWAYS 0
1015
(1<<10) | // ALWAYS 1
1016
(fifo_empty<<9 ) | // FIFO EMPTY
1017
(fifo_full<<8 ) | // FIFO FULL
1018
(megadrive_irq6_pending << 7) | // exmutants has a tight loop checking this ..
1019
(megadrive_sprite_overflow << 6) |
1020
(megadrive_sprite_collision << 5) |
1021
(megadrive_odd_frame << 4) |
1023
(megadrive_hblank_flag << 2) |
1024
(megadrive_dma_active << 1 ) |
1025
(megadrive_region_pal<<0); // PAL MODE FLAG checked by striker for region prot..
1028
static const UINT8 vc_ntsc_224[] =
1030
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1031
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
1032
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
1033
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
1034
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
1035
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
1036
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
1037
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
1038
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
1039
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
1040
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
1041
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
1042
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
1043
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
1044
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,/**/0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
1045
0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
1046
0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
1049
static const UINT8 vc_ntsc_240[] =
1051
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1052
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
1053
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
1054
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
1055
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
1056
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
1057
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
1058
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
1059
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
1060
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
1061
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
1062
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
1063
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
1064
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
1065
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
1066
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
1067
0x00, 0x01, 0x02, 0x03, 0x04, 0x05
1070
static const UINT8 vc_pal_224[] =
1072
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1073
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
1074
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
1075
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
1076
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
1077
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
1078
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
1079
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
1080
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
1081
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
1082
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
1083
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
1084
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
1085
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
1086
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
1087
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
1088
0x00, 0x01, 0x02,/**/0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
1089
0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
1090
0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
1091
0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
1094
static const UINT8 vc_pal_240[] =
1096
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1097
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
1098
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
1099
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
1100
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
1101
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
1102
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
1103
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
1104
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
1105
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
1106
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
1107
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
1108
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
1109
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
1110
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
1111
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
1112
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,/**/0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
1113
0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
1114
0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
1115
0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
1120
static UINT16 megadriv_read_hv_counters(void)
1122
/* Bubble and Squeek wants vcount=0xe0 */
1123
/* Dracula is very sensitive to this */
1124
/* Marvel Land is sensitive to this */
1126
int vpos = genesis_scanline_counter;
1127
UINT16 hpos = get_hposition();
1129
// if (hpos>424) vpos++; // fixes dracula, breaks road rash
1130
if (hpos>460) vpos++; // when does vpos increase.. also on sms, check game gear manual..
1132
/* shouldn't happen.. */
1135
vpos = megadrive_total_scanlines;
1136
mame_printf_debug("negative vpos?!\n");
1139
if (MEGADRIVE_REG01_240_LINE)
1141
if (!megadrive_region_pal)
1143
vpos = vc_ntsc_240[vpos%megadrive_total_scanlines];
1147
vpos = vc_pal_240[vpos%megadrive_total_scanlines];
1153
if (!megadrive_region_pal)
1155
vpos = vc_ntsc_224[vpos%megadrive_total_scanlines];
1159
vpos = vc_pal_224[vpos%megadrive_total_scanlines];
1163
if (hpos>0xf7) hpos -=0x49;
1165
return ((vpos&0xff)<<8)|(hpos&0xff);
1169
READ16_HANDLER( megadriv_vdp_r )
1171
UINT16 retvalue = 0;
1180
if ((!ACCESSING_BITS_8_15) || (!ACCESSING_BITS_0_7)) mame_printf_debug("8-bit VDP read data port access, offset %04x mem_mask %04x\n",offset,mem_mask);
1181
retvalue = megadriv_vdp_data_port_r(space->machine());
1186
// if ((!ACCESSING_BITS_8_15) || (!ACCESSING_BITS_0_7)) mame_printf_debug("8-bit VDP read control port access, offset %04x mem_mask %04x\n",offset,mem_mask);
1187
retvalue = megadriv_vdp_ctrl_port_r();
1188
// retvalue = space->machine().rand();
1189
// mame_printf_debug("%06x: Read Control Port at scanline %d hpos %d (return %04x)\n",cpu_get_pc(&space->device()),genesis_scanline_counter, get_hposition(),retvalue);
1196
// if ((!ACCESSING_BITS_8_15) || (!ACCESSING_BITS_0_7)) mame_printf_debug("8-bit VDP read HV counter port access, offset %04x mem_mask %04x\n",offset,mem_mask);
1197
retvalue = megadriv_read_hv_counters();
1198
// retvalue = space->machine().rand();
1199
// mame_printf_debug("%06x: Read HV counters at scanline %d hpos %d (return %04x)\n",cpu_get_pc(&space->device()),genesis_scanline_counter, get_hposition(),retvalue);
1206
logerror("Attempting to read PSG!\n");
1213
READ8_DEVICE_HANDLER( megadriv_68k_YM2612_read)
1215
//mame_printf_debug("megadriv_68k_YM2612_read %02x %04x\n",offset,mem_mask);
1216
if ( (genz80.z80_has_bus==0) && (genz80.z80_is_reset==0) )
1218
return ym2612_r(device, offset);
1222
logerror("%s: 68000 attempting to access YM2612 (read) without bus\n", device->machine().describe_context());
1230
// line length = 342
1233
The V counter counts up from 00h to EAh, then it jumps back to E5h and
1234
continues counting up to FFh. This allows it to cover the entire 262 line
1237
The H counter counts up from 00h to E9h, then it jumps back to 93h and
1238
continues counting up to FFh. This allows it to cover an entire 342 pixel
1244
- The 80th sprite has been drawn in 40-cell mode.
1245
- The 64th sprite has been drawn in 32-cell mode.
1246
- Twenty sprites on the same scanline have been drawn in 40 cell mode.
1247
- Sixteen sprites on the same scanline have been drawn in 32 cell mode.
1248
- 320 pixels worth of sprite data has been drawn on the same scanline
1250
- 256 pixels worth of sprite data has been drawn on the same scanline
1252
- The currently drawn sprite has a link field of zero.
1258
$05 - Sprite Attribute Table Base Address
1259
-----------------------------------------
1261
Bits 6-0 of this register correspond to bits A15-A09 of the sprite
1264
In 40-cell mode, A09 is always forced to zero.
1268
static void genesis_render_spriteline_to_spritebuffer(int scanline)
1273
UINT16 base_address=0;
1277
screenwidth = MEGADRIVE_REG0C_RS0 | (MEGADRIVE_REG0C_RS1 << 1);
1279
switch (screenwidth&3)
1281
case 0: maxsprites = 64; maxpixels = 256; base_address = (MEGADRIVE_REG05_SPRITE_ADDR&0x7f)<<9; break;
1282
case 1: maxsprites = 64; maxpixels = 256; base_address = (MEGADRIVE_REG05_SPRITE_ADDR&0x7f)<<9; break;
1283
case 2: maxsprites = 80; maxpixels = 320; base_address = (MEGADRIVE_REG05_SPRITE_ADDR&0x7e)<<9; break;
1284
case 3: maxsprites = 80; maxpixels = 320; base_address = (MEGADRIVE_REG05_SPRITE_ADDR&0x7e)<<9; break;
1288
/* Clear our Render Buffer */
1289
memset(sprite_renderline, 0, 1024);
1296
int /*drawwidth,*/ drawheight;
1298
UINT8 height,width=0,link=0,xflip,yflip,colour,pri;
1300
/* Get Sprite Attribs */
1303
//if (scanline==40) mame_printf_debug("spritelist start base %04x\n",base_address);
1307
//UINT16 value1,value2,value3,value4;
1309
//value1 = megadrive_vdp_vram[((base_address>>1)+spritenum*4)+0x0];
1310
//value2 = megadrive_vdp_vram[((base_address>>1)+spritenum*4)+0x1];
1311
//value3 = megadrive_vdp_vram[((base_address>>1)+spritenum*4)+0x2];
1312
//value4 = megadrive_vdp_vram[((base_address>>1)+spritenum*4)+0x3];
1314
ypos = (megadrive_vdp_internal_sprite_attribute_table[(spritenum*4)+0x0] & 0x01ff)>>0; /* 0x03ff? */ // puyo puyo requires 0x1ff mask, not 0x3ff, see speech bubble corners
1315
height= (megadrive_vdp_internal_sprite_attribute_table[(spritenum*4)+0x1] & 0x0300)>>8;
1316
width = (megadrive_vdp_internal_sprite_attribute_table[(spritenum*4)+0x1] & 0x0c00)>>10;
1317
link = (megadrive_vdp_internal_sprite_attribute_table[(spritenum*4)+0x1] & 0x007f)>>0;
1318
xpos = (MEGADRIV_VDP_VRAM(((base_address>>1)+spritenum*4)+0x3) & 0x01ff)>>0; /* 0x03ff? */ // pirates gold has a sprite with co-ord 0x200...
1320
if(megadrive_imode==3)
1322
ypos = (megadrive_vdp_internal_sprite_attribute_table[(spritenum*4)+0x0] & 0x03ff)>>0; /* 0x3ff requried in interlace mode (sonic 2 2 player) */
1323
drawypos = ypos - 256;
1324
drawheight = (height+1)*16;
1328
ypos = (megadrive_vdp_internal_sprite_attribute_table[(spritenum*4)+0x0] & 0x01ff)>>0; /* 0x03ff? */ // puyo puyo requires 0x1ff mask, not 0x3ff, see speech bubble corners
1329
drawypos = ypos - 128;
1330
drawheight = (height+1)*8;
1335
//if (scanline==40) mame_printf_debug("xpos %04x ypos %04x\n",xpos,ypos);
1337
if ((drawypos<=scanline) && ((drawypos+drawheight)>scanline))
1340
addr = (MEGADRIV_VDP_VRAM(((base_address>>1)+spritenum*4)+0x2) & 0x07ff)>>0;
1341
xflip = (MEGADRIV_VDP_VRAM(((base_address>>1)+spritenum*4)+0x2) & 0x0800)>>11;
1342
yflip = (MEGADRIV_VDP_VRAM(((base_address>>1)+spritenum*4)+0x2) & 0x1000)>>12;
1343
colour= (MEGADRIV_VDP_VRAM(((base_address>>1)+spritenum*4)+0x2) & 0x6000)>>13;
1344
pri = (MEGADRIV_VDP_VRAM(((base_address>>1)+spritenum*4)+0x2) & 0x8000)>>15;
1346
if(megadrive_imode==3)
1352
//drawwidth = (width+1)*8;
1353
if (pri==1) pri = 0x80;
1356
/* todo: fix me, I'm sure this isn't right but sprite 0 + other sprite seem to do something..
1357
maybe spritemask|=2 should be set for anything < 0x40 ?*/
1358
if (xpos==0x00) spritemask|=1;
1360
//if (xpos==0x01) spritemask|=2;
1361
//if (xpos==0x04) spritemask|=2; // sonic 2 title screen
1362
//if (xpos==0x08) spritemask|=2; // rocket night adventures
1363
//if (xpos==0x10) spritemask|=2; // mercs l1 boss
1364
//if (xpos==0x0a) spritemask|=2; // legend of galahad
1365
//if (xpos==0x21) spritemask|=2; // shadow of the beast?
1366
if ((xpos>0) && (xpos<0x40)) spritemask|=2;
1368
if (spritemask==0x3)
1375
int yline = scanline - drawypos;
1377
for (xtile=0;xtile<width+1;xtile++)
1388
if(megadrive_imode==3)
1390
if (!yflip) base_addr = (addr<<4)+(xtile*((height+1)*(2*16)))+(yline*2);
1391
else base_addr = (addr<<4)+(xtile*((height+1)*(2*16)))+((((height+1)*16)-yline-1)*2);
1395
if (!yflip) base_addr = (addr<<4)+(xtile*((height+1)*(2*8)))+(yline*2);
1396
else base_addr = (addr<<4)+(xtile*((height+1)*(2*8)))+((((height+1)*8)-yline-1)*2);
1399
xxx = (xpos+xtile*8)&0x1ff;
1401
gfxdata = MEGADRIV_VDP_VRAM(base_addr+1) | (MEGADRIV_VDP_VRAM(base_addr+0)<<16);
1403
for(loopcount=0;loopcount<8;loopcount++)
1405
dat = (gfxdata & 0xf0000000)>>28; gfxdata <<=4;
1406
if (dat) { if (!sprite_renderline[xxx]) { sprite_renderline[xxx] = dat | (colour<<4)| pri; } else { megadrive_sprite_collision = 1; } }
1408
if (--maxpixels == 0x00) return;
1420
if(megadrive_imode==3)
1422
if (!yflip) base_addr = (addr<<4)+(((width-xtile))*((height+1)*(2*16)))+(yline*2);
1423
else base_addr = (addr<<4)+(((width-xtile))*((height+1)*(2*16)))+((((height+1)*16)-yline-1)*2);
1428
if (!yflip) base_addr = (addr<<4)+(((width-xtile))*((height+1)*(2*8)))+(yline*2);
1429
else base_addr = (addr<<4)+(((width-xtile))*((height+1)*(2*8)))+((((height+1)*8)-yline-1)*2);
1432
xxx = (xpos+xtile*8)&0x1ff;
1434
gfxdata = MEGADRIV_VDP_VRAM((base_addr+1)&0x7fff) | (MEGADRIV_VDP_VRAM((base_addr+0)&0x7fff)<<16);
1436
for(loopcount=0;loopcount<8;loopcount++)
1438
dat = (gfxdata & 0x0000000f)>>0; gfxdata >>=4;
1439
if (dat) { if (!sprite_renderline[xxx]) { sprite_renderline[xxx] = dat | (colour<<4)| pri; } else { megadrive_sprite_collision = 1; } }
1441
if (--maxpixels == 0x00) return;
1452
while ((maxsprites>=0) && (link!=0));
1458
/* Clean up this function (!) */
1459
static void genesis_render_videoline_to_videobuffer(int scanline)
1468
UINT16 window_right;
1469
// UINT16 window_hpos;
1471
// UINT16 window_vpos;
1472
UINT16 hscroll_base;
1473
// UINT8 vscroll_mode;
1474
// UINT8 hscroll_mode;
1475
int window_firstline;
1476
int window_lastline;
1477
int window_firstcol;
1486
int window_is_bugged = 0;
1487
int non_window_firstcol;
1488
int non_window_lastcol;
1489
int screenheight = MEGADRIVE_REG01_240_LINE?240:224;
1491
/* Clear our Render Buffer */
1494
video_renderline[x]=MEGADRIVE_REG07_BGCOLOUR | 0x20000; // mark as BG
1497
memset(highpri_renderline, 0, 320);
1499
/* is this line enabled? */
1500
if (!MEGADRIVE_REG01_DISP_ENABLE)
1502
//mame_printf_debug("line disabled %d\n",scanline);
1506
/* looks different? */
1507
if (MEGADRIVE_REG0_DISPLAY_DISABLE)
1514
base_a = MEGADRIVE_REG02_PATTERN_ADDR_A << 13;
1516
base_b = MEGADRIVE_REG04_PATTERN_ADDR_B << 13;
1517
size = MEGADRIVE_REG10_HSCROLL_SIZE | (MEGADRIVE_REG10_VSCROLL_SIZE<<4);
1518
window_right = MEGADRIVE_REG11_WINDOW_RIGHT;
1519
// window_hpos = MEGADRIVE_REG11_WINDOW_HPOS;
1520
window_down = MEGADRIVE_REG12_WINDOW_DOWN;
1521
// window_vpos = MEGADRIVE_REG12_WINDOW_VPOS;
1523
screenwidth = MEGADRIVE_REG0C_RS0 | (MEGADRIVE_REG0C_RS1 << 1);
1525
switch (screenwidth)
1527
case 0: numcolumns = 32; window_hsize = 32; window_vsize = 32; base_w = (MEGADRIVE_REG03_PATTERN_ADDR_W&0x1f) << 11; break;
1528
case 1: numcolumns = 32; window_hsize = 32; window_vsize = 32; base_w = (MEGADRIVE_REG03_PATTERN_ADDR_W&0x1f) << 11; break;
1529
case 2: numcolumns = 40; window_hsize = 64; window_vsize = 32; base_w = (MEGADRIVE_REG03_PATTERN_ADDR_W&0x1e) << 11; break;
1530
case 3: numcolumns = 40; window_hsize = 64; window_vsize = 32; base_w = (MEGADRIVE_REG03_PATTERN_ADDR_W&0x1e) << 11; break; // talespin cares about base mask, used for status bar
1533
//mame_printf_debug("screenwidth %d\n",screenwidth);
1535
//base_w = Machine->rand()&0xff;
1537
/* Calculate Exactly where we're going to draw the Window, and if the Window Bug applies */
1538
window_is_bugged = 0;
1541
window_firstcol = MEGADRIVE_REG11_WINDOW_HPOS*16;
1542
window_lastcol = numcolumns*8;
1543
if (window_firstcol>window_lastcol) window_firstcol = window_lastcol;
1545
non_window_firstcol = 0;
1546
non_window_lastcol = window_firstcol;
1550
window_firstcol = 0;
1551
window_lastcol = MEGADRIVE_REG11_WINDOW_HPOS*16;
1552
if (window_lastcol>numcolumns*8) window_lastcol = numcolumns*8;
1554
non_window_firstcol = window_lastcol;
1555
non_window_lastcol = numcolumns*8;
1557
if (window_lastcol!=0) window_is_bugged=1;
1562
window_firstline = MEGADRIVE_REG12_WINDOW_VPOS*8;
1563
window_lastline = screenheight; // 240 in PAL?
1564
if (window_firstline>screenheight) window_firstline = screenheight;
1568
window_firstline = 0;
1569
window_lastline = MEGADRIVE_REG12_WINDOW_VPOS*8;
1570
if (window_lastline>screenheight) window_lastline = screenheight;
1573
/* if we're on a window scanline between window_firstline and window_lastline the window is the full width of the screen */
1574
if (scanline>=window_firstline && scanline < window_lastline)
1576
window_firstcol = 0; window_lastcol = numcolumns*8; // window is full-width of the screen
1577
non_window_firstcol = 0; non_window_lastcol=0; // disable non-window
1581
// vscroll_mode = MEGADRIVE_REG0B_VSCROLL_MODE;
1582
// hscroll_mode = MEGADRIVE_REG0B_HSCROLL_MODE;
1583
hscroll_base = MEGADRIVE_REG0D_HSCROLL_ADDR<<10;
1587
case 0x00: hsize = 32; vsize = 32; break;
1588
case 0x01: hsize = 64; vsize = 32; break;
1589
case 0x02: hsize = 64; vsize = 1; /* mame_printf_debug("Invalid HSize! %02x\n",size);*/ break;
1590
case 0x03: hsize = 128;vsize = 32; break;
1592
case 0x10: hsize = 32; vsize = 64; break;
1593
case 0x11: hsize = 64; vsize = 64; break;
1594
case 0x12: hsize = 64; vsize = 1; /*mame_printf_debug("Invalid HSize! %02x\n",size);*/ break;
1595
case 0x13: hsize = 128;vsize = 32;/*mame_printf_debug("Invalid Total Size! %02x\n",size);*/break;
1597
case 0x20: hsize = 32; vsize = 64; mame_printf_debug("Invalid VSize!\n"); break;
1598
case 0x21: hsize = 64; vsize = 64; mame_printf_debug("Invalid VSize!\n"); break;
1599
case 0x22: hsize = 64; vsize = 1; /*mame_printf_debug("Invalid HSize & Invalid VSize!\n");*/ break;
1600
case 0x23: hsize = 128;vsize = 64; mame_printf_debug("Invalid VSize!\n"); break;
1602
case 0x30: hsize = 32; vsize = 128; break;
1603
case 0x31: hsize = 64; vsize = 64; /*mame_printf_debug("Invalid Total Size! %02x\n",size);*/break; // super skidmarks attempts this..
1604
case 0x32: hsize = 64; vsize = 1; /*mame_printf_debug("Invalid HSize & Invalid Total Size!\n");*/ break;
1605
case 0x33: hsize = 128;vsize = 128; mame_printf_debug("Invalid Total Size! %02x\n",size);break;
1608
switch (MEGADRIVE_REG0B_HSCROLL_MODE)
1610
case 0x00: // Full Screen Scroll
1611
hscroll_a = MEGADRIV_VDP_VRAM((hscroll_base>>1)+0);
1612
hscroll_b = MEGADRIV_VDP_VRAM((hscroll_base>>1)+1);
1615
case 0x01: // 'Broken' Line Scroll
1616
if(megadrive_imode==3)
1618
hscroll_a = MEGADRIV_VDP_VRAM((hscroll_base>>1)+0+((scanline>>1)&7)*2);
1619
hscroll_b = MEGADRIV_VDP_VRAM((hscroll_base>>1)+1+((scanline>>1)&7)*2);
1623
hscroll_a = MEGADRIV_VDP_VRAM((hscroll_base>>1)+0+(scanline&7)*2);
1624
hscroll_b = MEGADRIV_VDP_VRAM((hscroll_base>>1)+1+(scanline&7)*2);
1628
case 0x02: // Cell Scroll
1629
if(megadrive_imode==3)
1631
hscroll_a = MEGADRIV_VDP_VRAM((hscroll_base>>1)+0+((scanline>>1)&~7)*2);
1632
hscroll_b = MEGADRIV_VDP_VRAM((hscroll_base>>1)+1+((scanline>>1)&~7)*2);
1636
hscroll_a = MEGADRIV_VDP_VRAM((hscroll_base>>1)+0+(scanline&~7)*2);
1637
hscroll_b = MEGADRIV_VDP_VRAM((hscroll_base>>1)+1+(scanline&~7)*2);
1641
case 0x03: // Full Line Scroll
1642
if(megadrive_imode==3)
1644
hscroll_a = MEGADRIV_VDP_VRAM((hscroll_base>>1)+0+(scanline>>1)*2);
1645
hscroll_b = MEGADRIV_VDP_VRAM((hscroll_base>>1)+1+(scanline>>1)*2);
1649
hscroll_a = MEGADRIV_VDP_VRAM((hscroll_base>>1)+0+scanline*2);
1650
hscroll_b = MEGADRIV_VDP_VRAM((hscroll_base>>1)+1+scanline*2);
1655
/* Low Priority B Tiles */
1660
for (column=0;column<numcolumns/2;column++)
1661
{ /* 20x 16x1 blocks */
1665
/* Get V Scroll Value for this block */
1670
/* hscroll is not divisible by 8, this segment will contain 3 tiles, 1 partial, 1 whole, 1 partial */
1671
int hscroll_part = 8-(hscroll_b%8);
1682
if (MEGADRIVE_REG0B_VSCROLL_MODE)
1684
if (hscroll_b&0xf) vscroll = megadrive_vdp_vsram[((column-1)*2+1)&0x3f];
1685
else vscroll = megadrive_vdp_vsram[((column)*2+1)&0x3f];
1689
vscroll = megadrive_vdp_vsram[1];
1692
hcolumn = ((column*2-1)-(hscroll_b>>3))&(hsize-1);
1694
if(megadrive_imode==3)
1696
vcolumn = (vscroll + scanline)&((vsize*16)-1);
1697
tile_base = (base_b>>1)+((vcolumn>>4)*hsize)+hcolumn;
1702
vcolumn = (vscroll + scanline)&((vsize*8)-1);
1703
tile_base = (base_b>>1)+((vcolumn>>3)*hsize)+hcolumn;
1708
tile_dat = MEGADRIV_VDP_VRAM(tile_base);
1709
tile_xflip = (tile_dat&0x0800);
1710
tile_yflip = (tile_dat&0x1000);
1711
tile_colour =(tile_dat&0x6000)>>13;
1712
tile_pri = (tile_dat&0x8000)>>15;
1713
tile_addr = ((tile_dat&0x07ff)<<4);
1715
if(megadrive_imode==3)
1719
if (!tile_yflip) tile_addr+=(vcolumn&0xf)*2;
1720
else tile_addr+=((0xf-vcolumn)&0xf)*2;
1724
if (!tile_yflip) tile_addr+=(vcolumn&7)*2;
1725
else tile_addr+=((7-vcolumn)&7)*2;
1731
UINT32 gfxdata = (MEGADRIV_VDP_VRAM(tile_addr+0)<<16)|MEGADRIV_VDP_VRAM(tile_addr+1);
1734
for (shift=hscroll_part;shift<8;shift++)
1736
dat = (gfxdata>>(28-(shift*4)))&0x000f; if (!tile_pri) { if(dat) video_renderline[dpos] = dat | (tile_colour<<4); } else highpri_renderline[dpos] = dat | (tile_colour<<4) | 0x80;
1742
UINT32 gfxdata = (MEGADRIV_VDP_VRAM(tile_addr+0)<<16)|MEGADRIV_VDP_VRAM(tile_addr+1);
1744
for (shift=hscroll_part;shift<8;shift++)
1746
dat = (gfxdata>>(shift*4) )&0x000f; if (!tile_pri) { if(dat) video_renderline[dpos] = dat | (tile_colour<<4); } else highpri_renderline[dpos] = dat | (tile_colour<<4) | 0x80;
1751
if (MEGADRIVE_REG0B_VSCROLL_MODE)
1753
if (hscroll_b&0xf) vscroll = megadrive_vdp_vsram[((column-1)*2+1)&0x3f];
1754
else vscroll = megadrive_vdp_vsram[((column)*2+1)&0x3f];
1758
vscroll = megadrive_vdp_vsram[1];
1761
hcolumn = ((column*2)-(hscroll_b>>3))&(hsize-1);
1763
if(megadrive_imode==3)
1765
vcolumn = (vscroll + scanline)&((vsize*16)-1);
1766
tile_base = (base_b>>1)+((vcolumn>>4)*hsize)+hcolumn;
1770
vcolumn = (vscroll + scanline)&((vsize*8)-1);
1771
tile_base = (base_b>>1)+((vcolumn>>3)*hsize)+hcolumn;
1775
tile_dat = MEGADRIV_VDP_VRAM(tile_base);
1776
tile_xflip = (tile_dat&0x0800);
1777
tile_yflip = (tile_dat&0x1000);
1778
tile_colour =(tile_dat&0x6000)>>13;
1779
tile_pri = (tile_dat&0x8000)>>15;
1780
tile_addr = ((tile_dat&0x07ff)<<4);
1782
if(megadrive_imode==3)
1787
if (!tile_yflip) tile_addr+=(vcolumn&0xf)*2;
1788
else tile_addr+=((0xf-vcolumn)&0xf)*2;
1792
if (!tile_yflip) tile_addr+=(vcolumn&7)*2;
1793
else tile_addr+=((7-vcolumn)&7)*2;
1799
UINT32 gfxdata = (MEGADRIV_VDP_VRAM(tile_addr+0)<<16)|MEGADRIV_VDP_VRAM(tile_addr+1);
1802
for (shift=0;shift<8;shift++)
1804
dat = (gfxdata>>(28-(shift*4)))&0x000f; if (!tile_pri) { if(dat) video_renderline[dpos] = dat | (tile_colour<<4); } else highpri_renderline[dpos] = dat | (tile_colour<<4) | 0x80;
1810
UINT32 gfxdata = (MEGADRIV_VDP_VRAM(tile_addr+0)<<16)|MEGADRIV_VDP_VRAM(tile_addr+1);
1812
for (shift=0;shift<8;shift++)
1814
dat = (gfxdata>>(shift*4))&0x000f; if (!tile_pri) { if(dat) video_renderline[dpos] = dat | (tile_colour<<4); } else highpri_renderline[dpos] = dat | (tile_colour<<4) | 0x80;
1819
if (MEGADRIVE_REG0B_VSCROLL_MODE)
1821
vscroll = megadrive_vdp_vsram[((column)*2+1)&0x3f];
1825
vscroll = megadrive_vdp_vsram[1];
1828
hcolumn = ((column*2+1)-(hscroll_b>>3))&(hsize-1);
1830
if(megadrive_imode==3)
1832
vcolumn = (vscroll + scanline)&((vsize*16)-1);
1833
tile_base = (base_b>>1)+((vcolumn>>4)*hsize)+hcolumn;
1837
vcolumn = (vscroll + scanline)&((vsize*8)-1);
1838
tile_base = (base_b>>1)+((vcolumn>>3)*hsize)+hcolumn;
1842
tile_dat = MEGADRIV_VDP_VRAM(tile_base);
1843
tile_xflip = (tile_dat&0x0800);
1844
tile_yflip = (tile_dat&0x1000);
1845
tile_colour =(tile_dat&0x6000)>>13;
1846
tile_pri = (tile_dat&0x8000)>>15;
1847
tile_addr = ((tile_dat&0x07ff)<<4);
1849
if(megadrive_imode==3)
1853
if (!tile_yflip) tile_addr+=(vcolumn&0xf)*2;
1854
else tile_addr+=((0xf-vcolumn)&0xf)*2;
1858
if (!tile_yflip) tile_addr+=(vcolumn&7)*2;
1859
else tile_addr+=((7-vcolumn)&7)*2;
1866
UINT32 gfxdata = (MEGADRIV_VDP_VRAM(tile_addr+0)<<16)|MEGADRIV_VDP_VRAM(tile_addr+1);
1869
for (shift=0;shift<(hscroll_part);shift++)
1871
dat = (gfxdata>>(28-(shift*4)))&0x000f; if (!tile_pri) { if(dat) video_renderline[dpos] = dat | (tile_colour<<4); } else highpri_renderline[dpos] = dat | (tile_colour<<4) | 0x80;
1877
UINT32 gfxdata = (MEGADRIV_VDP_VRAM(tile_addr+0)<<16)|MEGADRIV_VDP_VRAM(tile_addr+1);
1879
for (shift=0;shift<(hscroll_part);shift++)
1881
dat = (gfxdata>>(shift*4) )&0x000f; if (!tile_pri) { if(dat) video_renderline[dpos] = dat | (tile_colour<<4); } else highpri_renderline[dpos] = dat | (tile_colour<<4) | 0x80;
1889
/* Low Priority A Tiles + Window(!) */
1895
for (column=window_firstcol/16;column<window_lastcol/16;column++)
1910
vcolumn = scanline&((window_vsize*8)-1);
1912
hcolumn = (column*2)&(window_hsize-1);
1914
if(megadrive_imode==3)
1916
tile_base = (base_w>>1)+((vcolumn>>4)*window_hsize)+hcolumn;
1920
tile_base = (base_w>>1)+((vcolumn>>3)*window_hsize)+hcolumn;
1924
tile_dat = MEGADRIV_VDP_VRAM(tile_base);
1925
tile_xflip = (tile_dat&0x0800);
1926
tile_yflip = (tile_dat&0x1000);
1927
tile_colour =(tile_dat&0x6000)>>13;
1928
tile_pri = (tile_dat&0x8000)>>15;
1929
tile_addr = ((tile_dat&0x07ff)<<4);
1931
if(megadrive_imode==3)
1937
if(megadrive_imode==3)
1939
if (!tile_yflip) tile_addr+=(vcolumn&0xf)*2;
1940
else tile_addr+=((0xf-vcolumn)&0xf)*2;
1944
if (!tile_yflip) tile_addr+=(vcolumn&7)*2;
1945
else tile_addr+=((7-vcolumn)&7)*2;
1951
UINT32 gfxdata = (MEGADRIV_VDP_VRAM(tile_addr+0)<<16)|MEGADRIV_VDP_VRAM(tile_addr+1);
1954
for (shift=0;shift<8;shift++)
1956
dat = (gfxdata>>(28-(shift*4)))&0x000f;
1959
if(dat) video_renderline[dpos] = dat | (tile_colour<<4);
1963
if (dat) highpri_renderline[dpos] = dat | (tile_colour<<4) | 0x80;
1964
else highpri_renderline[dpos] = highpri_renderline[dpos]|0x80;
1971
UINT32 gfxdata = (MEGADRIV_VDP_VRAM(tile_addr+0)<<16)|MEGADRIV_VDP_VRAM(tile_addr+1);
1973
for (shift=0;shift<8;shift++)
1975
dat = (gfxdata>>(shift*4) )&0x000f;
1978
if(dat) video_renderline[dpos] = dat | (tile_colour<<4);
1982
if (dat) highpri_renderline[dpos] = dat | (tile_colour<<4) | 0x80;
1983
else highpri_renderline[dpos] = highpri_renderline[dpos]|0x80;
1991
hcolumn = (column*2+1)&(window_hsize-1);
1992
if(megadrive_imode==3)
1994
tile_base = (base_w>>1)+((vcolumn>>4)*window_hsize)+hcolumn;
1998
tile_base = (base_w>>1)+((vcolumn>>3)*window_hsize)+hcolumn;
2001
tile_dat = MEGADRIV_VDP_VRAM(tile_base);
2002
tile_xflip = (tile_dat&0x0800);
2003
tile_yflip = (tile_dat&0x1000);
2004
tile_colour =(tile_dat&0x6000)>>13;
2005
tile_pri = (tile_dat&0x8000)>>15;
2006
tile_addr = ((tile_dat&0x07ff)<<4);
2008
if(megadrive_imode==3)
2014
if(megadrive_imode==3)
2016
if (!tile_yflip) tile_addr+=(vcolumn&0xf)*2;
2017
else tile_addr+=((0xf-vcolumn)&0xf)*2;
2021
if (!tile_yflip) tile_addr+=(vcolumn&7)*2;
2022
else tile_addr+=((7-vcolumn)&7)*2;
2028
UINT32 gfxdata = (MEGADRIV_VDP_VRAM(tile_addr+0)<<16)|MEGADRIV_VDP_VRAM(tile_addr+1);
2031
for (shift=0;shift<8;shift++)
2033
dat = (gfxdata>>(28-(shift*4)))&0x000f;
2036
if(dat) video_renderline[dpos] = dat | (tile_colour<<4);
2040
if (dat) highpri_renderline[dpos] = dat | (tile_colour<<4) | 0x80;
2041
else highpri_renderline[dpos] = highpri_renderline[dpos]|0x80;
2048
UINT32 gfxdata = (MEGADRIV_VDP_VRAM(tile_addr+0)<<16)|MEGADRIV_VDP_VRAM(tile_addr+1);
2050
for (shift=0;shift<8;shift++)
2052
dat = (gfxdata>>(shift*4) )&0x000f;
2055
if(dat) video_renderline[dpos] = dat | (tile_colour<<4);
2059
if (dat) highpri_renderline[dpos] = dat | (tile_colour<<4) | 0x80;
2060
else highpri_renderline[dpos] = highpri_renderline[dpos]|0x80;
2067
/* Non Window Part */
2069
for (column=non_window_firstcol/16;column<non_window_lastcol/16;column++)
2070
{ /* 20x 16x1 blocks */
2077
{ /* hscroll is not divisible by 8, this segment will contain 3 tiles, 1 partial, 1 whole, 1 partial */
2078
int hscroll_part = 8-(hscroll_a%8);
2089
if (MEGADRIVE_REG0B_VSCROLL_MODE)
2091
if (hscroll_a&0xf) vscroll = megadrive_vdp_vsram[((column-1)*2+0)&0x3f];
2092
else vscroll = megadrive_vdp_vsram[((column)*2+0)&0x3f];
2096
vscroll = megadrive_vdp_vsram[0];
2100
if ((!window_is_bugged) || ((hscroll_a&0xf)==0) || (column>non_window_firstcol/16)) hcolumn = ((column*2-1)-(hscroll_a>>3))&(hsize-1);
2101
else hcolumn = ((column*2+1)-(hscroll_a>>3))&(hsize-1);
2103
if(megadrive_imode==3)
2105
vcolumn = (vscroll + scanline)&((vsize*16)-1);
2109
vcolumn = (vscroll + scanline)&((vsize*8)-1);
2112
if(megadrive_imode==3)
2114
tile_base = (base_a>>1)+((vcolumn>>4)*hsize)+hcolumn;
2118
tile_base = (base_a>>1)+((vcolumn>>3)*hsize)+hcolumn;
2123
tile_dat = MEGADRIV_VDP_VRAM(tile_base);
2124
tile_xflip = (tile_dat&0x0800);
2125
tile_yflip = (tile_dat&0x1000);
2126
tile_colour =(tile_dat&0x6000)>>13;
2127
tile_pri = (tile_dat&0x8000)>>15;
2128
tile_addr = ((tile_dat&0x07ff)<<4);
2130
if(megadrive_imode==3)
2134
if (!tile_yflip) tile_addr+=(vcolumn&0xf)*2;
2135
else tile_addr+=((0xf-vcolumn)&0xf)*2;
2139
if (!tile_yflip) tile_addr+=(vcolumn&7)*2;
2140
else tile_addr+=((7-vcolumn)&7)*2;
2146
UINT32 gfxdata = (MEGADRIV_VDP_VRAM(tile_addr+0)<<16)|MEGADRIV_VDP_VRAM(tile_addr+1);
2149
for (shift=hscroll_part;shift<8;shift++)
2151
dat = (gfxdata>>(28-(shift*4)))&0x000f;
2154
if(dat) video_renderline[dpos] = dat | (tile_colour<<4);
2158
if (dat) highpri_renderline[dpos] = dat | (tile_colour<<4) | 0x80;
2159
else highpri_renderline[dpos] = highpri_renderline[dpos]|0x80;
2166
UINT32 gfxdata = (MEGADRIV_VDP_VRAM(tile_addr+0)<<16)|MEGADRIV_VDP_VRAM(tile_addr+1);
2168
for (shift=hscroll_part;shift<8;shift++)
2170
dat = (gfxdata>>(shift*4) )&0x000f;
2173
if(dat) video_renderline[dpos] = dat | (tile_colour<<4);
2177
if (dat) highpri_renderline[dpos] = dat | (tile_colour<<4) | 0x80;
2178
else highpri_renderline[dpos] = highpri_renderline[dpos]|0x80;
2184
if (MEGADRIVE_REG0B_VSCROLL_MODE)
2186
if (hscroll_a&0xf) vscroll = megadrive_vdp_vsram[((column-1)*2+0)&0x3f];
2187
else vscroll = megadrive_vdp_vsram[((column)*2+0)&0x3f];
2191
vscroll = megadrive_vdp_vsram[0];
2194
if ((!window_is_bugged) || ((hscroll_a&0xf)==0) || (column>non_window_firstcol/16)) hcolumn = ((column*2)-(hscroll_a>>3))&(hsize-1); // not affected by bug?
2197
if ((hscroll_a&0xf)<8) hcolumn = ((column*2)-(hscroll_a>>3))&(hsize-1);
2198
else hcolumn = ((column*2+2)-(hscroll_a>>3))&(hsize-1);
2202
if(megadrive_imode==3)
2204
vcolumn = (vscroll + scanline)&((vsize*16)-1);
2205
tile_base = (base_a>>1)+((vcolumn>>4)*hsize)+hcolumn;
2209
vcolumn = (vscroll + scanline)&((vsize*8)-1);
2210
tile_base = (base_a>>1)+((vcolumn>>3)*hsize)+hcolumn;
2214
tile_dat = MEGADRIV_VDP_VRAM(tile_base);
2215
tile_xflip = (tile_dat&0x0800);
2216
tile_yflip = (tile_dat&0x1000);
2217
tile_colour =(tile_dat&0x6000)>>13;
2218
tile_pri = (tile_dat&0x8000)>>15;
2219
tile_addr = ((tile_dat&0x07ff)<<4);
2222
if(megadrive_imode==3)
2226
if (!tile_yflip) tile_addr+=(vcolumn&0xf)*2;
2227
else tile_addr+=((0xf-vcolumn)&0xf)*2;
2231
if (!tile_yflip) tile_addr+=(vcolumn&7)*2;
2232
else tile_addr+=((7-vcolumn)&7)*2;
2238
UINT32 gfxdata = (MEGADRIV_VDP_VRAM(tile_addr+0)<<16)|MEGADRIV_VDP_VRAM(tile_addr+1);
2241
for (shift=0;shift<8;shift++)
2243
dat = (gfxdata>>(28-(shift*4)))&0x000f;
2246
if(dat) video_renderline[dpos] = dat | (tile_colour<<4);
2250
if (dat) highpri_renderline[dpos] = dat | (tile_colour<<4) | 0x80;
2251
else highpri_renderline[dpos] = highpri_renderline[dpos]|0x80;
2258
UINT32 gfxdata = (MEGADRIV_VDP_VRAM(tile_addr+0)<<16)|MEGADRIV_VDP_VRAM(tile_addr+1);
2260
for (shift=0;shift<8;shift++)
2262
dat = (gfxdata>>(shift*4) )&0x000f;
2265
if(dat) video_renderline[dpos] = dat | (tile_colour<<4);
2269
if (dat) highpri_renderline[dpos] = dat | (tile_colour<<4) | 0x80;
2270
else highpri_renderline[dpos] = highpri_renderline[dpos]|0x80;
2276
if (MEGADRIVE_REG0B_VSCROLL_MODE)
2278
vscroll = megadrive_vdp_vsram[((column)*2+0)&0x3f];
2282
vscroll = megadrive_vdp_vsram[0];
2285
if ((!window_is_bugged) || ((hscroll_a&0xf)==0) || (column>non_window_firstcol/16)) hcolumn = ((column*2+1)-(hscroll_a>>3))&(hsize-1);
2286
else hcolumn = ((column*2+1)-(hscroll_a>>3))&(hsize-1);
2288
if(megadrive_imode==3)
2290
vcolumn = (vscroll + scanline)&((vsize*16)-1);
2291
tile_base = (base_a>>1)+((vcolumn>>4)*hsize)+hcolumn;
2295
vcolumn = (vscroll + scanline)&((vsize*8)-1);
2296
tile_base = (base_a>>1)+((vcolumn>>3)*hsize)+hcolumn;
2299
tile_dat = MEGADRIV_VDP_VRAM(tile_base);
2300
tile_xflip = (tile_dat&0x0800);
2301
tile_yflip = (tile_dat&0x1000);
2302
tile_colour =(tile_dat&0x6000)>>13;
2303
tile_pri = (tile_dat&0x8000)>>15;
2304
tile_addr = ((tile_dat&0x07ff)<<4);
2306
if(megadrive_imode==3)
2312
if(megadrive_imode==3)
2314
if (!tile_yflip) tile_addr+=(vcolumn&0xf)*2;
2315
else tile_addr+=((0xf-vcolumn)&0xf)*2;
2319
if (!tile_yflip) tile_addr+=(vcolumn&7)*2;
2320
else tile_addr+=((7-vcolumn)&7)*2;
2326
UINT32 gfxdata = (MEGADRIV_VDP_VRAM(tile_addr+0)<<16)|MEGADRIV_VDP_VRAM(tile_addr+1);
2329
for (shift=0;shift<(hscroll_part);shift++)
2331
dat = (gfxdata>>(28-(shift*4)))&0x000f;
2334
if(dat) video_renderline[dpos] = dat | (tile_colour<<4);
2338
if (dat) highpri_renderline[dpos] = dat | (tile_colour<<4) | 0x80;
2339
else highpri_renderline[dpos] = highpri_renderline[dpos]|0x80;
2346
UINT32 gfxdata = (MEGADRIV_VDP_VRAM(tile_addr+0)<<16)|MEGADRIV_VDP_VRAM(tile_addr+1);
2348
for (shift=0;shift<(hscroll_part);shift++)
2350
dat = (gfxdata>>(shift*4) )&0x000f;
2353
if(dat) video_renderline[dpos] = dat | (tile_colour<<4);
2357
if (dat) highpri_renderline[dpos] = dat | (tile_colour<<4) | 0x80;
2358
else highpri_renderline[dpos] = highpri_renderline[dpos]|0x80;
2368
/* MEGADRIVE_REG0C_SHADOW_HIGLIGHT */
2369
/* Low Priority Sprites */
2372
if (!MEGADRIVE_REG0C_SHADOW_HIGLIGHT)
2374
if (sprite_renderline[x+128] & 0x40)
2376
video_renderline[x] = sprite_renderline[x+128]&0x3f;
2377
video_renderline[x] |= 0x10000; // mark as sprite pixel
2381
{ /* Special Shadow / Highlight processing */
2383
if (sprite_renderline[x+128] & 0x40)
2386
spritedata = sprite_renderline[x+128]&0x3f;
2388
if ((spritedata==0x0e) || (spritedata==0x1e) || (spritedata==0x2e))
2390
/* BUG in sprite chip, these colours are always normal intensity */
2391
video_renderline[x] = spritedata | 0x4000;
2392
video_renderline[x] |= 0x10000; // mark as sprite pixel
2394
else if (spritedata==0x3e)
2396
/* Everything below this is half colour, mark with 0x8000 to mark highlight' */
2397
video_renderline[x] = video_renderline[x]|0x8000; // spiderwebs..
2399
else if (spritedata==0x3f)
2401
/* This is a Shadow operator, but everything below is already low pri, no effect */
2402
video_renderline[x] = video_renderline[x]|0x2000;
2407
video_renderline[x] = spritedata;
2408
video_renderline[x] |= 0x10000; // mark as sprite pixel
2414
/* High Priority A+B Tiles */
2417
if (!MEGADRIVE_REG0C_SHADOW_HIGLIGHT)
2419
/* Normal Processing */
2421
dat = highpri_renderline[x];
2425
if (dat&0x0f) video_renderline[x] = highpri_renderline[x]&0x3f;
2430
/* Shadow / Highlight Mode */
2432
dat = highpri_renderline[x];
2436
if (dat&0x0f) video_renderline[x] = (highpri_renderline[x]&0x3f) | 0x4000;
2437
else video_renderline[x] = video_renderline[x] | 0x4000; // set 'normal'
2442
/* High Priority Sprites */
2445
if (!MEGADRIVE_REG0C_SHADOW_HIGLIGHT)
2448
if (sprite_renderline[x+128] & 0x80)
2450
video_renderline[x] = sprite_renderline[x+128]&0x3f;
2451
video_renderline[x] |= 0x10000; // mark as sprite pixel
2456
if (sprite_renderline[x+128] & 0x80)
2459
spritedata = sprite_renderline[x+128]&0x3f;
2461
if (spritedata==0x3e)
2463
/* set flag 0x8000 to indicate highlight */
2464
video_renderline[x] = video_renderline[x]|0x8000;
2466
else if (spritedata==0x3f)
2468
/* This is a Shadow operator set shadow bit */
2469
video_renderline[x] = video_renderline[x]|0x2000;
2473
video_renderline[x] = spritedata | 0x4000;
2474
video_renderline[x] |= 0x10000; // mark as sprite pixel
2482
/* This converts our render buffer to real screen colours */
2483
static void genesis_render_videobuffer_to_screenbuffer(running_machine &machine, int scanline)
2487
lineptr = &megadriv_render_bitmap->pix16(scanline);
2489
UINT32* _32x_linerender = _32x_render_videobuffer_to_screenbuffer_helper(machine, scanline);
2493
if (!MEGADRIVE_REG0C_SHADOW_HIGLIGHT)
2499
dat = video_renderline[x];
2502
// low priority 32x - if it's the bg pen, we have a 32x, and it's display is enabled...
2503
if ((dat&0x20000) && (_32x_is_connected) && (_32x_displaymode != 0))
2505
if (!_32x_videopriority)
2507
if (!(_32x_linerender[x]&0x8000))
2509
lineptr[x] = _32x_linerender[x]&0x7fff;
2515
if ((_32x_linerender[x]&0x8000))
2517
lineptr[x] = _32x_linerender[x]&0x7fff;
2527
lineptr[x] = megadrive_vdp_palette_lookup_sprite[(dat&0x0f) | segac2_sp_pal_lookup[(dat&0x30)>>4]];
2529
lineptr[x] = megadrive_vdp_palette_lookup[(dat&0x0f) | segac2_bg_pal_lookup[(dat&0x30)>>4]];
2542
dat = video_renderline[x];
2546
// low priority 32x - if it's the bg pen, we have a 32x, and it's display is enabled...
2547
if ((dat&0x20000) && (_32x_is_connected) && (_32x_displaymode != 0))
2549
if (!_32x_videopriority)
2551
if (!(_32x_linerender[x]&0x8000))
2553
lineptr[x] = _32x_linerender[x]&0x7fff;
2559
if ((_32x_linerender[x]&0x8000))
2561
lineptr[x] = _32x_linerender[x]&0x7fff;
2570
/* Verify my handling.. I'm not sure all cases are correct */
2571
switch (dat&0x1e000)
2573
case 0x00000: // low priority, no shadow sprite, no highlight = shadow
2574
case 0x02000: // low priority, shadow sprite, no highlight = shadow
2575
case 0x06000: // normal pri, shadow sprite, no highlight = shadow?
2576
case 0x10000: // (sprite) low priority, no shadow sprite, no highlight = shadow
2577
case 0x12000: // (sprite) low priority, shadow sprite, no highlight = shadow
2578
case 0x16000: // (sprite) normal pri, shadow sprite, no highlight = shadow?
2579
lineptr[x] = megadrive_vdp_palette_lookup_shadow[(dat&0x0f) | segac2_bg_pal_lookup[(dat&0x30)>>4]];
2582
case 0x4000: // normal pri, no shadow sprite, no highlight = normal;
2583
case 0x8000: // low pri, highlight sprite = normal;
2584
lineptr[x] = megadrive_vdp_palette_lookup[(dat&0x0f) | segac2_bg_pal_lookup[(dat&0x30)>>4]];
2587
case 0x14000: // (sprite) normal pri, no shadow sprite, no highlight = normal;
2588
case 0x18000: // (sprite) low pri, highlight sprite = normal;
2589
lineptr[x] = megadrive_vdp_palette_lookup_sprite[(dat&0x0f) | segac2_sp_pal_lookup[(dat&0x30)>>4]];
2593
case 0x0c000: // normal pri, highlight set = highlight?
2594
case 0x1c000: // (sprite) normal pri, highlight set = highlight?
2595
lineptr[x] = megadrive_vdp_palette_lookup_highlight[(dat&0x0f) | segac2_bg_pal_lookup[(dat&0x30)>>4]];
2598
case 0x0a000: // shadow set, highlight set - not possible
2599
case 0x0e000: // shadow set, highlight set, normal set, not possible
2600
case 0x1a000: // (sprite)shadow set, highlight set - not possible
2601
case 0x1e000: // (sprite)shadow set, highlight set, normal set, not possible
2603
lineptr[x] = machine.rand()&0x3f;
2615
// high priority 32x
2616
if ((_32x_is_connected) && (_32x_displaymode != 0))
2620
if (!_32x_videopriority)
2622
if ((_32x_linerender[x]&0x8000))
2623
lineptr[x] = _32x_linerender[x]&0x7fff;
2627
if (!(_32x_linerender[x]&0x8000))
2628
lineptr[x] = _32x_linerender[x]&0x7fff;
2634
static void genesis_render_scanline(running_machine &machine, int scanline)
2636
//if (MEGADRIVE_REG01_DMA_ENABLE==0) mame_printf_debug("off\n");
2637
genesis_render_spriteline_to_spritebuffer(genesis_scanline_counter);
2638
genesis_render_videoline_to_videobuffer(scanline);
2639
genesis_render_videobuffer_to_screenbuffer(machine, scanline);
2642
UINT16 get_hposition(void)
2644
// static int lowest = 99999;
2645
// static int highest = -99999;
2647
attotime time_elapsed_since_megadriv_scanline_timer;
2650
time_elapsed_since_megadriv_scanline_timer = megadriv_scanline_timer->time_elapsed();
2652
if (time_elapsed_since_megadriv_scanline_timer.attoseconds<(ATTOSECONDS_PER_SECOND/megadriv_framerate /megadrive_total_scanlines))
2654
value4 = (UINT16)(megadrive_max_hposition*((double)(time_elapsed_since_megadriv_scanline_timer.attoseconds) / (double)(ATTOSECONDS_PER_SECOND/megadriv_framerate /megadrive_total_scanlines)));
2656
else /* in some cases (probably due to rounding errors) we get some stupid results (the odd huge value where the time elapsed is much higher than the scanline time??!).. hopefully by clamping the result to the maximum we limit errors */
2658
value4 = megadrive_max_hposition;
2661
// if (value4>highest) highest = value4;
2662
// if (value4<lowest) lowest = value4;
2664
//mame_printf_debug("%d low %d high %d scancounter %d\n", value4, lowest, highest,genesis_scanline_counter);
2670
VIDEO_START(megadriv)
2674
megadriv_render_bitmap = auto_bitmap_ind16_alloc(machine, machine.primary_screen->width(), machine.primary_screen->height());
2676
megadrive_vdp_vram = auto_alloc_array(machine, UINT16, 0x10000/2);
2677
megadrive_vdp_cram = auto_alloc_array(machine, UINT16, 0x80/2);
2678
megadrive_vdp_vsram = auto_alloc_array(machine, UINT16, 0x80/2);
2679
megadrive_vdp_internal_sprite_attribute_table = auto_alloc_array(machine, UINT16, 0x400/2);
2681
for (x=0;x<0x20;x++)
2682
megadrive_vdp_register[x]=0;
2683
// memset(megadrive_vdp_vram, 0xff, 0x10000);
2684
// memset(megadrive_vdp_cram, 0xff, 0x80);
2685
// memset(megadrive_vdp_vsram, 0xff, 0x80);
2687
memset(megadrive_vdp_vram, 0x00, 0x10000);
2688
memset(megadrive_vdp_cram, 0x00, 0x80);
2689
memset(megadrive_vdp_vsram, 0x00, 0x80);
2690
memset(megadrive_vdp_internal_sprite_attribute_table, 0x00, 0x400);
2692
megadrive_max_hposition = 480;
2694
sprite_renderline = auto_alloc_array(machine, UINT8, 1024);
2695
highpri_renderline = auto_alloc_array(machine, UINT8, 320);
2696
video_renderline = auto_alloc_array(machine, UINT32, 320);
2698
megadrive_vdp_palette_lookup = auto_alloc_array(machine, UINT16, 0x40);
2699
megadrive_vdp_palette_lookup_sprite = auto_alloc_array(machine, UINT16, 0x40);
2701
megadrive_vdp_palette_lookup_shadow = auto_alloc_array(machine, UINT16, 0x40);
2702
megadrive_vdp_palette_lookup_highlight = auto_alloc_array(machine, UINT16, 0x40);
2704
memset(megadrive_vdp_palette_lookup,0x00,0x40*2);
2705
memset(megadrive_vdp_palette_lookup_sprite,0x00,0x40*2);
2707
memset(megadrive_vdp_palette_lookup_shadow,0x00,0x40*2);
2708
memset(megadrive_vdp_palette_lookup_highlight,0x00,0x40*2);
2710
/* no special lookups */
2711
segac2_bg_pal_lookup[0] = 0x00;
2712
segac2_bg_pal_lookup[1] = 0x10;
2713
segac2_bg_pal_lookup[2] = 0x20;
2714
segac2_bg_pal_lookup[3] = 0x30;
2716
segac2_sp_pal_lookup[0] = 0x00;
2717
segac2_sp_pal_lookup[1] = 0x10;
2718
segac2_sp_pal_lookup[2] = 0x20;
2719
segac2_sp_pal_lookup[3] = 0x30;
2723
TIMER_DEVICE_CALLBACK( megadriv_scanline_timer_callback )
2725
/* This function is called at the very start of every scanline starting at the very
2726
top-left of the screen. The first scanline is scanline 0 (we set scanline to -1 in
2729
timer.machine().scheduler().synchronize();
2730
/* Compensate for some rounding errors
2732
When the counter reaches 261 we should have reached the end of the frame, however due
2733
to rounding errors in the timer calculation we're not quite there. Let's assume we are
2734
still in the previous scanline for now.
2737
if (genesis_scanline_counter!=(megadrive_total_scanlines-1))
2739
genesis_scanline_counter++;
2740
// mame_printf_debug("scanline %d\n",genesis_scanline_counter);
2741
megadriv_scanline_timer->adjust(attotime::from_hz(megadriv_framerate) / megadrive_total_scanlines);
2742
megadriv_render_timer->adjust(attotime::from_usec(1));
2744
if (genesis_scanline_counter==megadrive_irq6_scanline )
2746
// mame_printf_debug("x %d",genesis_scanline_counter);
2747
irq6_on_timer->adjust(attotime::from_usec(6));
2748
megadrive_irq6_pending = 1;
2749
megadrive_vblank_flag = 1;
2752
if (_32x_is_connected)
2754
_32x_scanline_cb0(timer.machine());
2761
_32x_check_framebuffer_swap();
2764
// if (genesis_scanline_counter==0) irq4counter = MEGADRIVE_REG0A_HINT_VALUE;
2765
// irq4counter = MEGADRIVE_REG0A_HINT_VALUE;
2767
if (genesis_scanline_counter<=224)
2771
if (irq4counter==-1)
2773
if (megadrive_imode==3) irq4counter = MEGADRIVE_REG0A_HINT_VALUE*2;
2774
else irq4counter=MEGADRIVE_REG0A_HINT_VALUE;
2776
megadrive_irq4_pending = 1;
2778
if (MEGADRIVE_REG0_IRQ4_ENABLE)
2780
irq4_on_timer->adjust(attotime::from_usec(1));
2781
//mame_printf_debug("irq4 on scanline %d reload %d\n",genesis_scanline_counter,MEGADRIVE_REG0A_HINT_VALUE);
2787
if (megadrive_imode==3) irq4counter = MEGADRIVE_REG0A_HINT_VALUE*2;
2788
else irq4counter=MEGADRIVE_REG0A_HINT_VALUE;
2791
//if (genesis_scanline_counter==0) irq4_on_timer->adjust(attotime::from_usec(2));
2793
if(_32x_is_connected)
2795
_32x_scanline_cb1();
2799
if (timer.machine().device("genesis_snd_z80") != NULL)
2801
if (genesis_scanline_counter == megadrive_z80irq_scanline)
2803
if ((genz80.z80_has_bus == 1) && (genz80.z80_is_reset == 0))
2804
cputag_set_input_line(timer.machine(), "genesis_snd_z80", 0, HOLD_LINE);
2806
if (genesis_scanline_counter == megadrive_z80irq_scanline + 1)
2808
cputag_set_input_line(timer.machine(), "genesis_snd_z80", 0, CLEAR_LINE);
2813
else /* pretend we're still on the same scanline to compensate for rounding errors */
2815
genesis_scanline_counter = megadrive_total_scanlines - 1;
2820
TIMER_DEVICE_CALLBACK( irq6_on_callback )
2822
//mame_printf_debug("irq6 active on %d\n",genesis_scanline_counter);
2825
// megadrive_irq6_pending = 1;
2826
if (MEGADRIVE_REG01_IRQ6_ENABLE || genesis_always_irq6)
2827
cputag_set_input_line(timer.machine(), "maincpu", 6, HOLD_LINE);
2832
SCREEN_VBLANK(megadriv)
2838
int scr_width = 320;
2840
megadrive_vblank_flag = 0;
2841
//megadrive_irq6_pending = 0; /* NO! (breaks warlock) */
2843
/* Set it to -1 here, so it becomes 0 when the first timer kicks in */
2844
genesis_scanline_counter = -1;
2845
megadrive_sprite_collision=0;//? when to reset this ..
2846
megadrive_imode = MEGADRIVE_REG0C_INTERLEAVE; // can't change mid-frame..
2847
megadrive_imode_odd_frame^=1;
2848
// cputag_set_input_line(machine, "genesis_snd_z80", 0, CLEAR_LINE); // if the z80 interrupt hasn't happened by now, clear it..
2850
if (screen.machine().root_device().ioport("RESET")->read_safe(0x00) & 0x01)
2851
cputag_set_input_line(screen.machine(), "maincpu", INPUT_LINE_RESET, PULSE_LINE);
2854
if (MEGADRIVE_REG01_240_LINE)
2856
if (!megadrive_region_pal)
2858
/* this is invalid! */
2859
megadrive_visible_scanlines = 240;
2860
megadrive_total_scanlines = 262;
2861
megadrive_irq6_scanline = 240;
2862
megadrive_z80irq_scanline = 240;
2866
megadrive_visible_scanlines = 240;
2867
megadrive_total_scanlines = 313;
2868
megadrive_irq6_scanline = 240;
2869
megadrive_z80irq_scanline = 240;
2874
if (!megadrive_region_pal)
2876
megadrive_visible_scanlines = 224;
2877
megadrive_total_scanlines=262;
2878
megadrive_irq6_scanline = 224;
2879
megadrive_z80irq_scanline = 224;
2883
megadrive_visible_scanlines = 224;
2884
megadrive_total_scanlines=313;
2885
megadrive_irq6_scanline = 224;
2886
megadrive_z80irq_scanline = 224;
2890
if (megadrive_imode==3)
2892
megadrive_visible_scanlines<<=1;
2893
megadrive_total_scanlines<<=1;
2894
megadrive_irq6_scanline <<=1;
2895
megadrive_z80irq_scanline <<=1;
2900
switch (MEGADRIVE_REG0C_RS0 | (MEGADRIVE_REG0C_RS1 << 1))
2902
/* note, add 240 mode + init new timings! */
2903
case 0:scr_width = 256;break;// configure_screen(0, 256-1, megadrive_visible_scanlines-1,(double)megadriv_framerate); break;
2904
case 1:scr_width = 256;break;// configure_screen(0, 256-1, megadrive_visible_scanlines-1,(double)megadriv_framerate); mame_printf_debug("invalid screenmode!\n"); break;
2905
case 2:scr_width = 320;break;// configure_screen(0, 320-1, megadrive_visible_scanlines-1,(double)megadriv_framerate); break; /* technically invalid, but used in rare cases */
2906
case 3:scr_width = 320;break;// configure_screen(0, 320-1, megadrive_visible_scanlines-1,(double)megadriv_framerate); break;
2908
// mame_printf_debug("my mode %02x", megadrive_vdp_register[0x0c]);
2910
visarea.set(0, scr_width-1, 0, megadrive_visible_scanlines-1);
2912
screen.machine().primary_screen->configure(scr_width, megadrive_visible_scanlines, visarea, HZ_TO_ATTOSECONDS(megadriv_framerate));
2914
megadriv_scanline_timer->adjust(attotime::zero);
2916
if(_32x_is_connected)
2917
_32x_hcount_compare_val = -1;
2921
timer_device* megadriv_render_timer;
2923
TIMER_DEVICE_CALLBACK( megadriv_render_timer_callback )
2925
if (genesis_scanline_counter>=0 && genesis_scanline_counter<megadrive_visible_scanlines)
2927
genesis_render_scanline(timer.machine(), genesis_scanline_counter);
2931
void megadriv_reset_vdp(void)
2933
megadrive_imode = 0;
2935
megadrive_total_scanlines = 262;
2936
megadrive_visible_scanlines = 224;
2937
megadrive_irq6_scanline = 224;
2938
megadrive_z80irq_scanline = 226;