diff options
author | 2013-07-08 21:32:44 +0000 | |
---|---|---|
committer | 2013-07-08 21:32:44 +0000 | |
commit | 11416b9d26309850c23f8cd152e2a51b2ebdf1fb (patch) | |
tree | 077e0ef83b0566b7fe58ca52ea9496bb21781649 /src | |
parent | 90174dd1399fd985ac5551492babdfccb4d9fe8e (diff) |
split out the roadgen (nw)
Diffstat (limited to 'src')
-rw-r--r-- | src/mame/drivers/segahang.c | 3 | ||||
-rw-r--r-- | src/mame/drivers/segaorun.c | 5 | ||||
-rw-r--r-- | src/mame/drivers/segaxbd.c | 7 | ||||
-rw-r--r-- | src/mame/includes/segahang.h | 3 | ||||
-rw-r--r-- | src/mame/includes/segaorun.h | 7 | ||||
-rw-r--r-- | src/mame/includes/segaxbd.h | 3 | ||||
-rw-r--r-- | src/mame/mame.mak | 1 | ||||
-rw-r--r-- | src/mame/video/segahang.c | 6 | ||||
-rw-r--r-- | src/mame/video/segaic16.c | 603 | ||||
-rw-r--r-- | src/mame/video/segaic16.h | 33 | ||||
-rw-r--r-- | src/mame/video/segaic16_road.c | 642 | ||||
-rw-r--r-- | src/mame/video/segaic16_road.h | 72 | ||||
-rw-r--r-- | src/mame/video/segaorun.c | 12 | ||||
-rw-r--r-- | src/mame/video/segaxbd.c | 8 |
14 files changed, 748 insertions, 657 deletions
diff --git a/src/mame/drivers/segahang.c b/src/mame/drivers/segahang.c index ea6ca5fbfa0..6838fe36ef6 100644 --- a/src/mame/drivers/segahang.c +++ b/src/mame/drivers/segahang.c @@ -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)); diff --git a/src/mame/drivers/segaorun.c b/src/mame/drivers/segaorun.c index 82714db730d..e77dd283020 100644 --- a/src/mame/drivers/segaorun.c +++ b/src/mame/drivers/segaorun.c @@ -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)); diff --git a/src/mame/drivers/segaxbd.c b/src/mame/drivers/segaxbd.c index 19caa8badf5..3ae081eb674 100644 --- a/src/mame/drivers/segaxbd.c +++ b/src/mame/drivers/segaxbd.c @@ -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)); diff --git a/src/mame/includes/segahang.h b/src/mame/includes/segahang.h index 986bce59b94..d407756d5d3 100644 --- a/src/mame/includes/segahang.h +++ b/src/mame/includes/segahang.h @@ -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; diff --git a/src/mame/includes/segaorun.h b/src/mame/includes/segaorun.h index 3496df510ae..895229d1462 100644 --- a/src/mame/includes/segaorun.h +++ b/src/mame/includes/segaorun.h @@ -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; diff --git a/src/mame/includes/segaxbd.h b/src/mame/includes/segaxbd.h index 9524744d917..aaa98c14ffb 100644 --- a/src/mame/includes/segaxbd.h +++ b/src/mame/includes/segaxbd.h @@ -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; diff --git a/src/mame/mame.mak b/src/mame/mame.mak index ba61146e8ae..26e4b2b920f 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -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 \ diff --git a/src/mame/video/segahang.c b/src/mame/video/segahang.c index 994f618c5c5..11a6d462139 100644 --- a/src/mame/video/segahang.c +++ b/src/mame/video/segahang.c @@ -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 diff --git a/src/mame/video/segaic16.c b/src/mame/video/segaic16.c index 8eea522fe39..44c893633b8 100644 --- a/src/mame/video/segaic16.c +++ b/src/mame/video/segaic16.c @@ -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); - } -} - /************************************* diff --git a/src/mame/video/segaic16.h b/src/mame/video/segaic16.h index 46375cec222..cc2b2a69646 100644 --- a/src/mame/video/segaic16.h +++ b/src/mame/video/segaic16.h @@ -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 ); diff --git a/src/mame/video/segaic16_road.c b/src/mame/video/segaic16_road.c new file mode 100644 index 00000000000..c386afb1330 --- /dev/null +++ b/src/mame/video/segaic16_road.c @@ -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); + } +} + + diff --git a/src/mame/video/segaic16_road.h b/src/mame/video/segaic16_road.h new file mode 100644 index 00000000000..ed4a9c85a23 --- /dev/null +++ b/src/mame/video/segaic16_road.h @@ -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 diff --git a/src/mame/video/segaorun.c b/src/mame/video/segaorun.c index 805b147343b..70bc0f096f6 100644 --- a/src/mame/video/segaorun.c +++ b/src/mame/video/segaorun.c @@ -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); diff --git a/src/mame/video/segaxbd.c b/src/mame/video/segaxbd.c index 14fc45eba19..cce9da3d547 100644 --- a/src/mame/video/segaxbd.c +++ b/src/mame/video/segaxbd.c @@ -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); |