new WORKING machines (Plug & Play) (#6764)

* new WORKING machines
----
Super Sonic Gold (Radica Plug & Play) (USA) [Sean Riddle, David Haywood, Kev (FBN), anonymous]
Street Fighter II: Special Champion Edition [Ghouls'n Ghosts] (Radica, Arcade Legends) (USA) [Sean Riddle, David Haywood, Kev (FBN), anonymous]

new NOT WORKING machines
----
Speed Racer (Senario) [Sean Riddle, Kamaal Brown]
My Arcade Go Gamer Portable (Family Sport 220-in-1) [Sean Riddle, Kev (FBN), anonymous]
This commit is contained in:
David Haywood 2020-05-30 14:55:57 +01:00 committed by GitHub
parent 1984fb5f94
commit ceccc2f7e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 616 additions and 662 deletions

View File

@ -934,8 +934,8 @@ void gcm394_base_video_device::draw_sprite(const rectangle& cliprect, uint32_t s
} }
else else
{ {
flip_x = 0;// (attr & TILE_X_FLIP); flip_x = 0;// (attr & 0x0004);
yflipmask = 0;// attr& TILE_Y_FLIP ? h - 1 : 0; yflipmask = 0;// attr& 0x0008 ? h - 1 : 0;
bpp = attr & 0x0003; bpp = attr & 0x0003;
palette_offset = (attr & 0x0f00) >> 4; palette_offset = (attr & 0x0f00) >> 4;
@ -998,10 +998,10 @@ uint32_t gcm394_base_video_device::screen_update(screen_device &screen, bitmap_r
uint16_t ctrl3 = m_tmap3_regs[1]; uint16_t ctrl3 = m_tmap3_regs[1];
popmessage( popmessage(
"p0ctrl u:%02x Bl:%d HC:%d u:%d u:%d RS:%d E:%d WP:%d Rg:%d Bm:%d\n" "p0ctrl u:%02x Bl:%d HC:%d Ycmp:%d Hcmp:%d RS:%d E:%d WP:%d Rg:%d Bm:%d\n"
"p1ctrl u:%02x Bl:%d HC:%d u:%d u:%d RS:%d E:%d WP:%d Rg:%d Bm:%d\n" "p1ctrl u:%02x Bl:%d HC:%d Ycmp:%d Hcmp:%d RS:%d E:%d WP:%d Rg:%d Bm:%d\n"
"p2ctrl u:%02x Bl:%d HC:%d u:%d u:%d RS:%d E:%d WP:%d Rg:%d Bm:%d\n" "p2ctrl u:%02x Bl:%d HC:%d Ycmp:%d Hcmp:%d RS:%d E:%d WP:%d Rg:%d Bm:%d\n"
"p3ctrl u:%02x Bl:%d HC:%d u:%d u:%d RS:%d E:%d WP:%d Rg:%d Bm:%d\n" "p3ctrl u:%02x Bl:%d HC:%d Ycmp:%d Hcmp:%d RS:%d E:%d WP:%d Rg:%d Bm:%d\n"
"p0attr u:%01x Z:%d P:%d V:%d H:%d FY:%d FX:%d D:%d\n" "p0attr u:%01x Z:%d P:%d V:%d H:%d FY:%d FX:%d D:%d\n"
"p1attr u:%01x Z:%d P:%d V:%d H:%d FY:%d FX:%d D:%d\n" "p1attr u:%01x Z:%d P:%d V:%d H:%d FY:%d FX:%d D:%d\n"
"p2attr u:%01x Z:%d P:%d V:%d H:%d FY:%d FX:%d D:%d\n" "p2attr u:%01x Z:%d P:%d V:%d H:%d FY:%d FX:%d D:%d\n"

View File

@ -70,7 +70,8 @@ void spg2xx_device::internal_map(address_map &map)
{ {
map(0x000000, 0x0027ff).ram(); map(0x000000, 0x0027ff).ram();
map(0x002800, 0x0028ff).rw(m_spg_video, FUNC(spg2xx_video_device::video_r), FUNC(spg2xx_video_device::video_w)); map(0x002800, 0x0028ff).rw(m_spg_video, FUNC(spg2xx_video_device::video_r), FUNC(spg2xx_video_device::video_w));
map(0x002900, 0x002aff).ram().share("spgvideo:scrollram"); map(0x002900, 0x0029ff).ram().share("spgvideo:scrollram");
map(0x002a00, 0x002aff).ram().share("spgvideo:hcompram"); // not all models?
map(0x002b00, 0x002bff).ram().share("spgvideo:paletteram"); map(0x002b00, 0x002bff).ram().share("spgvideo:paletteram");
map(0x002c00, 0x002fff).ram().share("spgvideo:spriteram"); map(0x002c00, 0x002fff).ram().share("spgvideo:spriteram");
map(0x003000, 0x0031ff).rw(m_spg_audio, FUNC(spg2xx_audio_device::audio_r), FUNC(spg2xx_audio_device::audio_w)); map(0x003000, 0x0031ff).rw(m_spg_audio, FUNC(spg2xx_audio_device::audio_r), FUNC(spg2xx_audio_device::audio_w));

View File

@ -23,8 +23,6 @@ DEFINE_DEVICE_TYPE(SPG24X_VIDEO, spg24x_video_device, "spg24x_video", "SPG240-se
#define VERBOSE (0) #define VERBOSE (0)
#include "logmacro.h" #include "logmacro.h"
#define SPG_DEBUG_VIDEO (0)
#define VIDEO_IRQ_ENABLE m_video_regs[0x62] #define VIDEO_IRQ_ENABLE m_video_regs[0x62]
#define VIDEO_IRQ_STATUS m_video_regs[0x63] #define VIDEO_IRQ_STATUS m_video_regs[0x63]
@ -36,6 +34,7 @@ spg2xx_video_device::spg2xx_video_device(const machine_config &mconfig, device_t
m_cpu(*this, finder_base::DUMMY_TAG), m_cpu(*this, finder_base::DUMMY_TAG),
m_screen(*this, finder_base::DUMMY_TAG), m_screen(*this, finder_base::DUMMY_TAG),
m_scrollram(*this, "scrollram"), m_scrollram(*this, "scrollram"),
m_hcompram(*this, "hcompram"),
m_paletteram(*this, "paletteram"), m_paletteram(*this, "paletteram"),
m_spriteram(*this, "spriteram"), m_spriteram(*this, "spriteram"),
m_video_irq_cb(*this) m_video_irq_cb(*this)
@ -66,14 +65,6 @@ void spg2xx_video_device::device_start()
m_screenpos_timer = timer_alloc(TIMER_SCREENPOS); m_screenpos_timer = timer_alloc(TIMER_SCREENPOS);
m_screenpos_timer->adjust(attotime::never); m_screenpos_timer->adjust(attotime::never);
save_item(NAME(m_hide_page0));
save_item(NAME(m_hide_page1));
save_item(NAME(m_hide_sprites));
save_item(NAME(m_debug_sprites));
save_item(NAME(m_debug_blit));
save_item(NAME(m_debug_palette));
save_item(NAME(m_sprite_index_to_debug));
save_item(NAME(m_video_regs)); save_item(NAME(m_video_regs));
m_sprlimit_read_cb.resolve_safe(0); m_sprlimit_read_cb.resolve_safe(0);
@ -90,130 +81,18 @@ void spg2xx_video_device::device_reset()
m_video_regs[0x3c] = 0x0020; m_video_regs[0x3c] = 0x0020;
m_video_regs[0x42] = 0x0001; m_video_regs[0x42] = 0x0001;
m_hide_page0 = false; for (int i = 0; i < 480; i++)
m_hide_page1 = false; {
m_hide_sprites = false; m_ycmp_table[i] = -1;
m_debug_sprites = false; }
m_debug_blit = false;
m_debug_palette = false;
m_sprite_index_to_debug = 0;
} }
/************************* /*************************
* Video Hardware * * Video Hardware *
*************************/ *************************/
// Perform a lerp between a and b
inline uint8_t spg2xx_video_device::mix_channel(uint8_t bottom, uint8_t top)
{
uint8_t alpha = (m_video_regs[0x2a] & 3) << 6;
return ((256 - alpha) * bottom + alpha * top) >> 8;
}
template<spg2xx_video_device::blend_enable_t Blend, spg2xx_video_device::rowscroll_enable_t RowScroll, spg2xx_video_device::flipx_t FlipX> void spg2xx_video_device::draw_linemap(const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t* regs)
void spg2xx_video_device::draw(const rectangle &cliprect, uint32_t line, uint32_t xoff, uint32_t yoff, uint32_t bitmap_addr, uint16_t tile, int32_t h, int32_t w, uint8_t bpp, uint32_t yflipmask, uint32_t palette_offset, int yscroll)
{
address_space &space = m_cpu->space(AS_PROGRAM);
uint32_t nc_bpp = ((bpp) + 1) << 1;
if (SPG_DEBUG_VIDEO && m_debug_blit)
{
printf("s:%d line:%d xy:%08x,%08x bitmap_addr:%08x tile:%04x\n", cliprect.min_x, line, xoff, yoff, bitmap_addr, tile);
printf("hw:%d,%d yfm:%d nc_bppols:%d pobs:%02x ", w, h, yflipmask, nc_bpp, palette_offset);
}
palette_offset >>= nc_bpp;
palette_offset <<= nc_bpp;
if (SPG_DEBUG_VIDEO && m_debug_blit)
{
printf("poas:%02x\n", palette_offset);
}
uint32_t bits_per_row = nc_bpp * w / 16;
uint32_t words_per_tile = bits_per_row * h;
uint32_t m = bitmap_addr + words_per_tile * tile + bits_per_row * (line ^ yflipmask);
uint32_t bits = 0;
uint32_t nbits = 0;
uint32_t y = line;
int yy = (yoff + y) & 0x1ff;
if (yy >= 0x01c0)
yy -= 0x0200;
if (yy > 240 || yy < 0)
return;
if (SPG_DEBUG_VIDEO && m_debug_blit)
printf("%3d:\n", yy);
int y_index = yy * 320;
for (int32_t x = FlipX ? (w - 1) : 0; FlipX ? x >= 0 : x < w; FlipX ? x-- : x++)
{
int xx = xoff + x;
bits <<= nc_bpp;
if (SPG_DEBUG_VIDEO && m_debug_blit)
printf(" %08x:%d ", bits, nbits);
if (nbits < nc_bpp)
{
uint16_t b = space.read_word(m++ & 0x3fffff);
b = (b << 8) | (b >> 8);
bits |= b << (nc_bpp - nbits);
nbits += 16;
if (SPG_DEBUG_VIDEO && m_debug_blit)
printf("(%04x:%08x:%d) ", b, bits, nbits);
}
nbits -= nc_bpp;
uint32_t pal = palette_offset + (bits >> 16);
if (SPG_DEBUG_VIDEO && m_debug_blit)
printf("%02x:%02x:%04x ", bits >> 16, pal, bits & 0xffff);
bits &= 0xffff;
if (RowScroll)
{
xx -= (int16_t)m_scrollram[(yy + yscroll) & 0xff];
}
xx &= 0x01ff;
if (xx >= 0x01c0)
xx -= 0x0200;
if (xx >= 0 && xx < 320)
{
int pix_index = xx + y_index;
uint16_t rgb = m_paletteram[pal];
if (SPG_DEBUG_VIDEO && m_debug_blit)
printf("rgb:%04x ", rgb);
if (!(rgb & 0x8000))
{
if (Blend)
{
if (SPG_DEBUG_VIDEO && m_debug_blit)
printf("M\n");
m_screenbuf[pix_index] = (mix_channel((uint8_t)(m_screenbuf[pix_index] >> 16), m_rgb5_to_rgb8[(rgb >> 10) & 0x1f]) << 16) |
(mix_channel((uint8_t)(m_screenbuf[pix_index] >> 8), m_rgb5_to_rgb8[(rgb >> 5) & 0x1f]) << 8) |
(mix_channel((uint8_t)(m_screenbuf[pix_index] >> 0), m_rgb5_to_rgb8[rgb & 0x1f]));
}
else
{
if (SPG_DEBUG_VIDEO && m_debug_blit)
printf("S\n");
m_screenbuf[pix_index] = m_rgb555_to_rgb888[rgb];
}
}
else if (SPG_DEBUG_VIDEO && m_debug_blit)
{
printf("X\n");
}
}
}
}
void spg2xx_video_device::draw_bitmap(const rectangle& cliprect, uint32_t scanline, int priority, uint32_t bitmap_addr, uint16_t* regs)
{ {
if ((scanline < 0) || (scanline >= 240)) if ((scanline < 0) || (scanline >= 240))
return; return;
@ -246,8 +125,6 @@ void spg2xx_video_device::draw_bitmap(const rectangle& cliprect, uint32_t scanli
//const int linewidth = 320 / 2; //const int linewidth = 320 / 2;
int sourcebase = tile | (palette << 16); int sourcebase = tile | (palette << 16);
uint32_t* dest = &m_screenbuf[320 * scanline];
uint32_t ctrl = regs[3]; uint32_t ctrl = regs[3];
if (ctrl & 0x80) // HiColor mode (rad_digi) if (ctrl & 0x80) // HiColor mode (rad_digi)
@ -258,7 +135,7 @@ void spg2xx_video_device::draw_bitmap(const rectangle& cliprect, uint32_t scanli
if (!(data & 0x8000)) if (!(data & 0x8000))
{ {
dest[i] = m_rgb555_to_rgb888[data & 0x7fff]; dst[i] = m_rgb555_to_rgb888[data & 0x7fff];
} }
} }
} }
@ -275,7 +152,7 @@ void spg2xx_video_device::draw_bitmap(const rectangle& cliprect, uint32_t scanli
if (!(color & 0x8000)) if (!(color & 0x8000))
{ {
dest[(i * 2) + 0] = m_rgb555_to_rgb888[color & 0x7fff]; dst[(i * 2) + 0] = m_rgb555_to_rgb888[color & 0x7fff];
} }
palette_entry = (data & 0xff00) >> 8; palette_entry = (data & 0xff00) >> 8;
@ -283,68 +160,29 @@ void spg2xx_video_device::draw_bitmap(const rectangle& cliprect, uint32_t scanli
if (!(color & 0x8000)) if (!(color & 0x8000))
{ {
dest[(i * 2) + 1] = m_rgb555_to_rgb888[color & 0x7fff]; dst[(i * 2) + 1] = m_rgb555_to_rgb888[color & 0x7fff];
} }
} }
} }
} }
void spg2xx_video_device::draw_page(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t bitmap_addr, uint16_t *regs)
bool spg2xx_video_device::get_tile_info(uint32_t tilemap_rambase, uint32_t palettemap_rambase, uint32_t x0, uint32_t y0, uint32_t tile_count_x, uint32_t ctrl, uint32_t attr, uint16_t& tile, bool& blend, bool& flip_x, bool& flip_y, uint32_t& palette_offset)
{ {
uint32_t xscroll = regs[0];
uint32_t yscroll = regs[1];
uint32_t attr = regs[2];
uint32_t ctrl = regs[3];
uint32_t tilemap = regs[4];
uint32_t palette_map = regs[5];
address_space &space = m_cpu->space(AS_PROGRAM); address_space &space = m_cpu->space(AS_PROGRAM);
uint32_t tile_address = x0 + (tile_count_x * y0);
if (!(ctrl & PAGE_ENABLE_MASK)) tile = (ctrl & 0x0004) ? space.read_word(tilemap_rambase) : space.read_word(tilemap_rambase + tile_address);
{
return;
}
if (((attr & PAGE_PRIORITY_FLAG_MASK) >> PAGE_PRIORITY_FLAG_SHIFT) != priority)
{
return;
}
if (ctrl & 0x0001) // Bitmap mode!
{
draw_bitmap(cliprect, scanline, priority, bitmap_addr, regs);
return;
}
uint32_t tile_h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT);
uint32_t tile_w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT);
uint32_t tile_count_x = 512 / tile_w;
uint32_t bitmap_y = (scanline + yscroll) & 0xff;
uint32_t y0 = bitmap_y / tile_h;
uint32_t tile_scanline = bitmap_y % tile_h;
uint32_t tile_address = tile_count_x * y0;
if (SPG_DEBUG_VIDEO && machine().input().code_pressed(KEYCODE_H))
printf("s:%3d | baddr:%08x | yscr:%3d | bity:%3d | y0:%2d | ts:%2d\n", scanline, bitmap_addr, yscroll, bitmap_y, y0, tile_scanline);
if (SPG_DEBUG_VIDEO && machine().input().code_pressed(KEYCODE_EQUALS))
m_debug_blit = true;
for (uint32_t x0 = 0; x0 < tile_count_x; x0++, tile_address++)
{
uint32_t yy = ((tile_h * y0 - yscroll + 0x10) & 0xff) - 0x10;
uint32_t xx = (tile_w * x0 - xscroll) & 0x1ff;
uint16_t tile = (ctrl & PAGE_WALLPAPER_MASK) ? space.read_word(tilemap) : space.read_word(tilemap + tile_address);
if (!tile) if (!tile)
continue; return false;
uint32_t tileattr = attr; uint32_t tileattr = attr;
uint32_t tilectrl = ctrl; uint32_t tilectrl = ctrl;
if ((ctrl & 2) == 0) if ((ctrl & 2) == 0)
{ // -(1) bld(1) flip(2) pal(4) { // -(1) bld(1) flip(2) pal(4)
uint16_t palette = (ctrl & PAGE_WALLPAPER_MASK) ? space.read_word(palette_map) : space.read_word(palette_map + tile_address / 2); uint16_t palette = (ctrl & 0x0004) ? space.read_word(palettemap_rambase) : space.read_word(palettemap_rambase + tile_address / 2);
if (x0 & 1) if (x0 & 1)
palette >>= 8; palette >>= 8;
else else
@ -361,56 +199,185 @@ void spg2xx_video_device::draw_page(const rectangle &cliprect, uint32_t scanline
tilectrl |= (palette << 2) & 0x0100; // blend tilectrl |= (palette << 2) & 0x0100; // blend
} }
const bool blend = (tileattr & 0x4000 || tilectrl & 0x0100); blend = (tileattr & 0x4000 || tilectrl & 0x0100);
const bool row_scroll = (tilectrl & 0x0010); flip_x = (tileattr & 0x0004);
const bool flip_x = (tileattr & TILE_X_FLIP); flip_y= (tileattr & 0x0008);
const uint32_t yflipmask = tileattr & TILE_Y_FLIP ? tile_h - 1 : 0;
const uint32_t palette_offset = (tileattr & 0x0f00) >> 4;
const uint8_t bpp = tileattr & 0x0003; palette_offset = (tileattr & 0x0f00) >> 4;
return true;
}
void spg2xx_video_device::update_vcmp_table()
{
for (int i = 0; i < 480; i++)
{
int currentline = 0;
if (i < m_video_regs[0x1d])
{
m_ycmp_table[i] = -1;
}
else
{
if (currentline < 240)
{
m_ycmp_table[i] = currentline;
currentline += m_video_regs[0x1c];
}
else
{
m_ycmp_table[i] = -1;
}
}
}
}
// Perform a lerp between a and b
inline uint8_t spg2xx_video_device::mix_channel(uint8_t bottom, uint8_t top)
{
uint8_t alpha = (m_video_regs[0x2a] & 3) << 6;
return ((256 - alpha) * bottom + alpha * top) >> 8;
}
template<spg2xx_video_device::blend_enable_t Blend, spg2xx_video_device::flipx_t FlipX>
void spg2xx_video_device::draw_tilestrip(const rectangle& cliprect, uint32_t* dst, uint32_t tile_h, uint32_t tile_w, uint32_t tilegfxdata_addr, uint16_t tile, uint32_t tile_scanline, int drawx, bool flip_y, uint32_t palette_offset, const uint32_t nc_bpp, const uint32_t bits_per_row, const uint32_t words_per_tile)
{
address_space &space = m_cpu->space(AS_PROGRAM);
const uint32_t yflipmask = flip_y ? tile_h - 1 : 0;
uint32_t m = tilegfxdata_addr + words_per_tile * tile + bits_per_row * (tile_scanline ^ yflipmask);
uint32_t bits = 0;
uint32_t nbits = 0;
for (int32_t x = FlipX ? (tile_w - 1) : 0; FlipX ? x >= 0 : x < tile_w; FlipX ? x-- : x++)
{
int realdrawpos = (drawx + x) & 0x1ff;
bits <<= nc_bpp;
if (nbits < nc_bpp)
{
uint16_t b = space.read_word(m++ & 0x3fffff);
b = (b << 8) | (b >> 8);
bits |= b << (nc_bpp - nbits);
nbits += 16;
}
nbits -= nc_bpp;
uint32_t pal = palette_offset + (bits >> 16);
bits &= 0xffff;
if (realdrawpos >= 0 && realdrawpos < 320)
{
uint16_t rgb = m_paletteram[pal];
if (!(rgb & 0x8000))
{
if (Blend)
{
dst[realdrawpos] = (mix_channel((uint8_t)(dst[realdrawpos] >> 16), m_rgb5_to_rgb8[(rgb >> 10) & 0x1f]) << 16) |
(mix_channel((uint8_t)(dst[realdrawpos] >> 8), m_rgb5_to_rgb8[(rgb >> 5) & 0x1f]) << 8) |
(mix_channel((uint8_t)(dst[realdrawpos] >> 0), m_rgb5_to_rgb8[rgb & 0x1f]));
}
else
{
dst[realdrawpos] = m_rgb555_to_rgb888[rgb];
}
}
}
}
}
void spg2xx_video_device::draw_page(const rectangle &cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t *regs)
{
const uint32_t attr = regs[2];
const uint32_t ctrl = regs[3];
if (!(ctrl & 0x0008))
{
return;
}
if (((attr & 0x3000) >> 12) != priority)
{
return;
}
if (ctrl & 0x0001) // Bitmap / Linemap mode! (basically screen width tile mode)
{
draw_linemap(cliprect, dst, scanline, priority, tilegfxdata_addr, regs);
return;
}
const uint32_t xscroll = regs[0];
const uint32_t yscroll = regs[1];
const uint32_t tilemap_rambase = regs[4];
const uint32_t palettemap_rambase = regs[5];
const int tile_width = (attr & 0x0030) >> 4;
const uint32_t tile_h = 8 << ((attr & 0x00c0) >> 6);
const uint32_t tile_w = 8 << (tile_width);
const uint32_t tile_count_x = 512 / tile_w; // all tilemaps are 512 pixels wide
const uint32_t bitmap_y = (scanline + yscroll) & 0xff; // all tilemaps are 256 pixels high
const uint32_t y0 = bitmap_y / tile_h;
const uint32_t tile_scanline = bitmap_y % tile_h;
const uint8_t bpp = attr & 0x0003;
const uint32_t nc_bpp = ((bpp)+1) << 1;
const uint32_t bits_per_row = nc_bpp * tile_w / 16;
const uint32_t words_per_tile = bits_per_row * tile_h;
const bool row_scroll = (ctrl & 0x0010);
int realxscroll = xscroll;
if (row_scroll)
{
realxscroll += (int16_t)m_scrollram[scanline & 0xff];
}
for (uint32_t x0 = 0; x0 < (320+tile_w)/tile_w; x0++)
{
bool blend, flip_x, flip_y;
uint16_t tile;
uint32_t palette_offset;
if (!get_tile_info(tilemap_rambase, palettemap_rambase, (x0 + (realxscroll >> (tile_width+3))) & (tile_count_x-1) , y0, tile_count_x, ctrl, attr, tile, blend, flip_x, flip_y, palette_offset))
continue;
palette_offset >>= nc_bpp;
palette_offset <<= nc_bpp;
int drawx = (x0 * tile_w);
drawx = drawx - (realxscroll & (tile_w-1));
if (blend) if (blend)
{
if (row_scroll)
{ {
if (flip_x) if (flip_x)
draw<BlendOn, RowScrollOn, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, yscroll); {
draw_tilestrip<BlendOn, FlipXOn>(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, tile_scanline, drawx, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile);
}
else else
draw<BlendOn, RowScrollOn, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, yscroll); {
draw_tilestrip<BlendOn, FlipXOff>(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, tile_scanline, drawx, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile);
}
} }
else else
{ {
if (flip_x) if (flip_x)
draw<BlendOn, RowScrollOff, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, yscroll); {
else draw_tilestrip<BlendOff, FlipXOn>(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, tile_scanline, drawx, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile);
draw<BlendOn, RowScrollOff, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, yscroll);
}
} }
else else
{ {
if (row_scroll) draw_tilestrip<BlendOff, FlipXOff>(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, tile_scanline, drawx, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile);
{
if (flip_x)
draw<BlendOff, RowScrollOn, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, yscroll);
else
draw<BlendOff, RowScrollOn, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, yscroll);
}
else
{
if (flip_x)
draw<BlendOff, RowScrollOff, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, yscroll);
else
draw<BlendOff, RowScrollOff, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, yscroll);
} }
} }
} }
if (SPG_DEBUG_VIDEO && machine().input().code_pressed(KEYCODE_EQUALS))
m_debug_blit = false;
} }
void spg2xx_video_device::draw_sprite(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t base_addr) void spg2xx_video_device::draw_sprite(const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t base_addr)
{ {
uint32_t bitmap_addr = 0x40 * m_video_regs[0x22]; uint32_t tilegfxdata_addr = 0x40 * m_video_regs[0x22];
uint16_t tile = m_spriteram[base_addr + 0]; uint16_t tile = m_spriteram[base_addr + 0];
int16_t x = m_spriteram[base_addr + 1]; int16_t x = m_spriteram[base_addr + 1];
int16_t y = m_spriteram[base_addr + 2]; int16_t y = m_spriteram[base_addr + 2];
@ -421,110 +388,160 @@ void spg2xx_video_device::draw_sprite(const rectangle &cliprect, uint32_t scanli
return; return;
} }
if (((attr & PAGE_PRIORITY_FLAG_MASK) >> PAGE_PRIORITY_FLAG_SHIFT) != priority) if (((attr & 0x3000) >> 12) != priority)
{ {
return; return;
} }
const uint32_t h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT); const uint32_t tile_h = 8 << ((attr & 0x00c0) >> 6);
const uint32_t w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT); const uint32_t tile_w = 8 << ((attr & 0x0030) >> 4);
if (!(m_video_regs[0x42] & SPRITE_COORD_TL_MASK)) if (!(m_video_regs[0x42] & 0x0002))
{ {
x = (160 + x) - w / 2; x = (160 + x) - tile_w / 2;
y = (120 - y) - (h / 2) + 8; y = (120 - y) - (tile_h / 2) + 8;
} }
x &= 0x01ff; x &= 0x01ff;
y &= 0x01ff; y &= 0x01ff;
uint32_t tile_line = ((scanline - y) + 0x200) % h; int firstline = y;
int16_t test_y = (y + tile_line) & 0x1ff; int lastline = y + (tile_h - 1);
if (test_y >= 0x01c0) lastline &= 0x1ff;
test_y -= 0x0200;
if (test_y != scanline)
{
return;
}
bool blend = (attr & 0x4000); bool blend = (attr & 0x4000);
bool flip_x = (attr & TILE_X_FLIP); bool flip_x = (attr & 0x0004);
const uint8_t bpp = attr & 0x0003; const uint8_t bpp = attr & 0x0003;
const uint32_t yflipmask = attr & TILE_Y_FLIP ? h - 1 : 0; const uint32_t nc_bpp = ((bpp)+1) << 1;
const uint32_t bits_per_row = nc_bpp * tile_w / 16;
const uint32_t words_per_tile = bits_per_row * tile_h;
bool flip_y = (attr & 0x0008);
const uint32_t palette_offset = (attr & 0x0f00) >> 4; const uint32_t palette_offset = (attr & 0x0f00) >> 4;
#if SPG_DEBUG_VIDEO if (firstline < lastline)
if (m_debug_sprites && machine().input().code_pressed(KEYCODE_MINUS)) {
m_debug_blit = true; int scanx = scanline - firstline;
if ((scanx >= 0) && (scanline <= lastline))
{
if (blend) if (blend)
{ {
if (flip_x) if (flip_x)
draw<BlendOn, RowScrollOff, FlipXOn>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, 0); {
draw_tilestrip<BlendOn, FlipXOn>(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile);
}
else else
draw<BlendOn, RowScrollOff, FlipXOff>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, 0); {
draw_tilestrip<BlendOn, FlipXOff>(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile);
}
} }
else else
{ {
if (flip_x) if (flip_x)
draw<BlendOff, RowScrollOff, FlipXOn>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, 0); {
else draw_tilestrip<BlendOff, FlipXOn>(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile);
draw<BlendOff, RowScrollOff, FlipXOff>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, 0);
} }
m_debug_blit = false; else
#else {
draw_tilestrip<BlendOff, FlipXOff>(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile);
}
}
}
}
else
{
// clipped from top
int tempfirstline = firstline - 0x200;
int templastline = lastline;
int scanx = scanline - tempfirstline;
if ((scanx >= 0) && (scanline <= templastline))
{
if (blend) if (blend)
{ {
if (flip_x) if (flip_x)
draw<BlendOn, RowScrollOff, FlipXOn>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, 0); {
draw_tilestrip<BlendOn, FlipXOn>(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile);
}
else else
draw<BlendOn, RowScrollOff, FlipXOff>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, 0); {
draw_tilestrip<BlendOn, FlipXOff>(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile);
}
} }
else else
{ {
if (flip_x) if (flip_x)
draw<BlendOff, RowScrollOff, FlipXOn>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, 0); {
else draw_tilestrip<BlendOff, FlipXOn>(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile);
draw<BlendOff, RowScrollOff, FlipXOff>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, 0); }
else
{
draw_tilestrip<BlendOff, FlipXOff>(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile);
}
}
}
// clipped against the bottom
tempfirstline = firstline;
templastline = lastline + 0x200;
scanx = scanline - tempfirstline;
if ((scanx >= 0) && (scanline <= templastline))
{
if (blend)
{
if (flip_x)
{
draw_tilestrip<BlendOn, FlipXOn>(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile);
}
else
{
draw_tilestrip<BlendOn, FlipXOff>(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile);
}
}
else
{
if (flip_x)
{
draw_tilestrip<BlendOff, FlipXOn>(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile);
}
else
{
draw_tilestrip<BlendOff, FlipXOff>(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile);
}
}
}
} }
#endif
} }
void spg2xx_video_device::draw_sprites(const rectangle &cliprect, uint32_t scanline, int priority) void spg2xx_video_device::draw_sprites(const rectangle &cliprect, uint32_t* dst, uint32_t scanline, int priority)
{ {
if (!(m_video_regs[0x42] & SPRITE_ENABLE_MASK)) if (!(m_video_regs[0x42] & 0x0001))
{ {
return; return;
} }
#if SPG_DEBUG_VIDEO
if (!m_debug_sprites)
{
#endif
for (uint32_t n = 0; n < m_sprlimit_read_cb(); n++) for (uint32_t n = 0; n < m_sprlimit_read_cb(); n++)
{ {
draw_sprite(cliprect, scanline, priority, 4 * n); draw_sprite(cliprect, dst, scanline, priority, 4 * n);
} }
#if SPG_DEBUG_VIDEO
}
else
{
draw_sprite(cliprect, scanline, priority, 4 * m_sprite_index_to_debug);
}
#endif
} }
void spg2xx_video_device::apply_saturation(const rectangle &cliprect) void spg2xx_video_device::apply_saturation_and_fade(bitmap_rgb32& bitmap, const rectangle& cliprect, int scanline)
{ {
static const float s_u8_to_float = 1.0f / 255.0f; static const float s_u8_to_float = 1.0f / 255.0f;
static const float s_gray_r = 0.299f; static const float s_gray_r = 0.299f;
static const float s_gray_g = 0.587f; static const float s_gray_g = 0.587f;
static const float s_gray_b = 0.114f; static const float s_gray_b = 0.114f;
const float sat_adjust = (0xff - (m_video_regs[0x3c] & 0x00ff)) / (float)(0xff - 0x20); const float sat_adjust = (0xff - (m_video_regs[0x3c] & 0x00ff)) / (float)(0xff - 0x20);
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
{ const uint16_t fade_offset = m_video_regs[0x30];
uint32_t *src = &m_screenbuf[cliprect.min_x + 320 * y];
uint32_t* src = &bitmap.pix32(scanline, cliprect.min_x);
for (int x = cliprect.min_x; x <= cliprect.max_x; x++) for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
{
if ((m_video_regs[0x3c] & 0x00ff) != 0x0020) // apply saturation
{ {
const uint32_t src_rgb = *src; const uint32_t src_rgb = *src;
const float src_r = (uint8_t)(src_rgb >> 16) * s_u8_to_float; const float src_r = (uint8_t)(src_rgb >> 16) * s_u8_to_float;
@ -537,20 +554,13 @@ void spg2xx_video_device::apply_saturation(const rectangle &cliprect)
const int integer_r = (int)floor(adjusted_r * 255.0f); const int integer_r = (int)floor(adjusted_r * 255.0f);
const int integer_g = (int)floor(adjusted_g * 255.0f); const int integer_g = (int)floor(adjusted_g * 255.0f);
const int integer_b = (int)floor(adjusted_b * 255.0f); const int integer_b = (int)floor(adjusted_b * 255.0f);
*src++ = (integer_r > 255 ? 0xff0000 : (integer_r < 0 ? 0 : ((uint8_t)integer_r << 16))) | *src = (integer_r > 255 ? 0xff0000 : (integer_r < 0 ? 0 : ((uint8_t)integer_r << 16))) |
(integer_g > 255 ? 0x00ff00 : (integer_g < 0 ? 0 : ((uint8_t)integer_g << 8))) | (integer_g > 255 ? 0x00ff00 : (integer_g < 0 ? 0 : ((uint8_t)integer_g << 8))) |
(integer_b > 255 ? 0x0000ff : (integer_b < 0 ? 0 : (uint8_t)integer_b)); (integer_b > 255 ? 0x0000ff : (integer_b < 0 ? 0 : (uint8_t)integer_b));
}
}
} }
void spg2xx_video_device::apply_fade(const rectangle &cliprect) if (fade_offset != 0) // apply fade
{
const uint16_t fade_offset = m_video_regs[0x30];
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
{
uint32_t *src = &m_screenbuf[cliprect.min_x + 320 * y];
for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
{ {
const uint32_t src_rgb = *src; const uint32_t src_rgb = *src;
const uint8_t src_r = (src_rgb >> 16) & 0xff; const uint8_t src_r = (src_rgb >> 16) & 0xff;
@ -559,70 +569,61 @@ void spg2xx_video_device::apply_fade(const rectangle &cliprect)
const uint8_t r = src_r - fade_offset; const uint8_t r = src_r - fade_offset;
const uint8_t g = src_g - fade_offset; const uint8_t g = src_g - fade_offset;
const uint8_t b = src_b - fade_offset; const uint8_t b = src_b - fade_offset;
*src++ = (r > src_r ? 0 : (r << 16)) | *src = (r > src_r ? 0 : (r << 16)) |
(g > src_g ? 0 : (g << 8)) | (g > src_g ? 0 : (g << 8)) |
(b > src_b ? 0 : (b << 0)); (b > src_b ? 0 : (b << 0));
} }
src++;
} }
} }
uint32_t spg2xx_video_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) uint32_t spg2xx_video_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{ {
memset(&m_screenbuf[320 * cliprect.min_y], 0, 4 * 320 * ((cliprect.max_y - cliprect.min_y) + 1)); if (0)
{
uint16_t attr1 = m_video_regs[0x12];
uint16_t ctrl1 = m_video_regs[0x13];
uint16_t attr2 = m_video_regs[0x18];
uint16_t ctrl2 = m_video_regs[0x19];
// attr --zz pppp ssss FFbb
// ctrl ---- ---b hZzR ewrb
popmessage("Pg1 Attr = %04x (unused: %01x, Depth:%d, Palette:%d, VSize:%d, HSize:%d, FlipY:%d, FlipX:%d, BPP:%d)\n"
"Pg2 Attr = %04x (unused: %01x, Depth:%d, Palette:%d, VSize:%d, HSize:%d, FlipY:%d, FlipX:%d, BPP:%d)\n"
"Pg1 Ctrl = %04x (unused: %04x, Blend:%d, HiColor:%d, Ycmp:%d, Hcmp:%d, RowScroll:%d, Enable:%d, Wallpaper:%d, RegSet:%d, Bitmap:%d)\n"
"Pg2 Ctrl = %04x (unused: %04x, Blend:%d, HiColor:%d, Ycmp:%d, Hcmp:%d, RowScroll:%d, Enable:%d, Wallpaper:%d, RegSet:%d, Bitmap:%d)\n",
attr1, (attr1 & 0xc000) >> 14, (attr1 >> 12) & 3, (attr1 >> 8) & 15, 8 << ((attr1 >> 6) & 3), 8 << ((attr1 >> 4) & 3), BIT(attr1, 3), BIT(attr1, 2), 2 * ((attr1 & 3) + 1),
attr2, (attr2 & 0xc000) >> 14, (attr2 >> 12) & 3, (attr2 >> 8) & 15, 8 << ((attr2 >> 6) & 3), 8 << ((attr2 >> 4) & 3), BIT(attr2, 3), BIT(attr2, 2), 2 * ((attr2 & 3) + 1),
ctrl1, (ctrl1 & 0xfe00), BIT(ctrl1, 8), BIT(ctrl1, 7), BIT(ctrl1, 6), BIT(ctrl1, 5), BIT(ctrl1, 4), BIT(ctrl1, 3), BIT(ctrl1, 2), BIT(ctrl1, 1), BIT(ctrl1, 0),
ctrl2, (ctrl2 & 0xfe00), BIT(ctrl2, 8), BIT(ctrl2, 7), BIT(ctrl2, 6), BIT(ctrl2, 5), BIT(ctrl2, 4), BIT(ctrl2, 3), BIT(ctrl2, 2), BIT(ctrl2, 1), BIT(ctrl2, 0));
}
const uint32_t page1_addr = 0x40 * m_video_regs[0x20]; const uint32_t page1_addr = 0x40 * m_video_regs[0x20];
const uint32_t page2_addr = 0x40 * m_video_regs[0x21]; const uint32_t page2_addr = 0x40 * m_video_regs[0x21];
uint16_t *page1_regs = m_video_regs + 0x10; uint16_t *page1_regs = m_video_regs + 0x10;
uint16_t *page2_regs = m_video_regs + 0x16; uint16_t *page2_regs = m_video_regs + 0x16;
bitmap.fill(0, cliprect);
for (uint32_t scanline = (uint32_t)cliprect.min_y; scanline <= (uint32_t)cliprect.max_y; scanline++) for (uint32_t scanline = (uint32_t)cliprect.min_y; scanline <= (uint32_t)cliprect.max_y; scanline++)
{ {
uint32_t* dst = &bitmap.pix32(scanline, cliprect.min_x);
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
if (!SPG_DEBUG_VIDEO || !m_hide_page0) draw_page(cliprect, dst, scanline, i, page1_addr, page1_regs);
draw_page(cliprect, scanline, i, page1_addr, page1_regs); draw_page(cliprect, dst, scanline, i, page2_addr, page2_regs);
if (!SPG_DEBUG_VIDEO || !m_hide_page1) draw_sprites(cliprect, dst, scanline, i);
draw_page(cliprect, scanline, i, page2_addr, page2_regs);
if (!SPG_DEBUG_VIDEO || !m_hide_sprites)
draw_sprites(cliprect, scanline, i);
}
} }
if ((m_video_regs[0x3c] & 0x00ff) != 0x0020) apply_saturation_and_fade(bitmap, cliprect, scanline);
{
apply_saturation(cliprect);
}
if (m_video_regs[0x30] != 0)
{
apply_fade(cliprect);
}
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
{
uint32_t *dest = &bitmap.pix32(y, cliprect.min_x);
uint32_t *src = &m_screenbuf[cliprect.min_x + 320 * y];
memcpy(dest, src, sizeof(uint32_t) * ((cliprect.max_x - cliprect.min_x) + 1));
}
if (SPG_DEBUG_VIDEO && m_debug_palette)
{
for (int y = cliprect.min_y; y <= cliprect.max_y && y < 128; y++)
{
const uint16_t high_nybble = (y / 8) << 4;
uint32_t *dest = &bitmap.pix32(y, cliprect.min_x);
for (int x = cliprect.min_x; x <= cliprect.max_x && x < 256; x++)
{
const uint16_t low_nybble = x / 16;
const uint16_t palette_entry = high_nybble | low_nybble;
const uint16_t color = m_paletteram[palette_entry];
if (!(color & 0x8000))
{
*dest = m_rgb555_to_rgb888[color & 0x7fff];
}
dest++;
}
}
} }
return 0; return 0;
@ -655,6 +656,15 @@ READ16_MEMBER(spg2xx_video_device::video_r)
{ {
switch (offset) switch (offset)
{ {
case 0x10: // Page 1 X scroll
LOGMASKED(LOG_PPU_WRITES, "video_r: Page 1 X Scroll\n");
return m_video_regs[offset];
case 0x11: // Page 1 Y scroll
LOGMASKED(LOG_PPU_WRITES, "video_r: Page 1 Y Scroll\n");
return m_video_regs[offset];
case 0x38: // Current Line case 0x38: // Current Line
LOGMASKED(LOG_VLINES, "video_r: Current Line: %04x\n", m_screen->vpos()); LOGMASKED(LOG_VLINES, "video_r: Current Line: %04x\n", m_screen->vpos());
return m_screen->vpos(); return m_screen->vpos();
@ -697,16 +707,22 @@ WRITE16_MEMBER(spg2xx_video_device::video_w)
break; break;
case 0x12: // Page 1 Attributes case 0x12: // Page 1 Attributes
LOGMASKED(LOG_PPU_WRITES, "video_w: Page 1 Attributes = %04x (Depth:%d, Palette:%d, VSize:%d, HSize:%d, FlipY:%d, FlipX:%d, BPP:%d)\n", data {
, (data >> 12) & 3, (data >> 8) & 15, 8 << ((data >> 6) & 3), 8 << ((data >> 4) & 3), BIT(data, 3), BIT(data, 2), 2 * ((data & 3) + 1)); uint16_t attr1 = data;
LOGMASKED(LOG_PPU_WRITES, "video_w: Pg1 Attr = %04x (unused: %01x, Depth:%d, Palette:%d, VSize:%d, HSize:%d, FlipY:%d, FlipX:%d, BPP:%d)\n",
attr1, (attr1 & 0xc000) >> 14, (attr1 >> 12) & 3, (attr1 >> 8) & 15, 8 << ((attr1 >> 6) & 3), 8 << ((attr1 >> 4) & 3), BIT(attr1, 3), BIT(attr1, 2), 2 * ((attr1 & 3) + 1));
m_video_regs[offset] = data; m_video_regs[offset] = data;
break; break;
}
case 0x13: // Page 1 Control case 0x13: // Page 1 Control
LOGMASKED(LOG_PPU_WRITES, "video_w: Page 1 Control = %04x (Blend:%d, HiColor:%d, RowScroll:%d, Enable:%d, Wallpaper:%d, RegSet:%d, Bitmap:%d)\n", data {
, BIT(data, 8), BIT(data, 7), BIT(data, 4), BIT(data, 3), BIT(data, 2), BIT(data, 1), BIT(data, 0)); uint16_t ctrl1 = data;
LOGMASKED(LOG_PPU_WRITES, "video_w Pg1 Ctrl = %04x (unused: %04x, Blend:%d, HiColor:%d, Ycmp:%d, Hcmp:%d, RowScroll:%d, Enable:%d, Wallpaper:%d, RegSet:%d, Bitmap:%d)\n",
ctrl1, (ctrl1 & 0xfe00), BIT(ctrl1, 8), BIT(ctrl1, 7), BIT(ctrl1, 6), BIT(ctrl1, 5), BIT(ctrl1, 4), BIT(ctrl1, 3), BIT(ctrl1, 2), BIT(ctrl1, 1), BIT(ctrl1, 0));
m_video_regs[offset] = data; m_video_regs[offset] = data;
break; break;
}
case 0x14: // Page 1 Tile Address case 0x14: // Page 1 Tile Address
LOGMASKED(LOG_PPU_WRITES, "video_w: Page 1 Tile Address = %04x\n", data & 0x1fff); LOGMASKED(LOG_PPU_WRITES, "video_w: Page 1 Tile Address = %04x\n", data & 0x1fff);
@ -729,27 +745,51 @@ WRITE16_MEMBER(spg2xx_video_device::video_w)
break; break;
case 0x18: // Page 2 Attributes case 0x18: // Page 2 Attributes
LOGMASKED(LOG_PPU_WRITES, "video_w: Page 2 Attributes = %04x (Depth:%d, Palette:%d, VSize:%d, HSize:%d, FlipY:%d, FlipX:%d, BPP:%d)\n", data {
, (data >> 12) & 3, (data >> 8) & 15, 8 << ((data >> 6) & 3), 8 << ((data >> 4) & 3), BIT(data, 3), BIT(data, 2), 2 * ((data & 3) + 1)); uint16_t attr2 = data;
LOGMASKED(LOG_PPU_WRITES, "video_w: Pg2 Attr = %04x (unused: %01x, Depth:%d, Palette:%d, VSize:%d, HSize:%d, FlipY:%d, FlipX:%d, BPP:%d)\n",
attr2, (attr2 & 0xc000) >> 14, (attr2 >> 12) & 3, (attr2 >> 8) & 15, 8 << ((attr2 >> 6) & 3), 8 << ((attr2 >> 4) & 3), BIT(attr2, 3), BIT(attr2, 2), 2 * ((attr2 & 3) + 1));
m_video_regs[offset] = data; m_video_regs[offset] = data;
break; break;
}
case 0x19: // Page 2 Control case 0x19: // Page 2 Control
LOGMASKED(LOG_PPU_WRITES, "video_w: Page 2 Control = %04x (Blend:%d, HiColor:%d, RowScroll:%d, Enable:%d, Wallpaper:%d, RegSet:%d, Bitmap:%d)\n", data {
, BIT(data, 8), BIT(data, 7), BIT(data, 4), BIT(data, 3), BIT(data, 2), BIT(data, 1), BIT(data, 0)); uint16_t ctrl2 = data;
LOGMASKED(LOG_PPU_WRITES, "video_w: Pg2 Ctrl = %04x (unused: %04x, Blend:%d, HiColor:%d, Ycmp:%d, Hcmp:%d, RowScroll:%d, Enable:%d, Wallpaper:%d, RegSet:%d, Bitmap:%d)\n",
ctrl2, (ctrl2 & 0xfe00), BIT(ctrl2, 8), BIT(ctrl2, 7), BIT(ctrl2, 6), BIT(ctrl2, 5), BIT(ctrl2, 4), BIT(ctrl2, 3), BIT(ctrl2, 2), BIT(ctrl2, 1), BIT(ctrl2, 0));
m_video_regs[offset] = data; m_video_regs[offset] = data;
break; break;
}
case 0x1a: // Page 2 Tile Address case 0x1a: // Page 2 Tile Address
LOGMASKED(LOG_PPU_WRITES, "video_w: Page 2 Tile Address = %04x\n", data & 0x1fff); LOGMASKED(LOG_PPU_WRITES, "video_w: Page 2 Tile Address = %04x\n", data);
m_video_regs[offset] = data; m_video_regs[offset] = data;
break; break;
case 0x1b: // Page 2 Attribute Address case 0x1b: // Page 2 Attribute Address
LOGMASKED(LOG_PPU_WRITES, "video_w: Page 2 Attribute Address = %04x\n", data & 0x1fff); LOGMASKED(LOG_PPU_WRITES, "video_w: Page 2 Attribute Address = %04x\n", data);
m_video_regs[offset] = data; m_video_regs[offset] = data;
break; break;
case 0x1c: // vertical compression, amount, 0x20 = no scale? (not on spg288?)
LOGMASKED(LOG_PPU_WRITES, "video_w: Ycmp_Value = %04x\n", data);
m_video_regs[offset] = data;
update_vcmp_table();
break;
case 0x1d: // (not on spg288?)
LOGMASKED(LOG_PPU_WRITES, "video_w: Ycmp_Y_Offset = %04x\n", data);
m_video_regs[offset] = data;
update_vcmp_table();
break;
case 0x1e: // (not on spg288?)
LOGMASKED(LOG_PPU_WRITES, "video_w: Ycmp_Step = %04x\n", data);
m_video_regs[offset] = data;
update_vcmp_table();
break;
case 0x20: // Page 1 Segment Address case 0x20: // Page 1 Segment Address
LOGMASKED(LOG_PPU_WRITES, "video_w: Page 1 Segment Address = %04x\n", data); LOGMASKED(LOG_PPU_WRITES, "video_w: Page 1 Segment Address = %04x\n", data);
m_video_regs[offset] = data; m_video_regs[offset] = data;
@ -874,23 +914,6 @@ WRITE_LINE_MEMBER(spg2xx_video_device::vblank)
return; return;
} }
#if SPG_DEBUG_VIDEO
if (machine().input().code_pressed_once(KEYCODE_5))
m_hide_page0 = !m_hide_page0;
if (machine().input().code_pressed_once(KEYCODE_6))
m_hide_page1 = !m_hide_page1;
if (machine().input().code_pressed_once(KEYCODE_7))
m_hide_sprites = !m_hide_sprites;
if (machine().input().code_pressed_once(KEYCODE_8))
m_debug_sprites = !m_debug_sprites;
if (machine().input().code_pressed_once(KEYCODE_9))
m_sprite_index_to_debug--;
if (machine().input().code_pressed_once(KEYCODE_0))
m_sprite_index_to_debug++;
if (machine().input().code_pressed_once(KEYCODE_L))
m_debug_palette = !m_debug_palette;
#endif
if (VIDEO_IRQ_ENABLE & 1) if (VIDEO_IRQ_ENABLE & 1)
{ {
VIDEO_IRQ_STATUS |= 1; VIDEO_IRQ_STATUS |= 1;

View File

@ -38,25 +38,6 @@ protected:
devcb_read16 m_guny_in; devcb_read16 m_guny_in;
devcb_read16 m_gunx_in; devcb_read16 m_gunx_in;
enum
{
PAGE_ENABLE_MASK = 0x0008,
PAGE_WALLPAPER_MASK = 0x0004,
SPRITE_ENABLE_MASK = 0x0001,
SPRITE_COORD_TL_MASK = 0x0002,
PAGE_PRIORITY_FLAG_MASK = 0x3000,
PAGE_PRIORITY_FLAG_SHIFT = 12,
PAGE_TILE_HEIGHT_MASK = 0x00c0,
PAGE_TILE_HEIGHT_SHIFT = 6,
PAGE_TILE_WIDTH_MASK = 0x0030,
PAGE_TILE_WIDTH_SHIFT = 4,
TILE_X_FLIP = 0x0004,
TILE_Y_FLIP = 0x0008
};
inline void check_video_irq(); inline void check_video_irq();
static const device_timer_id TIMER_SCREENPOS = 2; static const device_timer_id TIMER_SCREENPOS = 2;
@ -67,47 +48,43 @@ protected:
void do_sprite_dma(uint32_t len); void do_sprite_dma(uint32_t len);
enum blend_enable_t : bool enum blend_enable_t : const bool
{ {
BlendOff = false, BlendOff = false,
BlendOn = true BlendOn = true
}; };
enum rowscroll_enable_t : bool enum rowscroll_enable_t : const bool
{ {
RowScrollOff = false, RowScrollOff = false,
RowScrollOn = true RowScrollOn = true
}; };
enum flipx_t : bool enum flipx_t : const bool
{ {
FlipXOff = false, FlipXOff = false,
FlipXOn = true FlipXOn = true
}; };
void apply_saturation(const rectangle &cliprect); void apply_saturation_and_fade(bitmap_rgb32& bitmap, const rectangle& cliprect, int scanline);
void apply_fade(const rectangle &cliprect);
template<blend_enable_t Blend, rowscroll_enable_t RowScroll, flipx_t FlipX> void draw_page(const rectangle &cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t *regs);
void draw(const rectangle &cliprect, uint32_t line, uint32_t xoff, uint32_t yoff, uint32_t bitmap_addr, uint16_t tile, int32_t h, int32_t w, uint8_t bpp, uint32_t yflipmask, uint32_t palette_offset, int yscroll); void draw_sprites(const rectangle &cliprect, uint32_t* dst, uint32_t scanline, int priority);
void draw_bitmap(const rectangle& cliprect, uint32_t scanline, int priority, uint32_t bitmap_addr, uint16_t* regs);
void draw_page(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t bitmap_addr, uint16_t *regs); inline void draw_sprite(const rectangle &cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t base_addr);
void draw_sprite(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t base_addr); inline void draw_linemap(const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t* regs);
void draw_sprites(const rectangle &cliprect, uint32_t scanline, int priority); inline bool get_tile_info(uint32_t tilemap_rambase, uint32_t palettemap_rambase, uint32_t x0, uint32_t y0, uint32_t tile_count_x, uint32_t ctrl, uint32_t attr, uint16_t& tile, bool& blend, bool& flip_x, bool& flip_y, uint32_t& palette_offset);
template<spg2xx_video_device::blend_enable_t Blend, spg2xx_video_device::flipx_t FlipX>
inline void draw_tilestrip(const rectangle& cliprect, uint32_t* dst, uint32_t tile_h, uint32_t tile_w, uint32_t tilegfxdata_addr, uint16_t tile, uint32_t tile_scanline, int drawx, bool flip_y, uint32_t palette_offset, const uint32_t nc_bpp, const uint32_t bits_per_row, const uint32_t words_per_tile);
uint8_t mix_channel(uint8_t a, uint8_t b); uint8_t mix_channel(uint8_t a, uint8_t b);
uint32_t m_screenbuf[320 * 240];
uint8_t m_rgb5_to_rgb8[32]; uint8_t m_rgb5_to_rgb8[32];
uint32_t m_rgb555_to_rgb888[0x8000]; uint32_t m_rgb555_to_rgb888[0x8000];
bool m_hide_page0; int m_ycmp_table[480];
bool m_hide_page1; void update_vcmp_table();
bool m_hide_sprites;
bool m_debug_sprites;
bool m_debug_blit;
bool m_debug_palette;
uint8_t m_sprite_index_to_debug;
uint16_t m_video_regs[0x100]; uint16_t m_video_regs[0x100];
@ -118,6 +95,7 @@ protected:
required_device<unsp_device> m_cpu; required_device<unsp_device> m_cpu;
required_device<screen_device> m_screen; required_device<screen_device> m_screen;
required_shared_ptr<uint16_t> m_scrollram; required_shared_ptr<uint16_t> m_scrollram;
required_shared_ptr<uint16_t> m_hcompram;
required_shared_ptr<uint16_t> m_paletteram; required_shared_ptr<uint16_t> m_paletteram;
required_shared_ptr<uint16_t> m_spriteram; required_shared_ptr<uint16_t> m_spriteram;

View File

@ -400,6 +400,13 @@ ROM_START( tkmag220 )
ROM_END ROM_END
ROM_START( myac220 )
//ROM_REGION16_BE( 0x40000, "maincpu:internal", ROMREGION_ERASE00 ) // not on this model? (or at least not this size, as CS base is different)
//ROM_LOAD16_WORD_SWAP( "internal.rom", 0x00000, 0x40000, NO_DUMP )
ROM_REGION( 0x8000000, "maincpu", ROMREGION_ERASE00 )
ROM_LOAD16_WORD_SWAP( "myarcadegogamerportable.bin", 0x0000000, 0x8000000, BAD_DUMP CRC(c929a2fa) SHA1(e99007ccc45a268267b4ea0efaf22e3117f5a6bd) ) // again several sections seemed to be erased, was repaired with data from tkmag220, likely good but should be verified
ROM_END
void tkmag220_game_state::tkmag220(machine_config &config) void tkmag220_game_state::tkmag220(machine_config &config)
{ {
@ -465,7 +472,9 @@ CONS(2009, smartfps, smartfp, 0, base, smartfp, gcm394_game_state, empty_init,
// The menu style is close to 'm505neo' but the game selection is closer to 'dnv200fs' (but without the Sports titles removed, and with a few other extras not found on that unit) // The menu style is close to 'm505neo' but the game selection is closer to 'dnv200fs' (but without the Sports titles removed, and with a few other extras not found on that unit)
// do "go A1595" then "r1 = 0" in debugger to show menu, controls not yet working (which might be why it drops to test mode by default) will need banking hookup later. // do "go A1595" then "r1 = 0" in debugger to show menu, controls not yet working (which might be why it drops to test mode by default) will need banking hookup later.
// This could be useful for figuring out how the sound registers have been remapped when compared to spg2xx // This could be useful for figuring out how the sound registers have been remapped when compared to spg2xx
CONS(200?, tkmag220, 0, 0, tkmag220, tkmag220, tkmag220_game_state, empty_init, "TaiKee", "Mini Arcade Games Console (Family Sport 220-in-1)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) CONS(201?, tkmag220, 0, 0, tkmag220, tkmag220, tkmag220_game_state, empty_init, "TaiKee", "Mini Arcade Games Console (Family Sport 220-in-1)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
// DGUN-2891 or DGUN-2864 ? both look the same, no indication on unboxed unit?
CONS(201?, myac220, 0, 0, tkmag220, tkmag220, tkmag220_game_state, empty_init, "dreamGEAR", "My Arcade Go Gamer Portable (Family Sport 220-in-1)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
// die on this one is 'GCM420' // die on this one is 'GCM420'
CONS(2013, gormiti, 0, 0, base, gormiti, gormiti_game_state, empty_init, "Giochi Preziosi", "Gormiti Game Arena (Spain)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) CONS(2013, gormiti, 0, 0, base, gormiti, gormiti_game_state, empty_init, "Giochi Preziosi", "Gormiti Game Arena (Spain)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)

View File

@ -156,10 +156,21 @@ void megadriv_radica_state::megadriv_radica_6button_pal(machine_config &config)
MCFG_MACHINE_RESET_OVERRIDE(megadriv_radica_state, megadriv_radica) MCFG_MACHINE_RESET_OVERRIDE(megadriv_radica_state, megadriv_radica)
} }
void megadriv_radica_state::megadriv_radica_6button_ntsc(machine_config &config)
{
md_ntsc(config);
m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state::megadriv_radica_map);
MCFG_MACHINE_START_OVERRIDE(megadriv_radica_state, megadriv_radica_6button)
MCFG_MACHINE_RESET_OVERRIDE(megadriv_radica_state, megadriv_radica)
}
ROM_START( rad_sf2 )
ROM_REGION( 0x400000, "maincpu", 0 )
ROM_LOAD16_WORD_SWAP( "genesis2player.bin", 0x000000, 0x400000, CRC(a4426df8) SHA1(091f2a95ebd091141de5bcb83562c6087708cb32) )
ROM_END
ROM_START( rad_sf ) ROM_START( rad_sf2p )
ROM_REGION( 0x400000, "maincpu", 0 ) ROM_REGION( 0x400000, "maincpu", 0 )
ROM_LOAD16_WORD_SWAP( "radicasf.bin", 0x000000, 0x400000, CRC(868afb44) SHA1(f4339e36272c18b1d49aa4095127ed18e0961df6) ) ROM_LOAD16_WORD_SWAP( "radicasf.bin", 0x000000, 0x400000, CRC(868afb44) SHA1(f4339e36272c18b1d49aa4095127ed18e0961df6) )
ROM_END ROM_END
@ -174,6 +185,14 @@ ROM_START( rad_ssoc )
ROM_LOAD( "sensiblesoccer.bin", 0x000000, 0x400000, CRC(b8745ab3) SHA1(0ab3f26e5ffd288e5a3a5db676951b9095299eb0) ) // should be byteswapped? ROM_LOAD( "sensiblesoccer.bin", 0x000000, 0x400000, CRC(b8745ab3) SHA1(0ab3f26e5ffd288e5a3a5db676951b9095299eb0) ) // should be byteswapped?
ROM_END ROM_END
ROM_START( rad_sonic )
ROM_REGION( 0x400000, "maincpu", 0 )
ROM_LOAD16_WORD_SWAP( "supersonicgold.bin", 0x000000, 0x400000, CRC(853c9140) SHA1(cf70a9cdd3be4d8d1b6195698db3a941f4908791) )
ROM_END
void megadriv_radica_state::init_megadriv_radica_6button_pal() void megadriv_radica_state::init_megadriv_radica_6button_pal()
{ {
init_megadrie(); init_megadrie();
@ -182,10 +201,20 @@ void megadriv_radica_state::init_megadriv_radica_6button_pal()
m_megadrive_io_write_data_port_ptr = write16_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); m_megadrive_io_write_data_port_ptr = write16_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button));
} }
// NTSC releases void megadriv_radica_state::init_megadriv_radica_6button_ntsc()
{
init_megadriv();
// 6 button game, so overwrite 3 button io handlers
m_megadrive_io_read_data_port_ptr = read8_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button));
m_megadrive_io_write_data_port_ptr = write16_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button));
}
CONS( 2004, rad_sonic, 0, 0, megadriv_radica_3button_ntsc, megadriv_radica_3button_1player, megadriv_radica_state, init_megadriv, "Radica / Sega", "Super Sonic Gold (Radica Plug & Play) (USA)", 0)
CONS( 2004, rad_gen1, 0, 0, megadriv_radica_3button_ntsc, megadriv_radica_3button_1player, megadriv_radica_state, init_megadriv, "Radica / Sega", "Genesis Collection Volume 1 (Radica, Arcade Legends) (USA)", 0) CONS( 2004, rad_gen1, 0, 0, megadriv_radica_3button_ntsc, megadriv_radica_3button_1player, megadriv_radica_state, init_megadriv, "Radica / Sega", "Genesis Collection Volume 1 (Radica, Arcade Legends) (USA)", 0)
// PAL releases CONS( 2004, rad_sf2, 0, 0, megadriv_radica_6button_ntsc, megadriv_radica_6button, megadriv_radica_state, init_megadriv_radica_6button_ntsc,"Radica / Capcom / Sega", "Street Fighter II: Special Champion Edition [Ghouls'n Ghosts] (Radica, Arcade Legends) (USA)", 0)
CONS( 2004, rad_sf, 0, 0, megadriv_radica_6button_pal, megadriv_radica_6button, megadriv_radica_state, init_megadriv_radica_6button_pal, "Radica / Capcom / Sega", "Street Fighter II: Special Champion Edition [Ghouls'n Ghosts] (Radica, Arcade Legends) (Europe)", 0) // SF2 game is region locked, US version ROM is definitely different CONS( 2004, rad_sf2p, rad_sf2,0, megadriv_radica_6button_pal, megadriv_radica_6button, megadriv_radica_state, init_megadriv_radica_6button_pal, "Radica / Capcom / Sega", "Street Fighter II: Special Champion Edition [Ghouls'n Ghosts] (Radica, Arcade Legends) (Europe)", 0)
CONS( 2004, rad_ssoc, 0, 0, megadriv_radica_3button_pal, megadriv_radica_3button, megadriv_radica_state, init_megadrie, "Radica / Sensible Software / Sega", "Sensible Soccer plus [Cannon Fodder, Mega lo Mania] (Radica, Arcade Legends) (Europe)", 0) // still branded as Arcade Legends even if none of these were ever arcade games CONS( 2004, rad_ssoc, 0, 0, megadriv_radica_3button_pal, megadriv_radica_3button, megadriv_radica_state, init_megadrie, "Radica / Sensible Software / Sega", "Sensible Soccer plus [Cannon Fodder, Mega lo Mania] (Radica, Arcade Legends) (Europe)", 0) // still branded as Arcade Legends even if none of these were ever arcade games

