/***************************************************************************
Tatsumi TX-1/Buggy Boy video hardware
****************************************************************************/
#include "emu.h"
#include "render.h"
#include "video/resnet.h"
#include "cpu/i86/i86.h"
#include "includes/tx1.h"
/*************************************
*
* HD46505S-2 CRT Controller
*
*************************************/
#define CURSOR_YPOS 239
#define CURSOR_XPOS 168
#define PRINT_CRTC_DATA 0
/*
6845 cursor output is connected to the main CPU interrupt pin.
The CRTC is programmed to provide a rudimentary VBLANK interrupt.
TODO: Calc TX-1 values...
*/
/*
TODO: Check interrupt timing from CRT config. Probably different between games.
*/
static TIMER_CALLBACK( interrupt_callback )
{
tx1_state *state = machine.driver_data<tx1_state>();
cputag_set_input_line_and_vector(machine, "main_cpu", 0, HOLD_LINE, 0xff);
state->m_interrupt_timer->adjust(machine.primary_screen->time_until_pos(CURSOR_YPOS, CURSOR_XPOS));
}
READ16_HANDLER( tx1_crtc_r )
{
return 0xffff;
}
WRITE16_HANDLER( tx1_crtc_w )
{
if (PRINT_CRTC_DATA)
{
data &= 0xff;
if (offset == 0)
{
switch (data)
{
case 0x00: mame_printf_debug("Horizontal Total "); break;
case 0x01: mame_printf_debug("Horizontal displayed "); break;
case 0x02: mame_printf_debug("Horizontal sync position "); break;
case 0x03: mame_printf_debug("Horizontal sync width "); break;
case 0x04: mame_printf_debug("Vertical total "); break;
case 0x05: mame_printf_debug("Vertical total adjust "); break;
case 0x06: mame_printf_debug("Vertical displayed "); break;
case 0x07: mame_printf_debug("Vertical sync position "); break;
case 0x08: mame_printf_debug("Interlace mode "); break;
case 0x09: mame_printf_debug("Max. scan line address "); break;
case 0x0a: mame_printf_debug("Cursror start "); break;
case 0x0b: mame_printf_debug("Cursor end "); break;
case 0x0c: mame_printf_debug("Start address (h) "); break;
case 0x0d: mame_printf_debug("Start address (l) "); break;
case 0x0e: mame_printf_debug("Cursor (h) "); break;
case 0x0f: mame_printf_debug("Cursor (l) "); break;
case 0x10: mame_printf_debug("Light pen (h)) "); break;
case 0x11: mame_printf_debug("Light pen (l) "); break;
}
}
else if (offset == 1)
{
mame_printf_debug("0x%.2x, (%d)\n",data, data);
}
}
}
/***************************************************************************
TX-1
***************************************************************************/
enum
{
TX1_RDFLAG_RVA8 = 0,
TX1_RDFLAG_RVA9,
TX1_RDFLAG_RVA7,
TX1_RDFLAG_TNLF,
TX1_RDFLAG_STLF,
TX1_RDFLAG_SCCHGF
};
/***************************************************************************
Palette initialisation
bit 3 -- 220 ohm resistor -- RED/GREEN/BLUE
-- 470 ohm resistor -- RED/GREEN/BLUE
-- 1.0kohm resistor -- RED/GREEN/BLUE
bit 0 -- 2.2kohm resistor -- RED/GREEN/BLUE
***************************************************************************/
PALETTE_INIT( tx1 )
{
int i;
static const res_net_info tx1_net_info =
{
RES_NET_VCC_5V | RES_NET_VIN_TTL_OUT,
{
{ RES_NET_AMP_NONE, 0, 0, 4, { 2200, 1000, 470, 220 } },
{ RES_NET_AMP_NONE, 0, 0, 4, { 2200, 1000, 470, 220 } },
{ RES_NET_AMP_NONE, 0, 0, 4, { 2200, 1000, 470, 220 } }
}
};
for (i = 0; i < 256; ++i)
{
int r, g, b;
r = compute_res_net(color_prom[i + 0x300] & 0xf, 0, &tx1_net_info);
g = compute_res_net(color_prom[i + 0x400] & 0xf, 1, &tx1_net_info);
b = compute_res_net(color_prom[i + 0x500] & 0xf, 2, &tx1_net_info);
palette_set_color(machine, i, MAKE_RGB(r, g, b));
}
}
/*************************************
*
* Video Control Registers
*
*************************************/
WRITE16_HANDLER( tx1_bankcs_w )
{
tx1_state *state = space->machine().driver_data<tx1_state>();
vregs_t &tx1_vregs = state->m_vregs;
// AAB2 = /BASET0
// AAB3 = /BASET
// AAB4 = /BSET
// AAB5 = /HASET
// AAB6 = /HSET
offset <<= 1;
if (offset & 0x04)
{
tx1_vregs.ba_inc &= ~0x0000ffff;
tx1_vregs.ba_inc |= data;
if (!(offset & 2))
tx1_vregs.ba_val &= ~0x000ffff;
}
if (offset & 0x08)
{
data &= 0xff;
tx1_vregs.ba_inc &= ~0xffff0000;
tx1_vregs.ba_inc |= data << 16;
// TODO: Schems say D15.
tx1_vregs.bank_mode = BIT(data, 1);
if (!(offset & 2))
tx1_vregs.ba_val &= ~0xffff0000;
}
if ( !(offset & 0x10) )
{
/* Ignore data */
if (offset & 2)
tx1_vregs.ba_val = (tx1_vregs.ba_inc + tx1_vregs.ba_val) & 0x00ffffff;
}
if (offset & 0x20)
{
tx1_vregs.h_inc = data;
if ( !(offset & 2) )
tx1_vregs.h_val = 0;
}
if (!(offset & 0x40))
{
/* TODO: Looks safe to remove this */
// if ( offset & 2 )
tx1_vregs.h_val += tx1_vregs.h_inc;
}
}
WRITE16_HANDLER( tx1_slincs_w )
{
tx1_state *state = space->machine().driver_data<tx1_state>();
if (offset == 1)
state->m_vregs.slin_inc = data;
else
state->m_vregs.slin_inc = state->m_vregs.slin_val = 0;
}
WRITE16_HANDLER( tx1_slock_w )
{
tx1_state *state = space->machine().driver_data<tx1_state>();
state->m_vregs.slock = data & 1;
}
WRITE16_HANDLER( tx1_scolst_w )
{
tx1_state *state = space->machine().driver_data<tx1_state>();
state->m_vregs.scol = data & 0x0707;
}
WRITE16_HANDLER( tx1_flgcs_w )
{
tx1_state *state = space->machine().driver_data<tx1_state>();
state->m_vregs.flags = data & 0xff;
}
/*************************************
*
* Characters
*
*************************************/
static void tx1_draw_char(running_machine &machine, UINT8 *bitmap)
{
tx1_state *state = machine.driver_data<tx1_state>();
UINT16 *tx1_vram = state->m_vram;
INT32 x, y;
UINT32 scroll_x;
UINT8 *chars, *gfx2;
/* 2bpp characters */
chars = machine.region("char_tiles")->base();
gfx2 = chars + 0x4000;
/* X scroll value is the last word in char RAM */
scroll_x = tx1_vram[0xfff] & 0x3ff;
for (y = 0; y < 240; ++y)
{
UINT32 d0 = 0, d1 = 0;
UINT32 colour = 0;
UINT32 y_offs;
UINT32 x_offs;
UINT32 y_gran;
/* No y-scrolling? */
y_offs = y;
if ((y_offs >= 64) && (y_offs < 128))
x_offs = state->m_vregs.slock ? scroll_x : 0;
else
x_offs = 0;
y_gran = y_offs & 7;
if (x_offs & 7)
{
UINT32 tilenum;
UINT16 ram_val = tx1_vram[((y_offs << 4) & 0xf80) + ((x_offs >> 3) & 0x7f)];
tilenum = (ram_val & 0x03ff) | ((ram_val & 0x8000) >> 5);
colour = (ram_val & 0xfc00) >> 8;
d0 = *(gfx2 + (tilenum << 3) + y_gran);
d1 = *(chars + (tilenum << 3) + y_gran);
}
for (x = 0; x < 256 * 3; ++x)
{
UINT32 x_gran = x_offs & 7;
if (!x_gran)
{
UINT32 tilenum;
UINT16 ram_val = tx1_vram[((y_offs << 4) & 0xf80) + ((x_offs >> 3) & 0x7f)];
tilenum = (ram_val & 0x03ff) | ((ram_val & 0x8000) >> 5);
colour = (ram_val & 0xfc00) >> 8;
d0 = *(gfx2 + (tilenum << 3) + y_gran);
d1 = *(chars + (tilenum << 3) + y_gran);
}
*bitmap++ = colour |
(((d1 >> (7 ^ x_gran)) & 1) << 1) |
((d0 >> (7 ^ x_gran)) & 1);
x_offs = (x_offs + 1) & 0x3ff;
}
}
}
/*************************************
*
* Road
*
*************************************/
#define TX1_GET_ROADPIX(NUM) \
{ \
UINT32 addr = (rva6_0 << 5) | (road##NUM##_hcnt & 0x1f); \
UINT8 promaddr1, promaddr2, promaddr3; \
promaddr1 = rom_a[addr]; \
promaddr2 = rom_b[addr]; \
promaddr3 = rom_c[addr]; \
pix[NUM][0][0] = prom_a[promaddr1]; pix[NUM][0][1] = prom_b[promaddr1]; pix[NUM][0][2] = prom_c[promaddr1]; \
pix[NUM][1][0] = prom_a[promaddr2]; pix[NUM][1][1] = prom_b[promaddr2]; pix[NUM][1][2] = prom_c[promaddr2]; \
pix[NUM][2][0] = prom_a[promaddr3]; pix[NUM][2][1] = prom_b[promaddr3]; pix[NUM][2][2] = prom_c[promaddr3]; \
pix[NUM][3][0] = prom_a[0]; pix[NUM][3][1] = prom_b[0]; pix[NUM][3][2] = prom_c[0]; \
}
INLINE void tx1_draw_road_pixel(running_machine &machine, int screen, UINT8 *bmpaddr,
UINT8 apix[3], UINT8 bpix[3], UINT32 pixnuma, UINT32 pixnumb,
UINT8 stl, UINT8 sld, UINT8 selb,
UINT8 bnk, UINT8 rorev, UINT8 eb, UINT8 r, UINT8 delr)
{
tx1_state *state = machine.driver_data<tx1_state>();
vregs_t &tx1_vregs = state->m_vregs;
UINT8 a0 = BIT(apix[0], pixnuma);
UINT8 a1 = BIT(apix[1], pixnuma);
UINT8 a2 = BIT(apix[2], pixnuma);
UINT8 b0 = BIT(bpix[0], pixnumb);
UINT8 b1 = BIT(bpix[1], pixnumb);
UINT8 b2 = BIT(bpix[2], pixnumb);
UINT8 d3;
UINT8 d2;
UINT8 d1;
UINT8 d0;
UINT8 sel;
UINT8 c6 = BIT(sld, 6);
UINT8 c5 = BIT(sld, 5);
UINT8 c4 = BIT(sld, 4);
UINT8 c3 = BIT(sld, 2);
UINT32 addr_offset = screen * 256;
sel = !bnk && ( (a2 && !b0) || (!a0 && b2) || !a1 || !a2 || !b1 || !b2 );
d3 =
(a2 && a1 && a0 && b2 && b1 && b0 && !rorev)
|| (a1 && b1 && !b0 && stl && !bnk && !c6)
|| (a1 && !a0 && b1 && stl && !bnk && !c6)
|| (a1 && !b2 && b1 && stl && !bnk && !c6)
|| (a2 && b2 && !b1 && stl && !bnk && !c4)
|| (a2 && !a1 && b2 && stl && !bnk && !c4)
|| (!a2 && a1 && b2 && stl && !bnk && !c6)
|| (a2 && !b2 && b1 && stl && !bnk && !c6)
|| (!a2 && !a1 && stl && !bnk && !c5)
|| (!b2 && !b1 && stl && !bnk && !c5)
|| (!b0 && !stl && !bnk && !c3)
|| (!b1 && !stl && !bnk && !c3)
|| (!a0 && !stl && !bnk && !c3)
|| (!a1 && !stl && !bnk && !c3)
|| (!a2 && !stl && !bnk && !c3)
|| (!b2 && !stl && !bnk && !c3)
|| (bnk && !rorev);
if (eb == 0)
{
if (sel == 1)
{
d2 = stl && (!a2 || !b2);
d1 = !stl || (!a2 && !a1) || (!b1 && !b2) || (a2 && !b1) || (b2 && !a1);
d0 = !stl
|| (!a2 && !a0 && b1)
|| (a1 && !b2 && !b0)
|| (!a2 && !a1 && !a0)
|| (!b2 && !b1 && !b0)
|| (a2 && a1 && !b0)
|| (!a0 && b2 && b1)
|| (a2 && !b1 && !b0)
|| (!a1 && !a0 && b2)
|| (!a2 && !a0 && b2)
|| (a2 && !b2 && !b0);
}
else
{
d2 = BIT(tx1_vregs.scol, selb ? 2 : 10);
d1 = BIT(tx1_vregs.scol, selb ? 1 : 9);
d0 = BIT(tx1_vregs.scol, selb ? 0 : 8);
}
}
else
d2 = d1 = d0 = 0;
*(bmpaddr + addr_offset) = (bnk << 6) | (r << 5) | (!(sel && delr) << 4 ) | (d3 << 3) | (d2 << 2) | (d1 << 1) | d0;
}
/* This could do with a tidy up and more comments... */
static void tx1_draw_road(running_machine &machine, UINT8 *bitmap)
{
tx1_state *state = machine.driver_data<tx1_state>();
UINT16 *tx1_rcram = state->m_rcram;
vregs_t &tx1_vregs = state->m_vregs;
INT32 y;
UINT32 rva9_8;
UINT32 rva7;
UINT32 tnlf;
UINT32 stlf;
UINT32 scchgf;
UINT32 vc = 0;
UINT16 road0_hcnt;
UINT8 road0_pcnt;
UINT16 road1_hcnt;
UINT8 road1_pcnt;
UINT8 pix[2][4][3];
/* Road slice map ROMs */
const UINT8 *const gfx3 = machine.region("gfx3")->base();
const UINT8 *const rom_a = gfx3;
const UINT8 *const rom_b = gfx3 + 0x2000;
const UINT8 *const rom_c = gfx3 + 0x4000;
/* Pixel data */
const UINT8 *const proms = machine.region("proms")->base();
const UINT8 *const prom_a = proms + 0x1100;
const UINT8 *const prom_b = proms + 0x1300;
const UINT8 *const prom_c = proms + 0x1500;
const UINT8 *const vprom = proms + 0x1700;
rva9_8 = (tx1_vregs.flags & 3) << 8;
rva7 = !BIT(tx1_vregs.flags, TX1_RDFLAG_RVA7) << 7;
tnlf = BIT(tx1_vregs.flags, TX1_RDFLAG_TNLF);
scchgf = BIT(tx1_vregs.flags, TX1_RDFLAG_SCCHGF);
stlf = BIT(tx1_vregs.flags, TX1_RDFLAG_STLF);
for (y = 0; y < 240; ++y)
{
UINT32 x;
UINT8 sld;
UINT8 rva6_0;
UINT16 rcrdb15_0;
UINT16 rva_addr;
UINT32 bank_cnt;
UINT16 vat;
UINT16 vp0;
UINT16 vp1;
UINT16 vp2;
UINT16 vp3;
UINT16 vp4;
UINT32 va8, va9, va10, va11, va12, va13, va14, va15;
UINT32 v0, v1, v2;
UINT8 hc1_u, hc1_l;
UINT8 hc0_u, hc0_l;
UINT32 bnkls, bnkcs, bnkrs;
UINT32 rl, rc, rr;
UINT32 stl;
UINT32 selb;
UINT32 ebls, ebcs, ebrs;
UINT8 *bmpaddr = bitmap + (y * 768);
UINT32 rltmp, rctmp, rrtmp;
UINT32 eltmp, ectmp, ertmp;
UINT32 tmpm;
UINT32 tmpn;
UINT32 tmpc;
UINT32 tmpd;
UINT8 scrcnt0;
UINT8 scrcnt1;
UINT8 rorevls = 0;
UINT8 rorevcs = 0;
UINT8 rorevrs = 0;
int febl[2] = { 0, 0 };
int febr[2] = { 0, 0 };
int febc[2] = { 0, 0 };
/* Road vertical address */
if (BIT(tx1_vregs.h_val, 15))
rva6_0 = 0x7f;
else
rva6_0 = (~tx1_vregs.h_val >> 7) & 0x7f;
rva_addr = rva9_8 | rva6_0;
/* Get the stripe data also */
sld = vprom[rva6_0] + tx1_vregs.slin_val;
/* Load the left road h-counter */
rcrdb15_0 = tx1_rcram[(0x80 + rva_addr) ^ 0x7ff];
road0_pcnt = rcrdb15_0 & 0x7;
road0_hcnt = (rcrdb15_0 >> 3) & 0x7f;
road0_hcnt |= rcrdb15_0 & 0xfc00 ? 0x80 : 0;
road0_hcnt |= (rcrdb15_0 & 0xfc00) == 0xfc00 ? 0x100 : 0x000;
/* Load the second road h-counter */
rcrdb15_0 = tx1_rcram[(rva7 + rva_addr) ^ 0x7ff];
road1_pcnt = rcrdb15_0 & 0x7;
road1_hcnt = (rcrdb15_0 >> 3) & 0x7f;
road1_hcnt |= rcrdb15_0 & 0xfc00 ? 0x80 : 0;
road1_hcnt |= (rcrdb15_0 & 0xfc00) == 0xfc00 ? 0x100 : 0x000;
road1_hcnt |= (rcrdb15_0 & 0x800);
scrcnt0 = (road0_hcnt >> 5) & 0xf;
scrcnt1 = (road1_hcnt >> 5) & 0xf;
if (road0_pcnt & 7)
{
TX1_GET_ROADPIX(0);
febl[0] = (scrcnt0 + 0) & 0xc;
febc[0] = (scrcnt0 + 1) & 0xc;
febr[0] = (scrcnt0 + 2) & 0xc;
}
if (road1_pcnt & 7)
{
UINT32 y4 = (road1_hcnt >> 4) & 1;
UINT32 temp = (road1_hcnt >> 5) & 0xf;
UINT32 x, u;
UINT32 fl11 = BIT(road1_hcnt, 15);
TX1_GET_ROADPIX(1);
x = (temp & 0xc);
u = !(((temp & 1) && y4) || (temp & 2));
rorevls = ((fl11 && !x) || (fl11 && x && u));
febl[1] = x;
temp += 1;
x = (temp & 0xc);
u = !(((temp & 1) && y4) || (temp & 2));
rorevcs = ((fl11 && !x) || (fl11 && x && u));
febc[1] = x;
temp += 1;
x = (temp & 0xc);
u = !(((temp & 1) && y4) || (temp & 2));
rorevrs = ((fl11 && !x) || (fl11 && x && u));
febr[1] = x;
}
/* Load the bank counter with accumulator bits 14-5 */
bank_cnt = (tx1_vregs.ba_val >> 5) & 0x3ff;
/* Load vertical position data */
vat = tx1_rcram[(rva9_8 + 7) ^ 0x7f8];
vp0 = tx1_rcram[(rva9_8 + 6) ^ 0x7f8];
vp1 = tx1_rcram[(rva9_8 + 5) ^ 0x7f8];
vp2 = tx1_rcram[(rva9_8 + 4) ^ 0x7f8];
vp3 = tx1_rcram[(rva9_8 + 3) ^ 0x7f8];
vp4 = tx1_rcram[(rva9_8 + 2) ^ 0x7f8];
/* */
if (y-1 == vp0) vc++;
if (y-1 == vp1) vc++;
if (y-1 == vp2) vc++;
if (y-1 == vp3) vc++;
if (y-1 == vp4) vc++;
/* */
va8 = BIT(vat, 8);
va9 = BIT(vat, 9);
va10 = BIT(vat, 10);
va11 = BIT(vat, 11);
va12 = BIT(vat, 12);
va13 = BIT(vat, 13);
va14 = BIT(vat, 14);
va15 = BIT(vat, 15);
v0 = BIT(vc, 0);
v1 = BIT(vc, 1);
v2 = BIT(vc, 2);
/* Load the horizontal tunnel position counters */
hc1_u = tx1_rcram[(rva9_8 + 1) ^ 0x7f8] >> 8;
hc1_l = tx1_rcram[(rva9_8 + 1) ^ 0x7f8] & 0xff;
hc0_u = tx1_rcram[(rva9_8 + 0) ^ 0x7f8] >> 8;
hc0_l = tx1_rcram[(rva9_8 + 0) ^ 0x7f8] & 0xff;
stl = !stlf || v0 || (!v2 && !scchgf) || scchgf;
selb = (!v2 && !scchgf) || v2;
rltmp =
(v2 && !v0 && !va10)
|| (!v2 && v0 && !va10)
|| (v2 && !v0 && !va11)
|| (v2 && !v1 && !v0)
|| (!v2 && v0 && !va11)
|| (!v2 && v1 && !v0)
|| (!v2 && !v1 && v0);
rctmp =
(v2 && !v0 && va9 && va8)
|| (!v2 && v0 && va9 && va8)
|| (v2 && !v0 && !va11)
|| (v2 && !v1 && !v0)
|| (!v2 && v0 && !va11)
|| (!v2 && v1 && !v0)
|| (!v2 && !v1 && v0);
rrtmp =
(v2 && !v0 && !va11 && !va10)
|| (!v2 && v0 && !va11 && !va10)
|| (v2 && !v0 && va9)
|| (!v2 && v0 && va9)
|| (v2 && !v1 && !v0)
|| (!v2 && v1 && !v0)
|| (!v2 && !v1 && v0);
ectmp =
(v2 && !v0 && va13 && va12)
|| (!v2 && v1 && va13 && va12)
|| (!v2 && !v1 && v0)
|| (v2 && !v0 && !va15)
|| (!v2 && v1 && !va15);
eltmp =
(v2 && !v0 && !va14)
|| (!v2 && v1 && !va14)
|| (!v2 && !v1 && v0)
|| (v2 && !v0 && !va15)
|| (!v2 && v1 && !va15);
ertmp =
(v2 && !v0 && !va15 && !va14)
|| (!v2 && v1 && !va15 && !va14)
|| (v2 && !v0 && va13)
|| (!v2 && v1 && va13)
|| (!v2 && !v1 && v0);
tmpn = (v2 && !v0) || (!v2 && v0);
tmpm = (v2 && !v0) || (!v2 && v1);
tmpc = (!v1 && !v0) || (v2);
tmpd = v1 && v0 && va11;
for (x = 0; x < 256; x++)
{
UINT32 pixnum0 = (road0_pcnt & 7) ^ 7;
UINT32 pixnum1 = (road1_pcnt & 7) ^ 7;
UINT32 cyu, cyl;
UINT32 delrl, delrc, delrr;
/* */
scrcnt0 = (road0_hcnt >> 5) & 0xf;
scrcnt1 = (road1_hcnt >> 5) & 0xf;
/* Get new pixel data? */
if (!(road0_pcnt & 7))
{
TX1_GET_ROADPIX(0);
/* Road 0 enables */
febl[0] = (scrcnt0 + 0) & 0xc;
febc[0] = (scrcnt0 + 1) & 0xc;
febr[0] = (scrcnt0 + 2) & 0xc;
}
if (!(road1_pcnt & 7))
{
UINT32 y4 = (road1_hcnt >> 4) & 1;
UINT32 temp = (road1_hcnt >> 5) & 0xf;
UINT32 x, u;
UINT32 fl11 = BIT(road1_hcnt, 15);
TX1_GET_ROADPIX(1);
x = (temp & 0xc);
u = !(((temp & 1) && y4) || (temp & 2));
rorevls = ((fl11 && !x) || (fl11 && x && u));
febl[1] = x;
temp += 1;
x = (temp & 0xc);
u = !(((temp & 1) && y4) || (temp & 2));
rorevcs = ((fl11 && !x) || (fl11 && x && u));
febc[1] = x;
temp += 1;
x = (temp & 0xc);
u = !(((temp & 1) && y4) || (temp & 2));
rorevrs = ((fl11 && !x) || (fl11 && x && u));
febr[1] = x;
}
/* Road camber/banking */
if (BIT(tx1_vregs.ba_val, 23))
{
bnkls = 1;
bnkcs = 1;
bnkrs = 1;
}
else if (tx1_vregs.ba_val & 0x007f8000)
{
bnkls = 0;
bnkcs = 0;
bnkrs = 0;
}
else
{
bnkls = bank_cnt < 0x400;
bnkcs = bank_cnt < 0x300;
bnkrs = bank_cnt < 0x200;
}
if (tx1_vregs.bank_mode)
{
bnkls ^= 1;
bnkcs ^= 1;
bnkrs ^= 1;
}
cyu = hc1_u == 0xff;
cyl = hc1_l == 0xff;
rl = tnlf && ( rltmp || (tmpn && (!cyl || (va8 && va9 && cyu))) );
rc = tnlf && ( rctmp || (tmpn && ((!va10 && !cyl) || (va9 && cyu))) );
rr = tnlf && ( rrtmp || (tmpn && ((!va11 && !cyl) || (va8 && cyu))) );
/* Evaluates to 0 for tunnels */
delrl = !tnlf || tmpc || ((tmpd && va10) && ((!va8 && cyl) || (!va9 && cyl) || (!cyu && !cyl)));
delrr =
!tnlf
|| tmpc
|| (v1 && v0 && va10 && !va9 && !va8 && cyl)
|| (v1 && v0 && va10 && !va9 && cyl && !cyu)
|| (tmpd && !va9 && !cyu)
|| (tmpd && !va9 && !va8);
delrc = !tnlf || tmpc || (tmpd && ((!va8 && cyl && !cyu) || (!va8 && va10 && !cyu) || (!va9 && cyl) || (va10 && !va9)));
cyu = hc0_u == 0xff;
cyl = hc0_l == 0xff;
ebls = tnlf && ( eltmp || (tmpm && (!cyl || (va12 && va13 && cyu))));
ebcs = tnlf && ( ectmp || (tmpm && ((!va14 && !cyl) || (va13 && cyu))));
ebrs = tnlf && ( ertmp || (tmpm && ((!va15 && !cyl) || (va12 && cyu))));
/* Carry for horizontal position counters */
cyu = hc0_u == 0xff;
cyl = hc0_l == 0xff;
if (!(bnkls && !rl))
{
int a, b;
if (!febl[0])
a = (scrcnt0) & 3;
else
a = 3;
if (!febl[1])
b = (scrcnt1) & 3;
else
b = 3;
tx1_draw_road_pixel(machine, 0, bmpaddr,
&pix[0][a][0], &pix[1][b][0],
pixnum0, pixnum1,
stl, sld, selb, bnkls, rorevls, ebls, rl, delrl);
}
else
*(bmpaddr) = (bnkls << 6) | (rl << 5);
if (!(bnkcs && !rc))
{
int a, b;
if (!febc[0])
a = (scrcnt0 + 1) & 3;
else
a = 3;
if (!febc[1])
b = (scrcnt1 + 1) & 3;
else
b = 3;
tx1_draw_road_pixel(machine, 1, bmpaddr,
&pix[0][a][0], &pix[1][b][0],
pixnum0, pixnum1,
stl, sld, selb, bnkcs, rorevcs, ebcs, rc, delrc);
}
else
*(bmpaddr + 256) = (bnkcs << 6) | (rc << 5);
if (!(bnkrs && !rr))
{
int a, b;
if (!febr[0])
a = (scrcnt0 + 2) & 3;
else
a = 3;
if (!febr[1])
b = (scrcnt1 + 2) & 3;
else
b = 3;
tx1_draw_road_pixel(machine, 2, bmpaddr,
&pix[0][a][0], &pix[1][b][0],
pixnum0, pixnum1,
stl, sld, selb, bnkrs, rorevrs, ebrs, rr, delrr);
}
else
*(bmpaddr + 512) = (bnkrs << 6) | (rr << 5);
++bmpaddr;
/* Update road counters */
if (!(++road0_pcnt & 7))
++road0_hcnt;
if (!(++road1_pcnt & 7))
++road1_hcnt;
/* Increment horizontal counters (stop at 0xff) */
if (hc0_u != 0xff) ++hc0_u;
if (hc0_l != 0xff) ++hc0_l;
if (hc1_u != 0xff) ++hc1_u;
if (hc1_l != 0xff) ++hc1_l;
/* Update bank counter */
bank_cnt = (bank_cnt + 1) & 0x7ff;
}
tx1_vregs.h_val += tx1_vregs.h_inc;
/* Finally, increment the bank accumulator */
tx1_vregs.ba_val = (tx1_vregs.ba_val + tx1_vregs.ba_inc) & 0x00ffffff;
}
}
/*************************************
*
* Objects
*
*************************************/
static void tx1_draw_objects(running_machine &machine, UINT8 *bitmap)
{
tx1_state *state = machine.driver_data<tx1_state>();
UINT16 *tx1_objram = state->m_objram;
#define FRAC 16
UINT32 offs;
/* The many lookup table ROMs */
const UINT8 *const ic48 = machine.region("user3")->base();
const UINT8 *const ic281 = ic48 + 0x2000;
const UINT8 *const proms = machine.region("proms")->base();
const UINT8 *const ic190 = proms + 0xc00;
const UINT8 *const ic162 = proms + 0xe00;
const UINT8 *const ic25 = proms + 0x1000;
const UINT8 *const ic106 = machine.region("obj_map")->base();
const UINT8 *const ic73 = ic106 + 0x4000;
const UINT8 *const pixdata_rgn = machine.region("obj_tiles")->base();
for (offs = 0x0; offs <= 0x300; offs += 8)
{
UINT32 x;
UINT32 y;
UINT32 gxflip;
UINT32 x_scale;
UINT32 x_step;
UINT16 y_scale;
UINT16 y_step;
UINT8 pctmp0_7;
UINT8 code;
/* Check for end of object list */
if ((tx1_objram[offs] & 0xff00) == 0xff00)
break;
/* X scale */
x_scale = tx1_objram[offs + 2] & 0xff;
/* TODO: Confirm against hardware? */
if (x_scale == 0)
continue;
/* 16-bit y-scale accumulator */
y_scale = tx1_objram[offs + 1];
y_step = tx1_objram[offs + 3];
/* Object number */
code = tx1_objram[offs] & 0xff;
/* Attributes */
pctmp0_7 = tx1_objram[offs + 2] >> 8;
/* Global x-flip */
gxflip = (pctmp0_7 & 0x80) >> 7;
/* Add 1 to account for line buffering */
y = (tx1_objram[offs] >> 8) + 1;
for (; y < 240; ++y)
{
UINT32 rom_addr2 = 0;
UINT8 ic106_data = 0;
UINT8 ic73_data;
/* Are we drawing on this line? */
/* TODO: See big lampposts. */
if (y_scale & 0x8000)
break;
{
UINT32 psa0_11;
UINT32 ic48_addr;
UINT32 ic48_data;
UINT32 rom_addr;
UINT32 x_acc;
UINT32 newtile = 1;
UINT32 dataend = 0;
UINT8 data1 = 0;
UINT8 data2 = 0;
UINT32 xflip = 0;
UINT32 opcd0_7 = 0;
UINT32 lasttile = 0;
/* Use the object code to lookup the tile sequence data in ROM */
ic48_addr = code << 4;
ic48_addr |= ((y_scale >> 11) & 0xf);
ic48_data = ic48[ic48_addr];
/* Reached the bottom of the object? (/PASS2E) */
if (ic48_data == 0xff)
break;
/* Combine ROM and PROM data */
psa0_11 = ((ic25[code] << 8) | ic48_data) & 0xfff;
/* psa8_11 */
rom_addr = (psa0_11 & ~0xff) << 2;
/* Prepare the x-scaling */
x_step = (128 << FRAC) / x_scale;
x_acc = (psa0_11 & 0xff) << (FRAC + 5);
#define TX1_MASK 0xfff
x = tx1_objram[offs + 4] & TX1_MASK;
for (;;)
{
if (newtile)
{
UINT32 psbb0_12;
UINT32 pscb0_14;
UINT32 pscb11;
UINT8 *romptr;
UINT32 ic281_addr;
UINT32 grom_addr;
UINT32 lut_data;
UINT32 low_addr = ((x_acc >> (FRAC + 3)) & TX1_MASK);
if (gxflip)
{
UINT32 xor_mask;
if (BIT(psa0_11, 11) && BIT(psa0_11, 10))
xor_mask = 0xf;
else if (BIT(psa0_11, 11) || BIT(psa0_11, 10) || BIT(psa0_11, 9))
xor_mask = 0x7;
else
xor_mask = 0x3;
rom_addr2 = rom_addr + (xor_mask ^ low_addr);
}
else
rom_addr2 = rom_addr + low_addr;
ic106_data = ic106[rom_addr2 & 0x3fff];
if ((ic106_data & 0x40) && dataend)
lasttile = 1;
dataend |= ic106_data & 0x40;
/* Retrieve data for an 8x8 tile */
ic73_data = ic73[rom_addr2];
/* This is the data from the LUT pair */
lut_data = (ic106_data << 8) | ic73_data;
psbb0_12 = lut_data & 0x1fff;
pscb0_14 = (psbb0_12 & 0xc3f);
/* Bits 9_6 are from PCTMP11-8 or PSBB9-6 */
if (BIT(psbb0_12, 12))
pscb0_14 |= psbb0_12 & 0x3c0;
else
pscb0_14 |= (pctmp0_7 & 0xf) << 6;
if (BIT(lut_data, 13))
pscb0_14 |= BIT(psbb0_12, 10) << 12;
else
pscb0_14 |= ((pctmp0_7 & 0x70) << 8);
/* Bit 12 is bit 10 duplicated. */
pscb0_14 &= ~(1 << 12);
pscb0_14 |= BIT(psbb0_12, 10) << 12;
pscb11 = BIT(pscb0_14, 11);
/* TODO: Remove this - it's constant. */
romptr = (UINT8*)(pixdata_rgn + pscb11 * (0x4000 * 2));
grom_addr = ((pscb0_14 << 3) | ((y_scale >> 8) & 7)) & 0x3fff;
/* Get raw 8x8 2bpp pixel row data */
data1 = *(grom_addr + romptr);
data2 = *(grom_addr + romptr + 0x4000);
/* Determine flip state (global XOR local) */
xflip = gxflip ^ !BIT(lut_data, 15);
ic281_addr = pscb0_14 & 0x3ff;
ic281_addr |= ((pscb0_14 & 0x7000) >> 2);
ic281_addr |= pscb11 << 13;
opcd0_7 = ic281[ic281_addr];
newtile = 0;
}
/* Draw a pixel? */
if (x < 768)
{
UINT8 pix;
UINT8 bit;
bit = (x_acc >> FRAC) & 7;
if (xflip)
bit ^= 7;
pix = (((data1 >> bit) & 1) << 1) | ((data2 >> bit) & 1);
/* Draw pixel, if not transparent */
if ( !(!(opcd0_7 & 0x80) && !pix) )
{
UINT8 color;
UINT32 prom_addr;
prom_addr = ((opcd0_7 << 2) | pix) & 0x1ff;
/* Inverted on schematic */
if (x & 1)
color = ~ic190[prom_addr] & 0x3f;
else
color = ~ic162[prom_addr] & 0x3f;
*(bitmap + 768*y + x) = 0x40 | color;
}
}
/* Check if we've stepped into a new 8x8 tile */
if ((((x_acc + x_step) >> (FRAC + 3)) & TX1_MASK) != ((x_acc >> (FRAC + 3)) & TX1_MASK))
{
if (lasttile)
break;
newtile = 1;
}
x = (x + 1) & TX1_MASK;
x_acc += x_step;
}
}
y_scale += y_step;
}
}
}
/*************************************
*
* Core Functions
*
*************************************/
VIDEO_START( tx1 )
{
tx1_state *state = machine.driver_data<tx1_state>();
/* Allocate a large bitmap that covers the three screens */
state->m_bitmap = auto_bitmap_alloc(machine, 768, 256, BITMAP_FORMAT_INDEXED16);
/* Allocate some bitmaps */
state->m_chr_bmp = auto_alloc_array(machine, UINT8, 256 * 3 * 240);
state->m_obj_bmp = auto_alloc_array(machine, UINT8, 256 * 3 * 240);
state->m_rod_bmp = auto_alloc_array(machine, UINT8, 256 * 3 * 240);
/* Set a timer to run the interrupts */
state->m_interrupt_timer = machine.scheduler().timer_alloc(FUNC(interrupt_callback));
/* /CUDISP CRTC interrupt */
state->m_interrupt_timer->adjust(machine.primary_screen->time_until_pos(CURSOR_YPOS, CURSOR_XPOS));
}
SCREEN_EOF( tx1 )
{
tx1_state *state = machine.driver_data<tx1_state>();
/* /VSYNC: Update TZ113 */
state->m_vregs.slin_val += state->m_vregs.slin_inc;
}
static void tx1_combine_layers(running_machine &machine, bitmap_t *bitmap, int screen)
{
tx1_state *state = machine.driver_data<tx1_state>();
int x, y;
UINT8 *chr_pal = machine.region("proms")->base() + 0x900;
int x_offset = screen * 256;
for (y = 0; y < 240; ++y)
{
UINT16 *bmp_addr = BITMAP_ADDR16(bitmap, y, 0);
UINT32 bmp_offset = y * 768 + x_offset;
UINT8 *chr_addr = state->m_chr_bmp + bmp_offset;
UINT8 *rod_addr = state->m_rod_bmp + bmp_offset;
UINT8 *obj_addr = state->m_obj_bmp + bmp_offset;
for (x = 0; x < 256; ++x)
{
UINT8 out_val;
UINT32 char_val = chr_addr[x];
UINT32 c7 = BIT(char_val, 7);
UINT32 c1 = BIT(char_val, 1);
UINT32 c0 = BIT(char_val, 0);
UINT32 road_val = rod_addr[x];
UINT32 r6 = BIT(road_val, 6);
UINT32 r5 = BIT(road_val, 5);
UINT32 obj_val = obj_addr[x];
UINT32 obj6 = BIT(obj_val, 6);
UINT32 term1 = !(c7 && c1);
UINT32 term2 = !(c7 && c0);
UINT32 term3 = r5 || !r6;
UINT32 p12 = !(term1 && term2 && term3);
UINT32 p6 = !(obj6 && term1 && term2);
UINT32 sel = p12 | (p6 << 1);
UINT32 psel = (!(p6 && p12) << 1) | p6;
if (sel == 3) out_val = ((char_val & 0xc0) >> 2) | (chr_pal[char_val] & 0xf);
else if (sel == 2) out_val = road_val & 0x3f;
else out_val = obj_val & 0x3f;
*bmp_addr++ = (psel << 6) | out_val;
}
}
}
SCREEN_UPDATE( tx1 )
{
tx1_state *state = screen->machine().driver_data<tx1_state>();
device_t *left_screen = screen->machine().device("lscreen");
device_t *centre_screen = screen->machine().device("cscreen");
device_t *right_screen = screen->machine().device("rscreen");
if (screen == left_screen)
{
memset(state->m_obj_bmp, 0, 768*240);
tx1_draw_char(screen->machine(), state->m_chr_bmp);
tx1_draw_road(screen->machine(), state->m_rod_bmp);
tx1_draw_objects(screen->machine(), state->m_obj_bmp);
tx1_combine_layers(screen->machine(), bitmap, 0);
}
else if (screen == centre_screen)
{
tx1_combine_layers(screen->machine(), bitmap, 1);
}
else if (screen == right_screen)
{
tx1_combine_layers(screen->machine(), bitmap, 2);
}
return 0;
}
/***************************************************************************
Buggy Boy
***************************************************************************/
/* Road register bits */
#define BB_RDFLAG_WAVE1 7
#define BB_RDFLAG_WAVE0 6
#define BB_RDFLAG_TNLMD1 5
#define BB_RDFLAG_TNLMD0 4
#define BB_RDFLAG_TNLF 3
#define BB_RDFLAG_LINF 2
#define BB_RDFLAG_RVA7 1
#define BB_RDFLAG_WANGL 0
/***************************************************************************
Convert the color PROMs into a more useable format.
IC39, BB12 = Blue
IC40, BB11 = Green
IC41, BB10 = Red
IC42, BB13 = Brightness
bit 3 -- 220 ohm resistor -- RED/GREEN/BLUE
-- 470 ohm resistor -- RED/GREEN/BLUE
-- 1.0kohm resistor -- RED/GREEN/BLUE
bit 0 -- 2.2kohm resistor -- RED/GREEN/BLUE
bit 0 -- 4.7kohm resistor -- BLUE
bit 1 -- 4.7kohm resistor -- GREEN
bit 2 -- 4.7kohm resistor -- RED
***************************************************************************/
PALETTE_INIT( buggyboy )
{
int i;
for (i = 0; i < 0x100; i++)
{
int bit0, bit1, bit2, bit3, bit4;
int r, g, b;
bit0 = BIT(color_prom[i + 0x000], 0);
bit1 = BIT(color_prom[i + 0x000], 1);
bit2 = BIT(color_prom[i + 0x000], 2);
bit3 = BIT(color_prom[i + 0x000], 3);
bit4 = BIT(color_prom[i + 0x300], 2);
r = 0x06 * bit4 + 0x0d * bit0 + 0x1e * bit1 + 0x41 * bit2 + 0x8a * bit3;
bit0 = BIT(color_prom[i + 0x100], 0);
bit1 = BIT(color_prom[i + 0x100], 1);
bit2 = BIT(color_prom[i + 0x100], 2);
bit3 = BIT(color_prom[i + 0x100], 3);
bit4 = BIT(color_prom[i + 0x300], 1);
g = 0x06 * bit4 + 0x0d * bit0 + 0x1e * bit1 + 0x41 * bit2 + 0x8a * bit3;
bit0 = BIT(color_prom[i + 0x200], 0);
bit1 = BIT(color_prom[i + 0x200], 1);
bit2 = BIT(color_prom[i + 0x200], 2);
bit3 = BIT(color_prom[i + 0x200], 3);
bit4 = BIT(color_prom[i + 0x300], 0);
b = 0x06 * bit4 + 0x0d * bit0 + 0x1e * bit1 + 0x41 * bit2 + 0x8a * bit3;
palette_set_color(machine, i, MAKE_RGB(r, g, b));
}
}
/*************************************
*
* Characters
*
*************************************/
static void buggyboy_draw_char(running_machine &machine, UINT8 *bitmap, int wide)
{
tx1_state *state = machine.driver_data<tx1_state>();
UINT16 *buggyboy_vram = state->m_vram;
INT32 x, y;
UINT32 scroll_x, scroll_y;
UINT8 *chars, *gfx2;
UINT32 total_width;
UINT32 x_mask;
/* 2bpp characters */
chars = machine.region("char_tiles")->base();
gfx2 = machine.region("char_tiles")->base() + 0x4000;
/* X/Y scroll values are the last word in char RAM */
if (wide)
{
scroll_y = (buggyboy_vram[0xfff] >> 10) & 0x3f;
scroll_x = buggyboy_vram[0xfff] & 0x3ff;
total_width = 768;
x_mask = 0x3ff;
}
else
{
scroll_y = (buggyboy_vram[0x7ff] >> 10) & 0x3f;
scroll_x = buggyboy_vram[0x7ff] & 0x1ff;
total_width = 256;
x_mask = 0x1ff;
}
for (y = 0; y < 240; ++y)
{
UINT32 d0 = 0, d1 = 0;
UINT32 colour = 0;
UINT32 y_offs;
UINT32 x_offs;
UINT32 y_gran;
/* There's no y-scrolling between scanlines 0 and 63 */
if (y < 64)
y_offs = y;
else
{
y_offs = (y + (scroll_y | 0xc0) + 1) & 0xff;
/* Clamp */
if (y_offs < 64)
y_offs |= 0xc0;
}
if ((y_offs >= 64) && (y_offs < 128))
x_offs = scroll_x;
else
x_offs = 0;
y_gran = y_offs & 7;
if (x_offs & 7)
{
UINT32 tilenum;
UINT16 ram_val;
if (wide)
ram_val = buggyboy_vram[((y_offs << 4) & 0xf80) + ((x_offs >> 3) & 0x7f)];
else
ram_val = buggyboy_vram[((y_offs << 3) & 0x7c0) + ((x_offs >> 3) & 0x3f)];
tilenum = (ram_val & 0x03ff) | ((ram_val & 0x8000) >> 5);
colour = (ram_val & 0xfc00) >> 8;
d0 = *(gfx2 + (tilenum << 3) + y_gran);
d1 = *(chars + (tilenum << 3) + y_gran);
}
for (x = 0; x < total_width; ++x)
{
UINT32 x_gran = x_offs & 7;
if (!x_gran)
{
UINT32 tilenum;
UINT16 ram_val;
if (wide)
ram_val = buggyboy_vram[((y_offs << 4) & 0xf80) + ((x_offs >> 3) & 0x7f)];
else
ram_val = buggyboy_vram[((y_offs << 3) & 0x7c0) + ((x_offs >> 3) & 0x3f)];
tilenum = (ram_val & 0x03ff) | ((ram_val & 0x8000) >> 5);
colour = (ram_val & 0xfc00) >> 8;
d0 = *(gfx2 + (tilenum << 3) + y_gran);
d1 = *(chars + (tilenum << 3) + y_gran);
}
*bitmap++ = colour |
(((d1 >> (7 ^ x_gran)) & 1) << 1) |
((d0 >> (7 ^ x_gran)) & 1);
x_offs = (x_offs + 1) & x_mask;
}
}
}
/***************************************************************************
Buggy Boy Road Hardware
A hacked up version of TX-1 but without the second road.
There are two lists in road/common RAM (double buffered) starting at 0x800
and 0xa00:
0x1800 - 0x18ff: Road line horizontal position word (128 entries).
0x19e0 - 0x19ef: Vertical positions (starting line, water, tunnels etc)
0x19f0 - 0x19ff: Horizontal positions (walls and tunnels)
Three TZ1113 accumulators are used to vary:
* Road camber (update per pixel)
* Road vertical scale/position (update per scanline)
* Road 'speed' (update per frame)
Road flags register (0x24E0):
7 : Water sparkle control 1
6 : Water sparkle control 0 ('WAVE0,1')
5 : Tunnel mode 1
4 : Tunnel mode 0 ('TNLMD0,1')
3 : Tunnel flag ('TNLF')
2 : Starting Line flag ('LINF')
1 : Road list select
0 : Wall angle enable ('WANGL')
Buggy Boy Jr. Road PAL equations:
http://philwip.mameworld.info/buggyboy/PAL14H4.149.htm
http://philwip.mameworld.info/buggyboy/PAL14L4.151.htm
http://philwip.mameworld.info/buggyboy/PAL16H2.3.htm
http://philwip.mameworld.info/buggyboy/PAL16L8.4.htm
http://philwip.mameworld.info/buggyboy/PAL16L8.150.htm
***************************************************************************/
static void buggyboy_get_roadpix(int screen, int ls161, UINT8 rva0_6, UINT8 sld, UINT32 *_rorev,
UINT8 *rc0, UINT8 *rc1, UINT8 *rc2, UINT8 *rc3,
const UINT8 *rom, const UINT8 *prom0, const UINT8 *prom1, const UINT8 *prom2)
{
/* Counter Q10-7 are added to 384 */
UINT16 ls283_159 = (ls161 & 0x780) + 128 + (256 * screen);
UINT32 ls283_159_co = ls283_159 & 0x800;
UINT32 rom_flip = ls283_159 & 0x200 ? 0 : 1;
UINT32 rom_en = !(ls283_159 & 0x400) && !(ls283_159_co ^ (ls161 & 0x800));
UINT8 d0 = 0;
UINT8 d1 = 0;
/* Latch road reverse bit */
*_rorev = !( (rom_en && rom_flip) || (!rom_en && (ls161 & 0x4000)) );
/* TODO: ROM data is 0xff if not enabled. */
if (rom_en)
{
UINT8 rom_data;
UINT16 prom_addr;
/* 6 bit road horizontal address */
UINT16 rha = (ls283_159 & 0x180) | (ls161 & 0x78);
if (rom_flip)
rha ^= 0x1f8;
/* Get road chunk first */
rom_data = rom[(1 << 13) | (rha << 4) | rva0_6];
prom_addr = (rom_flip ? 0x80 : 0) | (rom_data & 0x7f);
*rc0 = prom0[prom_addr];
*rc1 = prom1[prom_addr];
*rc2 = prom2[prom_addr];
/* Now get the dirt chunk */
rom_data = rom[(rha << 4) | rva0_6];
prom_addr = 0x100 | rom_data;
d0 = prom0[prom_addr];
d1 = prom1[prom_addr];
}
else
{
/*
TODO: When ROM is not enabled, data = 0xff
But does anybody care?
*/
*rc0 = *rc1 = *rc2 = *rc3 = 0;
}
/* The data is mixed by two TZ0314 PALs */
if (BIT(sld, 4))
{
if (BIT(sld, 5))
d1 = ~d1;
*rc3 = d0 & d1;
if (rom_flip)
*rc3 = BITSWAP8(*rc3, 0, 1, 2, 3, 4, 5, 6, 7);
}
else
*rc3 = 0;
}
#define LOAD_HPOS_COUNTER(NUM) \
ram_val = buggyboy_rcram[(rva_offs + 0x1f8 + (2*NUM)) >> 1]; \
rcrs10 = ram_val & 0xfc00 ? 0x0400 : 0x0000; \
hp = vregs.wa8 + ((BIT(ram_val, 15) << 11) | rcrs10 | (ram_val & 0x03ff)); \
hp##NUM = hp & 0xff; \
hp >>= 8; \
hps##NUM##0 = (BIT(hp, 0) || BIT(hp, 2)) && !BIT(hp, 3); \
hps##NUM##1 = (BIT(hp, 1) || BIT(hp, 2)) && !BIT(hp, 3); \
hps##NUM##2 = BIT(hp, 2); \
#define UPDATE_HPOS(NUM) \
if (hp##NUM##_en) \
{ \
if ((hp##NUM & 0xff) == 0xff) \
hp##NUM##_cy = 1; \
else \
hp##NUM = hp##NUM + 1; \
} \
static void buggyboy_draw_road(running_machine &machine, UINT8 *bitmap)
{
tx1_state *state = machine.driver_data<tx1_state>();
UINT16 *buggyboy_rcram = state->m_rcram;
vregs_t &vregs = state->m_vregs;
INT32 x;
UINT32 y;
UINT16 rva_offs;
UINT32 tnlmd0;
UINT32 tnlmd1;
UINT32 linf;
UINT32 tnlf;
UINT32 wangl;
UINT32 tcmd;
UINT32 wave0;
UINT32 wave1;
UINT32 rva20_6;
/* ROM/PROM lookup tables */
const UINT8 *rcols = (UINT8*)(machine.region("proms")->base() + 0x1500);
const UINT8 *rom = machine.region("road")->base();
const UINT8 *prom0 = rom + 0x4000;
const UINT8 *prom1 = rom + 0x4200;
const UINT8 *prom2 = rom + 0x4400;
const UINT8 *vprom = rom + 0x4600;
/* Extract constant values */
tcmd = ((vregs.scol & 0xc000) >> 12) | ((vregs.scol & 0x00c0) >> 6);
tnlmd0 = BIT(vregs.flags, BB_RDFLAG_TNLMD0);
tnlmd1 = BIT(vregs.flags, BB_RDFLAG_TNLMD1);
linf = BIT(vregs.flags, BB_RDFLAG_LINF);
tnlf = BIT(vregs.flags, BB_RDFLAG_TNLF);
wangl = BIT(vregs.flags, BB_RDFLAG_WANGL);
wave0 = BIT(vregs.flags, BB_RDFLAG_WAVE0);
wave1 = BIT(vregs.flags, BB_RDFLAG_WAVE1);
rva_offs = BIT(vregs.flags, BB_RDFLAG_RVA7) ? 0x800 : 0xc00;
for (y = 0; y < 240; ++y)
{
UINT8 rva0_6;
UINT8 ram_addr;
UINT16 rcrdb0_15;
UINT16 rcrs10;
UINT16 ls161_156_a;
UINT16 ls161;
UINT8 sld;
UINT32 rva8;
UINT32 rm0, rm1;
UINT32 rcmd;
UINT32 bnkls = 1;
UINT32 bnkcs = 1;
UINT32 bnkrs = 1;
// UINT32 x_offs;
UINT8 sf;
/* Vertical positions shift register */
UINT32 ram_val;
UINT32 hp;
UINT32 vp1, vp2, vp3, vp4, vp5, vp6, vp7;
/* Horizontal positions */
UINT32 hp0, hp1, hp2, hp3;
UINT8 hps00, hps01, hps02;
UINT8 hps10, hps11, hps12;
UINT8 hps20, hps21, hps22;
UINT8 hps30, hps31, hps32;
/* Road pixel data planes */
UINT8 rc0[3] = {0, 0, 0};
UINT8 rc1[3] = {0, 0, 0};
UINT8 rc2[3] = {0, 0, 0};
UINT8 rc3[3] = {0, 0, 0};
/* Horizontal position counter carry out */
UINT8 hp0_cy = 0, hp1_cy = 0, hp2_cy = 0, hp3_cy = 0;
UINT8 *bmpaddr = bitmap + (y * 256 * 3);
UINT32 bank_cnt;
UINT32 _rorevls = 0;
UINT32 _rorevcs = 0;
UINT32 _rorevrs = 0;
UINT32 ic96_o17;
UINT32 ic96_term1;
UINT32 ic97_o12;
UINT32 ic97_o13;
UINT32 ic79_p19;
rva8 = (vregs.h_val & 0x8000) || !(vregs.shift & 0x80);
/* Get RVA0_6 from TZ113 accumulator chain @ 122/123 */
rva0_6 = (vregs.h_val >> 7) & 0x7f;
/* For /WAVE bit logic later */
rva20_6 = ((rva0_6 >> 3) & 0xe) | ((rva0_6 & 2) >> 1);
/* RVA is inverted! */
ram_addr = (~rva0_6 & 0x7f) << 1;
/* Get the road RAM data for this line */
rcrdb0_15 = buggyboy_rcram[(rva_offs + ram_addr) >> 1];
/* If 15-10 == 000000, then 0 */
rcrs10 = rcrdb0_15 & 0xfc00 ? 0x0400 : 0x0000;
/* If 15-10 == 111111, then 1 */
ls161_156_a = (rcrdb0_15 & 0xfc00) == 0xfc00 ? 0x800 : 0x0000;
/* LS161 15-bit counter chain - loaded with RAM data (bar bits 10-13) */
ls161 = ((rcrdb0_15 & 0x8000) >> 1) | ls161_156_a | rcrs10 | (rcrdb0_15 & 0x03ff);
/* SLD */
sld = (vprom[rva0_6] + vregs.slin_val) & 0x38;
/* Determine the x-offset */
// x_offs = ls161 & 7;
/* Fill vertical position shift register with bits for this line */
/* TODO; cheated slightly to shift stuff up one pixel*/
vp1 = buggyboy_rcram[(rva_offs + 0x1e2) >> 1] >= y ? 0 : 1;
vp2 = buggyboy_rcram[(rva_offs + 0x1e4) >> 1] >= y ? 0 : 1;
vp3 = buggyboy_rcram[(rva_offs + 0x1e6) >> 1] >= y ? 0 : 1;
vp4 = buggyboy_rcram[(rva_offs + 0x1e8) >> 1] >= y ? 0 : 1;
vp5 = buggyboy_rcram[(rva_offs + 0x1ea) >> 1] >= y ? 0 : 1;
vp6 = buggyboy_rcram[(rva_offs + 0x1ec) >> 1] >= y ? 0 : 1;
vp7 = buggyboy_rcram[(rva_offs + 0x1ee) >> 1] >= y ? 0 : 1;
/* Stuff */
rm0 = vp7 ? BIT(vregs.scol, 4) : BIT(vregs.scol, 12);
rm1 = vp7 ? BIT(vregs.scol, 5) : BIT(vregs.scol, 13);
/* Wall/tunnel control */
rcmd = (vp7 ? vregs.scol : vregs.scol >> 8) & 0xf;
/* Load 'em up */
LOAD_HPOS_COUNTER(0);
LOAD_HPOS_COUNTER(1);
LOAD_HPOS_COUNTER(2);
LOAD_HPOS_COUNTER(3);
/* Load the bank counter with accumulator bits 14-5 */
bank_cnt = (vregs.ba_val >> 5) & 0x3ff;
/* Have we crossed a road gfx strip boundary? */
if (ls161 & 7)
{
buggyboy_get_roadpix(0, ls161, rva0_6, sld, &_rorevls, &rc0[0], &rc1[0], &rc2[0], &rc3[0], rom, prom0, prom1, prom2);
buggyboy_get_roadpix(1, ls161, rva0_6, sld, &_rorevcs, &rc0[1], &rc1[1], &rc2[1], &rc3[1], rom, prom0, prom1, prom2);
buggyboy_get_roadpix(2, ls161, rva0_6, sld, &_rorevrs, &rc0[2], &rc1[2], &rc2[2], &rc3[2], rom, prom0, prom1, prom2);
}
/* We can evaluate some of the pixel logic outside of the x-loop */
ic96_term1 = !tnlf || (vp5 && vp6) || (!vp3 && vp6) || (!vp4 && vp5) || (!vp3 && !vp4);
ic96_o17 = (vp3 && vp4) || tnlmd0 || tnlmd1 || !vp1 || !tnlf;
ic97_o12 = (!vp1 && !vp2 && !vp6) || (!vp1 && !vp2 && vp7) || (vp4 && !vp6) || (vp4 && vp7);
ic97_o13 = (!vp1 && !vp2 && !vp5) || (!vp1 && !vp2 && vp7) || (vp3 && !vp5) || (vp3 && vp7);
ic79_p19 = !(!(vp5 || vp6) || vp7) && !(tnlmd0 || tnlmd1);
for (x = 0; x < 256; ++x)
{
UINT32 pix;
UINT32 hp0_en, hp1_en, hp2_en, hp3_en;
UINT32 ic97_o17;
UINT32 ic97_o18;
UINT32 ic97_o19;
UINT32 ic96_o14;
UINT32 ic96_o15;
UINT32 ic96_o16;
UINT32 ic79_o15;
UINT32 ic79_o16;
UINT32 ic79_o17;
UINT32 ic82_o17;
UINT32 ic82_o16;
UINT32 ic82_o15;
UINT32 ic82_o14;
UINT32 ic80_o17;
UINT32 ic80_o16;
UINT32 ic80_o15;
UINT32 ic80_o14;
UINT32 ic78_o17;
UINT32 ic78_o16;
UINT32 ic78_o15;
UINT32 ic78_o14;
UINT32 ic48_o12, ic50_o12, ic52_o12;
UINT32 ic48_o16, ic50_o16, ic52_o16;
UINT32 ic48_o17, ic50_o17, ic52_o17;
UINT32 ic48_o18, ic50_o18, ic52_o18;
UINT32 ic48_o19, ic50_o19, ic52_o19;
UINT32 tmp;
UINT8 px0[3];
UINT8 px1[3];
UINT8 px2[3];
UINT8 px3[3];
UINT32 lfsr = vregs.wave_lfsr;
UINT32 wave =
(wave0 ^ BIT(lfsr, 0))
&& (wave1 ^ BIT(lfsr, 3))
&& BIT(lfsr, 5)
&& !BIT(lfsr, 15)
&& BIT(lfsr, 11)
&& BIT(lfsr, 13)
&& (rva20_6 < ((lfsr >> 8) & 0xf));
/* Strip pixel number */
pix = (ls161 & 7) ^ 7;
/* Horizontal position counter enables - also used as PAL inputs */
hp0_en = !(hp0_cy || hps02);
hp1_en = !(hp1_cy || hps12);
hp2_en = !(hp2_cy || hps22);
hp3_en = !(hp3_cy || hps32);
/* Load in a new road gfx strip? */
if (!(ls161 & 7))
{
buggyboy_get_roadpix(0, ls161, rva0_6, sld, &_rorevls, &rc0[0], &rc1[0], &rc2[0], &rc3[0], rom, prom0, prom1, prom2);
buggyboy_get_roadpix(1, ls161, rva0_6, sld, &_rorevcs, &rc0[1], &rc1[1], &rc2[1], &rc3[1], rom, prom0, prom1, prom2);
buggyboy_get_roadpix(2, ls161, rva0_6, sld, &_rorevrs, &rc0[2], &rc1[2], &rc2[2], &rc3[2], rom, prom0, prom1, prom2);
}
/* Road camber/banking */
if (BIT(vregs.ba_val, 23))
{
bnkls = 1; bnkcs = 1; bnkrs = 1;
}
else if (vregs.ba_val & 0x007f8000)
{
bnkls = 0; bnkcs = 0; bnkrs = 0;
}
else
{
bnkls = bank_cnt < 0x400;
bnkcs = bank_cnt < 0x300;
bnkrs = bank_cnt < 0x200;
}
if (vregs.bank_mode)
{
bnkls ^= 1; bnkcs ^= 1; bnkrs ^= 1;
}
px0[0] = BIT(rc0[0], pix);
px1[0] = BIT(rc1[0], pix);
px2[0] = BIT(rc2[0], pix);
px3[0] = BIT(rc3[0], pix);
px0[1] = BIT(rc0[1], pix);
px1[1] = BIT(rc1[1], pix);
px2[1] = BIT(rc2[1], pix);
px3[1] = BIT(rc3[1], pix);
px0[2] = BIT(rc0[2], pix);
px1[2] = BIT(rc1[2], pix);
px2[2] = BIT(rc2[2], pix);
px3[2] = BIT(rc3[2], pix);
/*
Now evaluate the pixel logic for each of the three screens
TODO: A lot of this could be macrofied to avoid repetition.
Shuffling the equations around would squeeze out some extra speed.
*/
/* Left */
ic96_o14 =
ic96_term1
|| (!hp1_en && hps10 && vp4 && !hps20 && !hps21)
|| (!hp1_en && hps10 && vp4 && hp2_en && !hps21)
|| (!hp1_en && hps10 && vp4 && vp6)
|| (hps11 && vp4 && !hps20 && !hps21)
|| (hps11 && vp4 && hp2_en && !hps21)
|| (vp5 && !hps20 && !hps21)
|| (!vp3 && !hps20 && !hps21)
|| (vp5 && hp2_en && !hps21)
|| (!vp3 && hp2_en && !hps21)
|| (!hp1_en && hps10 && !vp4)
|| (hps11 && vp4 && vp6)
|| (hps11 && !vp4);
/* Centre */
ic96_o15 =
ic96_term1
|| (hps10 && hps11 && vp4 && hp2_en && !hps20)
||(!hp1_en && hps11 && vp4 && hp2_en && !hps20)
|| (hps10 && hps11 && vp6)
|| (!hp1_en && hps11 && vp6)
|| (hps10 && hps11 && vp4 && !hps21)
|| (!hp1_en && hps11 && vp4 && !hps21)
|| (vp5 && hp2_en && !hps20)
|| (!vp3 && hp2_en && !hps20)
|| (hps10 && hps11 && !vp4)
|| (!hp1_en && hps11 && !vp4)
|| (vp5 && !hps21)
|| (!vp3 && !hps21);
/* Right */
ic96_o16 =
ic96_term1
|| (!hp1_en && hps10 && hps11 && vp6)
|| (!hp1_en && hps10 && hps11 && !vp4)
|| (!hp1_en && hps10 && hps11 && !hps20)
|| (!hp1_en && hps10 && hps11 && hp2_en)
|| (!hp1_en && hps10 && hps11 && !hps21)
|| (vp5 && !hps20)
|| (!vp3 && !hps20)
|| (vp5 && hp2_en)
|| (!vp3 && hp2_en)
|| (vp5 && !hps21)
|| (!vp3 && !hps21);
tmp = (!vp1 && !vp2) || (vp2 && vp7);
ic97_o17 = tmp || (!hp0_en && hps00 && vp2 && !hps30 && !hps31) || (!hp0_en && hps00 && vp2 && hp3_en && !hps31) || (hps01 && vp2 && !hps30 && !hps31) || (hps01 && vp2 && hp3_en && !hps31);
ic97_o18 = tmp || (hps00 && hps01 && vp2 && hp3_en && !hps30) || (!hp0_en && hps01 && vp2 && hp3_en && !hps30) || (hps00 && hps01 && vp2 && !hps31) || (!hp0_en && hps01 && vp2 && !hps31);
ic97_o19 = tmp || (!hp0_en && hps00 && hps01 && vp2 && !hps30) || (!hp0_en && hps00 && hps01 && vp2 && hp3_en) || (!hp0_en && hps00 && hps01 && vp2 && !hps31);
/* Left */
{
UINT32 P4, P6, P7, P18, P19;
P4 = !(ic96_o16 && ic96_o17 && ic97_o19);
P6 = BIT(sld, 3);
P7 = (!vp5 && !vp6) || vp7 || !linf;
P19 = wangl && bnkls;
ic78_o17 = (_rorevls && !tnlmd1 && tnlmd0) || (!_rorevls && tnlmd1 && !tnlmd0) || (_rorevls && ic97_o12) || (!_rorevls && ic97_o13);
P18 = ic78_o17;
ic78_o16 = P7 || (px1[0] && !px0[0] && tnlmd1 && !tnlmd0) || (px2[0] && tnlmd1 && tnlmd0);
ic78_o15 = !tnlf || (!P4 && px0[0] && P19) || (!P4 && px1[0] && P19) || (!P4 && P18) || (!P4 && px2[0]);
ic78_o14 = !P6 || tnlmd0 || tnlmd1 || P7;
}
/* Centre */
{
UINT32 P4, P6, P7, P18, P19;
P4 = !(ic96_o15 && ic96_o17 && ic97_o18);
P6 = BIT(sld, 3);
P7 = (!vp5 && !vp6) || vp7 || !linf;
P19 = wangl && bnkcs;
ic80_o17 = (_rorevcs && !tnlmd1 && tnlmd0) || (!_rorevcs && tnlmd1 && !tnlmd0) || (_rorevcs && ic97_o12) || (!_rorevcs && ic97_o13);
P18 = ic80_o17;
ic80_o16 = P7 || (px1[1] && !px0[1] && tnlmd1 && !tnlmd0) || (px2[1] && tnlmd1 && tnlmd0);
ic80_o15 = !tnlf || (!P4 && px0[1] && P19) || (!P4 && px1[1] && P19) || (!P4 && P18) || (!P4 && px2[1]);
ic80_o14 = !P6 || tnlmd0 || tnlmd1 || P7;
}
/* Right */
{
UINT32 P4, P6, P7, P18, P19;
P4 = !(ic96_o14 && ic96_o17 && ic97_o17);
P6 = BIT(sld, 3);
P7 = (!vp5 && !vp6) || vp7 || !linf;
P19 = wangl && bnkrs;
ic82_o17 = (_rorevrs && !tnlmd1 && tnlmd0) || (!_rorevrs && tnlmd1 && !tnlmd0) || (_rorevrs && ic97_o12) || (!_rorevrs && ic97_o13);
P18 = ic82_o17;
ic82_o16 = P7 || (px1[2] && !px0[2] && tnlmd1 && !tnlmd0) || (px2[2] && tnlmd1 && tnlmd0);
ic82_o15 = !tnlf || (!P4 && px0[2] && P19) || (!P4 && px1[2] && P19) || (!P4 && P18) || (!P4 && px2[2]);
ic82_o14 = !P6 || tnlmd0 || tnlmd1 || P7;
}
ic79_o17 = (!px2[0] && _rorevls && ic78_o15) || (tnlf && !ic97_o19) || (tnlf && ic79_p19 && px2[0] && ic78_o15);
ic79_o16 = (!px2[1] && _rorevcs && ic80_o15) || (tnlf && !ic97_o18) || (tnlf && ic79_p19 && px2[1] && ic80_o15);
ic79_o15 = (!px2[2] && _rorevrs && ic82_o15) || (tnlf && !ic97_o17) || (tnlf && ic79_p19 && px2[2] && ic82_o15);
/* Left */
{
UINT32 P5,P7, P8;
UINT32 rcsd0_3;
UINT32 cprom_addr;
P5 = BIT(tcmd, 3) ? ((!vp5 && !vp6) || vp7 || !linf) : ic78_o16;
P7 = BIT(sld, 5);
P8 = BIT(sld, 4);
ic48_o19 = (px2[0] && !rva8) || !bnkls || !P5 || !ic78_o15;
if (ic48_o19)
{
ic48_o12 =
ic78_o14 &&
(
(px2[0] && px1[0] && px0[0] && rm1 && !rm0)
|| (!px2[0] && px1[0] && px0[0] && !P8 && rm0)
|| (px2[0] && px0[0] && !P7 && !rm1 && !rm0)
|| (px2[0] && !px1[0] && px0[0] && !P7 && !rm1)
|| (px2[0] && px1[0] && px0[0] && !P7 && !P8)
|| (px2[0] && px1[0] && px0[0] && !P8 && rm1)
|| (!px2[0] && !px3[0] && !rm0)
|| (!px1[0] && !px3[0] && rm1)
|| (!px2[0] && !px1[0] && !px3[0])
|| (rva8)
|| (!px0[0] && !px3[0])
|| (!ic78_o15)
|| (!P5)
);
ic48_o16 = (px2[0] && P5 && rm1) || (P5 && rva8 && ic78_o15) || (!px0[0] && P5) || !ic78_o15;
ic48_o17 = (px0[0] && P5 && !rm0 && ic78_o15) || (!px1[0] && P5 && ic78_o15) || (P5 && rva8 && ic78_o15);
ic48_o18 = (!px2[0] && P5 && ic78_o15) || (P5 && rva8 && ic78_o15);
if (vp6 || ic78_o16)
{
if (!(ic78_o15 && P5))
cprom_addr = (tcmd & 0x7) | (ic78_o16 << 3);
else
cprom_addr = rcmd;
cprom_addr = (~cprom_addr & 0xf) << 4;
}
else
cprom_addr = 0xf0;
cprom_addr |= (ic79_o17 << 3) |
(ic48_o18 << 2) |
(ic48_o17 << 1) |
ic48_o16;
rcsd0_3 = rcols[cprom_addr] & 0xf;
*(bmpaddr + 0) = 0x40 | (!wave << 5) | (ic48_o12 << 4) | rcsd0_3;
}
else
*(bmpaddr + 0) = 0;
}
/* Centre */
{
UINT32 rcsd0_3;
UINT32 cprom_addr;
UINT32 P5, P7, P8;
P5 = BIT(tcmd, 3) ? ((!vp5 && !vp6) || vp7 || !linf) : ic80_o16;
P7 = BIT(sld, 5);
P8 = BIT(sld, 4);
ic50_o19 = (px2[1] && !rva8) || !bnkcs || !P5 || !ic80_o15;
if (ic50_o19)
{
if (ic80_o14)
ic50_o12 =
(px2[1] && px1[1] && px0[1] && rm1 && !rm0)
|| (!px2[1] && px1[1] && px0[1] && !P8 && rm0)
|| (px2[1] && px0[1] && !P7 && !rm1 && !rm0)
|| (px2[1] && !px1[1] && px0[1] && !P7 && !rm1)
|| (px2[1] && px1[1] && px0[1] && !P7 && !P8)
|| (px2[1] && px1[1] && px0[1] && !P8 && rm1)
|| (!px2[1] && !px3[1] && !rm0)
|| (!px1[1] && !px3[1] && rm1)
|| (!px2[1] && !px1[1] && !px3[1])
|| (rva8)
|| (!px0[1] && !px3[1])
|| (!ic80_o15)
|| (!P5);
else
ic50_o12 = 0;
ic50_o16 = (P5 && px2[1] && rm1) || (P5 && rva8 && ic80_o15) || (P5 && !px0[1]) || !ic80_o15;
ic50_o17 = (P5 && px0[1] && !rm0 && ic80_o15) || (P5 && !px1[1] && ic80_o15) || (P5 && rva8 && ic80_o15);
ic50_o18 = (P5 && !px2[1] && ic80_o15) || (P5 && rva8 && ic80_o15);
if (vp6 || ic80_o16)
{
if (!(ic80_o15 && P5))
cprom_addr = (tcmd & 0x7) | (ic80_o16 << 3);
else
cprom_addr = rcmd;
cprom_addr = ((~cprom_addr) & 0xf) << 4;
}
else
cprom_addr = 0xf0;
cprom_addr |= (ic79_o16 << 3) |
(ic50_o18 << 2) |
(ic50_o17 << 1) |
ic50_o16;
rcsd0_3 = rcols[cprom_addr] & 0xf;
*(bmpaddr + 256) = 0x40 | (!wave << 5) | (ic50_o12 << 4) | rcsd0_3;
}
else
*(bmpaddr + 256) = 0;
}
/* Right */
{
UINT32 rcsd0_3;
UINT32 cprom_addr;
UINT32 P5, P7, P8;
P5 = BIT(tcmd, 3) ? ((!vp5 && !vp6) || vp7 || !linf) : ic82_o16;
P7 = BIT(sld, 5);
P8 = BIT(sld, 4);
ic52_o19 = (px2[2] && !rva8) || !bnkrs || !P5 || !ic82_o15;
if (ic52_o19)
{
ic52_o12 =
ic82_o14 &&
(
(px2[2] && px1[2] && px0[2] && rm1 && !rm0)
|| (!px2[2] && px1[2] && px0[2] && !P8 && rm0)
|| (px2[2] && px0[2] && !P7 && !rm1 && !rm0)
|| (px2[2] && !px1[2] && px0[2] && !P7 && !rm1)
|| (px2[2] && px1[2] && px0[2] && !P7 && !P8)
|| (px2[2] && px1[2] && px0[2] && !P8 && rm1)
|| (!px2[2] && !px3[2] && !rm0)
|| (!px1[2] && !px3[2] && rm1)
|| (!px2[2] && !px1[2] && !px3[2])
|| (rva8)
|| (!px0[2] && !px3[2])
|| (!ic82_o15)
|| (!P5)
);
ic52_o16 = (px2[2] && P5 && rm1) || (P5 && rva8 && ic82_o15) || (!px0[2] && P5) || !ic82_o15;
ic52_o17 = (px0[2] && P5 && !rm0 && ic82_o15) || (!px1[2] && P5 && ic82_o15) || (P5 && rva8 && ic82_o15);
ic52_o18 = (P5 && ic82_o15 && !px2[2]) || (P5 && ic82_o15 && rva8);
if (vp6 || ic82_o16)
{
if (!(ic82_o15 && P5))
cprom_addr = (tcmd & 0x7) | (ic82_o16 << 3);
else
cprom_addr = rcmd;
cprom_addr = (~cprom_addr & 0xf) << 4;
}
else
cprom_addr = 0xf0;
cprom_addr |= (ic79_o15 << 3) |
(ic52_o18 << 2) |
(ic52_o17 << 1) |
ic52_o16;
rcsd0_3 = rcols[cprom_addr] & 0xf;
*(bmpaddr + 512) = 0x40 | (!wave << 5) | (ic52_o12 ? 0x10 : 0) | rcsd0_3;
}
else
*(bmpaddr + 512) = 0;
}
/* Now update counters and whatnot */
++bmpaddr;
UPDATE_HPOS(0);
UPDATE_HPOS(1);
UPDATE_HPOS(2);
UPDATE_HPOS(3);
/* Update the wave LFSR */
vregs.wave_lfsr = (vregs.wave_lfsr << 1) | (BIT(vregs.wave_lfsr, 6) ^ !BIT(vregs.wave_lfsr, 15));
/* Increment the bank counter */
bank_cnt = (bank_cnt + 1) & 0x7ff;
/* X pos */
ls161 = (ls161 + 1) & 0x7fff;
}
/* WANGL active? Update the 8-bit counter */
if (wangl)
{
if (BIT(vregs.flags, BB_RDFLAG_TNLMD0))
--vregs.wa8;
else
++vregs.wa8;
}
/* No carry out - just increment */
if (vregs.wa4 != 0xf)
++vregs.wa4;
else
{
/* Carry out; increment again on /TMG2S rise */
if (wangl)
{
if (BIT(vregs.flags, BB_RDFLAG_TNLMD0))
--vregs.wa8;
else
++vregs.wa8;
}
vregs.wa4 = 1;
}
/* Update accumulator */
vregs.h_val += vregs.h_inc;
/* Seems correct */
sf = vregs.shift;
if ((vregs.shift & 0x80) == 0)
{
vregs.shift <<= 1;
if ((sf & 0x08) == 0)
vregs.shift |= BIT(vregs.h_val, 15);
}
if ((sf & 0x08) && !(vregs.shift & 0x08))
vregs.h_inc = vregs.gas;
/* Finally, increment the banking accumulator */
vregs.ba_val = (vregs.ba_val + vregs.ba_inc) & 0x00ffffff;
}
}
static void buggybjr_draw_road(running_machine &machine, UINT8 *bitmap, int wide)
{
tx1_state *state = machine.driver_data<tx1_state>();
UINT16 *buggyboy_rcram = state->m_rcram;
vregs_t &vregs = state->m_vregs;
INT32 x;
UINT32 y;
UINT16 rva_offs;
UINT32 tnlmd0;
UINT32 tnlmd1;
UINT32 linf;
UINT32 tnlf;
UINT32 wangl;
UINT32 tcmd;
UINT32 wave0;
UINT32 wave1;
UINT32 rva20_6;
/* ROM/PROM lookup tables */
const UINT8 *rcols = (UINT8*)(machine.region("proms")->base() + 0x1500);
const UINT8 *rom = machine.region("road")->base();
const UINT8 *prom0 = rom + 0x4000;
const UINT8 *prom1 = rom + 0x4200;
const UINT8 *prom2 = rom + 0x4400;
const UINT8 *vprom = rom + 0x4600;
/* Extract constant values */
tcmd = ((vregs.scol & 0xc000) >> 12) | ((vregs.scol & 0x00c0) >> 6);
tnlmd0 = BIT(vregs.flags, BB_RDFLAG_TNLMD0);
tnlmd1 = BIT(vregs.flags, BB_RDFLAG_TNLMD1);
linf = BIT(vregs.flags, BB_RDFLAG_LINF);
tnlf = BIT(vregs.flags, BB_RDFLAG_TNLF);
wangl = BIT(vregs.flags, BB_RDFLAG_WANGL);
wave0 = BIT(vregs.flags, BB_RDFLAG_WAVE0);
wave1 = BIT(vregs.flags, BB_RDFLAG_WAVE1);
rva_offs = BIT(vregs.flags, BB_RDFLAG_RVA7) ? 0x800 : 0xc00;
for (y = 0; y < 240; ++y)
{
UINT8 rva0_6;
UINT8 ram_addr;
UINT16 rcrdb0_15;
UINT16 rcrs10;
UINT16 ls161_156_a;
UINT16 ls161;
UINT8 sld;
UINT32 rva8;
UINT32 rm0, rm1;
UINT32 rcmd;
UINT32 bnkcs = 1;
// UINT32 x_offs;
UINT8 sf;
/* Vertical positions shift register */
UINT32 ram_val;
UINT32 hp;
UINT32 vp1, vp2, vp3, vp4, vp5, vp6, vp7;
/* PAL outputs */
UINT32 ic4_o12;
UINT32 ic4_o13;
UINT32 ic149_o15;
UINT32 ic151_o14;
/* Horizontal positions */
UINT32 hp0, hp1, hp2, hp3;
UINT8 hps00, hps01, hps02;
UINT8 hps10, hps11, hps12;
UINT8 hps20, hps21, hps22;
UINT8 hps30, hps31, hps32;
/* Road pixel data planes */
UINT8 rc0 = 0, rc1 = 0, rc2 = 0, rc3 = 0;
/* Horizontal position counter carry out */
UINT8 hp0_cy = 0, hp1_cy = 0, hp2_cy = 0, hp3_cy = 0;
UINT8 *bmpaddr = bitmap + (y * 256);
UINT32 bank_cnt;
UINT32 _rorevcs = 0;
rva8 = (vregs.h_val & 0x8000) || !(vregs.shift & 0x80);
/* Get RVA0_6 from TZ113 accumulator chain @ 122/123 */
rva0_6 = (vregs.h_val >> 7) & 0x7f;
/* For /WAVE bit logic later */
rva20_6 = ((rva0_6 >> 3) & 0xe) | ((rva0_6 & 2) >> 1);
/* RVA is inverted! */
ram_addr = (~rva0_6 & 0x7f) << 1;
/* Get the road RAM data for this line */
rcrdb0_15 = buggyboy_rcram[(rva_offs + ram_addr) >> 1];
/* If 15-10 == 000000, then 0 */
rcrs10 = rcrdb0_15 & 0xfc00 ? 0x0400 : 0x0000;
/* If 15-10 == 111111, then 1 */
ls161_156_a = (rcrdb0_15 & 0xfc00) == 0xfc00 ? 0x800 : 0x0000;
/* LS161 15-bit counter chain - loaded with RAM data (bar bits 10-13) */
ls161 = ((rcrdb0_15 & 0x8000) >> 1) | ls161_156_a | rcrs10 | (rcrdb0_15 & 0x03ff);
/* SLD */
sld = (vprom[rva0_6] + vregs.slin_val) & 0x38;
/* Determine the x-offset */
// x_offs = ls161 & 7;
/* Fill vertical position shift register with bits for this line */
/* TODO; cheated slightly to shift stuff up one pixel*/
vp1 = buggyboy_rcram[(rva_offs + 0x1e2) >> 1] >= y ? 0 : 1;
vp2 = buggyboy_rcram[(rva_offs + 0x1e4) >> 1] >= y ? 0 : 1;
vp3 = buggyboy_rcram[(rva_offs + 0x1e6) >> 1] >= y ? 0 : 1;
vp4 = buggyboy_rcram[(rva_offs + 0x1e8) >> 1] >= y ? 0 : 1;
vp5 = buggyboy_rcram[(rva_offs + 0x1ea) >> 1] >= y ? 0 : 1;
vp6 = buggyboy_rcram[(rva_offs + 0x1ec) >> 1] >= y ? 0 : 1;
vp7 = buggyboy_rcram[(rva_offs + 0x1ee) >> 1] >= y ? 0 : 1;
/* Stuff */
rm0 = vp7 ? BIT(vregs.scol, 4) : BIT(vregs.scol, 12);
rm1 = vp7 ? BIT(vregs.scol, 5) : BIT(vregs.scol, 13);
/* Wall/tunnel control */
rcmd = (vp7 ? vregs.scol : vregs.scol >> 8) & 0xf;
/* Load 'em up */
LOAD_HPOS_COUNTER(0);
LOAD_HPOS_COUNTER(1);
LOAD_HPOS_COUNTER(2);
LOAD_HPOS_COUNTER(3);
/* Some PAL equations that we can evaluate outside of the x-loop */
ic4_o12 = (!vp1 && !vp2 && !vp6) || (!vp1 && !vp2 && vp7) || (vp4 && !vp6) || (vp4 && vp7);
ic4_o13 = (!vp1 && !vp2 && !vp5) || (!vp1 && !vp2 && vp7) || (vp3 && !vp5) || (vp3 && vp7);
ic149_o15 = (!vp5 && !vp6) || vp7 || !linf;
ic151_o14 = !BIT(sld, 3) || tnlmd0 || tnlmd1 || ic149_o15;
/* Load the bank counter with accumulator bits 14-5 */
bank_cnt = (vregs.ba_val >> 5) & 0x3ff;
/* Have we crossed a road gfx strip boundary? */
if (ls161 & 7)
buggyboy_get_roadpix(1, ls161, rva0_6, sld, &_rorevcs, &rc0, &rc1, &rc2, &rc3, rom, prom0, prom1, prom2);
for (x = 0; x < 256; ++x)
{
UINT32 pix;
UINT32 hp0_en, hp1_en, hp2_en, hp3_en;
UINT32 ic149_o16;
UINT32 ic4_o18;
UINT32 ic3_o15;
UINT32 ic150_o12 = 0;
UINT32 ic150_o16;
UINT32 ic150_o17;
UINT32 ic150_o18;
UINT32 ic150_o19;
UINT32 ic151_o15;
UINT32 ic151_o16;
UINT32 ic151_o17;
UINT32 rcsd0_3 = 0;
UINT32 sld5 = BIT(sld, 5);
UINT32 sld4 = BIT(sld, 4);
UINT32 mux;
UINT32 cprom_addr;
UINT8 px0, px1, px2, px3;
/* Strip pixel number */
pix = (ls161 & 7) ^ 7;
/* Horizontal position counter enables - also used as PAL inputs */
hp0_en = !(hp0_cy || hps02);
hp1_en = !(hp1_cy || hps12);
hp2_en = !(hp2_cy || hps22);
hp3_en = !(hp3_cy || hps32);
/* Load in a new road gfx strip? */
if (!(ls161 & 7))
buggyboy_get_roadpix(1, ls161, rva0_6, sld, &_rorevcs, &rc0, &rc1, &rc2, &rc3, rom, prom0, prom1, prom2);
/* Road camber */
if (vregs.bank_mode == 0)
{
if (BIT(vregs.ba_val, 23))
bnkcs = 1;
else if (vregs.ba_val & 0x007f8000)
bnkcs = 0;
else
bnkcs = bank_cnt < 0x300;
}
else
{
if (BIT(vregs.ba_val, 23))
bnkcs = 0;
else if (vregs.ba_val & 0x007f8000)
bnkcs = 1;
else
bnkcs = bank_cnt >= 0x300;
}
px0 = BIT(rc0, pix);
px1 = BIT(rc1, pix);
px2 = BIT(rc2, pix);
px3 = BIT(rc3, pix);
/* Now go through and evaluate all the pixel logic */
if (vp2)
ic4_o18 = (hps00 && hps01 && hp3_en && !hps30) ||
(!hp0_en && hps01 && hp3_en && !hps30) ||
(hps00 && hps01 && !hps31) ||
(!hp0_en && hps01 && !hps31) ||
vp7;
else
ic4_o18 = !vp1;
if (tnlf)
ic3_o15 = (vp4 && !vp6 && !hp2_en && hps21) ||
(vp4 && !vp6 && hps20 && hps21) ||
(vp1 && !vp4 && !tnlmd1 && !tnlmd0) ||
(vp1 && !vp3 && !tnlmd1 && !tnlmd0) ||
(hp1_en && !hps10 && vp3 && !vp5) ||
(!hps11 && vp3 && !vp5);
else
ic3_o15 = !ic4_o18;
ic151_o17 = (_rorevcs && !tnlmd1 && tnlmd0) ||
(!_rorevcs && tnlmd1 && !tnlmd0) ||
(_rorevcs && ic4_o12) ||
(!_rorevcs && ic4_o13);
if (!ic3_o15)
ic151_o15 = (px0 && (bnkcs && wangl)) ||
(px1 && (bnkcs && wangl)) ||
ic151_o17 ||
px2 ||
!tnlf;
else
ic151_o15 = !tnlf;
ic151_o16 = (px1 && !px0 && tnlmd1 && !tnlmd0) ||
(px2 && tnlmd1 && tnlmd0) ||
ic149_o15;
mux = BIT(tcmd, 3) ? ic149_o15 : ic151_o16;
ic150_o19 = (px2 && !rva8) ||
!bnkcs ||
!mux ||
!ic151_o15;
/* Don't calculate the pixel colour if not visible */
if (ic150_o19)
{
ic149_o16 = (_rorevcs && !px2 && ic151_o15) ||
(tnlf && vp5 && !vp7 && px2 && !tnlmd0 && !tnlmd1 && ic151_o15) ||
(tnlf && vp6 && !vp7 && px2 && !tnlmd0 && !tnlmd1 && ic151_o15) ||
(tnlf && !ic4_o18);
ic150_o16 = (px2 && mux && rm1) ||
(mux && rva8 && ic151_o15) ||
(!px0 && mux) ||
!ic151_o15;
{
UINT32 a = mux && ic151_o15;
ic150_o17 = (a && !rm0 && px0) ||
(a && !px1) ||
(rva8 && a);
ic150_o18 = (a && !px2) ||
(rva8 && a);
}
if (ic151_o14)
ic150_o12 = rva8 || !mux || !ic151_o15 ||
(px2 && px1 && px0 && rm1 && !rm0) ||
(!px2 && px1 && px0 && !sld4 && rm0) ||
(px2 && px0 && !sld5 && !rm1 && !rm0) ||
(px2 && !px1 && px0 && !sld5 && !rm1) ||
(px2 && px1 && px0 && !sld5 && !sld4) ||
(px2 && px1 && px0 && !sld4 && rm1) ||
(!px2 && !px3 && !rm0) ||
(!px1 && !px3 && rm1) ||
(!px2 && !px1 && !px3) ||
(!px0 && !px3);
else
ic150_o12 = 0;
if (vp6 || ic151_o16)
{
UINT32 ic150_i5 = BIT(tcmd, 3) ? ic149_o15 : ic151_o16;
if (!(ic151_o15 && ic150_i5))
cprom_addr = (tcmd & 0x7) | (ic151_o16 ? 0x08 : 0);
else
cprom_addr = rcmd;
/* Inverted! */
cprom_addr = ((~cprom_addr) & 0xf) << 4;
}
else
cprom_addr = 0xf0;
cprom_addr |= (ic149_o16 ? 0x8 : 0) |
(ic150_o18 ? 0x4 : 0) |
(ic150_o17 ? 0x2 : 0) |
(ic150_o16 ? 0x1 : 0);
/* Lower four bits of colour output come from PROM BB7 @ 188 */
rcsd0_3 = rcols[cprom_addr] & 0xf;
{
UINT32 lfsr = vregs.wave_lfsr;
UINT32 wave =
(wave0 ^ BIT(lfsr, 0)) &&
(wave1 ^ BIT(lfsr, 3)) &&
BIT(lfsr, 5) &&
!BIT(lfsr, 15) &&
BIT(lfsr, 11) &&
BIT(lfsr, 13) &&
(rva20_6 < ((lfsr >> 8) & 0xf));
*bmpaddr++ = 0x40 | (wave ? 0 : 0x20) | (ic150_o12 ? 0x10 : 0) | rcsd0_3;
}
}
else
*bmpaddr++ = 0;
/* Update the various horizontal counters */
UPDATE_HPOS(0);
UPDATE_HPOS(1);
UPDATE_HPOS(2);
UPDATE_HPOS(3);
/* Update the LFSR */
vregs.wave_lfsr = (vregs.wave_lfsr << 1) | (BIT(vregs.wave_lfsr, 6) ^ !BIT(vregs.wave_lfsr, 15));
/* Increment the bank counter */
bank_cnt = (bank_cnt + 1) & 0x7ff;
/* X pos */
ls161 = (ls161 + 1) & 0x7fff;
}
/* WANGL active? Then update the 8-bit counter */
if (wangl)
{
if (BIT(vregs.flags, BB_RDFLAG_TNLMD0))
--vregs.wa8;
else
++vregs.wa8;
}
/* No carry out - just increment */
if (vregs.wa4 != 0xf)
++vregs.wa4;
else
{
/* Carry out; increment again on /TMG2S rise */
if (wangl)
{
if (BIT(vregs.flags, BB_RDFLAG_TNLMD0))
--vregs.wa8;
else
++vregs.wa8;
}
vregs.wa4 = 1;
}
/* Update accumulator */
vregs.h_val += vregs.h_inc;
/* Seems correct */
sf = vregs.shift;
if ((vregs.shift & 0x80) == 0)
{
vregs.shift <<= 1;
if ((sf & 0x08) == 0)
vregs.shift |= BIT(vregs.h_val, 15);
}
if ((sf & 0x08) && !(vregs.shift & 0x08))
vregs.h_inc = vregs.gas;
/* Finally, increment the banking accumulator */
vregs.ba_val = (vregs.ba_val + vregs.ba_inc) & 0x00ffffff;
}
}
/***************************************************************************
Buggy Boy Object Drawing
X-scaling isn't quite right but you wouldn't notice...
-------- xxxxxxxx Object number
xxxxxxxx -------- Y position
xxxxxxxx xxxxxxxx Y scale value
-------- xxxxxxxx X scale
00 = Invisible?
80 = 1:1
FF = Double size
xxxxxxxx -------- Attributes
xxxxxxxx xxxxxxxx Y scale delta
------xx xxxxxxxx X position
**************************************************************************/
static void buggyboy_draw_objs(running_machine &machine, UINT8 *bitmap, int wide)
{
tx1_state *state = machine.driver_data<tx1_state>();
UINT16 *buggyboy_objram = state->m_objram;
#define FRAC 16
UINT32 offs;
UINT32 x_mask;
UINT32 x_stride;
/* The many lookup table ROMs */
const UINT8 *const bug13 = (UINT8*)machine.region("obj_luts")->base();
const UINT8 *const bug18s = bug13 + 0x2000;
const UINT8 *const bb8 = (UINT8*)machine.region("proms")->base() + 0x1600;
const UINT8 *const bug16s = (UINT8*)machine.region("obj_map")->base();
const UINT8 *const bug17s = bug16s + 0x8000;
const UINT8 *const bb9o = (UINT8*)machine.region("proms")->base() + 0x500;
const UINT8 *const bb9e = bb9o + 0x800;
const UINT8 *const pixdata_rgn = (UINT8*)machine.region("obj_tiles")->base();
if (wide)
{
x_mask = 0x7ff;
x_stride = 768;
}
else
{
x_mask = 0x3ff;
x_stride = 256;
}
for (offs = 0; offs <= 0x300; offs += 8)
{
UINT32 x;
UINT32 y;
UINT32 gxflip;
UINT32 x_scale;
UINT32 x_step;
UINT16 y_scale;
UINT16 y_step;
UINT8 pctmp0_7;
UINT8 code;
/* Check for end of object list */
if ((buggyboy_objram[offs] & 0xff00) == 0xff00)
break;
/* X scale */
x_scale = buggyboy_objram[offs + 2] & 0xff;
/* TODO: Confirm against hardware? */
if (x_scale == 0)
continue;
/* 16-bit y-scale accumulator */
y_scale = buggyboy_objram[offs + 1];
y_step = buggyboy_objram[offs + 3];
/* Object number */
code = buggyboy_objram[offs] & 0xff;
/* Attributes */
pctmp0_7 = buggyboy_objram[offs + 2] >> 8;
/* Global x-flip */
gxflip = (pctmp0_7 & 0x80) >> 7;
/* Add 1 to account for line buffering */
y = (buggyboy_objram[offs] >> 8) + 1;
for (; y < 240; ++y)
{
UINT32 rom_addr2 = 0;
UINT8 bug17s_data = 0;
UINT8 bug16s_data;
/* Are we drawing on this line? */
// TODO: See big lampposts.
if (y_scale & 0x8000)
break;
{
UINT32 psa0_12;
UINT32 bug13_addr;
UINT32 bug13_data;
UINT32 rom_addr;
UINT32 x_acc;
UINT32 newtile = 1;
UINT32 dataend = 0;
UINT8 data1 = 0;
UINT8 data2 = 0;
UINT32 xflip = 0;
UINT32 opcd10_11;
UINT32 opcd8_9;
UINT32 opcd0_11 = 0;
UINT32 lasttile = 0;
/* Use the object code to lookup the tile sequence data */
bug13_addr = code << 4;
bug13_addr |= ((y_scale >> 11) & 0xf);
bug13_data = bug13[bug13_addr];
/* Reached the bottom of the object */
if (bug13_data == 0xff)
break;
psa0_12 = (((code & 0x80) << 5) | ((code & 0x40) << 6)) & 0x1000;
psa0_12 |= ((bb8[code] << 8) | bug13_data) & 0x1fff;
/* Static part of the BUG17S/BUG16S ROM address */
rom_addr = (psa0_12 & ~0xff) << 2;
/* Prepare the x-scaling */
x_step = (128 << FRAC) / x_scale;
x_acc = (psa0_12 & 0xff) << (FRAC + 5);
/* TODO Add note */
x = buggyboy_objram[offs + 4] & x_mask;
for (;;)
{
/* Get data and attributes for an 8x8 tile */
if (newtile)
{
UINT32 pscb0_11;
UINT32 psbb0_15;
UINT32 psbb6_7;
UINT32 rombank;
UINT8 *romptr;
UINT32 bug18s_data;
UINT32 low_addr = ((x_acc >> (FRAC + 3)) & x_mask);
/*
Objects are grouped by width (either 16, 8 or 4 tiles) in
the LUT ROMs. The ROM address lines therefore indicate
width and are used to determine the correct scan order
when x-flip is set.
*/
if (gxflip)
{
UINT32 xor_mask;
if (BIT(psa0_12, 11) || !BIT(psa0_12, 12))
xor_mask = 0xf;
else if (!BIT(psa0_12, 9))
xor_mask = 0x7;
else
xor_mask = 0x3;
rom_addr2 = rom_addr + (low_addr ^ xor_mask);
}
else
rom_addr2 = rom_addr + low_addr;
bug17s_data = bug17s[rom_addr2 & 0x7fff];
if ((bug17s_data & 0x40) && dataend)
lasttile = 1;
dataend |= (bug17s_data & 0x40);
/* Retrieve data for an 8x8 tile */
bug16s_data = bug16s[rom_addr2 & 0x7fff];
psbb0_15 = (bug17s_data << 8) | bug16s_data;
psbb6_7 = (BIT(psbb0_15, 12) ? psbb0_15 : (pctmp0_7 << 6)) & 0xc0;
/* Form the tile ROM address */
pscb0_11 = ((((psbb0_15 & ~0xc0) | psbb6_7) << 3) | ((y_scale >> 8) & 7)) & 0x7fff;
/* Choose from one of three banks */
rombank = ((BIT(pctmp0_7, 4) << 1) | BIT(psbb0_15, 13)) & 3;
romptr = (UINT8*)(pixdata_rgn + rombank * (0x8000 * 2));
/* Get raw 8x8 pixel row data */
data1 = *(pscb0_11 + romptr);
data2 = *(pscb0_11 + romptr + 0x8000);
/* Determine flip state (global XOR local) */
xflip = gxflip ^ !BIT(psbb0_15, 15);
bug18s_data = bug18s[ (BIT(pctmp0_7, 4) << 13) |
(BIT(psbb0_15, 13) << 12) |
(psbb0_15 & ~0xf0c0) |
psbb6_7 ];
/* Get the colour data. Note that bits 11 and 10 are inverted */
opcd10_11 = ((pctmp0_7 << 8) & 0xc00) ^ 0xc00;
opcd8_9 = ((pctmp0_7 & 0x60) << 3);
opcd0_11 = (opcd10_11 | opcd8_9 | bug18s_data) & 0xfff;
newtile = 0;
}
/* Draw a pixel? */
if (x < x_stride)
{
UINT8 pix;
UINT8 bit;
bit = (x_acc >> FRAC) & 7;
if (xflip)
bit ^= 7;
pix = (((data1 >> bit) & 1) << 1) | ((data2 >> bit) & 1);
/* Write the pixel if not transparent */
if (!(!(opcd0_11 & 0x80) && !pix))
{
UINT8 color;
UINT32 bb9_addr;
bb9_addr = ((opcd0_11 << 1) & 0x600) | ((opcd0_11 & 0x7f) << 2) | pix;
color = ((opcd0_11 >> 6) & 0x30);
/* Inverted on schematic */
if (x & 1)
color = ~(color | bb9o[bb9_addr]) & 0x3f;
else
color = ~(color | bb9e[bb9_addr]) & 0x3f;
*(bitmap + x_stride*y + x) = 0x40 | color;
}
}
/* Check if we've stepped into a new 8x8 tile */
if ((((x_acc + x_step) >> (FRAC + 3)) & x_mask) != ((x_acc >> (FRAC + 3)) & x_mask))
{
if (lasttile)
break;
newtile = 1;
}
x = (x + 1) & x_mask;
x_acc += x_step;
}
}// if (yscale)
y_scale += y_step;
} /* for (y) */
}/* for (offs) */
}
/*************************************
*
* Video Control Registers
*
*************************************/
/*
2400-24FF is road control (R/W)
/GAS = 24XX:
/BASET0 = 2400-F, 2410-F
/BASET1 = 2420-F, 2430-F
/BSET = 2440-F, 2450-F
/HASET = 2460-F, 2470-F
/HSET = 2480-F, 2490-F
/WASET = 24A0-F, 24B0-F
/FLAGS = 24E0-F, 24F0-F
*/
WRITE16_HANDLER( buggyboy_gas_w )
{
tx1_state *state = space->machine().driver_data<tx1_state>();
vregs_t &vregs = state->m_vregs;
offset <<= 1;
switch (offset & 0xe0)
{
case 0x00:
{
vregs.ba_inc &= ~0x0000ffff;
vregs.ba_inc |= data;
if (!(offset & 2))
vregs.ba_val &= ~0x0000ffff;
break;
}
case 0x20:
{
data &= 0xff;
vregs.ba_inc &= ~0xffff0000;
vregs.ba_inc |= data << 16;
vregs.bank_mode = data & 1;
if (!(offset & 2))
vregs.ba_val &= ~0xffff0000;
break;
}
case 0x40:
{
/* Ignore data? */
if (offset & 2)
vregs.ba_val = (vregs.ba_inc + vregs.ba_val) & 0x00ffffff;
break;
}
case 0x60:
{
vregs.h_inc = data;
vregs.shift = 0;
if (!(offset & 2))
vregs.h_val = 0;
break;
}
case 0x80:
{
/* Ignore data? */
if (offset & 2)
vregs.h_val += vregs.h_inc;
break;
}
case 0xa0:
{
vregs.wa8 = data >> 8;
vregs.wa4 = 0;
break;
}
case 0xe0:
{
cputag_set_input_line(space->machine(), "math_cpu", INPUT_LINE_TEST, CLEAR_LINE);
vregs.flags = data;
break;
}
}
/* Value is latched by LS373 76/77 */
vregs.gas = data;
}
WRITE16_HANDLER( buggyboy_sky_w )
{
tx1_state *state = space->machine().driver_data<tx1_state>();
state->m_vregs.sky = data;
}
WRITE16_HANDLER( buggyboy_scolst_w )
{
tx1_state *state = space->machine().driver_data<tx1_state>();
state->m_vregs.scol = data;
}
/*************************************
*
* Core Functions
*
*************************************/
static void bb_combine_layers(running_machine &machine, bitmap_t *bitmap, int screen)
{
tx1_state *state = machine.driver_data<tx1_state>();
UINT8 *chr_pal = machine.region("proms")->base() + 0x400;
UINT32 bmp_stride;
UINT32 x_offset;
UINT32 y;
if (screen < 0)
{
bmp_stride = 256;
x_offset = 0;
}
else
{
bmp_stride = 768;
x_offset = 256 * screen;
}
for (y = 0; y < 240; ++y)
{
UINT32 x;
UINT32 bmp_offset = y * bmp_stride + x_offset;
UINT8 *chr_addr = state->m_chr_bmp + bmp_offset;
UINT8 *rod_addr = state->m_rod_bmp + bmp_offset;
UINT8 *obj_addr = state->m_obj_bmp + bmp_offset;
UINT32 sky_en = BIT(state->m_vregs.sky, 7);
UINT32 sky_val = (((state->m_vregs.sky & 0x7f) + y) >> 2) & 0x3f;
UINT16 *bmp_addr = BITMAP_ADDR16(bitmap, y, 0);
for (x = 0; x < 256; ++x)
{
UINT32 out_val;
UINT32 char_val = *chr_addr++;
UINT32 char_6_7 = (char_val & 0xc0) >> 2;
UINT32 obj_val = *obj_addr++;
UINT32 obj6 = BIT(obj_val, 6);
UINT32 rod_val = *rod_addr++;
UINT32 rod6 = BIT(rod_val, 6);
UINT32 chr = !(BIT(char_val, 7) && (char_val & 3) );
UINT32 sel =
(
( BIT(obj_val, 6) && chr) ||
( sky_en && !(char_val & 3) && (!obj6 && !rod6) )
) ? 0 : 1;
sel |= (!(obj6 || rod6) || !chr) ? 2 : 0;
/* Select the layer */
if (sel == 0) out_val = obj_val & 0x3f;
else if (sel == 1) out_val = rod_val & 0x3f;
else if (sel == 2) out_val = sky_val;
else out_val = char_6_7 + chr_pal[char_val];
*bmp_addr++ = (sel << 6) + out_val;
}
}
}
VIDEO_START( buggyboy )
{
tx1_state *state = machine.driver_data<tx1_state>();
/* Allocate some bitmaps */
state->m_chr_bmp = auto_alloc_array(machine, UINT8, 3 * 256 * 240);
state->m_obj_bmp = auto_alloc_array(machine, UINT8, 3 * 256 * 240);
state->m_rod_bmp = auto_alloc_array(machine, UINT8, 3 * 256 * 240);
/* Set a timer to run the interrupts */
state->m_interrupt_timer = machine.scheduler().timer_alloc(FUNC(interrupt_callback));
/* /CUDISP CRTC interrupt */
state->m_interrupt_timer->adjust(machine.primary_screen->time_until_pos(CURSOR_YPOS, CURSOR_XPOS));
}
VIDEO_START( buggybjr )
{
tx1_state *state = machine.driver_data<tx1_state>();
/* Allocate some bitmaps */
state->m_chr_bmp = auto_alloc_array(machine, UINT8, 256 * 240);
state->m_obj_bmp = auto_alloc_array(machine, UINT8, 256 * 240);
state->m_rod_bmp = auto_alloc_array(machine, UINT8, 256 * 240);
/* Set a timer to run the interrupts */
state->m_interrupt_timer = machine.scheduler().timer_alloc(FUNC(interrupt_callback));
/* /CUDISP CRTC interrupt */
state->m_interrupt_timer->adjust(machine.primary_screen->time_until_pos(CURSOR_YPOS, CURSOR_XPOS));
}
SCREEN_EOF( buggyboy )
{
tx1_state *state = machine.driver_data<tx1_state>();
/* /VSYNC: Update TZ113 @ 219 */
state->m_vregs.slin_val += state->m_vregs.slin_inc;
/* /VSYNC: Clear wave LFSR */
state->m_vregs.wave_lfsr = 0;
}
SCREEN_UPDATE( buggyboy )
{
tx1_state *state = screen->machine().driver_data<tx1_state>();
device_t *left_screen = screen->machine().device("lscreen");
device_t *center_screen = screen->machine().device("cscreen");
device_t *right_screen = screen->machine().device("rscreen");
if (screen == left_screen)
{
memset(state->m_obj_bmp, 0, 768*240);
memset(state->m_rod_bmp, 0, 768*240);
buggyboy_draw_char(screen->machine(), state->m_chr_bmp, 1);
buggyboy_draw_road(screen->machine(), state->m_rod_bmp);
buggyboy_draw_objs(screen->machine(), state->m_obj_bmp, 1);
bb_combine_layers(screen->machine(), bitmap, 0);
}
else if (screen == center_screen)
{
bb_combine_layers(screen->machine(), bitmap, 1);
}
else if (screen == right_screen)
{
bb_combine_layers(screen->machine(), bitmap, 2);
}
return 0;
}
SCREEN_UPDATE( buggybjr )
{
tx1_state *state = screen->machine().driver_data<tx1_state>();
memset(state->m_obj_bmp, 0, 256*240);
buggyboy_draw_char(screen->machine(), state->m_chr_bmp, 0);
buggybjr_draw_road(screen->machine(), state->m_rod_bmp, 0);
buggyboy_draw_objs(screen->machine(), state->m_obj_bmp, 0);
bb_combine_layers(screen->machine(), bitmap, -1);
return 0;
}