mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
split out the roadgen (nw)
This commit is contained in:
parent
90174dd139
commit
11416b9d26
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -5756,6 +5756,8 @@ src/mame/video/segag80v.c svneol=native#text/plain
|
||||
src/mame/video/segahang.c svneol=native#text/plain
|
||||
src/mame/video/segaic16.c svneol=native#text/plain
|
||||
src/mame/video/segaic16.h svneol=native#text/plain
|
||||
src/mame/video/segaic16_road.c svneol=native#text/plain
|
||||
src/mame/video/segaic16_road.h svneol=native#text/plain
|
||||
src/mame/video/segaic24.c svneol=native#text/plain
|
||||
src/mame/video/segaic24.h svneol=native#text/plain
|
||||
src/mame/video/segaorun.c svneol=native#text/plain
|
||||
|
@ -846,6 +846,7 @@ static MACHINE_CONFIG_START( shared_base, segahang_state )
|
||||
MCFG_I8255_ADD( "i8255_2", hangon_ppi_intf_1 )
|
||||
|
||||
MCFG_SEGAIC16VID_ADD("segaic16vid")
|
||||
MCFG_SEGAIC16_ROAD_ADD("segaic16road")
|
||||
|
||||
// video hardware
|
||||
MCFG_GFXDECODE(segahang)
|
||||
@ -1819,7 +1820,7 @@ DRIVER_INIT_MEMBER(segahang_state,generic)
|
||||
// point globals to allocated memory regions
|
||||
m_segaic16vid->segaic16_tileram_0 = reinterpret_cast<UINT16 *>(memshare("tileram")->ptr());
|
||||
m_segaic16vid->segaic16_textram_0 = reinterpret_cast<UINT16 *>(memshare("textram")->ptr());
|
||||
m_segaic16vid->segaic16_roadram_0 = reinterpret_cast<UINT16 *>(memshare("roadram")->ptr());
|
||||
m_segaic16road->segaic16_roadram_0 = reinterpret_cast<UINT16 *>(memshare("roadram")->ptr());
|
||||
|
||||
// save states
|
||||
save_item(NAME(m_adc_select));
|
||||
|
@ -833,7 +833,7 @@ static ADDRESS_MAP_START( sub_map, AS_PROGRAM, 16, segaorun_state )
|
||||
AM_RANGE(0x000000, 0x05ffff) AM_ROM AM_SHARE("cpu1rom")
|
||||
AM_RANGE(0x060000, 0x067fff) AM_MIRROR(0x018000) AM_RAM AM_SHARE("cpu1ram")
|
||||
AM_RANGE(0x080000, 0x080fff) AM_MIRROR(0x00f000) AM_RAM AM_SHARE("roadram")
|
||||
AM_RANGE(0x090000, 0x09ffff) AM_DEVREADWRITE("segaic16vid", segaic16_video_device, segaic16_road_control_0_r, segaic16_road_control_0_w)
|
||||
AM_RANGE(0x090000, 0x09ffff) AM_DEVREADWRITE("segaic16road", segaic16_road_device, segaic16_road_control_0_r, segaic16_road_control_0_w)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
@ -1092,6 +1092,7 @@ static MACHINE_CONFIG_START( outrun_base, segaorun_state )
|
||||
MCFG_SCREEN_UPDATE_DRIVER(segaorun_state, screen_update_outrun)
|
||||
|
||||
MCFG_SEGAIC16VID_ADD("segaic16vid")
|
||||
MCFG_SEGAIC16_ROAD_ADD("segaic16road")
|
||||
|
||||
// sound hardware
|
||||
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
|
||||
@ -2124,7 +2125,7 @@ DRIVER_INIT_MEMBER(segaorun_state,generic)
|
||||
// point globals to allocated memory regions
|
||||
m_segaic16vid->segaic16_tileram_0 = reinterpret_cast<UINT16 *>(memshare("tileram")->ptr());
|
||||
m_segaic16vid->segaic16_textram_0 = reinterpret_cast<UINT16 *>(memshare("textram")->ptr());
|
||||
m_segaic16vid->segaic16_roadram_0 = reinterpret_cast<UINT16 *>(memshare("roadram")->ptr());
|
||||
m_segaic16road->segaic16_roadram_0 = reinterpret_cast<UINT16 *>(memshare("roadram")->ptr());
|
||||
|
||||
// save state
|
||||
save_item(NAME(m_adc_select));
|
||||
|
@ -926,7 +926,7 @@ static ADDRESS_MAP_START( main_map, AS_PROGRAM, 16, segaxbd_state )
|
||||
AM_RANGE(0x2e4000, 0x2e401f) AM_MIRROR(0x003fe0) AM_DEVREADWRITE("divider_subx", sega_315_5249_divider_device, read, write)
|
||||
AM_RANGE(0x2e8000, 0x2e800f) AM_MIRROR(0x003ff0) AM_DEVREADWRITE("cmptimer_subx", sega_315_5250_compare_timer_device, read, write)
|
||||
AM_RANGE(0x2ec000, 0x2ecfff) AM_MIRROR(0x001000) AM_RAM AM_SHARE("roadram")
|
||||
AM_RANGE(0x2ee000, 0x2effff) AM_DEVREADWRITE("segaic16vid", segaic16_video_device, segaic16_road_control_0_r, segaic16_road_control_0_w)
|
||||
AM_RANGE(0x2ee000, 0x2effff) AM_DEVREADWRITE("segaic16road", segaic16_road_device, segaic16_road_control_0_r, segaic16_road_control_0_w)
|
||||
// AM_RANGE(0x2f0000, 0x2f3fff) AM_READWRITE(excs_r, excs_w)
|
||||
AM_RANGE(0x3f8000, 0x3fbfff) AM_RAM AM_SHARE("backup1")
|
||||
AM_RANGE(0x3fc000, 0x3fffff) AM_RAM AM_SHARE("backup2")
|
||||
@ -948,7 +948,7 @@ static ADDRESS_MAP_START( sub_map, AS_PROGRAM, 16, segaxbd_state )
|
||||
AM_RANGE(0x0e4000, 0x0e401f) AM_MIRROR(0x003fe0) AM_DEVREADWRITE("divider_subx", sega_315_5249_divider_device, read, write)
|
||||
AM_RANGE(0x0e8000, 0x0e800f) AM_MIRROR(0x003ff0) AM_DEVREADWRITE("cmptimer_subx", sega_315_5250_compare_timer_device, read, write)
|
||||
AM_RANGE(0x0ec000, 0x0ecfff) AM_MIRROR(0x001000) AM_RAM AM_SHARE("roadram")
|
||||
AM_RANGE(0x0ee000, 0x0effff) AM_DEVREADWRITE("segaic16vid", segaic16_video_device, segaic16_road_control_0_r, segaic16_road_control_0_w)
|
||||
AM_RANGE(0x0ee000, 0x0effff) AM_DEVREADWRITE("segaic16road", segaic16_road_device, segaic16_road_control_0_r, segaic16_road_control_0_w)
|
||||
// AM_RANGE(0x0f0000, 0x0f3fff) AM_READWRITE(excs_r, excs_w)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
@ -1595,6 +1595,7 @@ static MACHINE_CONFIG_START( xboard, segaxbd_state )
|
||||
|
||||
MCFG_SEGA_XBOARD_SPRITES_ADD("sprites")
|
||||
MCFG_SEGAIC16VID_ADD("segaic16vid")
|
||||
MCFG_SEGAIC16_ROAD_ADD("segaic16road")
|
||||
|
||||
// sound hardware
|
||||
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
|
||||
@ -3201,7 +3202,7 @@ DRIVER_INIT_MEMBER(segaxbd_state,generic)
|
||||
// point globals to allocated memory regions
|
||||
m_segaic16vid->segaic16_tileram_0 = reinterpret_cast<UINT16 *>(memshare("tileram")->ptr());
|
||||
m_segaic16vid->segaic16_textram_0 = reinterpret_cast<UINT16 *>(memshare("textram")->ptr());
|
||||
m_segaic16vid->segaic16_roadram_0 = reinterpret_cast<UINT16 *>(memshare("roadram")->ptr());
|
||||
m_segaic16road->segaic16_roadram_0 = reinterpret_cast<UINT16 *>(memshare("roadram")->ptr());
|
||||
|
||||
// save state
|
||||
save_item(NAME(m_timer_irq_state));
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "machine/i8255.h"
|
||||
#include "machine/segaic16.h"
|
||||
#include "video/segaic16.h"
|
||||
#include "video/segaic16_road.h"
|
||||
#include "video/sega16sp.h"
|
||||
|
||||
|
||||
@ -60,6 +61,7 @@ public:
|
||||
m_i8255_2(*this, "i8255_2"),
|
||||
m_sprites(*this, "sprites"),
|
||||
m_segaic16vid(*this, "segaic16vid"),
|
||||
m_segaic16road(*this, "segaic16road"),
|
||||
m_workram(*this, "workram"),
|
||||
m_sharrier_video(false),
|
||||
m_adc_select(0)
|
||||
@ -122,6 +124,7 @@ protected:
|
||||
required_device<i8255_device> m_i8255_2;
|
||||
required_device<sega_16bit_sprite_device> m_sprites;
|
||||
required_device<segaic16_video_device> m_segaic16vid;
|
||||
required_device<segaic16_road_device> m_segaic16road;
|
||||
|
||||
// memory pointers
|
||||
required_shared_ptr<UINT16> m_workram;
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "machine/nvram.h"
|
||||
#include "machine/segaic16.h"
|
||||
#include "video/segaic16.h"
|
||||
#include "video/segaic16_road.h"
|
||||
#include "video/sega16sp.h"
|
||||
|
||||
|
||||
@ -60,6 +61,7 @@ public:
|
||||
m_nvram(*this, "nvram"),
|
||||
m_sprites(*this, "sprites"),
|
||||
m_segaic16vid(*this, "segaic16vid"),
|
||||
m_segaic16road(*this, "segaic16road"),
|
||||
m_workram(*this, "workram"),
|
||||
m_custom_map(NULL),
|
||||
m_shangon_video(false),
|
||||
@ -102,8 +104,8 @@ public:
|
||||
|
||||
DECLARE_WRITE16_HANDLER( sega_tileram_0_w ) { m_segaic16vid->segaic16_tileram_0_w(space,offset,data,mem_mask); };
|
||||
DECLARE_WRITE16_HANDLER( sega_textram_0_w ) { m_segaic16vid->segaic16_textram_0_w(space,offset,data,mem_mask); };
|
||||
DECLARE_READ16_HANDLER( sega_road_control_0_r ) { return m_segaic16vid->segaic16_road_control_0_r(space,offset,mem_mask); };
|
||||
DECLARE_WRITE16_HANDLER( sega_road_control_0_w ) { m_segaic16vid->segaic16_road_control_0_w(space,offset,data,mem_mask); };
|
||||
DECLARE_READ16_HANDLER( sega_road_control_0_r ) { return m_segaic16road->segaic16_road_control_0_r(space,offset,mem_mask); };
|
||||
DECLARE_WRITE16_HANDLER( sega_road_control_0_w ) { m_segaic16road->segaic16_road_control_0_w(space,offset,data,mem_mask); };
|
||||
|
||||
protected:
|
||||
// timer IDs
|
||||
@ -138,6 +140,7 @@ protected:
|
||||
optional_device<nvram_device> m_nvram;
|
||||
required_device<sega_16bit_sprite_device> m_sprites;
|
||||
required_device<segaic16_video_device> m_segaic16vid;
|
||||
required_device<segaic16_road_device> m_segaic16road;
|
||||
|
||||
// memory
|
||||
required_shared_ptr<UINT16> m_workram;
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "machine/segaic16.h"
|
||||
#include "video/segaic16.h"
|
||||
#include "video/segaic16_road.h"
|
||||
#include "video/sega16sp.h"
|
||||
|
||||
|
||||
@ -59,6 +60,7 @@ public:
|
||||
m_cmptimer_1(*this, "cmptimer_main"),
|
||||
m_sprites(*this, "sprites"),
|
||||
m_segaic16vid(*this, "segaic16vid"),
|
||||
m_segaic16road(*this, "segaic16road"),
|
||||
m_gprider_hack(false),
|
||||
m_road_priority(1),
|
||||
m_scanline_timer(NULL),
|
||||
@ -150,6 +152,7 @@ protected:
|
||||
required_device<sega_315_5250_compare_timer_device> m_cmptimer_1;
|
||||
required_device<sega_xboard_sprite_device> m_sprites;
|
||||
required_device<segaic16_video_device> m_segaic16vid;
|
||||
required_device<segaic16_road_device> m_segaic16road;
|
||||
|
||||
// configuration
|
||||
bool m_gprider_hack;
|
||||
|
@ -1552,6 +1552,7 @@ $(MAMEOBJ)/sega.a: \
|
||||
$(AUDIO)/pulsar.o \
|
||||
$(AUDIO)/segasnd.o \
|
||||
$(VIDEO)/segaic16.o \
|
||||
$(VIDEO)/segaic16_road.o \
|
||||
$(VIDEO)/sega16sp.o \
|
||||
$(VIDEO)/segaic24.o \
|
||||
$(MACHINE)/gdrom.o \
|
||||
|
@ -50,7 +50,7 @@ void segahang_state::video_start()
|
||||
m_segaic16vid->segaic16_tilemap_init(machine(), 0, SEGAIC16_TILEMAP_HANGON, 0x000, 0, 2);
|
||||
|
||||
// initialize the road
|
||||
m_segaic16vid->segaic16_road_init(machine(), 0, m_sharrier_video ? SEGAIC16_ROAD_SHARRIER : SEGAIC16_ROAD_HANGON, 0x038, 0x7c0, 0x7c0, 0);
|
||||
m_segaic16road->segaic16_road_init(machine(), 0, m_sharrier_video ? SEGAIC16_ROAD_SHARRIER : SEGAIC16_ROAD_HANGON, 0x038, 0x7c0, 0x7c0, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -74,7 +74,7 @@ UINT32 segahang_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap
|
||||
machine().priority_bitmap.fill(0, cliprect);
|
||||
|
||||
// draw the low priority road layer
|
||||
m_segaic16vid->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_BACKGROUND);
|
||||
m_segaic16road->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_BACKGROUND);
|
||||
|
||||
// draw background
|
||||
m_segaic16vid->segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_BACKGROUND, 0, 0x01);
|
||||
@ -85,7 +85,7 @@ UINT32 segahang_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap
|
||||
m_segaic16vid->segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_FOREGROUND, 1, 0x04);
|
||||
|
||||
// draw the high priority road
|
||||
m_segaic16vid->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_FOREGROUND);
|
||||
m_segaic16road->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_FOREGROUND);
|
||||
|
||||
// text layer
|
||||
// note that we inflate the priority of the text layer to prevent sprites
|
||||
|
@ -1291,609 +1291,6 @@ WRITE16_MEMBER( segaic16_video_device::segaic16_textram_0_w )
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* Hang On/Space Harrier-style road chip
|
||||
*
|
||||
* Road RAM:
|
||||
* Offset Bits Usage
|
||||
* 000-1FF ----pp-- -------- road priority versus tilemaps and sprites
|
||||
* ------s- -------- (Hang On only) Stripe coloring enable (1=enable)
|
||||
* ------s- -------- (Space Harrier only) Solid color fill (1=solid, 0=from ROM)
|
||||
* -------m -------- mirror enable (1=enable)
|
||||
* -------- iiiiiiii index for other tables
|
||||
* -------- rrrrrrrr road ROM line select
|
||||
* 200-3FF ----hhhh hhhhhhhh horizontal scroll
|
||||
* 400-5FF --bbbbbb -------- background color (colorset 0)
|
||||
* -------- --bbbbbb background color (colorset 1)
|
||||
* 600-7FF -------- s------- stripe color index (colorset 1)
|
||||
* -------- -s------ stripe color index (colorset 0)
|
||||
* -------- --a----- pixel value 2 color index (colorset 1)
|
||||
* -------- ---a---- pixel value 2 color index (colorset 0)
|
||||
* -------- ----b--- pixel value 1 color index (colorset 1)
|
||||
* -------- -----b-- pixel value 1 color index (colorset 0)
|
||||
* -------- ------c- pixel value 0 color index (colorset 1)
|
||||
* -------- -------c pixel value 0 color index (colorset 0)
|
||||
*
|
||||
* Logic:
|
||||
* First, the scanline is used to index into the table at 000-1FF
|
||||
*
|
||||
* The index is taken from the low 8 bits of the table value from 000-1FF
|
||||
*
|
||||
* The horizontal scroll value is looked up using the index in the table at
|
||||
* 200-3FF
|
||||
*
|
||||
* The background color information is looked up using the index in the table at 400-5FF.
|
||||
*
|
||||
* The pixel color information is looked up using the index in the table at 600-7FF.
|
||||
*
|
||||
*******************************************************************************************/
|
||||
|
||||
static void segaic16_road_hangon_decode(running_machine &machine, struct road_info *info)
|
||||
{
|
||||
int x, y;
|
||||
const UINT8 *gfx = machine.root_device().memregion("gfx3")->base();
|
||||
int len = machine.root_device().memregion("gfx3")->bytes();
|
||||
|
||||
/* allocate memory for the unpacked road data */
|
||||
info->gfx = auto_alloc_array(machine, UINT8, 256 * 512);
|
||||
|
||||
/* loop over rows */
|
||||
for (y = 0; y < 256; y++)
|
||||
{
|
||||
const UINT8 *src = gfx + ((y & 0xff) * 0x40) % len;
|
||||
UINT8 *dst = info->gfx + y * 512;
|
||||
|
||||
/* loop over columns */
|
||||
for (x = 0; x < 512; x++)
|
||||
dst[x] = (((src[x/8] >> (~x & 7)) & 1) << 0) | (((src[x/8 + 0x4000] >> (~x & 7)) & 1) << 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void segaic16_road_hangon_draw(struct road_info *info, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority)
|
||||
{
|
||||
UINT16 *roadram = info->roadram;
|
||||
int x, y;
|
||||
|
||||
/* loop over scanlines */
|
||||
for (y = cliprect.min_y; y <= cliprect.max_y; y++)
|
||||
{
|
||||
UINT16 *dest = &bitmap.pix16(y);
|
||||
int control = roadram[0x000 + y];
|
||||
int hpos = roadram[0x100 + (control & 0xff)];
|
||||
int color0 = roadram[0x200 + (control & 0xff)];
|
||||
int color1 = roadram[0x300 + (control & 0xff)];
|
||||
int ff9j1, ff9j2, ctr9m, ctr9n9p, ctr9n9p_ena, ss8j, plycont;
|
||||
UINT8 *src;
|
||||
|
||||
/* the PLYCONT signal controls the road layering */
|
||||
plycont = (control >> 10) & 3;
|
||||
|
||||
/* skip layers we aren't supposed to be drawing */
|
||||
if ((plycont == 0 && priority != SEGAIC16_ROAD_BACKGROUND) ||
|
||||
(plycont != 0 && priority != SEGAIC16_ROAD_FOREGROUND))
|
||||
continue;
|
||||
|
||||
/* compute the offset of the road graphics for this line */
|
||||
src = info->gfx + (0x000 + (control & 0xff)) * 512;
|
||||
|
||||
/* initialize the 4-bit counter at 9M, which counts bits within each road byte */
|
||||
ctr9m = hpos & 7;
|
||||
|
||||
/* initialize the two 4-bit counters at 9P (low) and 9N (high), which count road data bytes */
|
||||
ctr9n9p = (hpos >> 3) & 0xff;
|
||||
|
||||
/* initialize the flip-flop at 9J (lower half), which controls the counting direction */
|
||||
ff9j1 = (hpos >> 11) & 1;
|
||||
|
||||
/* initialize the flip-flop at 9J (upper half), which controls the background color */
|
||||
ff9j2 = 1;
|
||||
|
||||
/* initialize the serial shifter at 8S, which delays several signals after we flip */
|
||||
ss8j = 0;
|
||||
|
||||
/* draw this scanline from the beginning */
|
||||
for (x = -24; x <= cliprect.max_x; x++)
|
||||
{
|
||||
int md, color, select;
|
||||
|
||||
/* ---- the following logic all happens constantly ---- */
|
||||
|
||||
/* the enable is controlled by the value in the counter at 9M */
|
||||
ctr9n9p_ena = (ctr9m == 7);
|
||||
|
||||
/* if we carried out of the 9P/9N counters, we will forcibly clear the flip-flop at 9J (lower half) */
|
||||
if ((ctr9n9p & 0xff) == 0xff)
|
||||
ff9j1 = 0;
|
||||
|
||||
/* if the control word bit 8 is clear, we will forcibly set the flip-flop at 9J (lower half) */
|
||||
if (!(control & 0x100))
|
||||
ff9j1 = 1;
|
||||
|
||||
/* for the Hang On/Super Hang On case only: if the control word bit 9 is clear, we will forcibly */
|
||||
/* set the flip-flip at 9J (upper half) */
|
||||
if (info->type == SEGAIC16_ROAD_HANGON && !(control & 0x200))
|
||||
ff9j2 = 1;
|
||||
|
||||
/* ---- now process the pixel ---- */
|
||||
md = 3;
|
||||
|
||||
/* the Space Harrier/Enduro Racer hardware has a tweak that maps the control word bit 9 to the */
|
||||
/* /CE line on the road ROM; use this to effectively disable the road data */
|
||||
if (info->type != SEGAIC16_ROAD_SHARRIER || !(control & 0x200))
|
||||
|
||||
/* the /OE line on the road ROM is linked to the AND of bits 2 & 3 of the counter at 9N */
|
||||
if ((ctr9n9p & 0xc0) == 0xc0)
|
||||
{
|
||||
/* note that the pixel logic is hidden in a custom at 9S; this is just a guess */
|
||||
if (ss8j & 1)
|
||||
md = src[((ctr9n9p & 0x3f) << 3) | ctr9m];
|
||||
else
|
||||
md = src[((ctr9n9p & 0x3f) << 3) | (ctr9m ^ 7)];
|
||||
}
|
||||
|
||||
/* "select" is a made-up signal that comes from bit 3 of the serial shifter and is */
|
||||
/* used in several places for color selection */
|
||||
select = (ss8j >> 3) & 1;
|
||||
|
||||
/* check the flip-flop at 9J (upper half) to determine if we should use the background color; */
|
||||
/* the output of this is ANDed with M0 and M1 so it only affects pixels with a value of 3; */
|
||||
/* this is done by the AND gates at 9L and 7K */
|
||||
if (ff9j2 && md == 3)
|
||||
{
|
||||
/* in this case, the "select" signal is used to select which background color to use */
|
||||
/* since the color0 control word contains two selections */
|
||||
color = (color0 >> (select ? 0 : 8)) & 0x3f;
|
||||
color |= info->colorbase2;
|
||||
}
|
||||
|
||||
/* if we're not using the background color, we select pixel data from an alternate path */
|
||||
else
|
||||
{
|
||||
/* the AND gates at 7L, 9K, and 7K clamp the pixel value to 0 if bit 7 of the color 1 */
|
||||
/* signal is 1 and if the pixel value is 3 (both M0 and M1 == 1) */
|
||||
if ((color1 & 0x80) && md == 3)
|
||||
md = 0;
|
||||
|
||||
/* the pixel value plus the "select" line combine to form a mux into the low 8 bits of color1 */
|
||||
color = (color1 >> ((md << 1) | select)) & 1;
|
||||
|
||||
/* this value becomes the low bit of the final color; the "select" line itself and the pixel */
|
||||
/* value form the other bits */
|
||||
color |= select << 3;
|
||||
color |= md << 1;
|
||||
color |= info->colorbase1;
|
||||
}
|
||||
|
||||
/* write the pixel if we're past the minimum clip */
|
||||
if (x >= cliprect.min_x)
|
||||
dest[x] = color;
|
||||
|
||||
/* ---- the following logic all happens on the 6M clock ---- */
|
||||
|
||||
/* clock the counter at 9M */
|
||||
ctr9m = (ctr9m + 1) & 7;
|
||||
|
||||
/* if enabled, clock on the two cascaded 4-bit counters at 9P and 9N */
|
||||
if (ctr9n9p_ena)
|
||||
{
|
||||
if (ff9j1)
|
||||
ctr9n9p++;
|
||||
else
|
||||
ctr9n9p--;
|
||||
}
|
||||
|
||||
/* clock the flip-flop at 9J (upper half) */
|
||||
ff9j2 = !(!ff9j1 && (ss8j & 0x80));
|
||||
|
||||
/* clock the serial shift register at 8J */
|
||||
ss8j = (ss8j << 1) | ff9j1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* Out Run/X-Board-style road chip
|
||||
*
|
||||
* Road control register:
|
||||
* Bits Usage
|
||||
* -------- -----d-- (X-board only) Direct scanline mode (1) or indirect mode (0)
|
||||
* -------- ------pp Road enable/priorities:
|
||||
* 0 = road 0 only visible
|
||||
* 1 = both roads visible, road 0 has priority
|
||||
* 2 = both roads visible, road 1 has priority
|
||||
* 3 = road 1 only visible
|
||||
*
|
||||
* Road RAM:
|
||||
* Offset Bits Usage
|
||||
* 000-1FF ----s--- -------- Road 0: Solid fill (1) or ROM fill
|
||||
* -------- -ccccccc Road 0: Solid color (if solid fill)
|
||||
* -------i iiiiiiii Road 0: Index for other tables (if in indirect mode)
|
||||
* -------r rrrrrrr- Road 0: Road ROM line select
|
||||
* 200-3FF ----s--- -------- Road 1: Solid fill (1) or ROM fill
|
||||
* -------- -ccccccc Road 1: Solid color (if solid fill)
|
||||
* -------i iiiiiiii Road 1: Index for other tables (if in indirect mode)
|
||||
* -------r rrrrrrr- Road 1: Road ROM line select
|
||||
* 400-7FF ----hhhh hhhhhhhh Road 0: horizontal scroll
|
||||
* 800-BFF ----hhhh hhhhhhhh Road 1: horizontal scroll
|
||||
* C00-FFF ----bbbb -------- Background color index
|
||||
* -------- s------- Road 1: stripe color index
|
||||
* -------- -a------ Road 1: pixel value 2 color index
|
||||
* -------- --b----- Road 1: pixel value 1 color index
|
||||
* -------- ---c---- Road 1: pixel value 0 color index
|
||||
* -------- ----s--- Road 0: stripe color index
|
||||
* -------- -----a-- Road 0: pixel value 2 color index
|
||||
* -------- ------b- Road 0: pixel value 1 color index
|
||||
* -------- -------c Road 0: pixel value 0 color index
|
||||
*
|
||||
* Logic:
|
||||
* First, the scanline is used to index into the tables at 000-1FF/200-3FF
|
||||
* - if solid fill, the background is filled with the specified color index
|
||||
* - otherwise, the remaining tables are used
|
||||
*
|
||||
* If indirect mode is selected, the index is taken from the low 9 bits of the
|
||||
* table value from 000-1FF/200-3FF
|
||||
* If direct scanline mode is selected, the index is set equal to the scanline
|
||||
* for road 0, or the scanline + 256 for road 1
|
||||
*
|
||||
* The horizontal scroll value is looked up using the index in the tables at
|
||||
* 400-7FF/800-BFF
|
||||
*
|
||||
* The color information is looked up using the index in the table at C00-FFF. Note
|
||||
* that the same table is used for both roads.
|
||||
*
|
||||
*
|
||||
* Out Run road priorities are controlled by a PAL that maps as indicated below.
|
||||
* This was used to generate the priority_map. It is assumed that X-board is the
|
||||
* same, though this logic is locked inside a Sega custom.
|
||||
*
|
||||
* RRC0 = CENTA & (RDA == 3) & !RRC2
|
||||
* | CENTB & (RDB == 3) & RRC2
|
||||
* | (RDA == 1) & !RRC2
|
||||
* | (RDB == 1) & RRC2
|
||||
*
|
||||
* RRC1 = CENTA & (RDA == 3) & !RRC2
|
||||
* | CENTB & (RDB == 3) & RRC2
|
||||
* | (RDA == 2) & !RRC2
|
||||
* | (RDB == 2) & RRC2
|
||||
*
|
||||
* RRC2 = !/HSYNC & IIQ
|
||||
* | (CTRL == 3)
|
||||
* | !CENTA & (RDA == 3) & !CENTB & (RDB == 3) & (CTRL == 2)
|
||||
* | CENTB & (RDB == 3) & (CTRL == 2)
|
||||
* | !CENTA & (RDA == 3) & !M2 & (CTRL == 2)
|
||||
* | !CENTA & (RDA == 3) & !M3 & (CTRL == 2)
|
||||
* | !M0 & (RDB == 0) & (CTRL == 2)
|
||||
* | !M1 & (RDB == 0) & (CTRL == 2)
|
||||
* | !CENTA & (RDA == 3) & CENTB & (RDB == 3) & (CTRL == 1)
|
||||
* | !M0 & CENTB & (RDB == 3) & (CTRL == 1)
|
||||
* | !M1 & CENTB & (RDB == 3) & (CTRL == 1)
|
||||
* | !CENTA & M0 & (RDB == 0) & (CTRL == 1)
|
||||
* | !CENTA & M1 & (RDB == 0) & (CTRL == 1)
|
||||
* | !CENTA & (RDA == 3) & (RDB == 1) & (CTRL == 1)
|
||||
* | !CENTA & (RDA == 3) & (RDB == 2) & (CTRL == 1)
|
||||
*
|
||||
* RRC3 = VA11 & VB11
|
||||
* | VA11 & (CTRL == 0)
|
||||
* | (CTRL == 3) & VB11
|
||||
*
|
||||
* RRC4 = !CENTA & (RDA == 3) & !CENTB & (RDB == 3)
|
||||
* | VA11 & VB11
|
||||
* | VA11 & (CTRL == 0)
|
||||
* | (CTRL == 3) & VB11
|
||||
* | !CENTB & (RDB == 3) & (CTRL == 3)
|
||||
* | !CENTA & (RDA == 3) & (CTRL == 0)
|
||||
*
|
||||
*******************************************************************************************/
|
||||
|
||||
static void segaic16_road_outrun_decode(running_machine &machine, struct road_info *info)
|
||||
{
|
||||
int x, y;
|
||||
const UINT8 *gfx = machine.root_device().memregion("gfx3")->base();
|
||||
int len = machine.root_device().memregion("gfx3")->bytes();
|
||||
|
||||
/* allocate memory for the unpacked road data */
|
||||
info->gfx = auto_alloc_array(machine, UINT8, (256 * 2 + 1) * 512);
|
||||
|
||||
/* loop over rows */
|
||||
for (y = 0; y < 256 * 2; y++)
|
||||
{
|
||||
const UINT8 *src = gfx + ((y & 0xff) * 0x40 + (y >> 8) * 0x8000) % len;
|
||||
UINT8 *dst = info->gfx + y * 512;
|
||||
|
||||
/* loop over columns */
|
||||
for (x = 0; x < 512; x++)
|
||||
{
|
||||
dst[x] = (((src[x/8] >> (~x & 7)) & 1) << 0) | (((src[x/8 + 0x4000] >> (~x & 7)) & 1) << 1);
|
||||
|
||||
/* pre-mark road data in the "stripe" area with a high bit */
|
||||
if (x >= 256-8 && x < 256 && dst[x] == 3)
|
||||
dst[x] |= 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* set up a dummy road in the last entry */
|
||||
memset(info->gfx + 256 * 2 * 512, 3, 512);
|
||||
}
|
||||
|
||||
|
||||
static void segaic16_road_outrun_draw(struct road_info *info, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority)
|
||||
{
|
||||
UINT16 *roadram = info->buffer;
|
||||
int x, y;
|
||||
|
||||
/* loop over scanlines */
|
||||
for (y = cliprect.min_y; y <= cliprect.max_y; y++)
|
||||
{
|
||||
static const UINT8 priority_map[2][8] =
|
||||
{
|
||||
{ 0x80,0x81,0x81,0x87,0,0,0,0x00 },
|
||||
{ 0x81,0x81,0x81,0x8f,0,0,0,0x80 }
|
||||
//
|
||||
// Original guesses from X-board priorities:
|
||||
// { 0x80,0x81,0x81,0x83,0,0,0,0x00 },
|
||||
// { 0x81,0x87,0x87,0x8f,0,0,0,0x00 }
|
||||
};
|
||||
UINT16 *dest = &bitmap.pix16(y);
|
||||
int data0 = roadram[0x000 + y];
|
||||
int data1 = roadram[0x100 + y];
|
||||
|
||||
/* background case: look for solid fill scanlines */
|
||||
if (priority == SEGAIC16_ROAD_BACKGROUND)
|
||||
{
|
||||
int color = -1;
|
||||
|
||||
/* based on the info->control, we can figure out which sky to draw */
|
||||
switch (info->control & 3)
|
||||
{
|
||||
case 0:
|
||||
if (data0 & 0x800)
|
||||
color = data0 & 0x7f;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (data0 & 0x800)
|
||||
color = data0 & 0x7f;
|
||||
else if (data1 & 0x800)
|
||||
color = data1 & 0x7f;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (data1 & 0x800)
|
||||
color = data1 & 0x7f;
|
||||
else if (data0 & 0x800)
|
||||
color = data0 & 0x7f;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (data1 & 0x800)
|
||||
color = data1 & 0x7f;
|
||||
break;
|
||||
}
|
||||
|
||||
/* fill the scanline with color */
|
||||
if (color != -1)
|
||||
{
|
||||
color |= info->colorbase3;
|
||||
for (x = cliprect.min_x; x <= cliprect.max_x; x++)
|
||||
dest[x] = color;
|
||||
}
|
||||
}
|
||||
|
||||
/* foreground case: render from ROM */
|
||||
else
|
||||
{
|
||||
int hpos0, hpos1, color0, color1;
|
||||
int control = info->control & 3;
|
||||
UINT16 color_table[32];
|
||||
UINT8 *src0, *src1;
|
||||
UINT8 bgcolor;
|
||||
|
||||
/* if both roads are low priority, skip */
|
||||
if ((data0 & 0x800) && (data1 & 0x800))
|
||||
continue;
|
||||
|
||||
/* get road 0 data */
|
||||
src0 = (data0 & 0x800) ? info->gfx + 256 * 2 * 512 : (info->gfx + (0x000 + ((data0 >> 1) & 0xff)) * 512);
|
||||
hpos0 = (roadram[0x200 + ((info->control & 4) ? y : (data0 & 0x1ff))]) & 0xfff;
|
||||
color0 = roadram[0x600 + ((info->control & 4) ? y : (data0 & 0x1ff))];
|
||||
|
||||
/* get road 1 data */
|
||||
src1 = (data1 & 0x800) ? info->gfx + 256 * 2 * 512 : (info->gfx + (0x100 + ((data1 >> 1) & 0xff)) * 512);
|
||||
hpos1 = (roadram[0x400 + ((info->control & 4) ? (0x100 + y) : (data1 & 0x1ff))]) & 0xfff;
|
||||
color1 = roadram[0x600 + ((info->control & 4) ? (0x100 + y) : (data1 & 0x1ff))];
|
||||
|
||||
/* determine the 5 colors for road 0 */
|
||||
color_table[0x00] = info->colorbase1 ^ 0x00 ^ ((color0 >> 0) & 1);
|
||||
color_table[0x01] = info->colorbase1 ^ 0x02 ^ ((color0 >> 1) & 1);
|
||||
color_table[0x02] = info->colorbase1 ^ 0x04 ^ ((color0 >> 2) & 1);
|
||||
bgcolor = (color0 >> 8) & 0xf;
|
||||
color_table[0x03] = (data0 & 0x200) ? color_table[0x00] : (info->colorbase2 ^ 0x00 ^ bgcolor);
|
||||
color_table[0x07] = info->colorbase1 ^ 0x06 ^ ((color0 >> 3) & 1);
|
||||
|
||||
/* determine the 5 colors for road 1 */
|
||||
color_table[0x10] = info->colorbase1 ^ 0x08 ^ ((color1 >> 4) & 1);
|
||||
color_table[0x11] = info->colorbase1 ^ 0x0a ^ ((color1 >> 5) & 1);
|
||||
color_table[0x12] = info->colorbase1 ^ 0x0c ^ ((color1 >> 6) & 1);
|
||||
bgcolor = (color1 >> 8) & 0xf;
|
||||
color_table[0x13] = (data1 & 0x200) ? color_table[0x10] : (info->colorbase2 ^ 0x10 ^ bgcolor);
|
||||
color_table[0x17] = info->colorbase1 ^ 0x0e ^ ((color1 >> 7) & 1);
|
||||
|
||||
/* draw the road */
|
||||
switch (control)
|
||||
{
|
||||
case 0:
|
||||
if (data0 & 0x800)
|
||||
continue;
|
||||
hpos0 = (hpos0 - (0x5f8 + info->xoffs)) & 0xfff;
|
||||
for (x = cliprect.min_x; x <= cliprect.max_x; x++)
|
||||
{
|
||||
int pix0 = (hpos0 < 0x200) ? src0[hpos0] : 3;
|
||||
dest[x] = color_table[0x00 + pix0];
|
||||
hpos0 = (hpos0 + 1) & 0xfff;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
hpos0 = (hpos0 - (0x5f8 + info->xoffs)) & 0xfff;
|
||||
hpos1 = (hpos1 - (0x5f8 + info->xoffs)) & 0xfff;
|
||||
for (x = cliprect.min_x; x <= cliprect.max_x; x++)
|
||||
{
|
||||
int pix0 = (hpos0 < 0x200) ? src0[hpos0] : 3;
|
||||
int pix1 = (hpos1 < 0x200) ? src1[hpos1] : 3;
|
||||
if ((priority_map[0][pix0] >> pix1) & 1)
|
||||
dest[x] = color_table[0x10 + pix1];
|
||||
else
|
||||
dest[x] = color_table[0x00 + pix0];
|
||||
hpos0 = (hpos0 + 1) & 0xfff;
|
||||
hpos1 = (hpos1 + 1) & 0xfff;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
hpos0 = (hpos0 - (0x5f8 + info->xoffs)) & 0xfff;
|
||||
hpos1 = (hpos1 - (0x5f8 + info->xoffs)) & 0xfff;
|
||||
for (x = cliprect.min_x; x <= cliprect.max_x; x++)
|
||||
{
|
||||
int pix0 = (hpos0 < 0x200) ? src0[hpos0] : 3;
|
||||
int pix1 = (hpos1 < 0x200) ? src1[hpos1] : 3;
|
||||
if ((priority_map[1][pix0] >> pix1) & 1)
|
||||
dest[x] = color_table[0x10 + pix1];
|
||||
else
|
||||
dest[x] = color_table[0x00 + pix0];
|
||||
hpos0 = (hpos0 + 1) & 0xfff;
|
||||
hpos1 = (hpos1 + 1) & 0xfff;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (data1 & 0x800)
|
||||
continue;
|
||||
hpos1 = (hpos1 - (0x5f8 + info->xoffs)) & 0xfff;
|
||||
for (x = cliprect.min_x; x <= cliprect.max_x; x++)
|
||||
{
|
||||
int pix1 = (hpos1 < 0x200) ? src1[hpos1] : 3;
|
||||
dest[x] = color_table[0x10 + pix1];
|
||||
hpos1 = (hpos1 + 1) & 0xfff;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* General road initialization
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void segaic16_video_device::segaic16_road_init(running_machine &machine, int which, int type, int colorbase1, int colorbase2, int colorbase3, int xoffs)
|
||||
{
|
||||
struct road_info *info = &segaic16_road[which];
|
||||
|
||||
/* reset the tilemap info */
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->index = which;
|
||||
info->type = type;
|
||||
info->colorbase1 = colorbase1;
|
||||
info->colorbase2 = colorbase2;
|
||||
info->colorbase3 = colorbase3;
|
||||
info->xoffs = xoffs;
|
||||
|
||||
/* set up based on which road generator */
|
||||
switch (which)
|
||||
{
|
||||
case 0:
|
||||
info->roadram = segaic16_roadram_0;
|
||||
break;
|
||||
|
||||
default:
|
||||
fatalerror("Invalid road index specified in segaic16_road_init\n");
|
||||
}
|
||||
|
||||
/* determine the parameters of the road */
|
||||
switch (type)
|
||||
{
|
||||
case SEGAIC16_ROAD_HANGON:
|
||||
case SEGAIC16_ROAD_SHARRIER:
|
||||
info->draw = segaic16_road_hangon_draw;
|
||||
segaic16_road_hangon_decode(machine, info);
|
||||
break;
|
||||
|
||||
case SEGAIC16_ROAD_OUTRUN:
|
||||
case SEGAIC16_ROAD_XBOARD:
|
||||
info->buffer = auto_alloc_array(machine, UINT16, 0x1000/2);
|
||||
info->draw = segaic16_road_outrun_draw;
|
||||
segaic16_road_outrun_decode(machine, info);
|
||||
break;
|
||||
|
||||
default:
|
||||
fatalerror("Invalid road system specified in segaic16_road_init\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* General road drawing
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void segaic16_video_device::segaic16_road_draw(int which, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority)
|
||||
{
|
||||
struct road_info *info = &segaic16_road[which];
|
||||
(*info->draw)(info, bitmap, cliprect, priority);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* General road control read/write
|
||||
*
|
||||
*************************************/
|
||||
|
||||
READ16_MEMBER( segaic16_video_device::segaic16_road_control_0_r )
|
||||
{
|
||||
struct road_info *info = &segaic16_road[0];
|
||||
|
||||
if (info->buffer)
|
||||
{
|
||||
UINT32 *src = (UINT32 *)info->roadram;
|
||||
UINT32 *dst = (UINT32 *)info->buffer;
|
||||
int i;
|
||||
|
||||
/* swap the halves of the road RAM */
|
||||
for (i = 0; i < 0x1000/4; i++)
|
||||
{
|
||||
UINT32 temp = *src;
|
||||
*src++ = *dst;
|
||||
*dst++ = temp;
|
||||
}
|
||||
}
|
||||
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
|
||||
WRITE16_MEMBER( segaic16_video_device::segaic16_road_control_0_w )
|
||||
{
|
||||
struct road_info *info = &segaic16_road[0];
|
||||
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
info->control = data & ((info->type == SEGAIC16_ROAD_OUTRUN) ? 3 : 7);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
|
@ -24,17 +24,6 @@
|
||||
#define SEGAIC16_TILEMAP_BACKGROUND 1
|
||||
#define SEGAIC16_TILEMAP_TEXT 2
|
||||
|
||||
/* road systems */
|
||||
#define SEGAIC16_MAX_ROADS 1
|
||||
|
||||
#define SEGAIC16_ROAD_HANGON 0
|
||||
#define SEGAIC16_ROAD_SHARRIER 1
|
||||
#define SEGAIC16_ROAD_OUTRUN 2
|
||||
#define SEGAIC16_ROAD_XBOARD 3
|
||||
|
||||
#define SEGAIC16_ROAD_BACKGROUND 0
|
||||
#define SEGAIC16_ROAD_FOREGROUND 1
|
||||
|
||||
|
||||
|
||||
/* rotation systems */
|
||||
@ -84,20 +73,6 @@ struct tilemap_info
|
||||
emu_timer * latch_timer; /* timer for latching 16b tilemap scroll values */
|
||||
};
|
||||
|
||||
struct road_info
|
||||
{
|
||||
UINT8 index; /* index of this structure */
|
||||
UINT8 type; /* type of road system (see segaic16.h for details) */
|
||||
UINT8 control; /* control register value */
|
||||
UINT16 colorbase1; /* color base for road ROM data */
|
||||
UINT16 colorbase2; /* color base for road background data */
|
||||
UINT16 colorbase3; /* color base for sky data */
|
||||
INT32 xoffs; /* X scroll offset */
|
||||
void (*draw)(struct road_info *info, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority);
|
||||
UINT16 * roadram; /* pointer to roadram pointer */
|
||||
UINT16 * buffer; /* buffered roadram pointer */
|
||||
UINT8 * gfx; /* expanded road graphics */
|
||||
};
|
||||
|
||||
struct rotate_info
|
||||
{
|
||||
@ -125,7 +100,6 @@ public:
|
||||
UINT8 segaic16_display_enable;
|
||||
UINT16 *segaic16_tileram_0;
|
||||
UINT16 *segaic16_textram_0;
|
||||
UINT16 *segaic16_roadram_0;
|
||||
UINT16 *segaic16_rotateram_0;
|
||||
|
||||
void segaic16_tilemap_set_colscroll(running_machine &machine, int which, int enable);
|
||||
@ -142,12 +116,10 @@ public:
|
||||
TIMER_CALLBACK_MEMBER( segaic16_tilemap_16b_latch_values );
|
||||
|
||||
struct rotate_info segaic16_rotate[SEGAIC16_MAX_ROTATE];
|
||||
struct road_info segaic16_road[SEGAIC16_MAX_ROADS];
|
||||
struct tilemap_info bg_tilemap[SEGAIC16_MAX_TILEMAPS];
|
||||
|
||||
void segaic16_set_display_enable(running_machine &machine, int enable);
|
||||
void segaic16_tilemap_init(running_machine &machine, int which, int type, int colorbase, int xoffs, int numbanks);
|
||||
void segaic16_road_init(running_machine &machine, int which, int type, int colorbase1, int colorbase2, int colorbase3, int xoffs);
|
||||
void segaic16_rotate_init(running_machine &machine, int which, int type, int colorbase);
|
||||
|
||||
DECLARE_READ16_MEMBER( segaic16_tileram_0_r );
|
||||
@ -155,13 +127,8 @@ public:
|
||||
DECLARE_WRITE16_MEMBER( segaic16_tileram_0_w );
|
||||
DECLARE_WRITE16_MEMBER( segaic16_textram_0_w );
|
||||
|
||||
void segaic16_road_draw(int which, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority);
|
||||
void segaic16_rotate_draw(running_machine &machine, int which, bitmap_ind16 &bitmap, const rectangle &cliprect, bitmap_ind16 &srcbitmap);
|
||||
|
||||
DECLARE_READ16_MEMBER( segaic16_road_control_0_r );
|
||||
DECLARE_WRITE16_MEMBER( segaic16_road_control_0_w );
|
||||
|
||||
|
||||
DECLARE_READ16_MEMBER( segaic16_rotate_control_0_r );
|
||||
|
||||
TILE_GET_INFO_MEMBER( segaic16_tilemap_16b_tile_info );
|
||||
|
642
src/mame/video/segaic16_road.c
Normal file
642
src/mame/video/segaic16_road.c
Normal file
@ -0,0 +1,642 @@
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "segaic16_road.h"
|
||||
#include "video/resnet.h"
|
||||
|
||||
const device_type SEGAIC16_ROAD = &device_creator<segaic16_road_device>;
|
||||
|
||||
segaic16_road_device::segaic16_road_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, SEGAIC16_ROAD, "Sega 16-bit Road Generator", tag, owner, clock, "segaic16_road", __FILE__)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void segaic16_road_device::device_config_complete()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void segaic16_road_device::device_start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void segaic16_road_device::device_reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* Hang On/Space Harrier-style road chip
|
||||
*
|
||||
* Road RAM:
|
||||
* Offset Bits Usage
|
||||
* 000-1FF ----pp-- -------- road priority versus tilemaps and sprites
|
||||
* ------s- -------- (Hang On only) Stripe coloring enable (1=enable)
|
||||
* ------s- -------- (Space Harrier only) Solid color fill (1=solid, 0=from ROM)
|
||||
* -------m -------- mirror enable (1=enable)
|
||||
* -------- iiiiiiii index for other tables
|
||||
* -------- rrrrrrrr road ROM line select
|
||||
* 200-3FF ----hhhh hhhhhhhh horizontal scroll
|
||||
* 400-5FF --bbbbbb -------- background color (colorset 0)
|
||||
* -------- --bbbbbb background color (colorset 1)
|
||||
* 600-7FF -------- s------- stripe color index (colorset 1)
|
||||
* -------- -s------ stripe color index (colorset 0)
|
||||
* -------- --a----- pixel value 2 color index (colorset 1)
|
||||
* -------- ---a---- pixel value 2 color index (colorset 0)
|
||||
* -------- ----b--- pixel value 1 color index (colorset 1)
|
||||
* -------- -----b-- pixel value 1 color index (colorset 0)
|
||||
* -------- ------c- pixel value 0 color index (colorset 1)
|
||||
* -------- -------c pixel value 0 color index (colorset 0)
|
||||
*
|
||||
* Logic:
|
||||
* First, the scanline is used to index into the table at 000-1FF
|
||||
*
|
||||
* The index is taken from the low 8 bits of the table value from 000-1FF
|
||||
*
|
||||
* The horizontal scroll value is looked up using the index in the table at
|
||||
* 200-3FF
|
||||
*
|
||||
* The background color information is looked up using the index in the table at 400-5FF.
|
||||
*
|
||||
* The pixel color information is looked up using the index in the table at 600-7FF.
|
||||
*
|
||||
*******************************************************************************************/
|
||||
|
||||
|
||||
|
||||
static void segaic16_road_hangon_decode(running_machine &machine, struct road_info *info)
|
||||
{
|
||||
int x, y;
|
||||
const UINT8 *gfx = machine.root_device().memregion("gfx3")->base();
|
||||
int len = machine.root_device().memregion("gfx3")->bytes();
|
||||
|
||||
/* allocate memory for the unpacked road data */
|
||||
info->gfx = auto_alloc_array(machine, UINT8, 256 * 512);
|
||||
|
||||
/* loop over rows */
|
||||
for (y = 0; y < 256; y++)
|
||||
{
|
||||
const UINT8 *src = gfx + ((y & 0xff) * 0x40) % len;
|
||||
UINT8 *dst = info->gfx + y * 512;
|
||||
|
||||
/* loop over columns */
|
||||
for (x = 0; x < 512; x++)
|
||||
dst[x] = (((src[x/8] >> (~x & 7)) & 1) << 0) | (((src[x/8 + 0x4000] >> (~x & 7)) & 1) << 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void segaic16_road_hangon_draw(struct road_info *info, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority)
|
||||
{
|
||||
UINT16 *roadram = info->roadram;
|
||||
int x, y;
|
||||
|
||||
/* loop over scanlines */
|
||||
for (y = cliprect.min_y; y <= cliprect.max_y; y++)
|
||||
{
|
||||
UINT16 *dest = &bitmap.pix16(y);
|
||||
int control = roadram[0x000 + y];
|
||||
int hpos = roadram[0x100 + (control & 0xff)];
|
||||
int color0 = roadram[0x200 + (control & 0xff)];
|
||||
int color1 = roadram[0x300 + (control & 0xff)];
|
||||
int ff9j1, ff9j2, ctr9m, ctr9n9p, ctr9n9p_ena, ss8j, plycont;
|
||||
UINT8 *src;
|
||||
|
||||
/* the PLYCONT signal controls the road layering */
|
||||
plycont = (control >> 10) & 3;
|
||||
|
||||
/* skip layers we aren't supposed to be drawing */
|
||||
if ((plycont == 0 && priority != SEGAIC16_ROAD_BACKGROUND) ||
|
||||
(plycont != 0 && priority != SEGAIC16_ROAD_FOREGROUND))
|
||||
continue;
|
||||
|
||||
/* compute the offset of the road graphics for this line */
|
||||
src = info->gfx + (0x000 + (control & 0xff)) * 512;
|
||||
|
||||
/* initialize the 4-bit counter at 9M, which counts bits within each road byte */
|
||||
ctr9m = hpos & 7;
|
||||
|
||||
/* initialize the two 4-bit counters at 9P (low) and 9N (high), which count road data bytes */
|
||||
ctr9n9p = (hpos >> 3) & 0xff;
|
||||
|
||||
/* initialize the flip-flop at 9J (lower half), which controls the counting direction */
|
||||
ff9j1 = (hpos >> 11) & 1;
|
||||
|
||||
/* initialize the flip-flop at 9J (upper half), which controls the background color */
|
||||
ff9j2 = 1;
|
||||
|
||||
/* initialize the serial shifter at 8S, which delays several signals after we flip */
|
||||
ss8j = 0;
|
||||
|
||||
/* draw this scanline from the beginning */
|
||||
for (x = -24; x <= cliprect.max_x; x++)
|
||||
{
|
||||
int md, color, select;
|
||||
|
||||
/* ---- the following logic all happens constantly ---- */
|
||||
|
||||
/* the enable is controlled by the value in the counter at 9M */
|
||||
ctr9n9p_ena = (ctr9m == 7);
|
||||
|
||||
/* if we carried out of the 9P/9N counters, we will forcibly clear the flip-flop at 9J (lower half) */
|
||||
if ((ctr9n9p & 0xff) == 0xff)
|
||||
ff9j1 = 0;
|
||||
|
||||
/* if the control word bit 8 is clear, we will forcibly set the flip-flop at 9J (lower half) */
|
||||
if (!(control & 0x100))
|
||||
ff9j1 = 1;
|
||||
|
||||
/* for the Hang On/Super Hang On case only: if the control word bit 9 is clear, we will forcibly */
|
||||
/* set the flip-flip at 9J (upper half) */
|
||||
if (info->type == SEGAIC16_ROAD_HANGON && !(control & 0x200))
|
||||
ff9j2 = 1;
|
||||
|
||||
/* ---- now process the pixel ---- */
|
||||
md = 3;
|
||||
|
||||
/* the Space Harrier/Enduro Racer hardware has a tweak that maps the control word bit 9 to the */
|
||||
/* /CE line on the road ROM; use this to effectively disable the road data */
|
||||
if (info->type != SEGAIC16_ROAD_SHARRIER || !(control & 0x200))
|
||||
|
||||
/* the /OE line on the road ROM is linked to the AND of bits 2 & 3 of the counter at 9N */
|
||||
if ((ctr9n9p & 0xc0) == 0xc0)
|
||||
{
|
||||
/* note that the pixel logic is hidden in a custom at 9S; this is just a guess */
|
||||
if (ss8j & 1)
|
||||
md = src[((ctr9n9p & 0x3f) << 3) | ctr9m];
|
||||
else
|
||||
md = src[((ctr9n9p & 0x3f) << 3) | (ctr9m ^ 7)];
|
||||
}
|
||||
|
||||
/* "select" is a made-up signal that comes from bit 3 of the serial shifter and is */
|
||||
/* used in several places for color selection */
|
||||
select = (ss8j >> 3) & 1;
|
||||
|
||||
/* check the flip-flop at 9J (upper half) to determine if we should use the background color; */
|
||||
/* the output of this is ANDed with M0 and M1 so it only affects pixels with a value of 3; */
|
||||
/* this is done by the AND gates at 9L and 7K */
|
||||
if (ff9j2 && md == 3)
|
||||
{
|
||||
/* in this case, the "select" signal is used to select which background color to use */
|
||||
/* since the color0 control word contains two selections */
|
||||
color = (color0 >> (select ? 0 : 8)) & 0x3f;
|
||||
color |= info->colorbase2;
|
||||
}
|
||||
|
||||
/* if we're not using the background color, we select pixel data from an alternate path */
|
||||
else
|
||||
{
|
||||
/* the AND gates at 7L, 9K, and 7K clamp the pixel value to 0 if bit 7 of the color 1 */
|
||||
/* signal is 1 and if the pixel value is 3 (both M0 and M1 == 1) */
|
||||
if ((color1 & 0x80) && md == 3)
|
||||
md = 0;
|
||||
|
||||
/* the pixel value plus the "select" line combine to form a mux into the low 8 bits of color1 */
|
||||
color = (color1 >> ((md << 1) | select)) & 1;
|
||||
|
||||
/* this value becomes the low bit of the final color; the "select" line itself and the pixel */
|
||||
/* value form the other bits */
|
||||
color |= select << 3;
|
||||
color |= md << 1;
|
||||
color |= info->colorbase1;
|
||||
}
|
||||
|
||||
/* write the pixel if we're past the minimum clip */
|
||||
if (x >= cliprect.min_x)
|
||||
dest[x] = color;
|
||||
|
||||
/* ---- the following logic all happens on the 6M clock ---- */
|
||||
|
||||
/* clock the counter at 9M */
|
||||
ctr9m = (ctr9m + 1) & 7;
|
||||
|
||||
/* if enabled, clock on the two cascaded 4-bit counters at 9P and 9N */
|
||||
if (ctr9n9p_ena)
|
||||
{
|
||||
if (ff9j1)
|
||||
ctr9n9p++;
|
||||
else
|
||||
ctr9n9p--;
|
||||
}
|
||||
|
||||
/* clock the flip-flop at 9J (upper half) */
|
||||
ff9j2 = !(!ff9j1 && (ss8j & 0x80));
|
||||
|
||||
/* clock the serial shift register at 8J */
|
||||
ss8j = (ss8j << 1) | ff9j1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* Out Run/X-Board-style road chip
|
||||
*
|
||||
* Road control register:
|
||||
* Bits Usage
|
||||
* -------- -----d-- (X-board only) Direct scanline mode (1) or indirect mode (0)
|
||||
* -------- ------pp Road enable/priorities:
|
||||
* 0 = road 0 only visible
|
||||
* 1 = both roads visible, road 0 has priority
|
||||
* 2 = both roads visible, road 1 has priority
|
||||
* 3 = road 1 only visible
|
||||
*
|
||||
* Road RAM:
|
||||
* Offset Bits Usage
|
||||
* 000-1FF ----s--- -------- Road 0: Solid fill (1) or ROM fill
|
||||
* -------- -ccccccc Road 0: Solid color (if solid fill)
|
||||
* -------i iiiiiiii Road 0: Index for other tables (if in indirect mode)
|
||||
* -------r rrrrrrr- Road 0: Road ROM line select
|
||||
* 200-3FF ----s--- -------- Road 1: Solid fill (1) or ROM fill
|
||||
* -------- -ccccccc Road 1: Solid color (if solid fill)
|
||||
* -------i iiiiiiii Road 1: Index for other tables (if in indirect mode)
|
||||
* -------r rrrrrrr- Road 1: Road ROM line select
|
||||
* 400-7FF ----hhhh hhhhhhhh Road 0: horizontal scroll
|
||||
* 800-BFF ----hhhh hhhhhhhh Road 1: horizontal scroll
|
||||
* C00-FFF ----bbbb -------- Background color index
|
||||
* -------- s------- Road 1: stripe color index
|
||||
* -------- -a------ Road 1: pixel value 2 color index
|
||||
* -------- --b----- Road 1: pixel value 1 color index
|
||||
* -------- ---c---- Road 1: pixel value 0 color index
|
||||
* -------- ----s--- Road 0: stripe color index
|
||||
* -------- -----a-- Road 0: pixel value 2 color index
|
||||
* -------- ------b- Road 0: pixel value 1 color index
|
||||
* -------- -------c Road 0: pixel value 0 color index
|
||||
*
|
||||
* Logic:
|
||||
* First, the scanline is used to index into the tables at 000-1FF/200-3FF
|
||||
* - if solid fill, the background is filled with the specified color index
|
||||
* - otherwise, the remaining tables are used
|
||||
*
|
||||
* If indirect mode is selected, the index is taken from the low 9 bits of the
|
||||
* table value from 000-1FF/200-3FF
|
||||
* If direct scanline mode is selected, the index is set equal to the scanline
|
||||
* for road 0, or the scanline + 256 for road 1
|
||||
*
|
||||
* The horizontal scroll value is looked up using the index in the tables at
|
||||
* 400-7FF/800-BFF
|
||||
*
|
||||
* The color information is looked up using the index in the table at C00-FFF. Note
|
||||
* that the same table is used for both roads.
|
||||
*
|
||||
*
|
||||
* Out Run road priorities are controlled by a PAL that maps as indicated below.
|
||||
* This was used to generate the priority_map. It is assumed that X-board is the
|
||||
* same, though this logic is locked inside a Sega custom.
|
||||
*
|
||||
* RRC0 = CENTA & (RDA == 3) & !RRC2
|
||||
* | CENTB & (RDB == 3) & RRC2
|
||||
* | (RDA == 1) & !RRC2
|
||||
* | (RDB == 1) & RRC2
|
||||
*
|
||||
* RRC1 = CENTA & (RDA == 3) & !RRC2
|
||||
* | CENTB & (RDB == 3) & RRC2
|
||||
* | (RDA == 2) & !RRC2
|
||||
* | (RDB == 2) & RRC2
|
||||
*
|
||||
* RRC2 = !/HSYNC & IIQ
|
||||
* | (CTRL == 3)
|
||||
* | !CENTA & (RDA == 3) & !CENTB & (RDB == 3) & (CTRL == 2)
|
||||
* | CENTB & (RDB == 3) & (CTRL == 2)
|
||||
* | !CENTA & (RDA == 3) & !M2 & (CTRL == 2)
|
||||
* | !CENTA & (RDA == 3) & !M3 & (CTRL == 2)
|
||||
* | !M0 & (RDB == 0) & (CTRL == 2)
|
||||
* | !M1 & (RDB == 0) & (CTRL == 2)
|
||||
* | !CENTA & (RDA == 3) & CENTB & (RDB == 3) & (CTRL == 1)
|
||||
* | !M0 & CENTB & (RDB == 3) & (CTRL == 1)
|
||||
* | !M1 & CENTB & (RDB == 3) & (CTRL == 1)
|
||||
* | !CENTA & M0 & (RDB == 0) & (CTRL == 1)
|
||||
* | !CENTA & M1 & (RDB == 0) & (CTRL == 1)
|
||||
* | !CENTA & (RDA == 3) & (RDB == 1) & (CTRL == 1)
|
||||
* | !CENTA & (RDA == 3) & (RDB == 2) & (CTRL == 1)
|
||||
*
|
||||
* RRC3 = VA11 & VB11
|
||||
* | VA11 & (CTRL == 0)
|
||||
* | (CTRL == 3) & VB11
|
||||
*
|
||||
* RRC4 = !CENTA & (RDA == 3) & !CENTB & (RDB == 3)
|
||||
* | VA11 & VB11
|
||||
* | VA11 & (CTRL == 0)
|
||||
* | (CTRL == 3) & VB11
|
||||
* | !CENTB & (RDB == 3) & (CTRL == 3)
|
||||
* | !CENTA & (RDA == 3) & (CTRL == 0)
|
||||
*
|
||||
*******************************************************************************************/
|
||||
|
||||
static void segaic16_road_outrun_decode(running_machine &machine, struct road_info *info)
|
||||
{
|
||||
int x, y;
|
||||
const UINT8 *gfx = machine.root_device().memregion("gfx3")->base();
|
||||
int len = machine.root_device().memregion("gfx3")->bytes();
|
||||
|
||||
/* allocate memory for the unpacked road data */
|
||||
info->gfx = auto_alloc_array(machine, UINT8, (256 * 2 + 1) * 512);
|
||||
|
||||
/* loop over rows */
|
||||
for (y = 0; y < 256 * 2; y++)
|
||||
{
|
||||
const UINT8 *src = gfx + ((y & 0xff) * 0x40 + (y >> 8) * 0x8000) % len;
|
||||
UINT8 *dst = info->gfx + y * 512;
|
||||
|
||||
/* loop over columns */
|
||||
for (x = 0; x < 512; x++)
|
||||
{
|
||||
dst[x] = (((src[x/8] >> (~x & 7)) & 1) << 0) | (((src[x/8 + 0x4000] >> (~x & 7)) & 1) << 1);
|
||||
|
||||
/* pre-mark road data in the "stripe" area with a high bit */
|
||||
if (x >= 256-8 && x < 256 && dst[x] == 3)
|
||||
dst[x] |= 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* set up a dummy road in the last entry */
|
||||
memset(info->gfx + 256 * 2 * 512, 3, 512);
|
||||
}
|
||||
|
||||
|
||||
static void segaic16_road_outrun_draw(struct road_info *info, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority)
|
||||
{
|
||||
UINT16 *roadram = info->buffer;
|
||||
int x, y;
|
||||
|
||||
/* loop over scanlines */
|
||||
for (y = cliprect.min_y; y <= cliprect.max_y; y++)
|
||||
{
|
||||
static const UINT8 priority_map[2][8] =
|
||||
{
|
||||
{ 0x80,0x81,0x81,0x87,0,0,0,0x00 },
|
||||
{ 0x81,0x81,0x81,0x8f,0,0,0,0x80 }
|
||||
//
|
||||
// Original guesses from X-board priorities:
|
||||
// { 0x80,0x81,0x81,0x83,0,0,0,0x00 },
|
||||
// { 0x81,0x87,0x87,0x8f,0,0,0,0x00 }
|
||||
};
|
||||
UINT16 *dest = &bitmap.pix16(y);
|
||||
int data0 = roadram[0x000 + y];
|
||||
int data1 = roadram[0x100 + y];
|
||||
|
||||
/* background case: look for solid fill scanlines */
|
||||
if (priority == SEGAIC16_ROAD_BACKGROUND)
|
||||
{
|
||||
int color = -1;
|
||||
|
||||
/* based on the info->control, we can figure out which sky to draw */
|
||||
switch (info->control & 3)
|
||||
{
|
||||
case 0:
|
||||
if (data0 & 0x800)
|
||||
color = data0 & 0x7f;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (data0 & 0x800)
|
||||
color = data0 & 0x7f;
|
||||
else if (data1 & 0x800)
|
||||
color = data1 & 0x7f;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (data1 & 0x800)
|
||||
color = data1 & 0x7f;
|
||||
else if (data0 & 0x800)
|
||||
color = data0 & 0x7f;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (data1 & 0x800)
|
||||
color = data1 & 0x7f;
|
||||
break;
|
||||
}
|
||||
|
||||
/* fill the scanline with color */
|
||||
if (color != -1)
|
||||
{
|
||||
color |= info->colorbase3;
|
||||
for (x = cliprect.min_x; x <= cliprect.max_x; x++)
|
||||
dest[x] = color;
|
||||
}
|
||||
}
|
||||
|
||||
/* foreground case: render from ROM */
|
||||
else
|
||||
{
|
||||
int hpos0, hpos1, color0, color1;
|
||||
int control = info->control & 3;
|
||||
UINT16 color_table[32];
|
||||
UINT8 *src0, *src1;
|
||||
UINT8 bgcolor;
|
||||
|
||||
/* if both roads are low priority, skip */
|
||||
if ((data0 & 0x800) && (data1 & 0x800))
|
||||
continue;
|
||||
|
||||
/* get road 0 data */
|
||||
src0 = (data0 & 0x800) ? info->gfx + 256 * 2 * 512 : (info->gfx + (0x000 + ((data0 >> 1) & 0xff)) * 512);
|
||||
hpos0 = (roadram[0x200 + ((info->control & 4) ? y : (data0 & 0x1ff))]) & 0xfff;
|
||||
color0 = roadram[0x600 + ((info->control & 4) ? y : (data0 & 0x1ff))];
|
||||
|
||||
/* get road 1 data */
|
||||
src1 = (data1 & 0x800) ? info->gfx + 256 * 2 * 512 : (info->gfx + (0x100 + ((data1 >> 1) & 0xff)) * 512);
|
||||
hpos1 = (roadram[0x400 + ((info->control & 4) ? (0x100 + y) : (data1 & 0x1ff))]) & 0xfff;
|
||||
color1 = roadram[0x600 + ((info->control & 4) ? (0x100 + y) : (data1 & 0x1ff))];
|
||||
|
||||
/* determine the 5 colors for road 0 */
|
||||
color_table[0x00] = info->colorbase1 ^ 0x00 ^ ((color0 >> 0) & 1);
|
||||
color_table[0x01] = info->colorbase1 ^ 0x02 ^ ((color0 >> 1) & 1);
|
||||
color_table[0x02] = info->colorbase1 ^ 0x04 ^ ((color0 >> 2) & 1);
|
||||
bgcolor = (color0 >> 8) & 0xf;
|
||||
color_table[0x03] = (data0 & 0x200) ? color_table[0x00] : (info->colorbase2 ^ 0x00 ^ bgcolor);
|
||||
color_table[0x07] = info->colorbase1 ^ 0x06 ^ ((color0 >> 3) & 1);
|
||||
|
||||
/* determine the 5 colors for road 1 */
|
||||
color_table[0x10] = info->colorbase1 ^ 0x08 ^ ((color1 >> 4) & 1);
|
||||
color_table[0x11] = info->colorbase1 ^ 0x0a ^ ((color1 >> 5) & 1);
|
||||
color_table[0x12] = info->colorbase1 ^ 0x0c ^ ((color1 >> 6) & 1);
|
||||
bgcolor = (color1 >> 8) & 0xf;
|
||||
color_table[0x13] = (data1 & 0x200) ? color_table[0x10] : (info->colorbase2 ^ 0x10 ^ bgcolor);
|
||||
color_table[0x17] = info->colorbase1 ^ 0x0e ^ ((color1 >> 7) & 1);
|
||||
|
||||
/* draw the road */
|
||||
switch (control)
|
||||
{
|
||||
case 0:
|
||||
if (data0 & 0x800)
|
||||
continue;
|
||||
hpos0 = (hpos0 - (0x5f8 + info->xoffs)) & 0xfff;
|
||||
for (x = cliprect.min_x; x <= cliprect.max_x; x++)
|
||||
{
|
||||
int pix0 = (hpos0 < 0x200) ? src0[hpos0] : 3;
|
||||
dest[x] = color_table[0x00 + pix0];
|
||||
hpos0 = (hpos0 + 1) & 0xfff;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
hpos0 = (hpos0 - (0x5f8 + info->xoffs)) & 0xfff;
|
||||
hpos1 = (hpos1 - (0x5f8 + info->xoffs)) & 0xfff;
|
||||
for (x = cliprect.min_x; x <= cliprect.max_x; x++)
|
||||
{
|
||||
int pix0 = (hpos0 < 0x200) ? src0[hpos0] : 3;
|
||||
int pix1 = (hpos1 < 0x200) ? src1[hpos1] : 3;
|
||||
if ((priority_map[0][pix0] >> pix1) & 1)
|
||||
dest[x] = color_table[0x10 + pix1];
|
||||
else
|
||||
dest[x] = color_table[0x00 + pix0];
|
||||
hpos0 = (hpos0 + 1) & 0xfff;
|
||||
hpos1 = (hpos1 + 1) & 0xfff;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
hpos0 = (hpos0 - (0x5f8 + info->xoffs)) & 0xfff;
|
||||
hpos1 = (hpos1 - (0x5f8 + info->xoffs)) & 0xfff;
|
||||
for (x = cliprect.min_x; x <= cliprect.max_x; x++)
|
||||
{
|
||||
int pix0 = (hpos0 < 0x200) ? src0[hpos0] : 3;
|
||||
int pix1 = (hpos1 < 0x200) ? src1[hpos1] : 3;
|
||||
if ((priority_map[1][pix0] >> pix1) & 1)
|
||||
dest[x] = color_table[0x10 + pix1];
|
||||
else
|
||||
dest[x] = color_table[0x00 + pix0];
|
||||
hpos0 = (hpos0 + 1) & 0xfff;
|
||||
hpos1 = (hpos1 + 1) & 0xfff;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (data1 & 0x800)
|
||||
continue;
|
||||
hpos1 = (hpos1 - (0x5f8 + info->xoffs)) & 0xfff;
|
||||
for (x = cliprect.min_x; x <= cliprect.max_x; x++)
|
||||
{
|
||||
int pix1 = (hpos1 < 0x200) ? src1[hpos1] : 3;
|
||||
dest[x] = color_table[0x10 + pix1];
|
||||
hpos1 = (hpos1 + 1) & 0xfff;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* General road initialization
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void segaic16_road_device::segaic16_road_init(running_machine &machine, int which, int type, int colorbase1, int colorbase2, int colorbase3, int xoffs)
|
||||
{
|
||||
struct road_info *info = &segaic16_road[which];
|
||||
|
||||
/* reset the tilemap info */
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->index = which;
|
||||
info->type = type;
|
||||
info->colorbase1 = colorbase1;
|
||||
info->colorbase2 = colorbase2;
|
||||
info->colorbase3 = colorbase3;
|
||||
info->xoffs = xoffs;
|
||||
|
||||
/* set up based on which road generator */
|
||||
switch (which)
|
||||
{
|
||||
case 0:
|
||||
info->roadram = segaic16_roadram_0;
|
||||
break;
|
||||
|
||||
default:
|
||||
fatalerror("Invalid road index specified in segaic16_road_init\n");
|
||||
}
|
||||
|
||||
/* determine the parameters of the road */
|
||||
switch (type)
|
||||
{
|
||||
case SEGAIC16_ROAD_HANGON:
|
||||
case SEGAIC16_ROAD_SHARRIER:
|
||||
info->draw = segaic16_road_hangon_draw;
|
||||
segaic16_road_hangon_decode(machine, info);
|
||||
break;
|
||||
|
||||
case SEGAIC16_ROAD_OUTRUN:
|
||||
case SEGAIC16_ROAD_XBOARD:
|
||||
info->buffer = auto_alloc_array(machine, UINT16, 0x1000/2);
|
||||
info->draw = segaic16_road_outrun_draw;
|
||||
segaic16_road_outrun_decode(machine, info);
|
||||
break;
|
||||
|
||||
default:
|
||||
fatalerror("Invalid road system specified in segaic16_road_init\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* General road drawing
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void segaic16_road_device::segaic16_road_draw(int which, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority)
|
||||
{
|
||||
struct road_info *info = &segaic16_road[which];
|
||||
(*info->draw)(info, bitmap, cliprect, priority);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* General road control read/write
|
||||
*
|
||||
*************************************/
|
||||
|
||||
READ16_MEMBER( segaic16_road_device::segaic16_road_control_0_r )
|
||||
{
|
||||
struct road_info *info = &segaic16_road[0];
|
||||
|
||||
if (info->buffer)
|
||||
{
|
||||
UINT32 *src = (UINT32 *)info->roadram;
|
||||
UINT32 *dst = (UINT32 *)info->buffer;
|
||||
int i;
|
||||
|
||||
/* swap the halves of the road RAM */
|
||||
for (i = 0; i < 0x1000/4; i++)
|
||||
{
|
||||
UINT32 temp = *src;
|
||||
*src++ = *dst;
|
||||
*dst++ = temp;
|
||||
}
|
||||
}
|
||||
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
|
||||
WRITE16_MEMBER( segaic16_road_device::segaic16_road_control_0_w )
|
||||
{
|
||||
struct road_info *info = &segaic16_road[0];
|
||||
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
info->control = data & ((info->type == SEGAIC16_ROAD_OUTRUN) ? 3 : 7);
|
||||
}
|
||||
}
|
||||
|
||||
|
72
src/mame/video/segaic16_road.h
Normal file
72
src/mame/video/segaic16_road.h
Normal file
@ -0,0 +1,72 @@
|
||||
/* Sega Road Generators */
|
||||
|
||||
|
||||
#pragma once
|
||||
#ifndef __SEGAIC16_ROAD_H__
|
||||
#define __SEGAIC16_ROAD_H__
|
||||
|
||||
|
||||
/* road systems */
|
||||
#define SEGAIC16_MAX_ROADS 1
|
||||
|
||||
#define SEGAIC16_ROAD_HANGON 0
|
||||
#define SEGAIC16_ROAD_SHARRIER 1
|
||||
#define SEGAIC16_ROAD_OUTRUN 2
|
||||
#define SEGAIC16_ROAD_XBOARD 3
|
||||
|
||||
#define SEGAIC16_ROAD_BACKGROUND 0
|
||||
#define SEGAIC16_ROAD_FOREGROUND 1
|
||||
|
||||
|
||||
|
||||
struct road_info
|
||||
{
|
||||
UINT8 index; /* index of this structure */
|
||||
UINT8 type; /* type of road system (see segaic16.h for details) */
|
||||
UINT8 control; /* control register value */
|
||||
UINT16 colorbase1; /* color base for road ROM data */
|
||||
UINT16 colorbase2; /* color base for road background data */
|
||||
UINT16 colorbase3; /* color base for sky data */
|
||||
INT32 xoffs; /* X scroll offset */
|
||||
void (*draw)(struct road_info *info, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority);
|
||||
UINT16 * roadram; /* pointer to roadram pointer */
|
||||
UINT16 * buffer; /* buffered roadram pointer */
|
||||
UINT8 * gfx; /* expanded road graphics */
|
||||
};
|
||||
|
||||
|
||||
|
||||
class segaic16_road_device : public device_t
|
||||
{
|
||||
public:
|
||||
segaic16_road_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
~segaic16_road_device() {}
|
||||
|
||||
UINT16 *segaic16_roadram_0;
|
||||
|
||||
struct road_info segaic16_road[SEGAIC16_MAX_ROADS];
|
||||
void segaic16_road_init(running_machine &machine, int which, int type, int colorbase1, int colorbase2, int colorbase3, int xoffs);
|
||||
|
||||
void segaic16_road_draw(int which, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority);
|
||||
|
||||
DECLARE_READ16_MEMBER( segaic16_road_control_0_r );
|
||||
DECLARE_WRITE16_MEMBER( segaic16_road_control_0_w );
|
||||
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_config_complete();
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
|
||||
private:
|
||||
// internal state
|
||||
};
|
||||
|
||||
extern const device_type SEGAIC16_ROAD;
|
||||
|
||||
#define MCFG_SEGAIC16_ROAD_ADD(_tag) \
|
||||
MCFG_DEVICE_ADD(_tag, SEGAIC16_ROAD, 0) \
|
||||
|
||||
|
||||
#endif
|
@ -52,7 +52,7 @@ void segaorun_state::video_start()
|
||||
m_segaic16vid->segaic16_tilemap_init(machine(), 0, SEGAIC16_TILEMAP_16B_ALT, 0x000, 0, 2);
|
||||
|
||||
// initialize the road
|
||||
m_segaic16vid->segaic16_road_init(machine(), 0, SEGAIC16_ROAD_OUTRUN, 0x7f6, 0x7c0, 0x7c0, 0);
|
||||
m_segaic16road->segaic16_road_init(machine(), 0, SEGAIC16_ROAD_OUTRUN, 0x7f6, 0x7c0, 0x7c0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -60,7 +60,7 @@ void segaorun_state::video_start()
|
||||
m_segaic16vid->segaic16_tilemap_init(machine(), 0, SEGAIC16_TILEMAP_16B, 0x000, 0, 2);
|
||||
|
||||
// initialize the road
|
||||
m_segaic16vid->segaic16_road_init(machine(), 0, SEGAIC16_ROAD_OUTRUN, 0x400, 0x420, 0x780, 0);
|
||||
m_segaic16road->segaic16_road_init(machine(), 0, SEGAIC16_ROAD_OUTRUN, 0x400, 0x420, 0x780, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ UINT32 segaorun_state::screen_update_shangon(screen_device &screen, bitmap_ind16
|
||||
machine().priority_bitmap.fill(0, cliprect);
|
||||
|
||||
// draw the low priority road layer
|
||||
m_segaic16vid->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_BACKGROUND);
|
||||
m_segaic16road->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_BACKGROUND);
|
||||
|
||||
// draw background
|
||||
m_segaic16vid->segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_BACKGROUND, 0, 0x01);
|
||||
@ -90,7 +90,7 @@ UINT32 segaorun_state::screen_update_shangon(screen_device &screen, bitmap_ind16
|
||||
m_segaic16vid->segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_FOREGROUND, 1, 0x04);
|
||||
|
||||
// draw the high priority road
|
||||
m_segaic16vid->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_FOREGROUND);
|
||||
m_segaic16road->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_FOREGROUND);
|
||||
|
||||
// text layer
|
||||
// note that we inflate the priority of the text layer to prevent sprites
|
||||
@ -148,7 +148,7 @@ UINT32 segaorun_state::screen_update_outrun(screen_device &screen, bitmap_ind16
|
||||
machine().priority_bitmap.fill(0, cliprect);
|
||||
|
||||
// draw the low priority road layer
|
||||
m_segaic16vid->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_BACKGROUND);
|
||||
m_segaic16road->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_BACKGROUND);
|
||||
|
||||
// draw background
|
||||
m_segaic16vid->segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_BACKGROUND, 0, 0x01);
|
||||
@ -159,7 +159,7 @@ UINT32 segaorun_state::screen_update_outrun(screen_device &screen, bitmap_ind16
|
||||
m_segaic16vid->segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_FOREGROUND, 1, 0x04);
|
||||
|
||||
// draw the high priority road
|
||||
m_segaic16vid->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_FOREGROUND);
|
||||
m_segaic16road->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_FOREGROUND);
|
||||
|
||||
// text layer
|
||||
m_segaic16vid->segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_TEXT, 0, 0x04);
|
||||
|
@ -49,7 +49,7 @@ void segaxbd_state::video_start()
|
||||
m_segaic16vid->segaic16_tilemap_init(machine(), 0, SEGAIC16_TILEMAP_16B, 0x1c00, 0, 2);
|
||||
|
||||
// initialize the road
|
||||
m_segaic16vid->segaic16_road_init(machine(), 0, SEGAIC16_ROAD_XBOARD, 0x1700, 0x1720, 0x1780, -166);
|
||||
m_segaic16road->segaic16_road_init(machine(), 0, SEGAIC16_ROAD_XBOARD, 0x1700, 0x1720, 0x1780, -166);
|
||||
}
|
||||
|
||||
|
||||
@ -74,9 +74,9 @@ UINT32 segaxbd_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap,
|
||||
machine().priority_bitmap.fill(0, cliprect);
|
||||
|
||||
// draw the low priority road layer
|
||||
m_segaic16vid->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_BACKGROUND);
|
||||
m_segaic16road->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_BACKGROUND);
|
||||
if (m_road_priority == 0)
|
||||
m_segaic16vid->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_FOREGROUND);
|
||||
m_segaic16road->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_FOREGROUND);
|
||||
|
||||
// draw background
|
||||
m_segaic16vid->segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_BACKGROUND, 0, 0x01);
|
||||
@ -88,7 +88,7 @@ UINT32 segaxbd_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap,
|
||||
|
||||
// draw the high priority road
|
||||
if (m_road_priority == 1)
|
||||
m_segaic16vid->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_FOREGROUND);
|
||||
m_segaic16road->segaic16_road_draw(0, bitmap, cliprect, SEGAIC16_ROAD_FOREGROUND);
|
||||
|
||||
// text layer
|
||||
m_segaic16vid->segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_TEXT, 0, 0x04);
|
||||
|
Loading…
Reference in New Issue
Block a user