View File

@ -719,6 +719,134 @@ static INPUT_PORTS_START( fordrace )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
INPUT_PORTS_END INPUT_PORTS_END
static INPUT_PORTS_START( senspeed )
PORT_START("P1")
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT )
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT )
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_NAME("Accelerate / Select")
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_NAME("Reverse / Confirm")
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("A")
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("B")
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("C")
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("D")
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("E")
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("F")
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("G")
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_START1 ) PORT_NAME("Start / Pause")
PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x1000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x2000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x4000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x8000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_START("P2")
PORT_DIPNAME( 0x0001, 0x0001, "P2" )
PORT_DIPSETTING( 0x0001, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0002, 0x0002, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0002, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0004, 0x0004, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0004, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0008, 0x0008, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0008, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0010, 0x0010, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0010, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0020, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0040, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0080, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0100, 0x0100, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0100, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0200, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0400, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0800, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x1000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x2000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x4000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x8000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_START("P3")
PORT_DIPNAME( 0x0001, 0x0001, "P3" )
PORT_DIPSETTING( 0x0001, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0002, 0x0002, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0002, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0004, 0x0004, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0004, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0008, 0x0008, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0008, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0010, 0x0010, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0010, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0020, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0040, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0080, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0100, 0x0100, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0100, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0200, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0400, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0800, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x1000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x2000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x4000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x8000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
INPUT_PORTS_END
static INPUT_PORTS_START( ablkickb ) static INPUT_PORTS_START( ablkickb )
PORT_START("P1") PORT_START("P1")
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP )
@ -1674,6 +1802,11 @@ ROM_START( vtechtvsgr )
ROM_LOAD16_WORD_SWAP( "vtechtvstation_gr.bin", 0x000000, 0x800000, CRC(879f1b12) SHA1(c14d52bead2c190130ce88cbdd4f5e93145f13f9) ) ROM_LOAD16_WORD_SWAP( "vtechtvstation_gr.bin", 0x000000, 0x800000, CRC(879f1b12) SHA1(c14d52bead2c190130ce88cbdd4f5e93145f13f9) )
ROM_END ROM_END
ROM_START( senspeed )
ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 )
ROM_LOAD16_WORD_SWAP( "speedracer.bin", 0x000000, 0x800000, CRC(4efbcd39) SHA1(2edffbaa9ea309ad308fa60f32d8b7a98ee313c7) )
ROM_END
void spg2xx_game_state::init_crc() void spg2xx_game_state::init_crc()
{ {
// several games have a byte sum checksum listed at the start of ROM, this little helper function logs what it should match. // several games have a byte sum checksum listed at the start of ROM, this little helper function logs what it should match.
@ -1758,6 +1891,8 @@ CONS( 2009, gssytts, 0, 0, gssytts, guitarss, spg2xx_game_gssytts_s
CONS( 2006, vtechtvssp, 0, 0, abltenni, fordrace, spg2xx_game_state, empty_init, "VTech", "TV Station (VTech, Spain)", MACHINE_NOT_WORKING ) CONS( 2006, vtechtvssp, 0, 0, abltenni, fordrace, spg2xx_game_state, empty_init, "VTech", "TV Station (VTech, Spain)", MACHINE_NOT_WORKING )
CONS( 2006, vtechtvsgr, 0, 0, abltenni, fordrace, spg2xx_game_state, empty_init, "VTech", "TV Learning Station (VTech, Germany)", MACHINE_NOT_WORKING ) CONS( 2006, vtechtvsgr, 0, 0, abltenni, fordrace, spg2xx_game_state, empty_init, "VTech", "TV Learning Station (VTech, Germany)", MACHINE_NOT_WORKING )
CONS( 2008, senspeed, 0, 0, abltenni, senspeed, spg2xx_game_state, empty_init, "Senario", "Speed Racer (Senario)", MACHINE_NOT_WORKING )
CONS( 200?, jjstrip, 0, 0, tvsprt10, jjstrip, spg2xx_game_state, empty_init, "Shiggles Inc.", "Club Jenna Presents: Jenna Jameson's Strip Poker", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) CONS( 200?, jjstrip, 0, 0, tvsprt10, jjstrip, spg2xx_game_state, empty_init, "Shiggles Inc.", "Club Jenna Presents: Jenna Jameson's Strip Poker", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
CONS( 2005, tmntbftc, 0, 0, abltenni, tmntbftc, spg2xx_game_state, empty_init, "Tech2Go / WayForward", "Teenage Mutant Ninja Turtles: Battle for the City", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) CONS( 2005, tmntbftc, 0, 0, abltenni, tmntbftc, spg2xx_game_state, empty_init, "Tech2Go / WayForward", "Teenage Mutant Ninja Turtles: Battle for the City", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )

View File

@ -1,227 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
/*
(unSP 2.0 based System on a Chip)
JAKKS call this GPAC800, other sources (including Pac-Man Connect and Play test mode) call it GPL16250
die markings GCM394
- Smart Fit Park
- Spongebob Bikini Bottom 500
- Mobigo2 (sunplus_unsp20soc_mobigo.cpp)
some of the systems here might use newer dies but the video etc. appears the same.
Compared to vii.cpp this is clearly newer, has extra opcodes, different internal map etc. also scaling and higher resolutions based on Spongebob
note, these SoC types always have a 128Kwords internal ROM, which the JAKKS games appear to use for basic bootstrap purposes.
GPAC800 / GCM394 (SpongeBob Bikini Bottom 500 Test Mode also calls this GPAC800, even if the mappings appear different to the NAND version below - different CS base, maybe just depends on boot mode?)
Smart Fit Park
SpongeBob SquarePants Bikini Bottom 500
Spiderman - The Masked Menace 'Spider Sense' (pad type with Spiderman model)
(Wireless Hunting? - maybe, register map looks the same even if it sets stack to 2fff not 6fff)
GPAC800 (with NAND support)
Wireless Air 60
Golden Tee Golf
Cars 2
Toy Story Mania
V.Baby
Playskool Heroes Transformers Rescue Bots Beam Box
GPAC500 (based on test modes, unknown hardware, might be GPAC800 but without the higher resolution support?)
The Price is Right
Bejeweled? (might be GPAC800)
Notes
smartfp: hold button Circle, Star and Home on startup for Test Menu
these are all unsp 2.0 type, as they use the extended ocpodes
NAND types:
Toy Story Mania H27U518S2C dumped as HY27US08121A (512+16) x 32 x 4096
Beam Box GPR27P512A dumped as HY27US08121A (512+16) x 32 x 4096
Golden Tee GPR27P512A dumped as HY27US08121A (512+16) x 32 x 4096
Cars 2 GPR27P512A dumped as HY27US08121A (512+16) x 32 x 4096
V.Baby HY27UF081G2A (2048+64) x 64 x 1024
Non-emulation bugs (happen on real hardware):
paccon: Pac-Man - Bottom set of Power Pills are squashed.
Galaga - Incorrect sprite used for left shot in 'Double Ship' mode
JAKKS Pacific Test modes:
jak_hmhsm : uses the standard JAKKS code (on first screen - Hold Up, Hold A, Release Up, Down)
the High School Musical part has its own test mode which tests a different part of the ROM, use the same code but after selecting the game from menu
*/
#include "emu.h"
#include "includes/generalplus_gpl16250.h"
READ16_MEMBER(gcm394_game_state::cs0_r)
{
return m_romregion[offset & 0x3fffff];
}
WRITE16_MEMBER(gcm394_game_state::cs0_w)
{
logerror("cs0_w %04x %04x (to ROM!)\n", offset, data);
}
READ16_MEMBER(gcm394_game_state::cs1_r) { logerror("cs1_r %06n", offset); return 0x0000; }
WRITE16_MEMBER(gcm394_game_state::cs1_w) { logerror("cs1_w %06x %04x\n", offset, data); }
READ16_MEMBER(gcm394_game_state::cs2_r) { logerror("cs2_r %06n", offset); return 0x0000; }
WRITE16_MEMBER(gcm394_game_state::cs2_w) { logerror("cs2_w %06x %04x\n", offset, data); }
READ16_MEMBER(gcm394_game_state::cs3_r) { logerror("cs3_r %06n", offset); return 0x0000; }
WRITE16_MEMBER(gcm394_game_state::cs3_w) { logerror("cs3_w %06x %04x\n", offset, data); }
READ16_MEMBER(gcm394_game_state::cs4_r) { logerror("cs4_r %06n", offset); return 0x0000; }
WRITE16_MEMBER(gcm394_game_state::cs4_w) { logerror("cs4_w %06x %04x\n", offset, data); }
void gcm394_game_state::cs_map_base(address_map& map)
{
}
READ16_MEMBER(gcm394_game_state::read_external_space)
{
return m_memory->get_program()->read_word(offset);
}
WRITE16_MEMBER(gcm394_game_state::write_external_space)
{
m_memory->get_program()->write_word(offset, data);
}
READ16_MEMBER(gcm394_game_state::porta_r)
{
uint16_t data = m_io[0]->read();
logerror("Port A Read: %04x\n", data);
return data;
}
READ16_MEMBER(gcm394_game_state::portb_r)
{
uint16_t data = m_io[1]->read();
logerror("Port B Read: %04x\n", data);
return data;
}
READ16_MEMBER(gcm394_game_state::portc_r)
{
uint16_t data = m_io[2]->read();
logerror("Port C Read: %04x\n", data);
return data;
}
WRITE16_MEMBER(gcm394_game_state::porta_w)
{
logerror("%s: Port A:WRITE %04x\n", machine().describe_context(), data);
}
// some sources indicate these later SoC types run at 96Mhz, others indicate 48Mhz.
// unSP 2.0 CPUs have a lower average CPI too (2 instead of 6 on unSP 1.0 or 5 on unSP 1.1 / 1.2 / unSP 2.0) so using regular unSP timings might result in things being too slow
// as with the older SunPlus chips this appears to be an fully internally generated frequency, external XTALs again are typically 6MHz or simply not present.
void gcm394_game_state::base(machine_config &config)
{
GCM394(config, m_maincpu, 96000000/2, m_screen);
m_maincpu->porta_in().set(FUNC(gcm394_game_state::porta_r));
m_maincpu->portb_in().set(FUNC(gcm394_game_state::portb_r));
m_maincpu->portc_in().set(FUNC(gcm394_game_state::portc_r));
m_maincpu->porta_out().set(FUNC(gcm394_game_state::porta_w));
m_maincpu->space_read_callback().set(FUNC(gcm394_game_state::read_external_space));
m_maincpu->space_write_callback().set(FUNC(gcm394_game_state::write_external_space));
m_maincpu->set_irq_acknowledge_callback(m_maincpu, FUNC(sunplus_gcm394_base_device::irq_vector_cb));
m_maincpu->add_route(ALL_OUTPUTS, "lspeaker", 0.5);
m_maincpu->add_route(ALL_OUTPUTS, "rspeaker", 0.5);
m_maincpu->set_bootmode(1); // boot from external ROM / CS mirror
m_maincpu->set_cs_config_callback(FUNC(gcm394_game_state::cs_callback));
FULL_MEMORY(config, m_memory).set_map(&gcm394_game_state::cs_map_base);
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_refresh_hz(60);
m_screen->set_size(320*2, 262*2);
m_screen->set_visarea(0, (320*2)-1, 0, (240*2)-1);
m_screen->set_screen_update("maincpu", FUNC(sunplus_gcm394_device::screen_update));
m_screen->screen_vblank().set(m_maincpu, FUNC(sunplus_gcm394_device::vblank));
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
}
void tkmag220_game_state::tkmag220(machine_config &config)
{
gcm394_game_state::base(config);
m_maincpu->porta_in().set_ioport("IN0");
m_maincpu->portb_in().set_ioport("IN1");
m_maincpu->portc_in().set_ioport("IN2");
}
void gcm394_game_state::machine_start()
{
}
void gcm394_game_state::machine_reset()
{
cs_callback(0x00, 0x00, 0x00, 0x00, 0x00);
m_maincpu->set_cs_space(m_memory->get_program());
m_maincpu->reset(); // reset CPU so vector gets read etc.
m_maincpu->set_paldisplaybank_high_hack(1);
m_maincpu->set_alt_tile_addressing_hack(0);
}
void gcm394_game_state::cs_callback(uint16_t cs0, uint16_t cs1, uint16_t cs2, uint16_t cs3, uint16_t cs4)
{
// wipe existing mappings;
m_memory->get_program()->unmap_readwrite(0, (0x8000000*5)-1);
m_memory->get_program()->nop_readwrite(0, (0x8000000*5)-1); // stop logging spam if video params are invalid
int start_address = 0;
int end_address;
int size; // cs region sizes in kwords
size = (((cs0 & 0xff00) >> 8) + 1) * 0x10000;
end_address = start_address + (size - 1);
logerror("installing cs0 handler start_address %08x end_address %08x\n", start_address, end_address);
m_memory->get_program()->install_readwrite_handler( start_address, end_address, read16_delegate(*this, FUNC(gcm394_game_state::cs0_r)), write16_delegate(*this, FUNC(gcm394_game_state::cs0_w)));
start_address += size;
size = (((cs1 & 0xff00) >> 8) + 1) * 0x10000;
end_address = start_address + (size - 1);
logerror("installing cs1 handler start_address %08x end_address %08x\n", start_address, end_address);
m_memory->get_program()->install_readwrite_handler( start_address, end_address, read16_delegate(*this, FUNC(gcm394_game_state::cs1_r)), write16_delegate(*this, FUNC(gcm394_game_state::cs1_w)));
start_address += size;
size = (((cs2 & 0xff00) >> 8) + 1) * 0x10000;
end_address = start_address + (size - 1);
logerror("installing cs2 handler start_address %08x end_address %08x\n", start_address, end_address);
m_memory->get_program()->install_readwrite_handler( start_address, end_address, read16_delegate(*this, FUNC(gcm394_game_state::cs2_r)), write16_delegate(*this, FUNC(gcm394_game_state::cs2_w)));
start_address += size;
size = (((cs3 & 0xff00) >> 8) + 1) * 0x10000;
end_address = start_address + (size - 1);
logerror("installing cs3 handler start_address %08x end_address %08x\n", start_address, end_address);
m_memory->get_program()->install_readwrite_handler( start_address, end_address, read16_delegate(*this, FUNC(gcm394_game_state::cs3_r)), write16_delegate(*this, FUNC(gcm394_game_state::cs3_w)));
start_address += size;
size = (((cs4 & 0xff00) >> 8) + 1) * 0x10000;
end_address = start_address + (size - 1);
logerror("installing cs4 handler start_address %08x end_address %08x\n", start_address, end_address);
m_memory->get_program()->install_readwrite_handler( start_address, end_address, read16_delegate(*this, FUNC(gcm394_game_state::cs4_r)), write16_delegate(*this, FUNC(gcm394_game_state::cs4_w)));
//start_address += size;
}

View File

@ -14,6 +14,7 @@ public:
{} {}
void init_megadriv_radica_6button_pal(); void init_megadriv_radica_6button_pal();
void init_megadriv_radica_6button_ntsc();
DECLARE_MACHINE_START(megadriv_radica_6button); DECLARE_MACHINE_START(megadriv_radica_6button);
DECLARE_MACHINE_START(megadriv_radica_3button); DECLARE_MACHINE_START(megadriv_radica_3button);
@ -22,6 +23,7 @@ public:
DECLARE_READ16_MEMBER(read); DECLARE_READ16_MEMBER(read);
DECLARE_READ16_MEMBER(read_a13); DECLARE_READ16_MEMBER(read_a13);
void megadriv_radica_6button_ntsc(machine_config &config);
void megadriv_radica_6button_pal(machine_config &config); void megadriv_radica_6button_pal(machine_config &config);
void megadriv_radica_3button_ntsc(machine_config &config); void megadriv_radica_3button_ntsc(machine_config &config);
void megadriv_radica_3button_pal(machine_config &config); void megadriv_radica_3button_pal(machine_config &config);

View File

@ -14734,6 +14734,7 @@ smartfp // Smart Fit Park
smartfps smartfps
gormiti gormiti
tkmag220 // tkmag220 //
myac220
@source:generalplus_gpl16250_romram.cpp @source:generalplus_gpl16250_romram.cpp
paccon paccon
@ -22033,9 +22034,11 @@ topshoot // (c) 1995 Sun Mixing
twinktmb // MegaDrive-based hack twinktmb // MegaDrive-based hack
@source:megadriv_rad.cpp @source:megadriv_rad.cpp
rad_sf // (c)2004 Radica rad_sf2 // (c)2004 Radica
rad_sf2p // (c)2004 Radica
rad_gen1 // (c)2004 Radica rad_gen1 // (c)2004 Radica
rad_ssoc // (c)2004 Radica rad_ssoc // (c)2004 Radica
rad_sonic
@source:megaphx.cpp @source:megaphx.cpp
megaphx // (c) 1991 Dinamic / Inder megaphx // (c) 1991 Dinamic / Inder
@ -37479,6 +37482,7 @@ tmntmutm
pballpup pballpup
swclone swclone
dreamlss dreamlss
senspeed
@source:spg2xx_digimake.cpp @source:spg2xx_digimake.cpp
rad_digi rad_digi