Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/genplus-gx/core/vdp_ctrl.c
2 views
1
/***************************************************************************************
2
* Genesis Plus
3
* Video Display Processor (68k & Z80 CPU interface)
4
*
5
* Support for SG-1000, Master System (315-5124 & 315-5246), Game Gear & Mega Drive VDP
6
*
7
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
8
* Copyright (C) 2007-2013 Eke-Eke (Genesis Plus GX)
9
*
10
* Redistribution and use of this code or any derivative works are permitted
11
* provided that the following conditions are met:
12
*
13
* - Redistributions may not be sold, nor may they be used in a commercial
14
* product or activity.
15
*
16
* - Redistributions that are modified from the original source must include the
17
* complete source code, including the source code for all components used by a
18
* binary built from the modified sources. However, as a special exception, the
19
* source code distributed need not include anything that is normally distributed
20
* (in either source or binary form) with the major components (compiler, kernel,
21
* and so on) of the operating system on which the executable runs, unless that
22
* component itself accompanies the executable.
23
*
24
* - Redistributions must reproduce the above copyright notice, this list of
25
* conditions and the following disclaimer in the documentation and/or other
26
* materials provided with the distribution.
27
*
28
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
32
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
* POSSIBILITY OF SUCH DAMAGE.
39
*
40
****************************************************************************************/
41
42
#include "shared.h"
43
#include "hvc.h"
44
#include "../cinterface/callbacks.h"
45
46
/* Mark a pattern as modified */
47
#define MARK_BG_DIRTY(addr) \
48
{ \
49
name = (addr >> 5) & 0x7FF; \
50
if(bg_name_dirty[name] == 0) \
51
{ \
52
bg_name_list[bg_list_index++] = name; \
53
} \
54
bg_name_dirty[name] |= (1 << ((addr >> 2) & 7)); \
55
}
56
57
/* VDP context */
58
uint8 sat[0x400]; /* Internal copy of sprite attribute table */
59
uint8 vram[0x10000]; /* Video RAM (64K x 8-bit) */
60
uint8 cram[0x80]; /* On-chip color RAM (64 x 9-bit) */
61
uint8 vsram[0x80]; /* On-chip vertical scroll RAM (40 x 11-bit) */
62
uint8 reg[0x20]; /* Internal VDP registers (23 x 8-bit) */
63
uint8 hint_pending; /* 0= Line interrupt is pending */
64
uint8 vint_pending; /* 1= Frame interrupt is pending */
65
uint16 status; /* VDP status flags */
66
uint32 dma_length; /* DMA remaining length */
67
68
/* Global variables */
69
uint16 ntab; /* Name table A base address */
70
uint16 ntbb; /* Name table B base address */
71
uint16 ntwb; /* Name table W base address */
72
uint16 satb; /* Sprite attribute table base address */
73
uint16 hscb; /* Horizontal scroll table base address */
74
uint8 bg_name_dirty[0x800]; /* 1= This pattern is dirty */
75
uint16 bg_name_list[0x800]; /* List of modified pattern indices */
76
uint16 bg_list_index; /* # of modified patterns in list */
77
uint8 hscroll_mask; /* Horizontal Scrolling line mask */
78
uint8 playfield_shift; /* Width of planes A, B (in bits) */
79
uint8 playfield_col_mask; /* Playfield column mask */
80
uint16 playfield_row_mask; /* Playfield row mask */
81
uint16 vscroll; /* Latched vertical scroll value */
82
uint8 odd_frame; /* 1: odd field, 0: even field */
83
uint8 im2_flag; /* 1= Interlace mode 2 is being used */
84
uint8 interlaced; /* 1: Interlaced mode 1 or 2 */
85
uint8 vdp_pal; /* 1: PAL , 0: NTSC (default) */
86
uint16 v_counter; /* Vertical counter */
87
uint16 vc_max; /* Vertical counter overflow value */
88
uint16 lines_per_frame; /* PAL: 313 lines, NTSC: 262 lines */
89
uint16 max_sprite_pixels; /* Max. sprites pixels per line (parsing & rendering) */
90
int32 fifo_write_cnt; /* VDP FIFO write count */
91
uint32 fifo_slots; /* VDP FIFO access slot count */
92
uint32 hvc_latch; /* latched HV counter */
93
const uint8 *hctab; /* pointer to H Counter table */
94
95
/* Function pointers */
96
void (*vdp_68k_data_w)(unsigned int data);
97
void (*vdp_z80_data_w)(unsigned int data);
98
unsigned int (*vdp_68k_data_r)(void);
99
unsigned int (*vdp_z80_data_r)(void);
100
101
/* Function prototypes */
102
static void vdp_68k_data_w_m4(unsigned int data);
103
static void vdp_68k_data_w_m5(unsigned int data);
104
static unsigned int vdp_68k_data_r_m4(void);
105
static unsigned int vdp_68k_data_r_m5(void);
106
static void vdp_z80_data_w_m4(unsigned int data);
107
static void vdp_z80_data_w_m5(unsigned int data);
108
static unsigned int vdp_z80_data_r_m4(void);
109
static unsigned int vdp_z80_data_r_m5(void);
110
static void vdp_z80_data_w_ms(unsigned int data);
111
static void vdp_z80_data_w_gg(unsigned int data);
112
static void vdp_z80_data_w_sg(unsigned int data);
113
static void vdp_bus_w(unsigned int data);
114
static void vdp_fifo_update(unsigned int cycles);
115
static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles);
116
static void vdp_dma_68k_ext(unsigned int length);
117
static void vdp_dma_68k_ram(unsigned int length);
118
static void vdp_dma_68k_io(unsigned int length);
119
static void vdp_dma_copy(unsigned int length);
120
static void vdp_dma_fill(unsigned int length);
121
122
/* Tables that define the playfield layout */
123
static const uint8 hscroll_mask_table[] = { 0x00, 0x07, 0xF8, 0xFF };
124
static const uint8 shift_table[] = { 6, 7, 0, 8 };
125
static const uint8 col_mask_table[] = { 0x0F, 0x1F, 0x0F, 0x3F };
126
static const uint16 row_mask_table[] = { 0x0FF, 0x1FF, 0x2FF, 0x3FF };
127
128
uint8 border; /* Border color index */
129
static uint8 pending; /* Pending write flag */
130
static uint8 code; /* Code register */
131
static uint8 dma_type; /* DMA mode */
132
static uint16 addr; /* Address register */
133
static uint16 addr_latch; /* Latched A15, A14 of address */
134
static uint16 sat_base_mask; /* Base bits of SAT */
135
static uint16 sat_addr_mask; /* Index bits of SAT */
136
static uint16 dma_src; /* DMA source address */
137
static uint32 dma_endCycles; /* 68k cycles to DMA end */
138
static int dmafill; /* DMA Fill pending flag */
139
static int cached_write; /* 2nd part of 32-bit CTRL port write (Genesis mode) or LSB of CRAM data (Game Gear mode) */
140
static uint16 fifo[4]; /* FIFO ring-buffer */
141
static int fifo_idx; /* FIFO write index */
142
static int fifo_byte_access; /* FIFO byte access flag */
143
static uint32 fifo_cycles; /* FIFO next access cycle */
144
145
/* set Z80 or 68k interrupt lines */
146
static void (*set_irq_line)(unsigned int level);
147
static void (*set_irq_line_delay)(unsigned int level);
148
149
/* Vertical counter overflow values (see hvc.h) */
150
static const uint16 vc_table[4][2] =
151
{
152
/* NTSC, PAL */
153
{0xDA , 0xF2}, /* Mode 4 (192 lines) */
154
{0xEA , 0x102}, /* Mode 5 (224 lines) */
155
{0xDA , 0xF2}, /* Mode 4 (192 lines) */
156
{0x106, 0x10A} /* Mode 5 (240 lines) */
157
};
158
159
/* DMA Timings (number of access slots per line) */
160
static const uint8 dma_timing[2][2] =
161
{
162
/* H32, H40 */
163
{16 , 18}, /* active display */
164
{167, 205} /* blank display */
165
};
166
167
/* DMA processing functions (set by VDP register 23 high nibble) */
168
static void (*const dma_func[16])(unsigned int length) =
169
{
170
/* 0x0-0x3 : DMA from 68k bus $000000-$7FFFFF (external area) */
171
vdp_dma_68k_ext,vdp_dma_68k_ext,vdp_dma_68k_ext,vdp_dma_68k_ext,
172
173
/* 0x4-0x7 : DMA from 68k bus $800000-$FFFFFF (internal RAM & I/O) */
174
vdp_dma_68k_ram, vdp_dma_68k_io,vdp_dma_68k_ram,vdp_dma_68k_ram,
175
176
/* 0x8-0xB : DMA Fill */
177
vdp_dma_fill,vdp_dma_fill,vdp_dma_fill,vdp_dma_fill,
178
179
/* 0xC-0xF : DMA Copy */
180
vdp_dma_copy,vdp_dma_copy,vdp_dma_copy,vdp_dma_copy
181
};
182
183
184
void write_vram_byte(int addr, uint8 val)
185
{
186
uint8 *p;
187
addr &= 0xffff;
188
p = &vram[addr];
189
if (*p != val)
190
{
191
int name;
192
*p = val;
193
MARK_BG_DIRTY(addr);
194
}
195
}
196
197
void flush_vram_cache(void)
198
{
199
if (bg_list_index)
200
{
201
update_bg_pattern_cache(bg_list_index);
202
bg_list_index = 0;
203
}
204
}
205
206
/*--------------------------------------------------------------------------*/
207
/* Init, reset, context functions */
208
/*--------------------------------------------------------------------------*/
209
210
void vdp_init(void)
211
{
212
/* PAL/NTSC timings */
213
lines_per_frame = vdp_pal ? 313: 262;
214
215
/* CPU interrupt line(s)*/
216
if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
217
{
218
/* 68k cpu */
219
set_irq_line = m68k_set_irq;
220
set_irq_line_delay = m68k_set_irq_delay;
221
}
222
else
223
{
224
/* Z80 cpu */
225
set_irq_line = z80_set_irq_line;
226
set_irq_line_delay = z80_set_irq_line;
227
}
228
}
229
230
void vdp_reset(void)
231
{
232
int i;
233
234
memset ((char *) sat, 0, sizeof (sat));
235
memset ((char *) vram, 0, sizeof (vram));
236
memset ((char *) cram, 0, sizeof (cram));
237
memset ((char *) vsram, 0, sizeof (vsram));
238
memset ((char *) reg, 0, sizeof (reg));
239
240
addr = 0;
241
addr_latch = 0;
242
code = 0;
243
pending = 0;
244
border = 0;
245
hint_pending = 0;
246
vint_pending = 0;
247
dmafill = 0;
248
dma_src = 0;
249
dma_type = 0;
250
dma_length = 0;
251
dma_endCycles = 0;
252
odd_frame = 0;
253
im2_flag = 0;
254
interlaced = 0;
255
fifo_write_cnt = 0;
256
fifo_cycles = 0;
257
fifo_slots = 0;
258
fifo_idx = 0;
259
cached_write = -1;
260
fifo_byte_access = 1;
261
262
ntab = 0;
263
ntbb = 0;
264
ntwb = 0;
265
satb = 0;
266
hscb = 0;
267
268
vscroll = 0;
269
270
hscroll_mask = 0x00;
271
playfield_shift = 6;
272
playfield_col_mask = 0x0F;
273
playfield_row_mask = 0x0FF;
274
sat_base_mask = 0xFE00;
275
sat_addr_mask = 0x01FF;
276
277
/* reset pattern cache changes */
278
bg_list_index = 0;
279
memset ((char *) bg_name_dirty, 0, sizeof (bg_name_dirty));
280
memset ((char *) bg_name_list, 0, sizeof (bg_name_list));
281
282
/* default HVC */
283
hvc_latch = 0x10000;
284
hctab = cycle2hc32;
285
vc_max = vc_table[0][vdp_pal];
286
v_counter = lines_per_frame - 1;
287
288
/* default Window clipping */
289
window_clip(0,0);
290
291
/* reset VDP status (FIFO empty flag is set) */
292
if (system_hw & SYSTEM_MD)
293
{
294
status = vdp_pal | 0x200;
295
}
296
else
297
{
298
status = 0;
299
}
300
301
/* default display area */
302
bitmap.viewport.w = 256;
303
bitmap.viewport.h = 192;
304
bitmap.viewport.ow = 256;
305
bitmap.viewport.oh = 192;
306
307
/* default sprite pixel width */
308
max_sprite_pixels = 256;
309
310
/* default overscan area */
311
if ((system_hw == SYSTEM_GG) && !config.gg_extra)
312
{
313
/* Display area reduced to 160x144 if overscan is disabled */
314
bitmap.viewport.x = (config.overscan & 2) ? 14 : -48;
315
bitmap.viewport.y = (config.overscan & 1) ? (24 * (vdp_pal + 1)) : -24;
316
}
317
else
318
{
319
bitmap.viewport.x = (config.overscan & 2) * 7;
320
bitmap.viewport.y = (config.overscan & 1) * 24 * (vdp_pal + 1);
321
}
322
323
/* default rendering mode */
324
update_bg_pattern_cache = update_bg_pattern_cache_m4;
325
if (system_hw < SYSTEM_MD)
326
{
327
/* Mode 0 */
328
render_bg = render_bg_m0;
329
render_obj = render_obj_tms;
330
parse_satb = parse_satb_tms;
331
}
332
else
333
{
334
/* Mode 4 */
335
render_bg = render_bg_m4;
336
render_obj = render_obj_m4;
337
parse_satb = parse_satb_m4;
338
}
339
340
/* default 68k bus interface (Mega Drive VDP only) */
341
vdp_68k_data_w = vdp_68k_data_w_m4;
342
vdp_68k_data_r = vdp_68k_data_r_m4;
343
344
/* default Z80 bus interface */
345
switch (system_hw)
346
{
347
case SYSTEM_SG:
348
{
349
/* SG-1000 VDP (TMS99xx) */
350
vdp_z80_data_w = vdp_z80_data_w_sg;
351
vdp_z80_data_r = vdp_z80_data_r_m4;
352
break;
353
}
354
355
case SYSTEM_GG:
356
{
357
/* Game Gear VDP */
358
vdp_z80_data_w = vdp_z80_data_w_gg;
359
vdp_z80_data_r = vdp_z80_data_r_m4;
360
break;
361
}
362
363
case SYSTEM_MARKIII:
364
case SYSTEM_SMS:
365
case SYSTEM_SMS2:
366
case SYSTEM_GGMS:
367
{
368
/* Master System or Game Gear (in MS compatibility mode) VDP */
369
vdp_z80_data_w = vdp_z80_data_w_ms;
370
vdp_z80_data_r = vdp_z80_data_r_m4;
371
break;
372
}
373
374
default:
375
{
376
/* Mega Drive VDP (in MS compatibility mode) */
377
vdp_z80_data_w = vdp_z80_data_w_m4;
378
vdp_z80_data_r = vdp_z80_data_r_m4;
379
break;
380
}
381
}
382
383
/* SG-1000 specific */
384
if (system_hw == SYSTEM_SG)
385
{
386
/* 16k address decoding by default (Magical Kid Wiz) */
387
vdp_reg_w(1, 0x80, 0);
388
389
/* no H-INT on TMS99xx */
390
vdp_reg_w(10, 0xFF, 0);
391
}
392
393
/* Master System specific */
394
else if ((system_hw & SYSTEM_SMS) && (!(config.bios & 1) || !(system_bios & SYSTEM_SMS)))
395
{
396
/* force registers initialization (only if Master System BIOS is disabled or not loaded) */
397
vdp_reg_w(0 , 0x36, 0);
398
vdp_reg_w(1 , 0x80, 0);
399
vdp_reg_w(2 , 0xFF, 0);
400
vdp_reg_w(3 , 0xFF, 0);
401
vdp_reg_w(4 , 0xFF, 0);
402
vdp_reg_w(5 , 0xFF, 0);
403
vdp_reg_w(6 , 0xFF, 0);
404
vdp_reg_w(10, 0xFF, 0);
405
406
/* Mode 4 */
407
render_bg = render_bg_m4;
408
render_obj = render_obj_m4;
409
parse_satb = parse_satb_m4;
410
}
411
412
/* Mega Drive specific */
413
else if (((system_hw == SYSTEM_MD) || (system_hw == SYSTEM_MCD)) && (config.bios & 1) && !(system_bios & SYSTEM_MD))
414
{
415
/* force registers initialization (only if TMSS model is emulated and BOOT ROM is not loaded) */
416
vdp_reg_w(0 , 0x04, 0);
417
vdp_reg_w(1 , 0x04, 0);
418
vdp_reg_w(10, 0xFF, 0);
419
vdp_reg_w(12, 0x81, 0);
420
vdp_reg_w(15, 0x02, 0);
421
}
422
423
/* reset color palette */
424
for(i = 0; i < 0x20; i ++)
425
{
426
color_update_m4(i, 0x00);
427
}
428
color_update_m4(0x40, 0x00);
429
}
430
431
int vdp_context_save(uint8 *state)
432
{
433
int bufferptr = 0;
434
435
save_param(sat, sizeof(sat));
436
save_param(vram, sizeof(vram));
437
save_param(cram, sizeof(cram));
438
save_param(vsram, sizeof(vsram));
439
save_param(reg, sizeof(reg));
440
save_param(&addr, sizeof(addr));
441
save_param(&addr_latch, sizeof(addr_latch));
442
save_param(&code, sizeof(code));
443
save_param(&pending, sizeof(pending));
444
save_param(&status, sizeof(status));
445
save_param(&dmafill, sizeof(dmafill));
446
save_param(&fifo_idx, sizeof(fifo_idx));
447
save_param(&fifo, sizeof(fifo));
448
save_param(&hint_pending, sizeof(hint_pending));
449
save_param(&vint_pending, sizeof(vint_pending));
450
save_param(&dma_length, sizeof(dma_length));
451
save_param(&dma_type, sizeof(dma_type));
452
save_param(&dma_src, sizeof(dma_src));
453
save_param(&cached_write, sizeof(cached_write));
454
return bufferptr;
455
}
456
457
int vdp_context_load(uint8 *state, uint8 version)
458
{
459
int i, bufferptr = 0;
460
uint8 temp_reg[0x20];
461
462
load_param(sat, sizeof(sat));
463
load_param(vram, sizeof(vram));
464
load_param(cram, sizeof(cram));
465
load_param(vsram, sizeof(vsram));
466
load_param(temp_reg, sizeof(temp_reg));
467
468
/* restore VDP registers */
469
if (system_hw < SYSTEM_MD)
470
{
471
if (system_hw > SYSTEM_SG)
472
{
473
for (i=0;i<0x10;i++)
474
{
475
pending = 1;
476
addr_latch = temp_reg[i];
477
vdp_sms_ctrl_w(0x80 | i);
478
}
479
}
480
else
481
{
482
for (i=0;i<0x08;i++)
483
{
484
pending = 1;
485
addr_latch = temp_reg[i];
486
vdp_tms_ctrl_w(0x80 | i);
487
}
488
}
489
}
490
else
491
{
492
for (i=0;i<0x20;i++)
493
{
494
vdp_reg_w(i, temp_reg[i], 0);
495
}
496
}
497
498
load_param(&addr, sizeof(addr));
499
load_param(&addr_latch, sizeof(addr_latch));
500
load_param(&code, sizeof(code));
501
load_param(&pending, sizeof(pending));
502
load_param(&status, sizeof(status));
503
504
/* 1.7.1 state compatibility */
505
if (version < 0x35)
506
{
507
uint16 temp;
508
load_param(&temp, 2);
509
dmafill = temp >> 8;
510
temp &= 0xff;
511
fifo_idx = 0;
512
fifo[0] = fifo[1] = fifo[2] = fifo[3] = (temp << 8) | temp;
513
}
514
else
515
{
516
load_param(&dmafill, sizeof(dmafill));
517
load_param(&fifo_idx, sizeof(fifo_idx));
518
load_param(&fifo, sizeof(fifo));
519
}
520
521
load_param(&hint_pending, sizeof(hint_pending));
522
load_param(&vint_pending, sizeof(vint_pending));
523
load_param(&dma_length, sizeof(dma_length));
524
load_param(&dma_type, sizeof(dma_type));
525
load_param(&dma_src, sizeof(dma_src));
526
load_param(&cached_write, sizeof(cached_write));
527
528
/* restore FIFO byte access flag */
529
fifo_byte_access = ((code & 0x0F) < 0x03);
530
531
/* restore current NTSC/PAL mode */
532
if (system_hw & SYSTEM_MD)
533
{
534
status = (status & ~1) | vdp_pal;
535
}
536
537
if (reg[1] & 0x04)
538
{
539
/* Mode 5 */
540
bg_list_index = 0x800;
541
542
/* reinitialize palette */
543
color_update_m5(0, *(uint16 *)&cram[border << 1]);
544
for(i = 1; i < 0x40; i++)
545
{
546
color_update_m5(i, *(uint16 *)&cram[i << 1]);
547
}
548
}
549
else
550
{
551
/* Modes 0,1,2,3,4 */
552
bg_list_index = 0x200;
553
554
/* reinitialize palette */
555
for(i = 0; i < 0x20; i ++)
556
{
557
color_update_m4(i, *(uint16 *)&cram[i << 1]);
558
}
559
color_update_m4(0x40, *(uint16 *)&cram[(0x10 | (border & 0x0F)) << 1]);
560
}
561
562
/* invalidate cache */
563
for (i=0;i<bg_list_index;i++)
564
{
565
bg_name_list[i]=i;
566
bg_name_dirty[i]=0xFF;
567
}
568
569
return bufferptr;
570
}
571
572
573
/*--------------------------------------------------------------------------*/
574
/* DMA update function (Mega Drive VDP only) */
575
/*--------------------------------------------------------------------------*/
576
577
void vdp_dma_update(unsigned int cycles)
578
{
579
int dma_cycles, dma_bytes;
580
581
/* DMA transfer rate (bytes per line)
582
583
According to the manual, here's a table that describes the transfer
584
rates of each of the three DMA types:
585
586
DMA Mode Width Display Transfer Count
587
-----------------------------------------------------
588
68K > VDP 32-cell Active 16
589
Blanking 167
590
40-cell Active 18
591
Blanking 205
592
VRAM Fill 32-cell Active 15
593
Blanking 166
594
40-cell Active 17
595
Blanking 204
596
VRAM Copy 32-cell Active 8
597
Blanking 83
598
40-cell Active 9
599
Blanking 102
600
601
'Active' is the active display period, 'Blanking' is either the vertical
602
blanking period or when the display is forcibly blanked via register #1.
603
604
The above transfer counts are all in bytes, unless the destination is
605
CRAM or VSRAM for a 68K > VDP transfer, in which case it is in words.
606
*/
607
unsigned int rate = dma_timing[(status & 8) || !(reg[1] & 0x40)][reg[12] & 1];
608
609
/* Adjust for 68k bus DMA to VRAM (one word = 2 access) or DMA Copy (one read + one write = 2 access) */
610
rate = rate >> (dma_type & 1);
611
612
/* Remaining DMA cycles */
613
if (status & 8)
614
{
615
/* Process DMA until the end of VBLANK */
616
/* NOTE: DMA timings can not change during VBLANK because active display width cannot be modified. */
617
/* Indeed, writing VDP registers during DMA is either impossible (when doing DMA from 68k bus, CPU */
618
/* is locked) or will abort DMA operation (in case of DMA Fill or Copy). */
619
dma_cycles = (lines_per_frame * MCYCLES_PER_LINE) - cycles;
620
}
621
else
622
{
623
/* Process DMA until the end of current line */
624
dma_cycles = (mcycles_vdp + MCYCLES_PER_LINE) - cycles;
625
}
626
627
/* Remaining DMA bytes for that line */
628
dma_bytes = (dma_cycles * rate) / MCYCLES_PER_LINE;
629
630
#ifdef LOGVDP
631
error("[%d(%d)][%d(%d)] DMA type %d (%d access/line)(%d cycles left)-> %d access (%d remaining) (%x)\n", v_counter, m68k.cycles/MCYCLES_PER_LINE, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE,dma_type, rate, dma_cycles, dma_bytes, dma_length, m68k_get_reg(M68K_REG_PC));
632
#endif
633
634
/* Check if DMA can be finished before the end of current line */
635
if (dma_length < dma_bytes)
636
{
637
/* Adjust remaining DMA bytes */
638
dma_bytes = dma_length;
639
dma_cycles = (dma_bytes * MCYCLES_PER_LINE) / rate;
640
}
641
642
/* Update DMA timings */
643
if (dma_type < 2)
644
{
645
/* 68K is frozen during DMA from 68k bus */
646
m68k.cycles = cycles + dma_cycles;
647
#ifdef LOGVDP
648
error("-->CPU frozen for %d cycles\n", dma_cycles);
649
#endif
650
}
651
else
652
{
653
/* Set DMA Busy flag */
654
status |= 0x02;
655
656
/* 68K is still running, set DMA end cycle */
657
dma_endCycles = cycles + dma_cycles;
658
#ifdef LOGVDP
659
error("-->DMA ends in %d cycles\n", dma_cycles);
660
#endif
661
}
662
663
/* Process DMA */
664
if (dma_bytes > 0)
665
{
666
/* Update DMA length */
667
dma_length -= dma_bytes;
668
669
/* Process DMA operation */
670
dma_func[reg[23] >> 4](dma_bytes);
671
672
/* Check if DMA is finished */
673
if (!dma_length)
674
{
675
/* DMA source address registers are incremented during DMA (even DMA Fill) */
676
uint16 end = reg[21] + (reg[22] << 8) + reg[19] + (reg[20] << 8);
677
reg[21] = end & 0xff;
678
reg[22] = end >> 8;
679
680
/* DMA length registers are decremented during DMA */
681
reg[19] = reg[20] = 0;
682
683
/* perform cached write, if any */
684
if (cached_write >= 0)
685
{
686
vdp_68k_ctrl_w(cached_write);
687
cached_write = -1;
688
}
689
}
690
}
691
}
692
693
694
/*--------------------------------------------------------------------------*/
695
/* Control port access functions */
696
/*--------------------------------------------------------------------------*/
697
698
void vdp_68k_ctrl_w(unsigned int data)
699
{
700
/* Check pending flag */
701
if (pending == 0)
702
{
703
/* A single long word write instruction could have started DMA with the first word */
704
if (dma_length)
705
{
706
/* 68k is frozen during 68k bus DMA */
707
/* Second word should be written after DMA completion */
708
/* See Formula One & Kawasaki Superbike Challenge */
709
if (dma_type < 2)
710
{
711
/* Latch second control word for later */
712
cached_write = data;
713
return;
714
}
715
}
716
717
/* Check CD0-CD1 bits */
718
if ((data & 0xC000) == 0x8000)
719
{
720
/* VDP register write */
721
vdp_reg_w((data >> 8) & 0x1F, data & 0xFF, m68k.cycles);
722
}
723
else
724
{
725
/* Set pending flag (Mode 5 only) */
726
pending = reg[1] & 4;
727
}
728
729
/* Update address and code registers */
730
addr = addr_latch | (data & 0x3FFF);
731
code = ((code & 0x3C) | ((data >> 14) & 0x03));
732
}
733
else
734
{
735
/* Clear pending flag */
736
pending = 0;
737
738
/* Save address bits A15 and A14 */
739
addr_latch = (data & 3) << 14;
740
741
/* Update address and code registers */
742
addr = addr_latch | (addr & 0x3FFF);
743
code = ((code & 0x03) | ((data >> 2) & 0x3C));
744
745
/* Detect DMA operation (CD5 bit set) */
746
if (code & 0x20)
747
{
748
/* DMA must be enabled */
749
if (reg[1] & 0x10)
750
{
751
/* DMA type */
752
switch (reg[23] >> 6)
753
{
754
case 2:
755
{
756
/* DMA Fill */
757
dma_type = 2;
758
759
/* DMA is pending until next DATA port write */
760
dmafill = 1;
761
762
/* Set DMA Busy flag */
763
status |= 0x02;
764
765
/* DMA end cycle is not initialized yet (this prevents DMA Busy flag from being cleared on VDP status read) */
766
dma_endCycles = 0xffffffff;
767
break;
768
}
769
770
case 3:
771
{
772
/* DMA Copy */
773
dma_type = 3;
774
775
/* DMA length */
776
dma_length = (reg[20] << 8) | reg[19];
777
778
/* Zero DMA length (pre-decrementing counter) */
779
if (!dma_length)
780
{
781
dma_length = 0x10000;
782
}
783
784
/* DMA source address */
785
dma_src = (reg[22] << 8) | reg[21];
786
787
/* Trigger DMA */
788
vdp_dma_update(m68k.cycles);
789
break;
790
}
791
792
default:
793
{
794
/* DMA from 68k bus */
795
dma_type = (code & 0x06) ? 0 : 1;
796
797
/* DMA length */
798
dma_length = (reg[20] << 8) | reg[19];
799
800
/* Zero DMA length (pre-decrementing counter) */
801
if (!dma_length)
802
{
803
dma_length = 0x10000;
804
}
805
806
/* DMA source address */
807
dma_src = (reg[22] << 8) | reg[21];
808
809
/* Transfer from SVP ROM/RAM ($000000-$3fffff) or CD Word-RAM ($200000-$3fffff/$600000-$7fffff) */
810
if (((system_hw == SYSTEM_MCD) && ((reg[23] & 0x70) == ((scd.cartridge.boot >> 1) + 0x10))) || (svp && !(reg[23] & 0x60)))
811
{
812
/* source data is available with one cycle delay, i.e first word written by VDP is */
813
/* previous data being held on 68k bus at that time, then source words are written */
814
/* normally to VDP RAM, with only last source word being ignored */
815
addr += reg[15];
816
dma_length--;
817
}
818
819
/* Trigger DMA */
820
vdp_dma_update(m68k.cycles);
821
break;
822
}
823
}
824
}
825
}
826
}
827
828
/*
829
FIFO emulation (Chaos Engine/Soldier of Fortune, Double Clutch, Sol Deace)
830
--------------------------------------------------------------------------
831
Each VRAM access is byte wide, so one VRAM write (word) need two slot access.
832
833
NOTE: Invalid code 0x02 (register write) should not behave the same as VRAM
834
access, i.e data is ignored and only one access slot is used for each word,
835
BUT a few games ("Clue", "Microcosm") which accidentally corrupt code value
836
will have issues when emulating FIFO timings. They likely work fine on real
837
hardware because of periodical 68k wait-states which have been observed and
838
would naturaly add some delay between writes. Until those wait-states are
839
accurately measured and emulated, delay is forced when invalid code value
840
is being used.
841
*/
842
fifo_byte_access = ((code & 0x0F) <= 0x02);
843
}
844
845
/* Mega Drive VDP control port specific (MS compatibility mode) */
846
void vdp_z80_ctrl_w(unsigned int data)
847
{
848
switch (pending)
849
{
850
case 0:
851
{
852
/* Latch LSB */
853
addr_latch = data;
854
855
/* Set LSB pending flag */
856
pending = 1;
857
return;
858
}
859
860
case 1:
861
{
862
/* Update address and code registers */
863
addr = (addr & 0xC000) | ((data & 0x3F) << 8) | addr_latch ;
864
code = ((code & 0x3C) | ((data >> 6) & 0x03));
865
866
if ((code & 0x03) == 0x02)
867
{
868
/* VDP register write */
869
vdp_reg_w(data & 0x1F, addr_latch, Z80.cycles);
870
871
/* Clear pending flag */
872
pending = 0;
873
return;
874
}
875
876
/* Set Mode 5 pending flag */
877
pending = (reg[1] & 4) >> 1;
878
879
if (!pending && !(code & 0x03))
880
{
881
/* Process VRAM read */
882
fifo[0] = vram[addr & 0x3FFF];
883
884
/* Increment address register */
885
addr += (reg[15] + 1);
886
}
887
return;
888
}
889
890
case 2:
891
{
892
/* Latch LSB */
893
addr_latch = data;
894
895
/* Set LSB pending flag */
896
pending = 3;
897
return;
898
}
899
900
case 3:
901
{
902
/* Clear pending flag */
903
pending = 0;
904
905
/* Update address and code registers */
906
addr = ((addr_latch & 3) << 14) | (addr & 0x3FFF);
907
code = ((code & 0x03) | ((addr_latch >> 2) & 0x3C));
908
909
/* Detect DMA operation (CD5 bit set) */
910
if (code & 0x20)
911
{
912
/* DMA should be enabled */
913
if (reg[1] & 0x10)
914
{
915
/* DMA type */
916
switch (reg[23] >> 6)
917
{
918
case 2:
919
{
920
/* DMA Fill will be triggered by next write to DATA port */
921
dmafill = 1;
922
923
/* Set DMA Busy flag */
924
status |= 0x02;
925
926
/* DMA end cycle is not initialized yet (this prevents DMA Busy flag from being cleared on VDP status read) */
927
dma_endCycles = 0xffffffff;
928
break;
929
}
930
931
case 3:
932
{
933
/* DMA copy */
934
dma_type = 3;
935
936
/* DMA length */
937
dma_length = (reg[20] << 8) | reg[19];
938
939
/* Zero DMA length (pre-decrementing counter) */
940
if (!dma_length)
941
{
942
dma_length = 0x10000;
943
}
944
945
/* DMA source address */
946
dma_src = (reg[22] << 8) | reg[21];
947
948
/* Trigger DMA */
949
vdp_dma_update(Z80.cycles);
950
break;
951
}
952
953
default:
954
{
955
/* DMA from 68k bus does not work when Z80 is in control */
956
break;
957
}
958
}
959
}
960
}
961
}
962
return;
963
}
964
}
965
966
/* Master System & Game Gear VDP control port specific */
967
void vdp_sms_ctrl_w(unsigned int data)
968
{
969
if(pending == 0)
970
{
971
/* Update address register LSB */
972
addr = (addr & 0x3F00) | (data & 0xFF);
973
974
/* Latch LSB */
975
addr_latch = data;
976
977
/* Set LSB pending flag */
978
pending = 1;
979
}
980
else
981
{
982
/* Update address and code registers */
983
code = (data >> 6) & 3;
984
addr = (data << 8 | addr_latch) & 0x3FFF;
985
986
/* Clear pending flag */
987
pending = 0;
988
989
if (code == 0)
990
{
991
/* Process VRAM read */
992
fifo[0] = vram[addr & 0x3FFF];
993
994
/* Increment address register */
995
addr = (addr + 1) & 0x3FFF;
996
return;
997
}
998
999
if (code == 2)
1000
{
1001
/* Save current VDP mode */
1002
int mode, prev = (reg[0] & 0x06) | (reg[1] & 0x18);
1003
1004
/* Write VDP register 0-15 */
1005
vdp_reg_w(data & 0x0F, addr_latch, Z80.cycles);
1006
1007
/* Check VDP mode changes */
1008
mode = (reg[0] & 0x06) | (reg[1] & 0x18);
1009
prev ^= mode;
1010
1011
if (prev)
1012
{
1013
/* Check for extended modes */
1014
if (system_hw > SYSTEM_SMS)
1015
{
1016
int height;
1017
1018
if (mode == 0x0E) /* M1=0,M2=1,M3=1,M4=1 */
1019
{
1020
/* Mode 4 extended (240 lines) */
1021
height = 240;
1022
1023
/* Update vertical counter max value */
1024
vc_max = vc_table[3][vdp_pal];
1025
}
1026
else if (mode == 0x16) /* M1=1,M2=1,M3=0,M4=1 */
1027
{
1028
/* Mode 4 extended (224 lines) */
1029
height = 224;
1030
1031
/* Update vertical counter max value */
1032
vc_max = vc_table[1][vdp_pal];
1033
}
1034
else
1035
{
1036
/* Mode 4 default (224 lines) */
1037
height = 192;
1038
1039
/* Default vertical counter max value */
1040
vc_max = vc_table[0][vdp_pal];
1041
}
1042
1043
if (height != bitmap.viewport.h)
1044
{
1045
if (status & 8)
1046
{
1047
/* viewport changes should be applied on next frame */
1048
bitmap.viewport.changed |= 2;
1049
}
1050
else
1051
{
1052
/* update active display */
1053
bitmap.viewport.h = height;
1054
1055
/* update vertical overscan */
1056
if (config.overscan & 1)
1057
{
1058
bitmap.viewport.y = (240 + 48*vdp_pal - height) >> 1;
1059
}
1060
else
1061
{
1062
if ((system_hw == SYSTEM_GG) && !config.gg_extra)
1063
{
1064
/* Display area reduced to 160x144 */
1065
bitmap.viewport.y = (144 - height) / 2;
1066
}
1067
else
1068
{
1069
bitmap.viewport.y = 0;
1070
}
1071
}
1072
}
1073
}
1074
}
1075
1076
/* Rendering mode */
1077
switch (mode)
1078
{
1079
case 0x00: /* Graphics I */
1080
{
1081
render_bg = render_bg_m0;
1082
break;
1083
}
1084
1085
case 0x10: /* Text */
1086
{
1087
render_bg = render_bg_m1;
1088
break;
1089
}
1090
1091
case 0x02: /* Graphics II */
1092
{
1093
render_bg = render_bg_m2;
1094
break;
1095
}
1096
1097
case 0x12: /* Text (Extended PG) */
1098
{
1099
render_bg = render_bg_m1x;
1100
break;
1101
}
1102
1103
case 0x08: /* Multicolor */
1104
{
1105
render_bg = render_bg_m3;
1106
break;
1107
}
1108
1109
case 0x18: /* Invalid (1+3) */
1110
{
1111
render_bg = render_bg_inv;
1112
break;
1113
}
1114
1115
case 0x0A: /* Multicolor (Extended PG) */
1116
{
1117
render_bg = render_bg_m3x;
1118
break;
1119
}
1120
1121
case 0x1A: /* Invalid (1+2+3) */
1122
{
1123
render_bg = render_bg_inv;
1124
break;
1125
}
1126
1127
default: /* Mode 4 */
1128
{
1129
render_bg = render_bg_m4;
1130
break;
1131
}
1132
}
1133
1134
/* Mode switching */
1135
if (prev & 0x04)
1136
{
1137
int i;
1138
1139
if (mode & 0x04)
1140
{
1141
/* Mode 4 sprites */
1142
parse_satb = parse_satb_m4;
1143
render_obj = render_obj_m4;
1144
1145
/* force BG cache update*/
1146
bg_list_index = 0x200;
1147
}
1148
else
1149
{
1150
/* TMS-mode sprites */
1151
parse_satb = parse_satb_tms;
1152
render_obj = render_obj_tms;
1153
1154
/* BG cache is not used */
1155
bg_list_index = 0;
1156
}
1157
1158
/* reinitialize palette */
1159
for(i = 0; i < 0x20; i ++)
1160
{
1161
color_update_m4(i, *(uint16 *)&cram[i << 1]);
1162
}
1163
color_update_m4(0x40, *(uint16 *)&cram[(0x10 | (border & 0x0F)) << 1]);
1164
}
1165
}
1166
}
1167
}
1168
}
1169
1170
/* SG-1000 VDP (TMS99xx) control port specific */
1171
void vdp_tms_ctrl_w(unsigned int data)
1172
{
1173
if(pending == 0)
1174
{
1175
/* Latch LSB */
1176
addr_latch = data;
1177
1178
/* Set LSB pending flag */
1179
pending = 1;
1180
}
1181
else
1182
{
1183
/* Update address and code registers */
1184
code = (data >> 6) & 3;
1185
addr = (data << 8 | addr_latch) & 0x3FFF;
1186
1187
/* Clear pending flag */
1188
pending = 0;
1189
1190
if (code == 0)
1191
{
1192
/* Process VRAM read */
1193
fifo[0] = vram[addr & 0x3FFF];
1194
1195
/* Increment address register */
1196
addr = (addr + 1) & 0x3FFF;
1197
return;
1198
}
1199
1200
if (code & 2)
1201
{
1202
/* VDP register index (0-7) */
1203
data &= 0x07;
1204
1205
/* Write VDP register */
1206
vdp_reg_w(data, addr_latch, Z80.cycles);
1207
1208
/* Check VDP mode changes */
1209
if (data < 2)
1210
{
1211
int mode = (reg[0] & 0x02) | (reg[1] & 0x18);
1212
1213
/* Rendering mode */
1214
switch (mode)
1215
{
1216
case 0x00: /* Graphics I */
1217
{
1218
render_bg = render_bg_m0;
1219
break;
1220
}
1221
1222
case 0x10: /* Text */
1223
{
1224
render_bg = render_bg_m1;
1225
break;
1226
}
1227
1228
case 0x02: /* Graphics II */
1229
{
1230
render_bg = render_bg_m2;
1231
break;
1232
}
1233
1234
case 0x12: /* Text (Extended PG) */
1235
{
1236
render_bg = render_bg_m1x;
1237
break;
1238
}
1239
1240
case 0x08: /* Multicolor */
1241
{
1242
render_bg = render_bg_m3;
1243
break;
1244
}
1245
1246
case 0x18: /* Invalid (1+3) */
1247
{
1248
render_bg = render_bg_inv;
1249
break;
1250
}
1251
1252
case 0x0A: /* Multicolor (Extended PG) */
1253
{
1254
render_bg = render_bg_m3x;
1255
break;
1256
}
1257
1258
case 0x1A: /* Invalid (1+2+3) */
1259
{
1260
render_bg = render_bg_inv;
1261
break;
1262
}
1263
}
1264
}
1265
}
1266
}
1267
}
1268
1269
/*
1270
* Status register
1271
*
1272
* Bits
1273
* 0 NTSC(0)/PAL(1)
1274
* 1 DMA Busy
1275
* 2 During HBlank
1276
* 3 During VBlank
1277
* 4 0:1 even:odd field (interlaced modes only)
1278
* 5 Sprite collision
1279
* 6 Too many sprites per line
1280
* 7 v interrupt occurred
1281
* 8 Write FIFO full
1282
* 9 Write FIFO empty
1283
* 10 - 15 Open Bus
1284
*/
1285
unsigned int vdp_68k_ctrl_r(unsigned int cycles)
1286
{
1287
unsigned int temp;
1288
1289
/* Update FIFO status flags if not empty */
1290
if (fifo_write_cnt)
1291
{
1292
vdp_fifo_update(cycles);
1293
}
1294
1295
/* Check if DMA Busy flag is set */
1296
if (status & 2)
1297
{
1298
/* Check if DMA is finished */
1299
if (!dma_length && (cycles >= dma_endCycles))
1300
{
1301
/* Clear DMA Busy flag */
1302
status &= 0xFFFD;
1303
}
1304
}
1305
1306
/* Return VDP status */
1307
temp = status;
1308
1309
/* Clear pending flag */
1310
pending = 0;
1311
1312
/* Clear SOVR & SCOL flags */
1313
status &= 0xFF9F;
1314
1315
/* Display OFF: VBLANK flag is set */
1316
if (!(reg[1] & 0x40))
1317
{
1318
temp |= 0x08;
1319
}
1320
1321
/* HBLANK flag (Sonic 3 and Sonic 2 "VS Modes", Lemmings 2, Mega Turrican, V.R Troopers, Gouketsuji Ichizoku,...) */
1322
/* NB: this is not 100% accurate and need to be verified on real hardware */
1323
if ((cycles % MCYCLES_PER_LINE) < 588)
1324
{
1325
temp |= 0x04;
1326
}
1327
1328
#ifdef LOGVDP
1329
error("[%d(%d)][%d(%d)] VDP 68k status read -> 0x%x (0x%x) (%x)\n", v_counter, cycles/MCYCLES_PER_LINE-1, cycles, cycles%MCYCLES_PER_LINE, temp, status, m68k_get_reg(M68K_REG_PC));
1330
#endif
1331
return (temp);
1332
}
1333
1334
unsigned int vdp_z80_ctrl_r(unsigned int cycles)
1335
{
1336
unsigned int temp;
1337
1338
/* Cycle-accurate SOVR & VINT flags */
1339
int line = (lines_per_frame + (cycles / MCYCLES_PER_LINE) - 1) % lines_per_frame;
1340
1341
/* Check if DMA busy flag is set (Mega Drive VDP specific) */
1342
if (status & 2)
1343
{
1344
/* Check if DMA is finished */
1345
if (!dma_length && (cycles >= dma_endCycles))
1346
{
1347
/* Clear DMA Busy flag */
1348
status &= 0xFD;
1349
}
1350
}
1351
1352
/* Check if we are already on next line */
1353
if (line > v_counter)
1354
{
1355
v_counter = line;
1356
if (line == (bitmap.viewport.h + 1))
1357
{
1358
/* set VINT flag (immediately cleared after) */
1359
status |= 0x80;
1360
}
1361
else if ((line >= 0) && (line < bitmap.viewport.h) && !(work_ram[0x1ffb] & cart.special))
1362
{
1363
/* render next line to check sprites overflow & collision */
1364
render_line(line);
1365
}
1366
}
1367
1368
/* Return VDP status */
1369
temp = status;
1370
1371
/* Clear pending flag */
1372
pending = 0;
1373
1374
/* Clear VINT, SOVR & SCOL flags */
1375
status &= 0xFF1F;
1376
1377
/* Mega Drive VDP specific */
1378
if (system_hw & SYSTEM_MD)
1379
{
1380
/* Display OFF: VBLANK flag is set */
1381
if (!(reg[1] & 0x40))
1382
{
1383
temp |= 0x08;
1384
}
1385
1386
/* HBLANK flag */
1387
if ((cycles % MCYCLES_PER_LINE) < 588)
1388
{
1389
temp |= 0x04;
1390
}
1391
}
1392
else if (reg[0] & 0x04)
1393
{
1394
/* Mode 4 unused bits (fixes PGA Tour Golf) */
1395
temp |= 0x1F;
1396
}
1397
1398
/* Cycle-accurate SCOL flag */
1399
if ((temp & 0x20) && (line == (spr_col >> 8)))
1400
{
1401
if (system_hw & SYSTEM_MD)
1402
{
1403
/* COL flag is set at HCount 0xFF on MD */
1404
if ((cycles % MCYCLES_PER_LINE) < 105)
1405
{
1406
status |= 0x20;
1407
temp &= ~0x20;
1408
}
1409
}
1410
else
1411
{
1412
/* COL flag is set at the pixel it occurs */
1413
uint8 hc = hctab[(cycles + SMS_CYCLE_OFFSET + 15) % MCYCLES_PER_LINE];
1414
if ((hc < (spr_col & 0xff)) || (hc > 0xf3))
1415
{
1416
status |= 0x20;
1417
temp &= ~0x20;
1418
}
1419
}
1420
}
1421
1422
/* Clear HINT & VINT pending flags */
1423
hint_pending = vint_pending = 0;
1424
1425
/* Clear Z80 interrupt */
1426
Z80.irq_state = CLEAR_LINE;
1427
1428
#ifdef LOGVDP
1429
error("[%d(%d)][%d(%d)] VDP Z80 status read -> 0x%x (0x%x) (%x)\n", v_counter, cycles/MCYCLES_PER_LINE-1, cycles, cycles%MCYCLES_PER_LINE, temp, status, Z80.pc.w.l);
1430
#endif
1431
return (temp);
1432
}
1433
1434
/*--------------------------------------------------------------------------*/
1435
/* HV Counters */
1436
/*--------------------------------------------------------------------------*/
1437
1438
unsigned int vdp_hvc_r(unsigned int cycles)
1439
{
1440
int vc;
1441
unsigned int data = hvc_latch;
1442
1443
/* Check if HVC latch is enabled */
1444
if (data)
1445
{
1446
/* Mode 5: HV-counters are frozen (cf. lightgun games, Sunset Riders logo) */
1447
if (reg[1] & 0x04)
1448
{
1449
#ifdef LOGVDP
1450
error("[%d(%d)][%d(%d)] HVC latch read -> 0x%x (%x)\n", v_counter, (cycles/MCYCLES_PER_LINE-1)%lines_per_frame, cycles, cycles%MCYCLES_PER_LINE, data & 0xffff, m68k_get_reg(M68K_REG_PC));
1451
#endif
1452
/* return latched HVC value */
1453
return (data & 0xffff);
1454
}
1455
else
1456
{
1457
/* Mode 4: by default, V-counter runs normally & H counter is frozen */
1458
data &= 0xff;
1459
}
1460
}
1461
else
1462
{
1463
/* Cycle-accurate H-Counter (Striker, Mickey Mania, Skitchin, Road Rash I,II,III, Sonic 3D Blast...) */
1464
data = hctab[cycles % MCYCLES_PER_LINE];
1465
}
1466
1467
/* Cycle-accurate V-Counter (cycle counter starts from line -1) */
1468
vc = (cycles / MCYCLES_PER_LINE) - 1;
1469
1470
/* V-Counter overflow */
1471
if (vc > vc_max)
1472
{
1473
vc -= lines_per_frame;
1474
}
1475
1476
/* Interlaced modes */
1477
if (interlaced)
1478
{
1479
/* Interlace mode 2 (Sonic the Hedgehog 2, Combat Cars) */
1480
vc <<= im2_flag;
1481
1482
/* Replace bit 0 with bit 8 */
1483
vc = (vc & ~1) | ((vc >> 8) & 1);
1484
}
1485
1486
/* return H-Counter in LSB & V-Counter in MSB */
1487
data |= ((vc & 0xff) << 8);
1488
1489
#ifdef LOGVDP
1490
error("[%d(%d)][%d(%d)] HVC read -> 0x%x (%x)\n", v_counter, (cycles/MCYCLES_PER_LINE-1)%lines_per_frame, cycles, cycles%MCYCLES_PER_LINE, data, m68k_get_reg(M68K_REG_PC));
1491
#endif
1492
return (data);
1493
}
1494
1495
1496
/*--------------------------------------------------------------------------*/
1497
/* Test registers */
1498
/*--------------------------------------------------------------------------*/
1499
1500
void vdp_test_w(unsigned int data)
1501
{
1502
#ifdef LOGERROR
1503
error("Unused VDP Write 0x%x (%08x)\n", data, m68k_get_reg(M68K_REG_PC));
1504
#endif
1505
}
1506
1507
1508
/*--------------------------------------------------------------------------*/
1509
/* 68k interrupt handler (TODO: check how interrupts are handled in Mode 4) */
1510
/*--------------------------------------------------------------------------*/
1511
1512
int vdp_68k_irq_ack(int int_level)
1513
{
1514
#ifdef LOGVDP
1515
error("[%d(%d)][%d(%d)] INT Level %d ack (%x)\n", v_counter, m68k.cycles/MCYCLES_PER_LINE-1, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE,int_level, m68k_get_reg(M68K_REG_PC));
1516
#endif
1517
1518
/* VINT has higher priority (Fatal Rewind) */
1519
if (vint_pending & reg[1])
1520
{
1521
#ifdef LOGVDP
1522
error("---> VINT cleared\n");
1523
#endif
1524
1525
/* Clear VINT pending flag */
1526
vint_pending = 0;
1527
status &= ~0x80;
1528
1529
/* Update IRQ status */
1530
if (hint_pending & reg[0])
1531
{
1532
m68k_set_irq(4);
1533
}
1534
else
1535
{
1536
m68k_set_irq(0);
1537
}
1538
}
1539
else
1540
{
1541
#ifdef LOGVDP
1542
error("---> HINT cleared\n");
1543
#endif
1544
1545
/* Clear HINT pending flag */
1546
hint_pending = 0;
1547
1548
/* Update IRQ status */
1549
m68k_set_irq(0);
1550
}
1551
1552
return M68K_INT_ACK_AUTOVECTOR;
1553
}
1554
1555
1556
/*--------------------------------------------------------------------------*/
1557
/* VDP registers update function */
1558
/*--------------------------------------------------------------------------*/
1559
1560
static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles)
1561
{
1562
#ifdef LOGVDP
1563
error("[%d(%d)][%d(%d)] VDP register %d write -> 0x%x (%x)\n", v_counter, cycles/MCYCLES_PER_LINE-1, cycles, cycles%MCYCLES_PER_LINE, r, d, m68k_get_reg(M68K_REG_PC));
1564
#endif
1565
1566
/* VDP registers #11 to #23 cannot be updated in Mode 4 (Captain Planet & Avengers, Bass Master Classic Pro Edition) */
1567
if (!(reg[1] & 4) && (r > 10))
1568
{
1569
return;
1570
}
1571
1572
switch(r)
1573
{
1574
case 0: /* CTRL #1 */
1575
{
1576
/* Look for changed bits */
1577
r = d ^ reg[0];
1578
reg[0] = d;
1579
1580
/* Line Interrupt */
1581
if ((r & 0x10) && hint_pending)
1582
{
1583
/* Update IRQ status */
1584
if (vint_pending & reg[1])
1585
{
1586
set_irq_line(6);
1587
}
1588
else if (d & 0x10)
1589
{
1590
set_irq_line_delay(4);
1591
}
1592
else
1593
{
1594
set_irq_line(0);
1595
}
1596
}
1597
1598
/* Palette selection */
1599
if (r & 0x04)
1600
{
1601
/* Mega Drive VDP only */
1602
if (system_hw & SYSTEM_MD)
1603
{
1604
/* Reset color palette */
1605
int i;
1606
if (reg[1] & 0x04)
1607
{
1608
/* Mode 5 */
1609
color_update_m5(0x00, *(uint16 *)&cram[border << 1]);
1610
for (i = 1; i < 0x40; i++)
1611
{
1612
color_update_m5(i, *(uint16 *)&cram[i << 1]);
1613
}
1614
}
1615
else
1616
{
1617
/* Mode 4 */
1618
for (i = 0; i < 0x20; i++)
1619
{
1620
color_update_m4(i, *(uint16 *)&cram[i << 1]);
1621
}
1622
color_update_m4(0x40, *(uint16 *)&cram[(0x10 | (border & 0x0F)) << 1]);
1623
}
1624
}
1625
}
1626
1627
/* HVC latch (Sunset Riders, Lightgun games) */
1628
if (r & 0x02)
1629
{
1630
/* Mega Drive VDP only */
1631
if (system_hw & SYSTEM_MD)
1632
{
1633
/* Mode 5 only */
1634
if (reg[1] & 0x04)
1635
{
1636
if (d & 0x02)
1637
{
1638
/* Latch current HVC */
1639
hvc_latch = vdp_hvc_r(cycles) | 0x10000;
1640
}
1641
else
1642
{
1643
/* Free-running HVC */
1644
hvc_latch = 0;
1645
}
1646
}
1647
}
1648
}
1649
break;
1650
}
1651
1652
case 1: /* CTRL #2 */
1653
{
1654
/* Look for changed bits */
1655
r = d ^ reg[1];
1656
reg[1] = d;
1657
1658
/* Display status (modified during active display) */
1659
if ((r & 0x40) && (v_counter < bitmap.viewport.h))
1660
{
1661
/* Cycle offset vs HBLANK */
1662
int offset = cycles - mcycles_vdp;
1663
if (offset <= 860)
1664
{
1665
/* Sprite rendering is limited if display was disabled during HBLANK (Mickey Mania 3d level, Overdrive Demo) */
1666
if (d & 0x40)
1667
{
1668
/* NB: This is not 100% accurate. On real hardware, the maximal number of rendered sprites pixels */
1669
/* for the current line (normally 256 or 320 pixels) but also the maximal number of pre-processed */
1670
/* sprites for the next line (normally 64 or 80 sprites) are both reduced depending on the amount */
1671
/* of cycles spent with display disabled. Here we only reduce them by a fixed amount when display */
1672
/* has been reenabled after a specific point within HBLANK. */
1673
if (offset > 360)
1674
{
1675
max_sprite_pixels = 128;
1676
}
1677
}
1678
1679
/* Redraw entire line (Legend of Galahad, Lemmings 2, Formula One, Kawasaki Super Bike, Deadly Moves,...) */
1680
render_line(v_counter);
1681
1682
/* Restore default */
1683
max_sprite_pixels = 256 + ((reg[12] & 1) << 6);
1684
}
1685
else if (system_hw & SYSTEM_MD)
1686
{
1687
/* Active pixel offset */
1688
if (reg[12] & 1)
1689
{
1690
/* dot clock = MCLK / 8 */
1691
offset = ((offset - 860) / 8) + 16;
1692
}
1693
else
1694
{
1695
/* dot clock = MCLK / 10 */
1696
offset = ((offset - 860) / 10) + 16;
1697
}
1698
1699
/* Line is partially blanked (Nigel Mansell's World Championship Racing , Ren & Stimpy Show, ...) */
1700
if (offset < bitmap.viewport.w)
1701
{
1702
if (d & 0x40)
1703
{
1704
render_line(v_counter);
1705
blank_line(v_counter, 0, offset);
1706
}
1707
else
1708
{
1709
blank_line(v_counter, offset, bitmap.viewport.w - offset);
1710
}
1711
}
1712
}
1713
}
1714
1715
/* Frame Interrupt */
1716
if ((r & 0x20) && vint_pending)
1717
{
1718
/* Update IRQ status */
1719
if (d & 0x20)
1720
{
1721
set_irq_line_delay(6);
1722
}
1723
else if (hint_pending & reg[0])
1724
{
1725
set_irq_line(4);
1726
}
1727
else
1728
{
1729
set_irq_line(0);
1730
}
1731
}
1732
1733
/* Active display height */
1734
if (r & 0x08)
1735
{
1736
/* Mega Drive VDP only */
1737
if (system_hw & SYSTEM_MD)
1738
{
1739
/* Mode 5 only */
1740
if (d & 0x04)
1741
{
1742
/* Changes should be applied on next frame */
1743
bitmap.viewport.changed |= 2;
1744
1745
/* Update vertical counter max value */
1746
vc_max = vc_table[(d >> 2) & 3][vdp_pal];
1747
}
1748
}
1749
}
1750
1751
/* Rendering mode */
1752
if (r & 0x04)
1753
{
1754
/* Mega Drive VDP only */
1755
if (system_hw & SYSTEM_MD)
1756
{
1757
int i;
1758
if (d & 0x04)
1759
{
1760
/* Mode 5 rendering */
1761
parse_satb = parse_satb_m5;
1762
update_bg_pattern_cache = update_bg_pattern_cache_m5;
1763
if (im2_flag)
1764
{
1765
render_bg = (reg[11] & 0x04) ? render_bg_m5_im2_vs : render_bg_m5_im2;
1766
render_obj = (reg[12] & 0x08) ? render_obj_m5_im2_ste : render_obj_m5_im2;
1767
}
1768
else
1769
{
1770
render_bg = (reg[11] & 0x04) ? render_bg_m5_vs : render_bg_m5;
1771
render_obj = (reg[12] & 0x08) ? render_obj_m5_ste : render_obj_m5;
1772
}
1773
1774
/* Reset color palette */
1775
color_update_m5(0x00, *(uint16 *)&cram[border << 1]);
1776
for (i = 1; i < 0x40; i++)
1777
{
1778
color_update_m5(i, *(uint16 *)&cram[i << 1]);
1779
}
1780
1781
/* Mode 5 bus access */
1782
vdp_68k_data_w = vdp_68k_data_w_m5;
1783
vdp_z80_data_w = vdp_z80_data_w_m5;
1784
vdp_68k_data_r = vdp_68k_data_r_m5;
1785
vdp_z80_data_r = vdp_z80_data_r_m5;
1786
1787
/* Change display height */
1788
if (status & 8)
1789
{
1790
/* viewport changes should be applied on next frame */
1791
bitmap.viewport.changed |= 2;
1792
}
1793
else
1794
{
1795
/* Update current frame active display height */
1796
bitmap.viewport.h = 224 + ((d & 8) << 1);
1797
bitmap.viewport.y = (config.overscan & 1) * (8 - (d & 8) + 24*vdp_pal);
1798
}
1799
1800
/* Clear HVC latched value */
1801
hvc_latch = 0;
1802
1803
/* Check if HVC latch bit is set */
1804
if (reg[0] & 0x02)
1805
{
1806
/* Latch current HVC */
1807
hvc_latch = vdp_hvc_r(cycles) | 0x10000;
1808
}
1809
1810
/* max tiles to invalidate */
1811
bg_list_index = 0x800;
1812
}
1813
else
1814
{
1815
/* Mode 4 rendering */
1816
parse_satb = parse_satb_m4;
1817
update_bg_pattern_cache = update_bg_pattern_cache_m4;
1818
render_bg = render_bg_m4;
1819
render_obj = render_obj_m4;
1820
1821
/* Reset color palette */
1822
for (i = 0; i < 0x20; i++)
1823
{
1824
color_update_m4(i, *(uint16 *)&cram[i << 1]);
1825
}
1826
color_update_m4(0x40, *(uint16 *)&cram[(0x10 | (border & 0x0F)) << 1]);
1827
1828
/* Mode 4 bus access */
1829
vdp_68k_data_w = vdp_68k_data_w_m4;
1830
vdp_z80_data_w = vdp_z80_data_w_m4;
1831
vdp_68k_data_r = vdp_68k_data_r_m4;
1832
vdp_z80_data_r = vdp_z80_data_r_m4;
1833
1834
if (status & 8)
1835
{
1836
/* viewport changes should be applied on next frame */
1837
bitmap.viewport.changed |= 2;
1838
}
1839
else
1840
{
1841
/* Update current frame active display */
1842
bitmap.viewport.h = 192;
1843
bitmap.viewport.y = (config.overscan & 1) * 24 * (vdp_pal + 1);
1844
}
1845
1846
/* Latch current HVC */
1847
hvc_latch = vdp_hvc_r(cycles) | 0x10000;
1848
1849
/* max tiles to invalidate */
1850
bg_list_index = 0x200;
1851
}
1852
1853
/* Invalidate pattern cache */
1854
for (i=0;i<bg_list_index;i++)
1855
{
1856
bg_name_list[i] = i;
1857
bg_name_dirty[i] = 0xFF;
1858
}
1859
1860
/* Update vertical counter max value */
1861
vc_max = vc_table[(d >> 2) & 3][vdp_pal];
1862
}
1863
else
1864
{
1865
/* No effect (cleared to avoid mode 5 detection elsewhere) */
1866
reg[1] &= ~0x04;
1867
}
1868
}
1869
break;
1870
}
1871
1872
case 2: /* Plane A Name Table Base */
1873
{
1874
reg[2] = d;
1875
ntab = (d << 10) & 0xE000;
1876
1877
/* Plane A Name Table Base changed during HBLANK */
1878
if ((v_counter < bitmap.viewport.h) && (reg[1] & 0x40) && (cycles <= (mcycles_vdp + 860)))
1879
{
1880
/* render entire line */
1881
render_line(v_counter);
1882
}
1883
break;
1884
}
1885
1886
case 3: /* Window Plane Name Table Base */
1887
{
1888
reg[3] = d;
1889
if (reg[12] & 0x01)
1890
{
1891
ntwb = (d << 10) & 0xF000;
1892
}
1893
else
1894
{
1895
ntwb = (d << 10) & 0xF800;
1896
}
1897
1898
/* Window Plane Name Table Base changed during HBLANK */
1899
if ((v_counter < bitmap.viewport.h) && (reg[1] & 0x40) && (cycles <= (mcycles_vdp + 860)))
1900
{
1901
/* render entire line */
1902
render_line(v_counter);
1903
}
1904
break;
1905
}
1906
1907
case 4: /* Plane B Name Table Base */
1908
{
1909
reg[4] = d;
1910
ntbb = (d << 13) & 0xE000;
1911
1912
/* Plane B Name Table Base changed during HBLANK (Adventures of Batman & Robin) */
1913
if ((v_counter < bitmap.viewport.h) && (reg[1] & 0x40) && (cycles <= (mcycles_vdp + 860)))
1914
{
1915
/* render entire line */
1916
render_line(v_counter);
1917
}
1918
1919
break;
1920
}
1921
1922
case 5: /* Sprite Attribute Table Base */
1923
{
1924
reg[5] = d;
1925
satb = (d << 9) & sat_base_mask;
1926
break;
1927
}
1928
1929
case 7: /* Backdrop color */
1930
{
1931
reg[7] = d;
1932
1933
/* Check if backdrop color changed */
1934
d &= 0x3F;
1935
1936
if (d != border)
1937
{
1938
/* Update backdrop color */
1939
border = d;
1940
1941
/* Reset palette entry */
1942
if (reg[1] & 4)
1943
{
1944
/* Mode 5 */
1945
color_update_m5(0x00, *(uint16 *)&cram[d << 1]);
1946
}
1947
else
1948
{
1949
/* Mode 4 */
1950
color_update_m4(0x40, *(uint16 *)&cram[(0x10 | (d & 0x0F)) << 1]);
1951
}
1952
1953
/* Backdrop color modified during HBLANK (Road Rash 1,2,3)*/
1954
if ((v_counter < bitmap.viewport.h) && (cycles <= (mcycles_vdp + 860)))
1955
{
1956
/* remap entire line */
1957
remap_line(v_counter);
1958
}
1959
}
1960
break;
1961
}
1962
1963
case 8: /* Horizontal Scroll (Mode 4 only) */
1964
{
1965
int line;
1966
1967
/* Hscroll is latched at HCount 0xF3, HCount 0xF6 on MD */
1968
/* Line starts at HCount 0xF4, HCount 0xF6 on MD */
1969
if (system_hw < SYSTEM_MD)
1970
{
1971
cycles = cycles + 15;
1972
}
1973
1974
/* Make sure Hscroll has not already been latched */
1975
line = (lines_per_frame + (cycles / MCYCLES_PER_LINE) - 1) % lines_per_frame;
1976
if ((line > v_counter) && (line < bitmap.viewport.h) && !(work_ram[0x1ffb] & cart.special))
1977
{
1978
v_counter = line;
1979
render_line(line);
1980
}
1981
1982
reg[8] = d;
1983
break;
1984
}
1985
1986
case 11: /* CTRL #3 */
1987
{
1988
reg[11] = d;
1989
1990
/* Horizontal scrolling mode */
1991
hscroll_mask = hscroll_mask_table[d & 0x03];
1992
1993
/* Vertical Scrolling mode */
1994
if (d & 0x04)
1995
{
1996
render_bg = im2_flag ? render_bg_m5_im2_vs : render_bg_m5_vs;
1997
}
1998
else
1999
{
2000
render_bg = im2_flag ? render_bg_m5_im2 : render_bg_m5;
2001
}
2002
break;
2003
}
2004
2005
case 12: /* CTRL #4 */
2006
{
2007
/* Look for changed bits */
2008
r = d ^ reg[12];
2009
reg[12] = d;
2010
2011
/* Shadow & Highlight mode */
2012
if (r & 0x08)
2013
{
2014
/* Reset color palette */
2015
int i;
2016
color_update_m5(0x00, *(uint16 *)&cram[border << 1]);
2017
for (i = 1; i < 0x40; i++)
2018
{
2019
color_update_m5(i, *(uint16 *)&cram[i << 1]);
2020
}
2021
2022
/* Update sprite rendering function */
2023
if (d & 0x08)
2024
{
2025
render_obj = im2_flag ? render_obj_m5_im2_ste : render_obj_m5_ste;
2026
}
2027
else
2028
{
2029
render_obj = im2_flag ? render_obj_m5_im2 : render_obj_m5;
2030
}
2031
}
2032
2033
/* Interlaced modes */
2034
if (r & 0x06)
2035
{
2036
/* changes should be applied on next frame */
2037
bitmap.viewport.changed |= 2;
2038
}
2039
2040
/* Active display width */
2041
if (r & 0x01)
2042
{
2043
if (d & 0x01)
2044
{
2045
/* Update display-dependant registers */
2046
ntwb = (reg[3] << 10) & 0xF000;
2047
satb = (reg[5] << 9) & 0xFC00;
2048
sat_base_mask = 0xFC00;
2049
sat_addr_mask = 0x03FF;
2050
2051
/* Update HC table */
2052
hctab = cycle2hc40;
2053
2054
/* Update clipping */
2055
window_clip(reg[17], 1);
2056
2057
/* Max. sprite pixels per line */
2058
max_sprite_pixels = 320;
2059
}
2060
else
2061
{
2062
/* Update display-dependant registers */
2063
ntwb = (reg[3] << 10) & 0xF800;
2064
satb = (reg[5] << 9) & 0xFE00;
2065
sat_base_mask = 0xFE00;
2066
sat_addr_mask = 0x01FF;
2067
2068
/* Update HC table */
2069
hctab = cycle2hc32;
2070
2071
/* Update clipping */
2072
window_clip(reg[17], 0);
2073
2074
/* Max. sprite pixels per line */
2075
max_sprite_pixels = 256;
2076
}
2077
2078
/* Active display width modified during HBLANK (Bugs Bunny Double Trouble) */
2079
if ((v_counter < bitmap.viewport.h) && (cycles <= (mcycles_vdp + 860)))
2080
{
2081
/* Update active display width */
2082
bitmap.viewport.w = 256 + ((d & 1) << 6);
2083
2084
/* Redraw entire line */
2085
render_line(v_counter);
2086
}
2087
else if (v_counter == (lines_per_frame - 1))
2088
{
2089
/* Update starting frame active display width */
2090
bitmap.viewport.w = 256 + ((d & 1) << 6);
2091
}
2092
else
2093
{
2094
/* Changes should be applied on next frame (Golden Axe III intro) */
2095
/* NB: not 100% accurate but required since backend framebuffer width cannot be modified mid-frame. */
2096
/* This would require a fixed framebuffer width (based on TV screen aspect ratio) and pixel scaling */
2097
/* to be done during rendering (depending on active display pixel aspect ratio in H32 or H40 mode). */
2098
/* Display is generally disabled when this is modified so it shouldn't be really noticeable anyway. */
2099
bitmap.viewport.changed |= 2;
2100
}
2101
}
2102
break;
2103
}
2104
2105
case 13: /* HScroll Base Address */
2106
{
2107
reg[13] = d;
2108
hscb = (d << 10) & 0xFC00;
2109
break;
2110
}
2111
2112
case 16: /* Playfield size */
2113
{
2114
reg[16] = d;
2115
playfield_shift = shift_table[(d & 3)];
2116
playfield_col_mask = col_mask_table[(d & 3)];
2117
playfield_row_mask = row_mask_table[(d >> 4) & 3];
2118
break;
2119
}
2120
2121
case 17: /* Window/Plane A vertical clipping */
2122
{
2123
reg[17] = d;
2124
window_clip(d, reg[12] & 1);
2125
break;
2126
}
2127
2128
default:
2129
{
2130
reg[r] = d;
2131
break;
2132
}
2133
}
2134
}
2135
2136
/*--------------------------------------------------------------------------*/
2137
/* FIFO emulation (Mega Drive VDP specific) */
2138
/* ---------------------------------------- */
2139
/* */
2140
/* CPU access to VRAM, CRAM & VSRAM is limited during active display: */
2141
/* H32 mode -> 16 access per line */
2142
/* H40 mode -> 18 access per line */
2143
/* */
2144
/* with fixed access slots timings detailled below. */
2145
/* */
2146
/* Each VRAM access is byte wide, so one VRAM write (word) need two slots. */
2147
/* */
2148
/*--------------------------------------------------------------------------*/
2149
2150
static void vdp_fifo_update(unsigned int cycles)
2151
{
2152
int slots, count = 0;
2153
2154
const int *fifo_timing;
2155
2156
const int fifo_cycles_h32[16+2] =
2157
{
2158
230, 510, 810, 970, 1130, 1450, 1610, 1770, 2090, 2250, 2410, 2730, 2890, 3050, 3350, 3370,
2159
MCYCLES_PER_LINE + 230, MCYCLES_PER_LINE + 510
2160
};
2161
2162
const int fifo_cycles_h40[18+2] =
2163
{
2164
352, 820, 948, 1076, 1332, 1460, 1588, 1844, 1972, 2100, 2356, 2484, 2612, 2868, 2996, 3124, 3364, 3380,
2165
MCYCLES_PER_LINE + 352, MCYCLES_PER_LINE + 820
2166
};
2167
2168
2169
/* number of access slots up to current line */
2170
if (reg[12] & 0x01)
2171
{
2172
fifo_timing = fifo_cycles_h40;
2173
slots = 18 * (cycles / MCYCLES_PER_LINE);
2174
}
2175
else
2176
{
2177
fifo_timing = fifo_cycles_h32;
2178
slots = 16 * (cycles / MCYCLES_PER_LINE);
2179
}
2180
2181
/* number of access slots within current line */
2182
cycles = cycles % MCYCLES_PER_LINE;
2183
while (fifo_timing[count] <= cycles)
2184
{
2185
count++;
2186
}
2187
2188
/* number of processed FIFO entries since last access */
2189
slots = (slots + count - fifo_slots) >> fifo_byte_access;
2190
2191
if (slots > 0)
2192
{
2193
/* process FIFO entries */
2194
fifo_write_cnt -= slots;
2195
2196
/* Clear FIFO full flag */
2197
status &= 0xFEFF;
2198
2199
if (fifo_write_cnt <= 0)
2200
{
2201
/* No more FIFO entries */
2202
fifo_write_cnt = 0;
2203
2204
/* Set FIFO empty flag */
2205
status |= 0x200;
2206
}
2207
2208
/* Update FIFO access slot counter */
2209
fifo_slots += (slots << fifo_byte_access);
2210
}
2211
2212
/* next FIFO update cycle */
2213
fifo_cycles = mcycles_vdp + fifo_timing[count | fifo_byte_access];
2214
}
2215
2216
2217
/*--------------------------------------------------------------------------*/
2218
/* Internal 16-bit data bus access function (Mode 5 only) */
2219
/*--------------------------------------------------------------------------*/
2220
static void vdp_bus_w(unsigned int data)
2221
{
2222
/* write data to next FIFO entry */
2223
fifo[fifo_idx] = data;
2224
2225
/* increment FIFO write pointer */
2226
fifo_idx = (fifo_idx + 1) & 3;
2227
2228
/* Check destination code (CD0-CD3) */
2229
switch (code & 0x0F)
2230
{
2231
case 0x01: /* VRAM */
2232
{
2233
/* VRAM address */
2234
int index = addr & 0xFFFE;
2235
2236
/* Pointer to VRAM */
2237
uint16 *p = (uint16 *)&vram[index];
2238
2239
/* Byte-swap data if A0 is set */
2240
if (addr & 1)
2241
{
2242
data = ((data >> 8) | (data << 8)) & 0xFFFF;
2243
}
2244
2245
/* Intercept writes to Sprite Attribute Table */
2246
if ((index & sat_base_mask) == satb)
2247
{
2248
/* Update internal SAT */
2249
*(uint16 *) &sat[index & sat_addr_mask] = data;
2250
}
2251
2252
/* Only write unique data to VRAM */
2253
if (data != *p)
2254
{
2255
int name;
2256
2257
/* Write data to VRAM */
2258
*p = data;
2259
2260
/* Update pattern cache */
2261
MARK_BG_DIRTY (index);
2262
}
2263
2264
#ifdef LOGVDP
2265
error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, m68k.cycles/MCYCLES_PER_LINE-1, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
2266
#endif
2267
break;
2268
}
2269
2270
case 0x03: /* CRAM */
2271
{
2272
/* Pointer to CRAM 9-bit word */
2273
uint16 *p = (uint16 *)&cram[addr & 0x7E];
2274
2275
/* Pack 16-bit bus data (BBB0GGG0RRR0) to 9-bit CRAM data (BBBGGGRRR) */
2276
data = ((data & 0xE00) >> 3) | ((data & 0x0E0) >> 2) | ((data & 0x00E) >> 1);
2277
2278
/* Check if CRAM data is being modified */
2279
if (data != *p)
2280
{
2281
/* CRAM index (64 words) */
2282
int index = (addr >> 1) & 0x3F;
2283
2284
/* Write CRAM data */
2285
*p = data;
2286
2287
/* Color entry 0 of each palette is never displayed (transparent pixel) */
2288
if (index & 0x0F)
2289
{
2290
/* Update color palette */
2291
color_update_m5(index, data);
2292
}
2293
2294
/* Update backdrop color */
2295
if (index == border)
2296
{
2297
color_update_m5(0x00, data);
2298
}
2299
2300
/* CRAM modified during HBLANK (Striker, Zero the Kamikaze, etc) */
2301
if ((v_counter < bitmap.viewport.h) && (reg[1]& 0x40) && (m68k.cycles <= (mcycles_vdp + 860)))
2302
{
2303
/* Remap current line */
2304
remap_line(v_counter);
2305
}
2306
}
2307
#ifdef LOGVDP
2308
error("[%d(%d)][%d(%d)] CRAM 0x%x write -> 0x%x (%x)\n", v_counter, m68k.cycles/MCYCLES_PER_LINE-1, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
2309
#endif
2310
break;
2311
}
2312
2313
case 0x05: /* VSRAM */
2314
{
2315
*(uint16 *)&vsram[addr & 0x7E] = data;
2316
2317
/* 2-cell Vscroll mode */
2318
if (reg[11] & 0x04)
2319
{
2320
/* VSRAM writes during HBLANK (Adventures of Batman & Robin) */
2321
if ((v_counter < bitmap.viewport.h) && (reg[1] & 0x40) && (m68k.cycles <= (mcycles_vdp + 860)))
2322
{
2323
/* Remap current line */
2324
render_line(v_counter);
2325
}
2326
}
2327
#ifdef LOGVDP
2328
error("[%d(%d)][%d(%d)] VSRAM 0x%x write -> 0x%x (%x)\n", v_counter, m68k.cycles/MCYCLES_PER_LINE-1, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
2329
#endif
2330
break;
2331
}
2332
2333
default:
2334
{
2335
/* add some delay until 68k periodical wait-states are accurately emulated ("Clue", "Microcosm") */
2336
m68k.cycles += 2;
2337
#ifdef LOGERROR
2338
error("[%d(%d)][%d(%d)] Invalid (%d) 0x%x write -> 0x%x (%x)\n", v_counter, m68k.cycles/MCYCLES_PER_LINE-1, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE, code, addr, data, m68k_get_reg(M68K_REG_PC));
2339
#endif
2340
break;
2341
}
2342
}
2343
2344
/* Increment address register */
2345
addr += reg[15];
2346
}
2347
2348
2349
/*--------------------------------------------------------------------------*/
2350
/* 68k bus interface (Mega Drive VDP only) */
2351
/*--------------------------------------------------------------------------*/
2352
2353
static void vdp_68k_data_w_m4(unsigned int data)
2354
{
2355
/* Clear pending flag */
2356
pending = 0;
2357
2358
/* Restricted VDP writes during active display */
2359
if (!(status & 8) && (reg[1] & 0x40))
2360
{
2361
/* Update VDP FIFO */
2362
vdp_fifo_update(m68k.cycles);
2363
2364
/* Clear FIFO empty flag */
2365
status &= 0xFDFF;
2366
2367
/* up to 4 words can be stored */
2368
if (fifo_write_cnt < 4)
2369
{
2370
/* Increment FIFO counter */
2371
fifo_write_cnt++;
2372
2373
/* Set FIFO full flag if 4 words are stored */
2374
status |= ((fifo_write_cnt & 4) << 6);
2375
}
2376
else
2377
{
2378
/* CPU is halted until next FIFO entry processing */
2379
m68k.cycles = fifo_cycles;
2380
2381
/* Update FIFO access slot counter */
2382
fifo_slots = fifo_slots + 1 + fifo_byte_access;
2383
}
2384
}
2385
2386
/* Check destination code */
2387
if (code & 0x02)
2388
{
2389
/* CRAM index (32 words) */
2390
int index = addr & 0x1F;
2391
2392
/* Pointer to CRAM 9-bit word */
2393
uint16 *p = (uint16 *)&cram[index << 1];
2394
2395
/* Pack 16-bit data (xxx000BBGGRR) to 9-bit CRAM data (xxxBBGGRR) */
2396
data = ((data & 0xE00) >> 3) | (data & 0x3F);
2397
2398
/* Check if CRAM data is being modified */
2399
if (data != *p)
2400
{
2401
/* Write CRAM data */
2402
*p = data;
2403
2404
/* Update color palette */
2405
color_update_m4(index, data);
2406
2407
/* Update backdrop color */
2408
if (index == (0x10 | (border & 0x0F)))
2409
{
2410
color_update_m4(0x40, data);
2411
}
2412
}
2413
}
2414
else
2415
{
2416
/* VRAM address (interleaved format) */
2417
int index = ((addr << 1) & 0x3FC) | ((addr & 0x200) >> 8) | (addr & 0x3C00);
2418
2419
/* Pointer to VRAM */
2420
uint16 *p = (uint16 *)&vram[index];
2421
2422
/* Byte-swap data if A0 is set */
2423
if (addr & 1)
2424
{
2425
data = ((data >> 8) | (data << 8)) & 0xFFFF;
2426
}
2427
2428
/* Only write unique data to VRAM */
2429
if (data != *p)
2430
{
2431
int name;
2432
2433
/* Write data to VRAM */
2434
*p = data;
2435
2436
/* Update the pattern cache */
2437
MARK_BG_DIRTY (index);
2438
}
2439
}
2440
2441
/* Increment address register (TODO: check how address is incremented in Mode 4) */
2442
addr += (reg[15] + 1);
2443
}
2444
2445
static void vdp_68k_data_w_m5(unsigned int data)
2446
{
2447
/* Clear pending flag */
2448
pending = 0;
2449
2450
/* Restricted VDP writes during active display */
2451
if (!(status & 8) && (reg[1] & 0x40))
2452
{
2453
/* Update VDP FIFO */
2454
vdp_fifo_update(m68k.cycles);
2455
2456
/* Clear FIFO empty flag */
2457
status &= 0xFDFF;
2458
2459
/* up to 4 words can be stored */
2460
if (fifo_write_cnt < 4)
2461
{
2462
/* Increment FIFO counter */
2463
fifo_write_cnt++;
2464
2465
/* Set FIFO full flag if 4 words are stored */
2466
status |= ((fifo_write_cnt & 4) << 6);
2467
}
2468
else
2469
{
2470
/* CPU is halted until next FIFO entry processing (Chaos Engine / Soldiers of Fortune, Double Clutch, Titan Overdrive Demo) */
2471
m68k.cycles = fifo_cycles;
2472
2473
/* Update FIFO access slot counter */
2474
fifo_slots += (1 + fifo_byte_access);
2475
}
2476
}
2477
2478
/* Write data */
2479
vdp_bus_w(data);
2480
2481
/* Check if DMA Fill is pending */
2482
if (dmafill)
2483
{
2484
/* Clear DMA Fill pending flag */
2485
dmafill = 0;
2486
2487
/* DMA length */
2488
dma_length = (reg[20] << 8) | reg[19];
2489
2490
/* Zero DMA length (pre-decrementing counter) */
2491
if (!dma_length)
2492
{
2493
dma_length = 0x10000;
2494
}
2495
2496
/* Trigger DMA */
2497
vdp_dma_update(m68k.cycles);
2498
}
2499
}
2500
2501
static unsigned int vdp_68k_data_r_m4(void)
2502
{
2503
/* VRAM address (interleaved format) */
2504
int index = ((addr << 1) & 0x3FC) | ((addr & 0x200) >> 8) | (addr & 0x3C00);
2505
2506
/* Clear pending flag */
2507
pending = 0;
2508
2509
/* Increment address register (TODO: check how address is incremented in Mode 4) */
2510
addr += (reg[15] + 1);
2511
2512
/* Read VRAM data */
2513
return *(uint16 *) &vram[index];
2514
}
2515
2516
static unsigned int vdp_68k_data_r_m5(void)
2517
{
2518
uint16 data = 0;
2519
2520
/* Clear pending flag */
2521
pending = 0;
2522
2523
/* Check destination code (CD0-CD3) & CD4 */
2524
switch (code & 0x1F)
2525
{
2526
case 0x00:
2527
{
2528
/* read two bytes from VRAM */
2529
data = *(uint16 *)&vram[addr & 0xFFFE];
2530
2531
#ifdef LOGVDP
2532
error("[%d(%d)][%d(%d)] VRAM 0x%x read -> 0x%x (%x)\n", v_counter, m68k.cycles/MCYCLES_PER_LINE-1, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
2533
#endif
2534
break;
2535
}
2536
2537
case 0x04:
2538
{
2539
/* VSRAM index */
2540
int index = addr & 0x7E;
2541
2542
/* Check against VSRAM max size (80 x 11-bits) */
2543
if (index >= 0x50)
2544
{
2545
/* Wrap to address 0 (TODO: check if still true with Genesis 3 model) */
2546
index = 0;
2547
}
2548
2549
/* Read 11-bit word from VSRAM */
2550
data = *(uint16 *)&vsram[index] & 0x7FF;
2551
2552
/* Unused bits are set using data from next available FIFO entry */
2553
data |= (fifo[fifo_idx] & ~0x7FF);
2554
2555
#ifdef LOGVDP
2556
error("[%d(%d)][%d(%d)] VSRAM 0x%x read -> 0x%x (%x)\n", v_counter, m68k.cycles/MCYCLES_PER_LINE-1, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
2557
#endif
2558
break;
2559
}
2560
2561
case 0x08:
2562
{
2563
/* Read 9-bit word from CRAM */
2564
data = *(uint16 *)&cram[addr & 0x7E];
2565
2566
/* Unpack 9-bit CRAM data (BBBGGGRRR) to 16-bit bus data (BBB0GGG0RRR0) */
2567
data = ((data & 0x1C0) << 3) | ((data & 0x038) << 2) | ((data & 0x007) << 1);
2568
2569
/* Unused bits are set using data from next available FIFO entry */
2570
data |= (fifo[fifo_idx] & ~0xEEE);
2571
2572
#ifdef LOGVDP
2573
error("[%d(%d)][%d(%d)] CRAM 0x%x read -> 0x%x (%x)\n", v_counter, m68k.cycles/MCYCLES_PER_LINE-1, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
2574
#endif
2575
break;
2576
}
2577
2578
case 0x0c: /* undocumented 8-bit VRAM read */
2579
{
2580
/* Read one byte from VRAM adjacent address */
2581
data = READ_BYTE(vram, addr ^ 1);
2582
2583
/* Unused bits are set using data from next available FIFO entry */
2584
data |= (fifo[fifo_idx] & ~0xFF);
2585
2586
#ifdef LOGVDP
2587
error("[%d(%d)][%d(%d)] 8-bit VRAM 0x%x read -> 0x%x (%x)\n", v_counter, m68k.cycles/MCYCLES_PER_LINE-1, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE, addr, data, m68k_get_reg(M68K_REG_PC));
2588
#endif
2589
break;
2590
}
2591
2592
default:
2593
{
2594
/* Invalid code value (normally locks VDP, hard reset required) */
2595
#ifdef LOGERROR
2596
error("[%d(%d)][%d(%d)] Invalid (%d) 0x%x read (%x)\n", v_counter, m68k.cycles/MCYCLES_PER_LINE-1, m68k.cycles, m68k.cycles%MCYCLES_PER_LINE, code, addr, m68k_get_reg(M68K_REG_PC));
2597
#endif
2598
break;
2599
}
2600
}
2601
2602
/* Increment address register */
2603
addr += reg[15];
2604
2605
/* Return data */
2606
return data;
2607
}
2608
2609
2610
/*--------------------------------------------------------------------------*/
2611
/* Z80 bus interface (Mega Drive VDP in Master System compatibility mode) */
2612
/*--------------------------------------------------------------------------*/
2613
2614
static void vdp_z80_data_w_m4(unsigned int data)
2615
{
2616
/* Clear pending flag */
2617
pending = 0;
2618
2619
/* Check destination code */
2620
if (code & 0x02)
2621
{
2622
/* CRAM index (32 words) */
2623
int index = addr & 0x1F;
2624
2625
/* Pointer to CRAM word */
2626
uint16 *p = (uint16 *)&cram[index << 1];
2627
2628
/* Check if CRAM data is being modified */
2629
if (data != *p)
2630
{
2631
/* Write CRAM data */
2632
*p = data;
2633
2634
/* Update color palette */
2635
color_update_m4(index, data);
2636
2637
/* Update backdrop color */
2638
if (index == (0x10 | (border & 0x0F)))
2639
{
2640
color_update_m4(0x40, data);
2641
}
2642
}
2643
}
2644
else
2645
{
2646
/* VRAM address */
2647
int index = addr & 0x3FFF;
2648
2649
/* Only write unique data to VRAM */
2650
if (data != vram[index])
2651
{
2652
int name;
2653
2654
/* Write data */
2655
vram[index] = data;
2656
2657
/* Update pattern cache */
2658
MARK_BG_DIRTY(index);
2659
}
2660
}
2661
2662
/* Increment address register (TODO: check how address is incremented in Mode 4) */
2663
addr += (reg[15] + 1);
2664
}
2665
2666
static void vdp_z80_data_w_m5(unsigned int data)
2667
{
2668
/* Clear pending flag */
2669
pending = 0;
2670
2671
/* Push byte into FIFO */
2672
fifo[fifo_idx] = data << 8;
2673
fifo_idx = (fifo_idx + 1) & 3;
2674
2675
/* Check destination code (CD0-CD3) */
2676
switch (code & 0x0F)
2677
{
2678
case 0x01: /* VRAM */
2679
{
2680
/* VRAM address (write low byte to even address & high byte to odd address) */
2681
int index = addr ^ 1;
2682
2683
/* Intercept writes to Sprite Attribute Table */
2684
if ((index & sat_base_mask) == satb)
2685
{
2686
/* Update internal SAT */
2687
WRITE_BYTE(sat, index & sat_addr_mask, data);
2688
}
2689
2690
/* Only write unique data to VRAM */
2691
if (data != READ_BYTE(vram, index))
2692
{
2693
int name;
2694
2695
/* Write data */
2696
WRITE_BYTE(vram, index, data);
2697
2698
/* Update pattern cache */
2699
MARK_BG_DIRTY (index);
2700
}
2701
break;
2702
}
2703
2704
case 0x03: /* CRAM */
2705
{
2706
/* Pointer to CRAM word */
2707
uint16 *p = (uint16 *)&cram[addr & 0x7E];
2708
2709
/* Pack 8-bit value into 9-bit CRAM data */
2710
if (addr & 1)
2711
{
2712
/* Write high byte (0000BBB0 -> BBBxxxxxx) */
2713
data = (*p & 0x3F) | ((data & 0x0E) << 5);
2714
}
2715
else
2716
{
2717
/* Write low byte (GGG0RRR0 -> xxxGGGRRR) */
2718
data = (*p & 0x1C0) | ((data & 0x0E) >> 1)| ((data & 0xE0) >> 2);
2719
}
2720
2721
/* Check if CRAM data is being modified */
2722
if (data != *p)
2723
{
2724
/* CRAM index (64 words) */
2725
int index = (addr >> 1) & 0x3F;
2726
2727
/* Write CRAM data */
2728
*p = data;
2729
2730
/* Color entry 0 of each palette is never displayed (transparent pixel) */
2731
if (index & 0x0F)
2732
{
2733
/* Update color palette */
2734
color_update_m5(index, data);
2735
}
2736
2737
/* Update backdrop color */
2738
if (index == border)
2739
{
2740
color_update_m5(0x00, data);
2741
}
2742
}
2743
break;
2744
}
2745
2746
case 0x05: /* VSRAM */
2747
{
2748
/* Write low byte to even address & high byte to odd address */
2749
WRITE_BYTE(vsram, (addr & 0x7F) ^ 1, data);
2750
break;
2751
}
2752
}
2753
2754
/* Increment address register */
2755
addr += reg[15];
2756
2757
/* Check if DMA Fill is pending */
2758
if (dmafill)
2759
{
2760
/* Clear DMA Fill pending flag */
2761
dmafill = 0;
2762
2763
/* DMA length */
2764
dma_length = (reg[20] << 8) | reg[19];
2765
2766
/* Zero DMA length (pre-decrementing counter) */
2767
if (!dma_length)
2768
{
2769
dma_length = 0x10000;
2770
}
2771
2772
/* Trigger DMA */
2773
vdp_dma_update(Z80.cycles);
2774
}
2775
}
2776
2777
static unsigned int vdp_z80_data_r_m4(void)
2778
{
2779
/* Read buffer */
2780
unsigned int data = fifo[0];
2781
2782
/* Clear pending flag */
2783
pending = 0;
2784
2785
/* Process next read */
2786
fifo[0] = vram[addr & 0x3FFF];
2787
2788
/* Increment address register (TODO: check how address is incremented in Mode 4) */
2789
addr += (reg[15] + 1);
2790
2791
/* Return data */
2792
return data;
2793
}
2794
2795
static unsigned int vdp_z80_data_r_m5(void)
2796
{
2797
unsigned int data = 0;
2798
2799
/* Clear pending flag */
2800
pending = 0;
2801
2802
/* Check destination code (CD0-CD3) & CD4 */
2803
switch (code & 0x1F)
2804
{
2805
case 0x00: /* VRAM */
2806
{
2807
/* Return low byte from even address & high byte from odd address */
2808
data = READ_BYTE(vram, addr ^ 1);
2809
break;
2810
}
2811
2812
case 0x04: /* VSRAM */
2813
{
2814
/* Return low byte from even address & high byte from odd address */
2815
data = READ_BYTE(vsram, (addr & 0x7F) ^ 1);
2816
break;
2817
}
2818
2819
case 0x08: /* CRAM */
2820
{
2821
/* Read CRAM data */
2822
data = *(uint16 *)&cram[addr & 0x7E];
2823
2824
/* Unpack 9-bit CRAM data (BBBGGGRRR) to 16-bit data (BBB0GGG0RRR0) */
2825
data = ((data & 0x1C0) << 3) | ((data & 0x038) << 2) | ((data & 0x007) << 1);
2826
2827
/* Return low byte from even address & high byte from odd address */
2828
if (addr & 1)
2829
{
2830
data = data >> 8;
2831
}
2832
2833
data &= 0xFF;
2834
break;
2835
}
2836
}
2837
2838
/* Increment address register */
2839
addr += reg[15];
2840
2841
/* Return data */
2842
return data;
2843
}
2844
2845
2846
/*-----------------------------------------------------------------------------*/
2847
/* Z80 bus interface (Master System, Game Gear & SG-1000 VDP) */
2848
/*-----------------------------------------------------------------------------*/
2849
2850
static void vdp_z80_data_w_ms(unsigned int data)
2851
{
2852
/* Clear pending flag */
2853
pending = 0;
2854
2855
if (code < 3)
2856
{
2857
int index;
2858
2859
/* Check if we are already on next line */
2860
int line = (lines_per_frame + (Z80.cycles / MCYCLES_PER_LINE) - 1) % lines_per_frame;
2861
if ((line > v_counter) && (line < bitmap.viewport.h) && !(work_ram[0x1ffb] & cart.special))
2862
{
2863
/* Render next line */
2864
v_counter = line;
2865
render_line(line);
2866
}
2867
2868
/* VRAM address */
2869
index = addr & 0x3FFF;
2870
2871
/* VRAM write */
2872
if (data != vram[index])
2873
{
2874
int name;
2875
vram[index] = data;
2876
MARK_BG_DIRTY(index);
2877
}
2878
2879
#ifdef LOGVDP
2880
error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, Z80.cycles/MCYCLES_PER_LINE-1, Z80.cycles, Z80.cycles%MCYCLES_PER_LINE, index, data, Z80.pc.w.l);
2881
#endif
2882
}
2883
else
2884
{
2885
/* CRAM address */
2886
int index = addr & 0x1F;
2887
2888
/* Pointer to CRAM word */
2889
uint16 *p = (uint16 *)&cram[index << 1];
2890
2891
/* Check if CRAM data is being modified */
2892
if (data != *p)
2893
{
2894
/* Write CRAM data */
2895
*p = data;
2896
2897
/* Update color palette */
2898
color_update_m4(index, data);
2899
2900
/* Update backdrop color */
2901
if (index == (0x10 | (border & 0x0F)))
2902
{
2903
color_update_m4(0x40, data);
2904
}
2905
}
2906
#ifdef LOGVDP
2907
error("[%d(%d)][%d(%d)] CRAM 0x%x write -> 0x%x (%x)\n", v_counter, Z80.cycles/MCYCLES_PER_LINE-1, Z80.cycles, Z80.cycles%MCYCLES_PER_LINE, addr, data, Z80.pc.w.l);
2908
#endif
2909
}
2910
2911
/* Update read buffer */
2912
fifo[0] = data;
2913
2914
/* Update address register */
2915
addr++;
2916
}
2917
2918
static void vdp_z80_data_w_gg(unsigned int data)
2919
{
2920
/* Clear pending flag */
2921
pending = 0;
2922
2923
if (code < 3)
2924
{
2925
int index;
2926
2927
/* Check if we are already on next line*/
2928
int line = (lines_per_frame + (Z80.cycles / MCYCLES_PER_LINE) - 1) % lines_per_frame;
2929
if ((line > v_counter) && (line < bitmap.viewport.h) && !(work_ram[0x1ffb] & cart.special))
2930
{
2931
/* Render next line */
2932
v_counter = line;
2933
render_line(line);
2934
}
2935
2936
/* VRAM address */
2937
index = addr & 0x3FFF;
2938
2939
/* VRAM write */
2940
if (data != vram[index])
2941
{
2942
int name;
2943
vram[index] = data;
2944
MARK_BG_DIRTY(index);
2945
}
2946
#ifdef LOGVDP
2947
error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, Z80.cycles/MCYCLES_PER_LINE-1, Z80.cycles, Z80.cycles%MCYCLES_PER_LINE, index, data, Z80.pc.w.l);
2948
#endif
2949
}
2950
else
2951
{
2952
if (addr & 1)
2953
{
2954
/* Pointer to CRAM word */
2955
uint16 *p = (uint16 *)&cram[addr & 0x3E];
2956
2957
/* 12-bit data word */
2958
data = (data << 8) | cached_write;
2959
2960
/* Check if CRAM data is being modified */
2961
if (data != *p)
2962
{
2963
/* Color index (0-31) */
2964
int index = (addr >> 1) & 0x1F;
2965
2966
/* Write CRAM data */
2967
*p = data;
2968
2969
/* Update color palette */
2970
color_update_m4(index, data);
2971
2972
/* Update backdrop color */
2973
if (index == (0x10 | (border & 0x0F)))
2974
{
2975
color_update_m4(0x40, data);
2976
}
2977
}
2978
}
2979
else
2980
{
2981
/* Latch LSB */
2982
cached_write = data;
2983
}
2984
#ifdef LOGVDP
2985
error("[%d(%d)][%d(%d)] CRAM 0x%x write -> 0x%x (%x)\n", v_counter, Z80.cycles/MCYCLES_PER_LINE-1, Z80.cycles, Z80.cycles%MCYCLES_PER_LINE, addr, data, Z80.pc.w.l);
2986
#endif
2987
}
2988
2989
/* Update read buffer */
2990
fifo[0] = data;
2991
2992
/* Update address register */
2993
addr++;
2994
}
2995
2996
static void vdp_z80_data_w_sg(unsigned int data)
2997
{
2998
/* VRAM address */
2999
int index = addr & 0x3FFF;
3000
3001
/* Clear pending flag */
3002
pending = 0;
3003
3004
/* 4K address decoding (cf. tms9918a.txt) */
3005
if (!(reg[1] & 0x80))
3006
{
3007
index = (index & 0x203F) | ((index >> 6) & 0x40) | ((index << 1) & 0x1F80);
3008
}
3009
3010
/* VRAM write */
3011
vram[index] = data;
3012
3013
/* Update address register */
3014
addr++;
3015
3016
#ifdef LOGVDP
3017
error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, Z80.cycles/MCYCLES_PER_LINE-1, Z80.cycles, Z80.cycles%MCYCLES_PER_LINE, index, data, Z80.pc.w.l);
3018
#endif
3019
}
3020
3021
/*--------------------------------------------------------------------------*/
3022
/* DMA operations (Mega Drive VDP only) */
3023
/*--------------------------------------------------------------------------*/
3024
3025
void CDLog68k(uint addr, uint flags);
3026
3027
/* DMA from 68K bus: $000000-$7FFFFF (external area) */
3028
static void vdp_dma_68k_ext(unsigned int length)
3029
{
3030
uint16 data;
3031
3032
/* 68k bus source address */
3033
uint32 source = (reg[23] << 17) | (dma_src << 1);
3034
3035
do
3036
{
3037
/* Read data word from 68k bus */
3038
if (m68k.memory_map[source>>16].read16)
3039
{
3040
data = m68k.memory_map[source>>16].read16(source);
3041
}
3042
else
3043
{
3044
data = *(uint16 *)(m68k.memory_map[source>>16].base + (source & 0xFFFF));
3045
}
3046
3047
if(biz_cdcallback)
3048
{
3049
//if((code & 0x0F) == 0x01) //VRAM target //lets handle everything here
3050
{
3051
CDLog68k(source,eCDLog_Flags_DMASource);
3052
CDLog68k(source+1,eCDLog_Flags_DMASource);
3053
}
3054
}
3055
3056
3057
/* Increment source address */
3058
source += 2;
3059
3060
/* 128k DMA window */
3061
source = (reg[23] << 17) | (source & 0x1FFFF);
3062
3063
/* Write data word to VRAM, CRAM or VSRAM */
3064
vdp_bus_w(data);
3065
}
3066
while (--length);
3067
3068
/* Update DMA source address */
3069
dma_src = (source >> 1) & 0xffff;
3070
}
3071
3072
/* DMA from 68K bus: $800000-$FFFFFF (internal area) except I/O area */
3073
static void vdp_dma_68k_ram(unsigned int length)
3074
{
3075
uint16 data;
3076
3077
/* 68k bus source address */
3078
uint32 source = (reg[23] << 17) | (dma_src << 1);
3079
3080
do
3081
{
3082
/* access Work-RAM by default */
3083
data = *(uint16 *)(work_ram + (source & 0xFFFF));
3084
3085
/* Increment source address */
3086
source += 2;
3087
3088
/* 128k DMA window */
3089
source = (reg[23] << 17) | (source & 0x1FFFF);
3090
3091
/* Write data word to VRAM, CRAM or VSRAM */
3092
vdp_bus_w(data);
3093
}
3094
while (--length);
3095
3096
/* Update DMA source address */
3097
dma_src = (source >> 1) & 0xffff;
3098
}
3099
3100
/* DMA from 68K bus: $A00000-$A1FFFF (I/O area) specific */
3101
static void vdp_dma_68k_io(unsigned int length)
3102
{
3103
uint16 data;
3104
3105
/* 68k bus source address */
3106
uint32 source = (reg[23] << 17) | (dma_src << 1);
3107
3108
do
3109
{
3110
/* Z80 area */
3111
if (source <= 0xA0FFFF)
3112
{
3113
/* Return $FFFF only when the Z80 isn't hogging the Z-bus.
3114
(e.g. Z80 isn't reset and 68000 has the bus) */
3115
data = ((zstate ^ 3) ? *(uint16 *)(work_ram + (source & 0xFFFF)) : 0xFFFF);
3116
}
3117
3118
/* The I/O chip and work RAM try to drive the data bus which results
3119
in both values being combined in random ways when read.
3120
We return the I/O chip values which seem to have precedence, */
3121
else if (source <= 0xA1001F)
3122
{
3123
data = io_68k_read((source >> 1) & 0x0F);
3124
data = (data << 8 | data);
3125
}
3126
3127
/* All remaining locations access work RAM */
3128
else
3129
{
3130
data = *(uint16 *)(work_ram + (source & 0xFFFF));
3131
}
3132
3133
/* Increment source address */
3134
source += 2;
3135
3136
/* 128k DMA window */
3137
source = (reg[23] << 17) | (source & 0x1FFFF);
3138
3139
/* Write data to VRAM, CRAM or VSRAM */
3140
vdp_bus_w(data);
3141
}
3142
while (--length);
3143
3144
/* Update DMA source address */
3145
dma_src = (source >> 1) & 0xffff;
3146
}
3147
3148
/* VRAM Copy */
3149
static void vdp_dma_copy(unsigned int length)
3150
{
3151
/* CD4 should be set (CD0-CD3 ignored) otherwise VDP locks (hard reset needed) */
3152
if (code & 0x10)
3153
{
3154
int name;
3155
uint8 data;
3156
3157
/* VRAM source address */
3158
uint16 source = dma_src;
3159
3160
do
3161
{
3162
/* Read byte from adjacent VRAM source address */
3163
data = READ_BYTE(vram, source ^ 1);
3164
3165
/* Intercept writes to Sprite Attribute Table */
3166
if ((addr & sat_base_mask) == satb)
3167
{
3168
/* Update internal SAT */
3169
WRITE_BYTE(sat, (addr & sat_addr_mask) ^ 1, data);
3170
}
3171
3172
/* Write byte to adjacent VRAM destination address */
3173
WRITE_BYTE(vram, addr ^ 1, data);
3174
3175
/* Update pattern cache */
3176
MARK_BG_DIRTY(addr);
3177
3178
/* Increment VRAM source address */
3179
source++;
3180
3181
/* Increment VRAM destination address */
3182
addr += reg[15];
3183
}
3184
while (--length);
3185
3186
/* Update DMA source address */
3187
dma_src = source;
3188
}
3189
}
3190
3191
/* DMA Fill */
3192
static void vdp_dma_fill(unsigned int length)
3193
{
3194
/* Check destination code (CD0-CD3) */
3195
switch (code & 0x0F)
3196
{
3197
case 0x01: /* VRAM */
3198
{
3199
int name;
3200
3201
/* Get source data from last written FIFO entry */
3202
uint8 data = fifo[(fifo_idx+3)&3] >> 8;
3203
3204
do
3205
{
3206
/* Intercept writes to Sprite Attribute Table */
3207
if ((addr & sat_base_mask) == satb)
3208
{
3209
/* Update internal SAT */
3210
WRITE_BYTE(sat, (addr & sat_addr_mask) ^ 1, data);
3211
}
3212
3213
/* Write byte to adjacent VRAM address */
3214
WRITE_BYTE(vram, addr ^ 1, data);
3215
3216
/* Update pattern cache */
3217
MARK_BG_DIRTY (addr);
3218
3219
/* Increment VRAM address */
3220
addr += reg[15];
3221
}
3222
while (--length);
3223
break;
3224
}
3225
3226
case 0x03: /* CRAM */
3227
{
3228
/* Get source data from next available FIFO entry */
3229
uint16 data = fifo[fifo_idx];
3230
3231
/* Pack 16-bit bus data (BBB0GGG0RRR0) to 9-bit CRAM data (BBBGGGRRR) */
3232
data = ((data & 0xE00) >> 3) | ((data & 0x0E0) >> 2) | ((data & 0x00E) >> 1);
3233
3234
do
3235
{
3236
/* Pointer to CRAM 9-bit word */
3237
uint16 *p = (uint16 *)&cram[addr & 0x7E];
3238
3239
/* Check if CRAM data is being modified */
3240
if (data != *p)
3241
{
3242
/* CRAM index (64 words) */
3243
int index = (addr >> 1) & 0x3F;
3244
3245
/* Write CRAM data */
3246
*p = data;
3247
3248
/* Color entry 0 of each palette is never displayed (transparent pixel) */
3249
if (index & 0x0F)
3250
{
3251
/* Update color palette */
3252
color_update_m5(index, data);
3253
}
3254
3255
/* Update backdrop color */
3256
if (index == border)
3257
{
3258
color_update_m5(0x00, data);
3259
}
3260
}
3261
3262
/* Increment CRAM address */
3263
addr += reg[15];
3264
}
3265
while (--length);
3266
break;
3267
}
3268
3269
case 0x05: /* VSRAM */
3270
{
3271
/* Get source data from next available FIFO entry */
3272
uint16 data = fifo[fifo_idx];
3273
3274
do
3275
{
3276
/* Write VSRAM data */
3277
*(uint16 *)&vsram[addr & 0x7E] = data;
3278
3279
/* Increment VSRAM address */
3280
addr += reg[15];
3281
}
3282
while (--length);
3283
break;
3284
}
3285
3286
default:
3287
{
3288
/* invalid destination does nothing (Williams Greatest Hits after soft reset) */
3289
3290
/* address is still incremented */
3291
addr += reg[15] * length;
3292
}
3293
}
3294
}
3295
3296