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