/******************************************************************************
Atari 400/800
ANTIC video controller
Juergen Buchmueller, June 1998
******************************************************************************/
#include "emu.h"
#include "cpu/m6502/m6502.h"
#include "includes/atari.h"
#ifdef MAME_DEBUG
#define VERBOSE 1
#else
#define VERBOSE 0
#endif
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
ANTIC antic;
/**************************************************************
*
* Reset ANTIC
*
**************************************************************/
void antic_reset(void)
{
/* reset the ANTIC read / write registers */
memset(&antic.r, 0, sizeof(antic.r));
memset(&antic.w, 0, sizeof(antic.w));
antic.r.antic00 = 0xff;
antic.r.antic01 = 0xff;
antic.r.antic02 = 0xff;
antic.r.antic03 = 0xff;
antic.r.antic04 = 0xff;
antic.r.antic05 = 0xff;
antic.r.antic06 = 0xff;
antic.r.antic07 = 0xff;
antic.r.antic08 = 0xff;
antic.r.antic09 = 0xff;
antic.r.antic0a = 0xff;
antic.r.penh = 0x00;
antic.r.penv = 0x00;
antic.r.antic0e = 0xff;
antic.r.nmist = 0x1f;
}
/**************************************************************
*
* Read ANTIC hardware registers
*
**************************************************************/
READ8_HANDLER ( atari_antic_r )
{
UINT8 data = 0xff;
switch (offset & 15)
{
case 0: /* nothing */
data = antic.r.antic00;
break;
case 1: /* nothing */
data = antic.r.antic01;
break;
case 2: /* nothing */
data = antic.r.antic02;
break;
case 3: /* nothing */
data = antic.r.antic03;
break;
case 4: /* nothing */
data = antic.r.antic04;
break;
case 5: /* nothing */
data = antic.r.antic05;
break;
case 6: /* nothing */
data = antic.r.antic06;
break;
case 7: /* nothing */
data = antic.r.antic07;
break;
case 8: /* nothing */
data = antic.r.antic08;
break;
case 9: /* nothing */
data = antic.r.antic09;
break;
case 10: /* WSYNC read */
device_spin_until_trigger(space->machine().device("maincpu"), TRIGGER_HSYNC);
antic.w.wsync = 1;
data = antic.r.antic0a;
break;
case 11: /* vert counter (scanline / 2) */
data = antic.r.vcount = antic.scanline >> 1;
break;
case 12: /* light pen horz pos */
data = antic.r.penh;
break;
case 13: /* light pen vert pos */
data = antic.r.penv;
break;
case 14: /* NMI enable */
data = antic.r.antic0e;
break;
case 15: /* NMI status */
data = antic.r.nmist;
break;
}
return data;
}
/**************************************************************
*
* Write ANTIC hardware registers
*
**************************************************************/
WRITE8_HANDLER ( atari_antic_w )
{
int temp;
switch (offset & 15)
{
case 0:
if( data == antic.w.dmactl )
break;
LOG(("ANTIC 00 write DMACTL $%02X\n", data));
antic.w.dmactl = data;
switch (data & 3)
{
case 0: antic.pfwidth = 0; break;
case 1: antic.pfwidth = 32; break;
case 2: antic.pfwidth = 40; break;
case 3: antic.pfwidth = 48; break;
}
break;
case 1:
if( data == antic.w.chactl )
break;
LOG(("ANTIC 01 write CHACTL $%02X\n", data));
antic.w.chactl = data;
antic.chand = (data & 1) ? 0x00 : 0xff;
antic.chxor = (data & 2) ? 0xff : 0x00;
break;
case 2:
LOG(("ANTIC 02 write DLISTL $%02X\n", data));
antic.w.dlistl = data;
temp = (antic.w.dlisth << 8) + antic.w.dlistl;
antic.dpage = temp & DPAGE;
antic.doffs = temp & DOFFS;
break;
case 3:
LOG(("ANTIC 03 write DLISTH $%02X\n", data));
antic.w.dlisth = data;
temp = (antic.w.dlisth << 8) + antic.w.dlistl;
antic.dpage = temp & DPAGE;
antic.doffs = temp & DOFFS;
break;
case 4:
if( data == antic.w.hscrol )
break;
LOG(("ANTIC 04 write HSCROL $%02X\n", data));
antic.w.hscrol = data & 15;
break;
case 5:
if( data == antic.w.vscrol )
break;
LOG(("ANTIC 05 write VSCROL $%02X\n", data));
antic.w.vscrol = data & 15;
break;
case 6:
if( data == antic.w.pmbasl )
break;
LOG(("ANTIC 06 write PMBASL $%02X\n", data));
/* antic.w.pmbasl = data; */
break;
case 7:
if( data == antic.w.pmbash )
break;
LOG(("ANTIC 07 write PMBASH $%02X\n", data));
antic.w.pmbash = data;
antic.pmbase_s = (data & 0xfc) << 8;
antic.pmbase_d = (data & 0xf8) << 8;
break;
case 8:
if( data == antic.w.chbasl )
break;
LOG(("ANTIC 08 write CHBASL $%02X\n", data));
/* antic.w.chbasl = data; */
break;
case 9:
if( data == antic.w.chbash )
break;
LOG(("ANTIC 09 write CHBASH $%02X\n", data));
antic.w.chbash = data;
break;
case 10: /* WSYNC write */
LOG(("ANTIC 0A write WSYNC $%02X\n", data));
device_spin_until_trigger(space->machine().device("maincpu"), TRIGGER_HSYNC);
antic.w.wsync = 1;
break;
case 11:
if( data == antic.w.antic0b )
break;
LOG(("ANTIC 0B write ?????? $%02X\n", data));
antic.w.antic0b = data;
break;
case 12:
if( data == antic.w.antic0c )
break;
LOG(("ANTIC 0C write ?????? $%02X\n", data));
antic.w.antic0c = data;
break;
case 13:
if( data == antic.w.antic0d )
break;
LOG(("ANTIC 0D write ?????? $%02X\n", data));
antic.w.antic0d = data;
break;
case 14:
if( data == antic.w.nmien )
break;
LOG(("ANTIC 0E write NMIEN $%02X\n", data));
antic.w.nmien = data;
break;
case 15:
LOG(("ANTIC 0F write NMIRES $%02X\n", data));
antic.r.nmist = 0x1f;
antic.w.nmires = data;
break;
}
}
/************* ANTIC mode 00: *********************************
* generate 1-8 empty scanlines
***************************************************************/
ANTIC_RENDERER( antic_mode_0_xx )
{
PREPARE();
memset(dst, PBK, HWIDTH*4);
POST();
}
/************* ANTIC mode 01: *********************************
* display list jump, eventually wait for vsync
***************************************************************/
/************* ANTIC mode 02: *********************************
* character mode 8x8:2 (32/40/48 byte per line)
***************************************************************/
#define MODE2(s) COPY4(dst, antic.pf_21[video->data[s]])
ANTIC_RENDERER( antic_mode_2_32 )
{
PREPARE_TXT2(space, 32);
REP32(MODE2);
POST_TXT(32);
}
ANTIC_RENDERER( antic_mode_2_40 )
{
PREPARE_TXT2(space, 40);
REP40(MODE2);
POST_TXT(40);
}
ANTIC_RENDERER( antic_mode_2_48 )
{
PREPARE_TXT2(space, 48);
REP48(MODE2);
POST_TXT(48);
}
/************* ANTIC mode 03: *********************************
* character mode 8x10:2 (32/40/48 byte per line)
***************************************************************/
#define MODE3(s) COPY4(dst, antic.pf_21[video->data[s]])
ANTIC_RENDERER( antic_mode_3_32 )
{
PREPARE_TXT3(space, 32);
REP32(MODE3);
POST_TXT(32);
}
ANTIC_RENDERER( antic_mode_3_40 )
{
PREPARE_TXT3(space, 40);
REP40(MODE3);
POST_TXT(40);
}
ANTIC_RENDERER( antic_mode_3_48 )
{
PREPARE_TXT3(space, 48);
REP48(MODE3);
POST_TXT(48);
}
/************* ANTIC mode 04: *********************************
* character mode 8x8:4 multi color (32/40/48 byte per line)
***************************************************************/
#define MODE4(s) COPY4(dst, antic.pf_x10b[video->data[s]])
ANTIC_RENDERER( antic_mode_4_32 )
{
PREPARE_TXT45(space, 32,0);
REP32(MODE4);
POST_TXT(32);
}
ANTIC_RENDERER( antic_mode_4_40 )
{
PREPARE_TXT45(space, 40,0);
REP40(MODE4);
POST_TXT(40);
}
ANTIC_RENDERER( antic_mode_4_48 )
{
PREPARE_TXT45(space, 48,0);
REP48(MODE4);
POST_TXT(48);
}
/************* ANTIC mode 05: *********************************
* character mode 8x16:4 multi color (32/40/48 byte per line)
***************************************************************/
#define MODE5(s) COPY4(dst, antic.pf_x10b[video->data[s]])
ANTIC_RENDERER( antic_mode_5_32 )
{
PREPARE_TXT45(space, 32,1);
REP32(MODE5);
POST_TXT(32);
}
ANTIC_RENDERER( antic_mode_5_40 )
{
PREPARE_TXT45(space, 40,1);
REP40(MODE5);
POST_TXT(40);
}
ANTIC_RENDERER( antic_mode_5_48 )
{
PREPARE_TXT45(space, 48,1);
REP48(MODE5);
POST_TXT(48);
}
/************* ANTIC mode 06: *********************************
* character mode 16x8:5 single color (16/20/24 byte per line)
***************************************************************/
#define MODE6(s) COPY8(dst, antic.pf_3210b2[video->data[s]], antic.pf_3210b2[video->data[s]+1])
ANTIC_RENDERER( antic_mode_6_32 )
{
PREPARE_TXT67(space, 16,0);
REP16(MODE6);
POST_TXT(16);
}
ANTIC_RENDERER( antic_mode_6_40 )
{
PREPARE_TXT67(space, 20,0);
REP20(MODE6);
POST_TXT(20);
}
ANTIC_RENDERER( antic_mode_6_48 )
{
PREPARE_TXT67(space, 24,0);
REP24(MODE6);
POST_TXT(24);
}
/************* ANTIC mode 07: *********************************
* character mode 16x16:5 single color (16/20/24 byte per line)
***************************************************************/
#define MODE7(s) COPY8(dst, antic.pf_3210b2[video->data[s]], antic.pf_3210b2[video->data[s]+1])
ANTIC_RENDERER( antic_mode_7_32 )
{
PREPARE_TXT67(space, 16,1);
REP16(MODE7);
POST_TXT(16);
}
ANTIC_RENDERER( antic_mode_7_40 )
{
PREPARE_TXT67(space, 20,1);
REP20(MODE7);
POST_TXT(20);
}
ANTIC_RENDERER( antic_mode_7_48 )
{
PREPARE_TXT67(space, 24,1);
REP24(MODE7);
POST_TXT(24);
}
/************* ANTIC mode 08: *********************************
* graphics mode 8x8:4 (8/10/12 byte per line)
***************************************************************/
#define MODE8(s) COPY16(dst, antic.pf_210b4[video->data[s]],antic.pf_210b4[video->data[s]+1],antic.pf_210b4[video->data[s]+2],antic.pf_210b4[video->data[s]+3])
ANTIC_RENDERER( antic_mode_8_32 )
{
PREPARE_GFX8(space, 8);
REP08(MODE8);
POST_GFX(8);
}
ANTIC_RENDERER( antic_mode_8_40 )
{
PREPARE_GFX8(space, 10);
REP10(MODE8);
POST_GFX(10);
}
ANTIC_RENDERER( antic_mode_8_48 )
{
PREPARE_GFX8(space, 12);
REP12(MODE8);
POST_GFX(12);
}
/************* ANTIC mode 09: *********************************
* graphics mode 4x4:2 (8/10/12 byte per line)
***************************************************************/
#define MODE9(s) COPY8(dst, antic.pf_3210b2[video->data[s]], antic.pf_3210b2[video->data[s]+1])
ANTIC_RENDERER( antic_mode_9_32 )
{
PREPARE_GFX9BC(space, 16);
REP16(MODE9);
POST_GFX(16);
}
ANTIC_RENDERER( antic_mode_9_40 )
{
PREPARE_GFX9BC(space, 20);
REP20(MODE9);
POST_GFX(20);
}
ANTIC_RENDERER( antic_mode_9_48 )
{
PREPARE_GFX9BC(space, 24);
REP24(MODE9);
POST_GFX(24);
}
/************* ANTIC mode 0A: *********************************
* graphics mode 4x4:4 (16/20/24 byte per line)
***************************************************************/
#define MODEA(s) COPY8(dst, antic.pf_210b2[video->data[s]], antic.pf_210b2[video->data[s]+1])
ANTIC_RENDERER( antic_mode_a_32 )
{
PREPARE_GFXA(space, 16);
REP16(MODEA);
POST_GFX(16);
}
ANTIC_RENDERER( antic_mode_a_40 )
{
PREPARE_GFXA(space, 20);
REP20(MODEA);
POST_GFX(20);
}
ANTIC_RENDERER( antic_mode_a_48 )
{
PREPARE_GFXA(space, 24);
REP24(MODEA);
POST_GFX(24);
}
/************* ANTIC mode 0B: *********************************
* graphics mode 2x2:2 (16/20/24 byte per line)
***************************************************************/
#define MODEB(s) COPY8(dst, antic.pf_3210b2[video->data[s]], antic.pf_3210b2[video->data[s]+1])
ANTIC_RENDERER( antic_mode_b_32 )
{
PREPARE_GFX9BC(space, 16);
REP16(MODEB);
POST_GFX(16);
}
ANTIC_RENDERER( antic_mode_b_40 )
{
PREPARE_GFX9BC(space, 20);
REP20(MODEB);
POST_GFX(20);
}
ANTIC_RENDERER( antic_mode_b_48 )
{
PREPARE_GFX9BC(space, 24);
REP24(MODEB);
POST_GFX(24);
}
/************* ANTIC mode 0C: *********************************
* graphics mode 2x1:2 (16/20/24 byte per line)
***************************************************************/
#define MODEC(s) COPY8(dst, antic.pf_3210b2[video->data[s]], antic.pf_3210b2[video->data[s]+1])
ANTIC_RENDERER( antic_mode_c_32 )
{
PREPARE_GFX9BC(space, 16);
REP16(MODEC);
POST_GFX(16);
}
ANTIC_RENDERER( antic_mode_c_40 )
{
PREPARE_GFX9BC(space, 20);
REP20(MODEC);
POST_GFX(20);
}
ANTIC_RENDERER( antic_mode_c_48 )
{
PREPARE_GFX9BC(space, 24);
REP24(MODEC);
POST_GFX(24);
}
/************* ANTIC mode 0D: *********************************
* graphics mode 2x2:4 (32/40/48 byte per line)
***************************************************************/
#define MODED(s) COPY4(dst, antic.pf_x10b[video->data[s]])
ANTIC_RENDERER( antic_mode_d_32 )
{
PREPARE_GFXDE(space, 32);
REP32(MODED);
POST_GFX(32);
}
ANTIC_RENDERER( antic_mode_d_40 )
{
PREPARE_GFXDE(space, 40);
REP40(MODED);
POST_GFX(40);
}
ANTIC_RENDERER( antic_mode_d_48 )
{
PREPARE_GFXDE(space, 48);
REP48(MODED);
POST_GFX(48);
}
/************* ANTIC mode 0E: *********************************
* graphics mode 2x1:4 (32/40/48 byte per line)
***************************************************************/
#define MODEE(s) COPY4(dst, antic.pf_x10b[video->data[s]])
ANTIC_RENDERER( antic_mode_e_32 )
{
PREPARE_GFXDE(space, 32);
REP32(MODEE);
POST_GFX(32);
}
ANTIC_RENDERER( antic_mode_e_40 )
{
PREPARE_GFXDE(space, 40);
REP40(MODEE);
POST_GFX(40);
}
ANTIC_RENDERER( antic_mode_e_48 )
{
PREPARE_GFXDE(space, 48);
REP48(MODEE);
POST_GFX(48);
}
/************* ANTIC mode 0F: *********************************
* graphics mode 1x1:2 (32/40/48 byte per line)
***************************************************************/
#define MODEF(s) COPY4(dst, antic.pf_1b[video->data[s]])
ANTIC_RENDERER( antic_mode_f_32 )
{
PREPARE_GFXF(space, 32);
REP32(MODEF);
POST_GFX(32);
}
ANTIC_RENDERER( antic_mode_f_40 )
{
PREPARE_GFXF(space, 40);
REP40(MODEF);
POST_GFX(40);
}
ANTIC_RENDERER( antic_mode_f_48 )
{
PREPARE_GFXF(space, 48);
REP48(MODEF);
POST_GFX(48);
}