1
/***************************************************************************
5
Driver by: Ernesto Corvi, Mariusz Wojcieszek, Aaron Giles
7
***************************************************************************/
10
#include "includes/amiga.h"
14
/*************************************
18
*************************************/
20
#define COPPER_CYCLES_TO_PIXELS(x) (4 * (x))
24
/*************************************
28
*************************************/
30
/* expand an 8-bit bit pattern into 16 bits, every other bit */
31
const UINT16 amiga_expand_byte[256] =
33
0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015,
34
0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055,
35
0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115,
36
0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155,
37
0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415,
38
0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455,
39
0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515,
40
0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555,
41
0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015,
42
0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055,
43
0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115,
44
0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155,
45
0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415,
46
0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455,
47
0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515,
48
0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555,
50
0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015,
51
0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055,
52
0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115,
53
0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155,
54
0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415,
55
0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455,
56
0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515,
57
0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555,
58
0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015,
59
0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055,
60
0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115,
61
0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155,
62
0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415,
63
0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455,
64
0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515,
65
0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555
68
const UINT16 delay[256] =
70
1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* 0x000 - 0x03e */
71
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x040 - 0x05e */
72
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x060 - 0x07e */
73
0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0, /* 0x080 - 0x09e */
74
1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0, /* 0x0a0 - 0x0de */
76
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x0e0 - 0x0fe */
77
/* BPLCON0-3,BPLMOD1-2 */
78
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x100 - 0x11e */
80
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0x120 - 0x13e */
81
/* SPRxPOS/SPRxCTL/SPRxDATA/SPRxDATB */
82
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0x140 - 0x17e */
84
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x180 - 0x1be */
86
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 0x1c0 - 0x1fe */
91
/*************************************
95
*************************************/
101
for (i = 0; i < 0x1000; i++)
102
palette_set_color_rgb(machine, i, pal4bit(i >> 8), pal4bit(i >> 4), pal4bit(i));
107
/*************************************
111
*************************************/
115
amiga_state *state = machine.driver_data<amiga_state>();
118
/* generate tables that produce the correct playfield color for dual playfield mode */
119
for (j = 0; j < 64; j++)
121
int pf1pix = ((j >> 0) & 1) | ((j >> 1) & 2) | ((j >> 2) & 4);
122
int pf2pix = ((j >> 1) & 1) | ((j >> 2) & 2) | ((j >> 3) & 4);
124
state->m_separate_bitplanes[0][j] = (pf1pix || !pf2pix) ? pf1pix : (pf2pix + 8);
125
state->m_separate_bitplanes[1][j] = pf2pix ? (pf2pix + 8) : pf1pix;
128
#if GUESS_COPPER_OFFSET
129
state->m_wait_offset = 3;
132
/* reset the genlock color */
133
state->m_genlock_color = 0xffff;
135
state->m_sprite_ctl_written = 0;
140
/*************************************
144
*************************************/
146
UINT32 amiga_gethvpos(screen_device &screen)
148
amiga_state *state = screen.machine().driver_data<amiga_state>();
149
UINT32 hvpos = (state->m_last_scanline << 8) | (screen.hpos() >> 2);
150
UINT32 latchedpos = input_port_read_safe(screen.machine(), "HVPOS", 0);
152
/* if there's no latched position, or if we are in the active display area */
153
/* but before the latching point, return the live HV position */
154
if ((CUSTOM_REG(REG_BPLCON0) & 0x0008) == 0 || latchedpos == 0 || (state->m_last_scanline >= 20 && hvpos < latchedpos))
157
/* otherwise, return the latched position */
163
/*************************************
165
* Genlock interaction
167
*************************************/
169
void amiga_set_genlock_color(running_machine &machine, UINT16 color)
171
amiga_state *state = machine.driver_data<amiga_state>();
173
state->m_genlock_color = color;
178
/*************************************
182
*************************************/
184
void amiga_copper_setpc(running_machine &machine, UINT32 pc)
186
amiga_state *state = machine.driver_data<amiga_state>();
189
logerror("copper_setpc(%06x)\n", pc);
191
state->m_copper_pc = pc;
192
state->m_copper_waiting = FALSE;
196
int amiga_copper_execute_next(running_machine &machine, int xpos)
198
amiga_state *state = machine.driver_data<amiga_state>();
201
/* bail if not enabled */
202
if ((CUSTOM_REG(REG_DMACON) & (DMACON_COPEN | DMACON_DMAEN)) != (DMACON_COPEN | DMACON_DMAEN))
205
/* flush any pending writes */
206
if (state->m_copper_pending_offset)
209
logerror("%02X.%02X: Write to %s = %04x\n", state->m_last_scanline, xpos / 2, amiga_custom_names[state->m_copper_pending_offset & 0xff], state->m_copper_pending_data);
210
amiga_custom_w(machine.device("maincpu")->memory().space(AS_PROGRAM), state->m_copper_pending_offset, state->m_copper_pending_data, 0xffff);
211
state->m_copper_pending_offset = 0;
214
/* if we're waiting, check for a breakthrough */
215
if (state->m_copper_waiting)
217
int curpos = (state->m_last_scanline << 8) | (xpos >> 1);
219
/* if we're past the wait time, stop it and hold up 2 cycles */
220
if ((curpos & state->m_copper_waitmask) >= (state->m_copper_waitval & state->m_copper_waitmask) &&
221
(!state->m_copper_waitblit || !(CUSTOM_REG(REG_DMACON) & DMACON_BBUSY)))
223
state->m_copper_waiting = FALSE;
224
#if GUESS_COPPER_OFFSET
225
return xpos + COPPER_CYCLES_TO_PIXELS(1 + state->m_wait_offset);
227
return xpos + COPPER_CYCLES_TO_PIXELS(1 + 3);
231
/* otherwise, see if this line is even a possibility; if not, punt */
232
if (((curpos | 0xff) & state->m_copper_waitmask) < (state->m_copper_waitval & state->m_copper_waitmask))
235
/* else just advance another pixel */
236
xpos += COPPER_CYCLES_TO_PIXELS(1);
240
/* fetch the first data word */
241
word0 = (*state->m_chip_ram_r)(state, state->m_copper_pc);
242
state->m_copper_pc += 2;
243
xpos += COPPER_CYCLES_TO_PIXELS(1);
245
/* fetch the second data word */
246
word1 = (*state->m_chip_ram_r)(state, state->m_copper_pc);
247
state->m_copper_pc += 2;
248
xpos += COPPER_CYCLES_TO_PIXELS(1);
251
logerror("%02X.%02X: Copper inst @ %06x = %04x %04x\n", state->m_last_scanline, xpos / 2, state->m_copper_pc, word0, word1);
254
if ((word0 & 1) == 0)
256
int min = (CUSTOM_REG(REG_COPCON) & 2) ? 0x20 : 0x40;
258
/* do the write if we're allowed */
259
word0 = (word0 >> 1) & 0xff;
262
if (delay[word0] == 0)
265
logerror("%02X.%02X: Write to %s = %04x\n", state->m_last_scanline, xpos / 2, amiga_custom_names[word0 & 0xff], word1);
266
amiga_custom_w(machine.device("maincpu")->memory().space(AS_PROGRAM), word0, word1, 0xffff);
268
else // additional 2 cycles needed for non-Agnus registers
270
state->m_copper_pending_offset = word0;
271
state->m_copper_pending_data = word1;
275
/* illegal writes suspend until next frame */
279
logerror("%02X.%02X: Aborting copper on illegal write\n", state->m_last_scanline, xpos / 2);
281
state->m_copper_waitval = 0xffff;
282
state->m_copper_waitmask = 0xffff;
283
state->m_copper_waitblit = FALSE;
284
state->m_copper_waiting = TRUE;
290
/* extract common wait/skip values */
291
state->m_copper_waitval = word0 & 0xfffe;
292
state->m_copper_waitmask = word1 | 0x8001;
293
state->m_copper_waitblit = (~word1 >> 15) & 1;
296
if ((word1 & 1) == 0)
299
logerror(" Waiting for %04x & %04x (currently %04x)\n", state->m_copper_waitval, state->m_copper_waitmask, (state->m_last_scanline << 8) | (xpos >> 1));
301
state->m_copper_waiting = TRUE;
307
int curpos = (state->m_last_scanline << 8) | (xpos >> 1);
310
logerror(" Skipping if %04x & %04x (currently %04x)\n", state->m_copper_waitval, state->m_copper_waitmask, (state->m_last_scanline << 8) | (xpos >> 1));
312
/* if we're past the wait time, stop it and hold up 2 cycles */
313
if ((curpos & state->m_copper_waitmask) >= (state->m_copper_waitval & state->m_copper_waitmask) &&
314
(!state->m_copper_waitblit || !(CUSTOM_REG(REG_DMACON) & DMACON_BBUSY)))
317
logerror(" Skipped\n");
319
/* count the cycles it out have taken to fetch the next instruction */
320
state->m_copper_pc += 4;
321
xpos += COPPER_CYCLES_TO_PIXELS(2);
326
/* advance and consume 8 cycles */
332
/*************************************
334
* External sprite controls
336
*************************************/
338
void amiga_sprite_dma_reset(running_machine &machine, int which)
340
amiga_state *state = machine.driver_data<amiga_state>();
342
if (LOG_SPRITE_DMA) logerror("sprite %d dma reset\n", which );
343
state->m_sprite_dma_reload_mask |= 1 << which;
344
state->m_sprite_dma_live_mask |= 1 << which;
348
void amiga_sprite_enable_comparitor(running_machine &machine, int which, int enable)
350
amiga_state *state = machine.driver_data<amiga_state>();
352
if (LOG_SPRITE_DMA) logerror("sprite %d comparitor %sable\n", which, enable ? "en" : "dis" );
355
state->m_sprite_comparitor_enable_mask |= 1 << which;
356
state->m_sprite_dma_live_mask &= ~(1 << which);
360
state->m_sprite_comparitor_enable_mask &= ~(1 << which);
361
state->m_sprite_ctl_written |= (1 << which);
367
/*************************************
369
* Per-scanline sprite fetcher
371
*************************************/
373
INLINE void fetch_sprite_data(amiga_state *state, int scanline, int sprite)
375
CUSTOM_REG(REG_SPR0DATA + 4 * sprite) = (*state->m_chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0);
376
CUSTOM_REG(REG_SPR0DATB + 4 * sprite) = (*state->m_chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 2);
377
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4;
378
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d fetch: data=%04X-%04X\n", scanline, sprite, CUSTOM_REG(REG_SPR0DATA + 4 * sprite), CUSTOM_REG(REG_SPR0DATB + 4 * sprite));
381
static void update_sprite_dma(amiga_state *state, int scanline)
383
int dmaenable = (CUSTOM_REG(REG_DMACON) & (DMACON_SPREN | DMACON_DMAEN)) == (DMACON_SPREN | DMACON_DMAEN);
386
/* channels are limited by DDFSTART */
387
maxdma = (CUSTOM_REG(REG_DDFSTRT) - 0x14) / 4;
391
/* loop over sprite channels */
392
for (num = 0; num < maxdma; num++)
394
int bitmask = 1 << num;
397
/* if we are == VSTOP, fetch new control words */
398
if (dmaenable && (state->m_sprite_dma_live_mask & bitmask) && (state->m_sprite_dma_reload_mask & bitmask))
400
/* disable the sprite */
401
state->m_sprite_comparitor_enable_mask &= ~bitmask;
402
state->m_sprite_dma_reload_mask &= ~bitmask;
404
/* fetch data into the control words */
405
CUSTOM_REG(REG_SPR0POS + 4 * num) = (*state->m_chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 0);
406
CUSTOM_REG(REG_SPR0CTL + 4 * num) = (*state->m_chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 2);
407
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) += 4;
408
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d fetch: pos=%04X ctl=%04X\n", scanline, num, CUSTOM_REG(REG_SPR0POS + 4 * num), CUSTOM_REG(REG_SPR0CTL + 4 * num));
411
/* compute vstart/vstop */
412
vstart = (CUSTOM_REG(REG_SPR0POS + 4 * num) >> 8) | ((CUSTOM_REG(REG_SPR0CTL + 4 * num) << 6) & 0x100);
413
vstop = (CUSTOM_REG(REG_SPR0CTL + 4 * num) >> 8) | ((CUSTOM_REG(REG_SPR0CTL + 4 * num) << 7) & 0x100);
415
/* if we hit vstart, enable the comparitor */
416
if (scanline == vstart)
418
state->m_sprite_comparitor_enable_mask |= 1 << num;
419
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d comparitor enable\n", scanline, num);
422
/* if we hit vstop, disable the comparitor and trigger a reload for the next scanline */
423
if (scanline == vstop)
425
state->m_sprite_ctl_written &= ~bitmask;
426
state->m_sprite_comparitor_enable_mask &= ~bitmask;
427
state->m_sprite_dma_reload_mask |= 1 << num;
428
CUSTOM_REG(REG_SPR0DATA + 4 * num) = 0; /* just a guess */
429
CUSTOM_REG(REG_SPR0DATB + 4 * num) = 0;
430
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d comparitor disable, prepare for reload\n", scanline, num);
433
/* fetch data if this sprite is enabled */
434
if (dmaenable && (state->m_sprite_dma_live_mask & bitmask) && (state->m_sprite_comparitor_enable_mask & bitmask))
436
fetch_sprite_data(state, scanline, num);
443
/*************************************
445
* Per-pixel sprite computations
447
*************************************/
449
INLINE UINT32 interleave_sprite_data(UINT16 lobits, UINT16 hibits)
451
return (amiga_expand_byte[lobits & 0xff] << 0) | (amiga_expand_byte[lobits >> 8] << 16) |
452
(amiga_expand_byte[hibits & 0xff] << 1) | (amiga_expand_byte[hibits >> 8] << 17);
456
static int get_sprite_pixel(amiga_state *state, int x)
461
/* loop over sprite channels */
462
for (num = 0; num < 8; num++)
463
if (state->m_sprite_comparitor_enable_mask & (1 << num))
465
/* if we're not currently clocking, check against hstart */
466
if (state->m_sprite_remain[num] == 0)
468
int hstart = ((CUSTOM_REG(REG_SPR0POS + 4 * num) & 0xff) << 1) | (CUSTOM_REG(REG_SPR0CTL + 4 * num) & 1);
471
state->m_sprite_remain[num] = 16;
472
state->m_sprite_shiftreg[num] = interleave_sprite_data(CUSTOM_REG(REG_SPR0DATA + 4 * num), CUSTOM_REG(REG_SPR0DATB + 4 * num));
476
/* clock the next pixel if we're doing it */
477
if (state->m_sprite_remain[num] != 0)
479
state->m_sprite_remain[num]--;
480
pixels |= (state->m_sprite_shiftreg[num] & 0xc0000000) >> (16 + 2 * (7 - num));
481
state->m_sprite_shiftreg[num] <<= 2;
485
/* if we have pixels, determine the actual color and get out */
488
static const UINT16 ormask[16] =
490
0x0000, 0x000c, 0x00c0, 0x00cc, 0x0c00, 0x0c0c, 0x0cc0, 0x0ccc,
491
0xc000, 0xc00c, 0xc0c0, 0xc0cc, 0xcc00, 0xcc0c, 0xccc0, 0xcccc
493
static const UINT16 spritecollide[16] =
495
0x0000, 0x0000, 0x0000, 0x0200, 0x0000, 0x0400, 0x1000, 0x1600,
496
0x0000, 0x0800, 0x2000, 0x2a00, 0x4000, 0x4c00, 0x7000, 0x7e00
499
const int esprm = 0x10, osprm = 0x10;
501
/* OR the two sprite bits together so we only have 1 bit per sprite */
502
collide = pixels | (pixels >> 1);
504
/* based on the CLXCON, merge even/odd sprite results */
505
collide |= (collide & ormask[CUSTOM_REG(REG_CLXCON) >> 12]) >> 2;
507
/* collapse down to a 4-bit final "sprite present" mask */
508
collide = (collide & 1) | ((collide >> 3) & 2) | ((collide >> 6) & 4) | ((collide >> 9) & 8);
510
/* compute sprite-sprite collisions */
511
CUSTOM_REG(REG_CLXDAT) |= spritecollide[collide];
513
/* now determine the actual color */
514
for (pair = 0; pixels; pair++, pixels >>= 4)
518
topmost sprite color in bits 0-5
519
sprite present bitmask in bits 6-9
520
topmost sprite pair index in bits 10-11
522
UINT32 result = (collide << 6) | (pair << 10);
525
if (CUSTOM_REG(REG_SPR1CTL + 8 * pair) & 0x0080)
526
return (pixels & 0xf) | osprm | result;
528
/* lower-numbered sprite of pair */
530
return (pixels & 3) | esprm | (pair << 2) | result;
532
/* higher-numbered sprite of pair */
534
return ((pixels >> 2) & 3) | osprm | (pair << 2) | result;
543
/*************************************
547
*************************************/
549
INLINE UINT8 assemble_odd_bitplanes(amiga_state *state, int planes, int obitoffs)
551
UINT8 pix = (CUSTOM_REG(REG_BPL1DAT) >> obitoffs) & 1;
554
pix |= ((CUSTOM_REG(REG_BPL3DAT) >> obitoffs) & 1) << 2;
556
pix |= ((CUSTOM_REG(REG_BPL5DAT) >> obitoffs) & 1) << 4;
562
INLINE UINT8 assemble_even_bitplanes(amiga_state *state, int planes, int ebitoffs)
567
pix |= ((CUSTOM_REG(REG_BPL2DAT) >> ebitoffs) & 1) << 1;
570
pix |= ((CUSTOM_REG(REG_BPL4DAT) >> ebitoffs) & 1) << 3;
572
pix |= ((CUSTOM_REG(REG_BPL6DAT) >> ebitoffs) & 1) << 5;
578
INLINE void fetch_bitplane_data(amiga_state *state, int plane)
580
CUSTOM_REG(REG_BPL1DAT + plane) = (*state->m_chip_ram_r)(state, CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2));
581
CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2) += 2;
585
/*************************************
587
* Hold and modify pixel computations
589
*************************************/
591
INLINE int update_ham(amiga_state *state, int newpix)
596
state->m_ham_color = CUSTOM_REG(REG_COLOR00 + (newpix & 0xf));
600
state->m_ham_color = (state->m_ham_color & 0xff0) | ((newpix & 0xf) << 0);
604
state->m_ham_color = (state->m_ham_color & 0x0ff) | ((newpix & 0xf) << 8);
608
state->m_ham_color = (state->m_ham_color & 0xf0f) | ((newpix & 0xf) << 4);
611
return state->m_ham_color;
616
/*************************************
618
* Single scanline rasterizer
620
*************************************/
622
void amiga_render_scanline(running_machine &machine, bitmap_t *bitmap, int scanline)
624
amiga_state *state = machine.driver_data<amiga_state>();
625
UINT16 save_color0 = CUSTOM_REG(REG_COLOR00);
626
int ddf_start_pixel = 0, ddf_stop_pixel = 0;
627
int hires = 0, dualpf = 0, ham = 0;
628
int hstart = 0, hstop = 0;
629
int vstart = 0, vstop = 0;
630
int pf1pri = 0, pf2pri = 0;
635
int ebitoffs = 0, obitoffs = 0;
636
int ecolmask = 0, ocolmask = 0;
637
int edelay = 0, odelay = 0;
640
const int defbitoffs = 15;
642
state->m_last_scanline = scanline;
644
/* on the first scanline, reset the COPPER and HAM color */
647
amiga_copper_setpc(machine, CUSTOM_REG_LONG(REG_COP1LCH));
648
state->m_ham_color = CUSTOM_REG(REG_COLOR00);
651
/* update sprite data fetching */
652
update_sprite_dma(state, scanline);
654
/* start of a new line, signal we're not done with it and fill up vars */
656
dst = BITMAP_ADDR16(bitmap, scanline, 0);
658
/* all sprites off at the start of the line */
659
memset(state->m_sprite_remain, 0, sizeof(state->m_sprite_remain));
661
/* temporary set color 0 to the genlock color */
662
if (state->m_genlock_color != 0xffff)
663
CUSTOM_REG(REG_COLOR00) = state->m_genlock_color;
665
/* loop over the line */
667
for (x = 0; x < 0xe4*2; x++)
671
/* time to execute the copper? */
672
if (x == next_copper_x)
674
/* execute the next batch, restoring and re-saving color 0 around it */
675
CUSTOM_REG(REG_COLOR00) = save_color0;
676
next_copper_x = amiga_copper_execute_next(machine, x);
677
save_color0 = CUSTOM_REG(REG_COLOR00);
678
if (state->m_genlock_color != 0xffff)
679
CUSTOM_REG(REG_COLOR00) = state->m_genlock_color;
681
/* compute update-related register values */
682
planes = (CUSTOM_REG(REG_BPLCON0) & (BPLCON0_BPU0 | BPLCON0_BPU1 | BPLCON0_BPU2)) >> 12;
683
hires = CUSTOM_REG(REG_BPLCON0) & BPLCON0_HIRES;
684
ham = CUSTOM_REG(REG_BPLCON0) & BPLCON0_HOMOD;
685
dualpf = CUSTOM_REG(REG_BPLCON0) & BPLCON0_DBLPF;
686
// lace = CUSTOM_REG(REG_BPLCON0) & BPLCON0_LACE;
688
/* compute the pixel fetch parameters */
689
ddf_start_pixel = ( CUSTOM_REG(REG_DDFSTRT) & 0xfc ) * 2 + (hires ? 9 : 17);
690
ddf_stop_pixel = ( CUSTOM_REG(REG_DDFSTOP) & 0xfc ) * 2 + (hires ? (9 + defbitoffs) : (17 + defbitoffs));
692
if ( ( CUSTOM_REG(REG_DDFSTRT) ^ CUSTOM_REG(REG_DDFSTOP) ) & 0x04 )
695
/* compute the horizontal start/stop */
696
hstart = CUSTOM_REG(REG_DIWSTRT) & 0xff;
697
hstop = (CUSTOM_REG(REG_DIWSTOP) & 0xff);
700
/* compute the vertical start/stop */
701
vstart = CUSTOM_REG(REG_DIWSTRT) >> 8;
702
vstop = (CUSTOM_REG(REG_DIWSTOP) >> 8);
703
vstop |= ((~CUSTOM_REG(REG_DIWSTOP) >> 7) & 0x100);
705
/* extract playfield priorities */
706
pf1pri = CUSTOM_REG(REG_BPLCON2) & 7;
707
pf2pri = (CUSTOM_REG(REG_BPLCON2) >> 3) & 7;
709
/* extract collision masks */
710
ocolmask = (CUSTOM_REG(REG_CLXCON) >> 6) & 0x15;
711
ecolmask = (CUSTOM_REG(REG_CLXCON) >> 6) & 0x2a;
714
/* clear the target pixels to the background color as a starting point */
717
dst[x*2+1] = CUSTOM_REG(REG_COLOR00);
719
/* if we hit the first fetch pixel, reset the counters and latch the delays */
720
if (x == ddf_start_pixel)
722
odelay = CUSTOM_REG(REG_BPLCON1) & 0xf;
723
edelay = ( CUSTOM_REG(REG_BPLCON1) >> 4 ) & 0x0f;
727
obitoffs = defbitoffs + ( odelay << 1 );
728
ebitoffs = defbitoffs + ( edelay << 1 );
732
if ( CUSTOM_REG(REG_DDFSTRT) & 0x04 )
734
odelay = ( odelay + 8 ) & 0x0f;
735
edelay = ( edelay + 8 ) & 0x0f;
738
obitoffs = defbitoffs + odelay;
739
ebitoffs = defbitoffs + edelay;
742
for (pl = 0; pl < 6; pl++)
743
CUSTOM_REG(REG_BPL1DAT + pl) = 0;
746
/* need to run the sprite engine every pixel to ensure display */
747
sprpix = get_sprite_pixel(state, x);
749
/* to render, we must have bitplane DMA enabled, at least 1 plane, and be within the */
750
/* vertical display window */
751
if ((CUSTOM_REG(REG_DMACON) & (DMACON_BPLEN | DMACON_DMAEN)) == (DMACON_BPLEN | DMACON_DMAEN) &&
752
planes > 0 && scanline >= vstart && scanline < vstop)
754
int pfpix0 = 0, pfpix1 = 0, collide;
756
/* fetch the odd bits if we are within the fetching region */
757
if (x >= ddf_start_pixel && x <= ddf_stop_pixel + odelay)
759
/* if we need to fetch more data, do it now */
760
if (obitoffs == defbitoffs)
762
for (pl = 0; pl < planes; pl += 2)
764
fetch_bitplane_data(state, pl);
768
/* now assemble the bits */
769
pfpix0 |= assemble_odd_bitplanes(state, planes, obitoffs);
772
/* for high res, assemble a second set of bits */
775
/* reset bit offsets and fetch more data if needed */
778
obitoffs = defbitoffs;
780
for (pl = 0; pl < planes; pl += 2)
782
fetch_bitplane_data(state, pl);
786
pfpix1 |= assemble_odd_bitplanes(state, planes, obitoffs);
790
pfpix1 |= pfpix0 & 0x15;
792
/* reset bit offsets if needed */
794
obitoffs = defbitoffs;
797
/* fetch the even bits if we are within the fetching region */
798
if (x >= ddf_start_pixel && x <= ddf_stop_pixel + edelay)
800
/* if we need to fetch more data, do it now */
801
if (ebitoffs == defbitoffs)
803
for (pl = 1; pl < planes; pl += 2)
805
fetch_bitplane_data(state, pl);
809
/* now assemble the bits */
810
pfpix0 |= assemble_even_bitplanes(state, planes, ebitoffs);
813
/* for high res, assemble a second set of bits */
816
/* reset bit offsets and fetch more data if needed */
819
ebitoffs = defbitoffs;
821
for (pl = 1; pl < planes; pl += 2)
823
fetch_bitplane_data(state, pl);
827
pfpix1 |= assemble_even_bitplanes(state, planes, ebitoffs);
831
pfpix1 |= pfpix0 & 0x2a;
833
/* reset bit offsets if needed */
835
ebitoffs = defbitoffs;
838
/* compute playfield/sprite collisions for first pixel */
839
collide = pfpix0 ^ CUSTOM_REG(REG_CLXCON);
840
if ((collide & ocolmask) == 0)
841
CUSTOM_REG(REG_CLXDAT) |= (sprpix >> 5) & 0x01e;
842
if ((collide & ecolmask) == 0)
843
CUSTOM_REG(REG_CLXDAT) |= (sprpix >> 1) & 0x1e0;
844
if ((collide & (ecolmask | ocolmask)) == 0)
845
CUSTOM_REG(REG_CLXDAT) |= 0x001;
847
/* compute playfield/sprite collisions for second pixel */
848
collide = pfpix1 ^ CUSTOM_REG(REG_CLXCON);
849
if ((collide & ocolmask) == 0)
850
CUSTOM_REG(REG_CLXDAT) |= (sprpix >> 5) & 0x01e;
851
if ((collide & ecolmask) == 0)
852
CUSTOM_REG(REG_CLXDAT) |= (sprpix >> 1) & 0x1e0;
853
if ((collide & (ecolmask | ocolmask)) == 0)
854
CUSTOM_REG(REG_CLXDAT) |= 0x001;
856
/* if we are within the display region, render */
857
if (dst != NULL && x >= hstart && x < hstop)
861
/* hold-and-modify mode -- assume low-res (hi-res not supported by the hardware) */
864
/* update the HAM color */
865
pfpix0 = update_ham(state, pfpix0);
868
pri = (sprpix >> 10);
870
/* sprite has priority */
871
if (sprpix && pf1pri > pri)
874
dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + pix);
877
/* playfield has priority */
885
/* dual playfield mode */
888
/* mask out the sprite if it doesn't have priority */
890
pri = (sprpix >> 10);
893
if ((pfpix0 & 0x15) && pf1pri <= pri)
895
if ((pfpix0 & 0x2a) && pf2pri <= pri)
899
/* write out the left pixel */
901
dst[x*2+0] = CUSTOM_REG(REG_COLOR00 + pix);
903
dst[x*2+0] = CUSTOM_REG(REG_COLOR00 + state->m_separate_bitplanes[(CUSTOM_REG(REG_BPLCON2) >> 6) & 1][pfpix0]);
905
/* mask out the sprite if it doesn't have priority */
909
if ((pfpix1 & 0x15) && pf1pri <= pri)
911
if ((pfpix1 & 0x2a) && pf2pri <= pri)
915
/* write out the right pixel */
917
dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + pix);
919
dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + state->m_separate_bitplanes[(CUSTOM_REG(REG_BPLCON2) >> 6) & 1][pfpix1]);
922
/* single playfield mode */
926
pri = (sprpix >> 10);
928
/* sprite has priority */
929
if (sprpix && pf1pri > pri)
932
dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + pix);
935
/* playfield has priority */
938
dst[x*2+0] = CUSTOM_REG(REG_COLOR00 + pfpix0);
939
dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + pfpix1);
947
if ( machine.primary_screen->frame_number() % 64 == 0 && scanline == 100 )
949
const char *m_lores = "LORES";
950
const char *m_hires = "HIRES";
951
const char *m_ham = "HAM";
952
const char *m_dualpf = "DUALPF";
953
const char *m_lace = "LACE";
954
const char *m_hilace = "HI-LACE";
955
const char *p = m_lores;
957
if ( hires ) p = m_hires;
958
if ( ham ) p = m_ham;
959
if ( dualpf ) p = m_dualpf;
960
if ( lace ) p = m_lace;
962
if ( hires && lace ) p = m_hilace;
964
popmessage("%s(%d pl od=%04x ed=%04x start=%04x stop=%04x)", p, planes, odelay, edelay, CUSTOM_REG(REG_DDFSTRT), CUSTOM_REG(REG_DDFSTOP) );
968
/* end of the line: time to add the modulos */
969
if (scanline >= vstart && scanline < vstop)
971
/* update odd planes */
972
for (pl = 0; pl < planes; pl += 2)
973
CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += CUSTOM_REG_SIGNED(REG_BPL1MOD);
975
/* update even planes */
976
for (pl = 1; pl < planes; pl += 2)
977
CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += CUSTOM_REG_SIGNED(REG_BPL2MOD);
980
/* restore color00 */
981
CUSTOM_REG(REG_COLOR00) = save_color0;
983
#if GUESS_COPPER_OFFSET
984
if (machine.primary_screen->frame_number() % 64 == 0 && scanline == 0)
986
if (machine.input().code_pressed(KEYCODE_Q))
987
popmessage("%d", state->m_wait_offset -= 1);
988
if (machine.input().code_pressed(KEYCODE_W))
989
popmessage("%d", state->m_wait_offset += 1);
996
/*************************************
1000
*************************************/
1002
SCREEN_UPDATE( amiga )
1006
/* render each scanline in the visible region */
1007
for (y = cliprect->min_y; y <= cliprect->max_y; y++)
1008
amiga_render_scanline(screen->machine(), bitmap, y);