/***************************************************************************
video.c
Functions to emulate the video hardware of the machine.
***************************************************************************/
#include "emu.h"
#include "video/resnet.h"
#include "audio/pleiads.h"
#include "includes/naughtyb.h"
static const rectangle scrollvisiblearea =
{
2*8, 34*8-1,
0*8, 28*8-1
};
static const rectangle leftvisiblearea =
{
0*8, 2*8-1,
0*8, 28*8-1
};
static const rectangle rightvisiblearea =
{
34*8, 36*8-1,
0*8, 28*8-1
};
static const res_net_decode_info naughtyb_decode_info =
{
2, /* two proms */
0, /* start at 0 */
255, /* end at 255 */
/* R, G, B, R, G, B */
{ 0, 0, 0, 256, 256, 256}, /* offsets */
{ 0, 2, 1, -1, 1, 0}, /* shifts */
{0x01,0x01,0x01,0x02,0x02,0x02} /* masks */
};
static const res_net_info naughtyb_net_info =
{
RES_NET_VCC_5V | RES_NET_VBIAS_5V | RES_NET_VIN_OPEN_COL,
{
{ RES_NET_AMP_NONE, 130, 270, 2, { 270, 1 } }, /* no resistor for bit1 */
{ RES_NET_AMP_NONE, 130, 270, 2, { 270, 1 } }, /* no resistor for bit1 */
{ RES_NET_AMP_NONE, 130, 270, 2, { 270, 1 } } /* no resistor for bit1 */
}
};
/***************************************************************************
Convert the color PROMs into a more useable format.
Naughty Boy has two 256x4 palette PROMs, one containing the high bits and
the other the low bits (2x2x2 color space).
The palette PROMs are connected to a 7407 (hex open collector buffer),
which in turn is connected to the RGB output this way:
bit 3 --
-- 270 ohm resistor -- GREEN
-- 270 ohm resistor -- BLUE
bit 0 -- 270 ohm resistor -- RED
bit 3 --
-- GREEN
-- BLUE
bit 0 -- RED
plus 130 ohm pullup and 270 ohm pulldown resistors on all lines
***************************************************************************/
PALETTE_INIT( naughtyb )
{
static const int resistances[2] = { 270, 130 };
double weights[2];
int i;
/* compute the color output resistor weights */
compute_resistor_weights(0, 255, -1.0,
2, resistances, weights, 0, 0,
2, resistances, weights, 0, 0,
0, 0, 0, 0, 0);
for (i = 0;i < machine.total_colors(); i++)
{
int bit0, bit1;
int r, g, b;
/* red component */
bit0 = (color_prom[i] >> 0) & 0x01;
bit1 = (color_prom[i+0x100] >> 0) & 0x01;
r = combine_2_weights(weights, bit0, bit1);
/* green component */
bit0 = (color_prom[i] >> 2) & 0x01;
bit1 = (color_prom[i+0x100] >> 2) & 0x01;
g = combine_2_weights(weights, bit0, bit1);
/* blue component */
bit0 = (color_prom[i] >> 1) & 0x01;
bit1 = (color_prom[i+0x100] >> 1) & 0x01;
b = combine_2_weights(weights, bit0, bit1);
palette_set_color(machine, BITSWAP8(i,5,7,6,2,1,0,4,3), MAKE_RGB(r, g, b));
}
}
/***************************************************************************
Start the video hardware emulation.
***************************************************************************/
VIDEO_START( naughtyb )
{
naughtyb_state *state = machine.driver_data<naughtyb_state>();
state->m_palreg = state->m_bankreg = 0;
/* Naughty Boy has a virtual screen twice as large as the visible screen */
machine.generic.tmpbitmap = auto_bitmap_alloc(machine,68*8,28*8,machine.primary_screen->format());
}
WRITE8_HANDLER( naughtyb_videoreg_w )
{
naughtyb_state *state = space->machine().driver_data<naughtyb_state>();
// bits 4+5 control the sound circuit
pleiads_sound_control_c_w(space->machine().device("cust"),offset,data);
state->m_cocktail =
( ( input_port_read(space->machine(), "DSW0") & 0x80 ) && // cabinet == cocktail
( data & 0x01 ) ); // handling player 2
state->m_palreg = (data >> 1) & 0x03; // pallette sel is bit 1 & 2
state->m_bankreg = (data >> 2) & 0x01; // banksel is just bit 2
}
WRITE8_HANDLER( popflame_videoreg_w )
{
naughtyb_state *state = space->machine().driver_data<naughtyb_state>();
// bits 4+5 control the sound circuit
pleiads_sound_control_c_w(space->machine().device("cust"),offset,data);
state->m_cocktail =
( ( input_port_read(space->machine(), "DSW0") & 0x80 ) && // cabinet == cocktail
( data & 0x01 ) ); // handling player 2
state->m_palreg = (data >> 1) & 0x03; // pallette sel is bit 1 & 2
state->m_bankreg = (data >> 3) & 0x01; // banksel is just bit 3
}
/***************************************************************************
The Naughty Boy screen is split into two sections by the hardware
NonScrolled = 28x4 - (rows 0,1,34,35, as shown below)
this area is split between the top and bottom of the screen,
and the address mapping is really funky.
Scrolled = 28x64, with a 28x32 viewport, as shown below
Each column in the virtual screen is 64 (40h) characters high.
Thus, column 27 is stored in VRAm at address 0-3fh,
column 26 is stored at 40-7f, and so on.
This illustration shows the horizonal scroll register set to zero,
so the topmost 32 rows of the virtual screen are shown.
The following screen-to-memory mapping. This is shown from player's viewpoint,
which with the CRT rotated 90 degrees CCW. This example shows the horizonal
scroll register set to zero.
COLUMN
0 1 2 - 25 26 27
-------------------------------
0| 76E 76A 762 - 70A 706 702 |
| | Nonscrolled display
1| 76F 76B 762 - 70B 707 703 |
|-------------------------------| -----
2| 6C0 680 640 - 80 40 00 |
| |
R 3| 6C1 681 641 - 81 41 01 |
O | | 28 x 32 viewport
W || | | | into 28x64 virtual,
| | scrollable screen
32| 6DE 69E 65E 9E 5E 1E |
| |
33| 6DF 69F 65F - 9F 5F 1F |
|-------------------------------| -----
34| 76C 768 764 708 704 700 |
| | Nonscrolled display
35| 76D 769 765 709 705 701 |
-------------------------------
***************************************************************************/
SCREEN_UPDATE( naughtyb )
{
naughtyb_state *state = screen->machine().driver_data<naughtyb_state>();
UINT8 *videoram = state->m_videoram;
int offs;
// for every character in the Video RAM
for (offs = 0x800 - 1; offs >= 0; offs--)
{
int sx,sy;
if ( state->m_cocktail )
{
if (offs < 0x700)
{
sx = 63 - offs % 64;
sy = 27 - offs / 64;
}
else
{
sx = 64 + ( 3 - (offs - 0x700) % 4 );
sy = 27 - (offs - 0x700) / 4;
}
}
else
{
if (offs < 0x700)
{
sx = offs % 64;
sy = offs / 64;
}
else
{
sx = 64 + (offs - 0x700) % 4;
sy = (offs - 0x700) / 4;
}
}
drawgfx_opaque(screen->machine().generic.tmpbitmap,0,screen->machine().gfx[0],
state->m_videoram2[offs] + 256 * state->m_bankreg,
(state->m_videoram2[offs] >> 5) + 8 * state->m_palreg,
state->m_cocktail,state->m_cocktail,
8*sx,8*sy);
drawgfx_transpen(screen->machine().generic.tmpbitmap,0,screen->machine().gfx[1],
videoram[offs] + 256*state->m_bankreg,
(videoram[offs] >> 5) + 8 * state->m_palreg,
state->m_cocktail,state->m_cocktail,
8*sx,8*sy,0);
}
// copy the temporary bitmap to the screen
{
int scrollx;
copybitmap(bitmap,screen->machine().generic.tmpbitmap,0,0,-66*8,0,&leftvisiblearea);
copybitmap(bitmap,screen->machine().generic.tmpbitmap,0,0,-30*8,0,&rightvisiblearea);
scrollx = ( state->m_cocktail ) ? *state->m_scrollreg - 239 : -*state->m_scrollreg + 16;
copyscrollbitmap(bitmap,screen->machine().generic.tmpbitmap,1,&scrollx,0,0,&scrollvisiblearea);
}
return 0;
}