From 370807115062124fd7304101665eb2d51a56f32f Mon Sep 17 00:00:00 2001 From: David Haywood <28625134+DavidHaywood@users.noreply.github.com> Date: Thu, 4 Jun 2020 21:09:03 +0100 Subject: SunPlus refactoring checkpoint (nw) (#6793) --- src/devices/machine/generalplus_gpl16250soc.cpp | 4 +- .../machine/generalplus_gpl16250soc_video.cpp | 738 ++------------------- .../machine/generalplus_gpl16250soc_video.h | 38 +- src/devices/machine/spg2xx_video.cpp | 11 +- src/devices/machine/spg_renderer.cpp | 519 +++++++++++---- src/devices/machine/spg_renderer.h | 35 +- 6 files changed, 475 insertions(+), 870 deletions(-) diff --git a/src/devices/machine/generalplus_gpl16250soc.cpp b/src/devices/machine/generalplus_gpl16250soc.cpp index dc16e9985f7..29c7f7a2585 100644 --- a/src/devices/machine/generalplus_gpl16250soc.cpp +++ b/src/devices/machine/generalplus_gpl16250soc.cpp @@ -1538,6 +1538,9 @@ void sunplus_gcm394_base_device::device_reset() m_system_dma_memtype = 0x0000; m_unk_timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60)); + + m_spg_video->set_video_spaces(this->space(AS_PROGRAM), *m_cs_space, m_csbase); + m_spg_video->reset(); } void generalplus_gpac800_device::device_reset() @@ -1649,7 +1652,6 @@ uint16_t sunplus_gcm394_base_device::read_space(uint32_t offset) - void sunplus_gcm394_base_device::write_space(uint32_t offset, uint16_t data) { address_space& space = this->space(AS_PROGRAM); diff --git a/src/devices/machine/generalplus_gpl16250soc_video.cpp b/src/devices/machine/generalplus_gpl16250soc_video.cpp index a45961389cf..3967898d637 100644 --- a/src/devices/machine/generalplus_gpl16250soc_video.cpp +++ b/src/devices/machine/generalplus_gpl16250soc_video.cpp @@ -8,97 +8,6 @@ **********************************************************************/ -/* lots of games, including wrlshunt are not copying tilemap data properly - the analysis below is for wrlshunt, although gormiti could prove to be an easier case to look at - while jak_ths and jak_swc might be more difficult (the latter uses line/bitmap mode, but still - fails to copy the line data) - - - -- - - wrlshunt BG Tilemap location note - - background tilemap appears to be at 24ad30 - 24af87 (byte address) in RAM == 125698 - 1257c3 (word address) - there are pointers to this - (2879-287a) = 98 56 12 00 (00125698) (main background tilemap data is at this address) - (287b-287c) = 30 5e 12 00 (00125e30) (address for other layer tilemap) (or 'end' of above) - where do we get these copied to registers or used as a source to copy from? - - - -- callled from here - 058F79: call 054e56 (with values above, for tilemap 0) - and - 058FB1: call 054e56 (for tilemap 1) - (both of these are at the start of the function at 058F46, which we loop in at the moment, possible main loop for the menu?) - - there are other calls in the code, but those are the ones before sprites are uploaded for the menu - - -- - 054E91: r4 = [bp+27] (contains lower part of address) - 054E92: ds:[r1++] = r4 -- write 5698 to 2879 - 054E93: r4 = [bp+28] (contains upper part of address) - 054E94: ds:[r1] = r4 -- write 0012 to 287a - - (this is a huge function that ends at 55968, also has lots of calls in it) - - --- - - the base for tilemap params being written to RAM is 2879 + 0xe * tilmap number (0,1,2,3) - the code to calculate this offset from base uses 32-bit multiplication and even sign extends the tilemap number before using it, making it - look more complex than it really is! - - 054E7B: 0B0D 0088 bp = bp + 0088 - 054E7D: 9800 r4 = [bp+00] -- which tilemap? (0,1,2,3) - 054E7E: 2B0D 0088 bp = bp - 0088 - - 054E80: 973C r3 = r4 asr 4 -- sign extend tilemap 16-bit register r4 with r3 forming the upper word (always 0) - 054E81: 973B r3 = r3 asr 4 - 054E82: 973B r3 = r3 asr 4 - 054E83: 973B r3 = r3 asr 4 - - 054E84: D688 push r3, r3 to [sp] -- push onto stack for use in call below - 054E85: D888 push r4, r4 to [sp] - - 054E86: 964E r3 = 0e -- store 0000 000e as the 32-bit value to multply with - 054E87: 9840 r4 = 00 - 054E88: D890 push r3, r4 to [sp] -- push that onto stack for function call below - - 054E89: F045 D706 call 05d706 -- returns result in r1,r2 - - the result of this is then added to the base value of 2879 (which was stored earlier) - an additional offset is then added for each parameter. - - this code is repeated multiple times, with slight changes - - --- - - by the time you hit 055098 (which is a switch on tilemap type to disable a tilemap) the following params have been put at - 2879 ( tilemap 0 call ) - 2879 + 0x0e (tilemap 1 call ) - - tmap0 params - 5698 0012 | 5E30 0012 | 0280 01E0 | 0002 0020 0020 0000 0000 0100 0000 0000 - 125698 | 125e30 | = 640 = 480 - - tmap1 params - 7280 000D | 89F0 000D | 0280 01E0 | 0002 0020 0020 0002 0000 0040 0000 0000 - 0d7280 | 0d89f0 | = 640 = 480 | - - these parameter lists are not read after this? is there some kind of indirect dma mode, or is code not being called that should use them. - plenty more code is called, including more that looks a lot like the above, some use of 707f and at the end of the funciton, code to - write various tilemap registers, including reenabling the tilemap that was disabled around 055098. - - -- - - - if you return rand() on 707f reads sometimes you see - [:maincpu] pc:053775: r4 = r4 lsr r3 (5698 0009) : [:maincpu] result 002b (possible unrelated) - - (bg tile addressing is also done by tile #, like the sprites, not fixed step like smartfp) - - -*/ - #include "emu.h" #include "generalplus_gpl16250soc_video.h" @@ -118,20 +27,15 @@ DEFINE_DEVICE_TYPE(GCM394_VIDEO, gcm394_video_device, "gcm394_video", "GeneralPl gcm394_base_video_device::gcm394_base_video_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock), - //device_gfx_interface(mconfig, *this, nullptr), device_video_interface(mconfig, *this), m_cpu(*this, finder_base::DUMMY_TAG), m_screen(*this, finder_base::DUMMY_TAG), -// m_scrollram(*this, "scrollram"), m_video_irq_cb(*this), m_palette(*this, "palette"), m_gfxdecode(*this, "gfxdecode"), m_space_read_cb(*this), m_rowscroll(*this, "^rowscroll"), m_rowzoom(*this, "^rowzoom"), -// m_pal_displaybank_high(0), -// m_pal_sprites(0x100), -// m_pal_back(0x000), m_alt_extrasprite_hack(0), m_alt_tile_addressing(0), m_renderer(*this, "renderer") @@ -295,17 +199,6 @@ void gcm394_base_video_device::decodegfx(const char* tag) void gcm394_base_video_device::device_start() { - for (uint8_t i = 0; i < 32; i++) - { - m_rgb5_to_rgb8[i] = (i << 3) | (i >> 2); - } - for (uint16_t i = 0; i < 0x8000; i++) - { - m_rgb555_to_rgb888[i] = (m_rgb5_to_rgb8[(i >> 10) & 0x1f] << 16) | - (m_rgb5_to_rgb8[(i >> 5) & 0x1f] << 8) | - (m_rgb5_to_rgb8[(i >> 0) & 0x1f] << 0); - } - m_video_irq_cb.resolve(); m_maxgfxelement = 0; @@ -319,10 +212,6 @@ void gcm394_base_video_device::device_start() m_screenpos_timer = timer_alloc(TIMER_SCREENPOS); m_screenpos_timer->adjust(attotime::never); - - save_item(NAME(m_screenbuf)); - save_item(NAME(m_rgb5_to_rgb8)); - save_item(NAME(m_rgb555_to_rgb888)); save_item(NAME(m_page0_addr_lsb)); save_item(NAME(m_page0_addr_msb)); save_item(NAME(m_page1_addr_lsb)); @@ -365,10 +254,8 @@ void gcm394_base_video_device::device_start() save_item(NAME(m_page3_addr_lsb)); save_item(NAME(m_page3_addr_msb)); save_item(NAME(m_spriteram)); - save_item(NAME(m_spriteextra)); save_item(NAME(m_paletteram)); save_item(NAME(m_maxgfxelement)); -// save_item(NAME(m_pal_displaybank_high)); save_item(NAME(m_alt_tile_addressing)); } @@ -390,16 +277,14 @@ void gcm394_base_video_device::device_reset() m_tmap1_scroll[i] = 0x0000; } - for (int i = 0; i < 0x400; i++) + for (int i = 0; i < 0x400*2; i++) { - m_spriteextra[i] = 0x0000; m_spriteram[i] = 0x0000; } for (int i=0;i<0x100 * 0x10;i++) m_paletteram[i] = machine().rand()&0x7fff; - m_707f = 0x0000; m_703a_palettebank = 0x0000; m_video_irq_enable = 0x0000; @@ -435,546 +320,7 @@ void gcm394_base_video_device::device_reset() m_page3_addr_lsb = 0; m_page3_addr_msb = 0; -} - -/************************* -* Video Hardware * -*************************/ - -template -void gcm394_base_video_device::draw(const rectangle &cliprect, uint32_t line, uint32_t xoff, uint32_t yoff, uint32_t bitmap_addr, uint32_t tile, int32_t h, int32_t w, uint8_t bpp, uint32_t yflipmask, uint32_t palette_offset, int addressing_mode) -{ - uint32_t nc_bpp = ((bpp) + 1) << 1; - - // probably don't do this here as this SoC has extended palette for higher bpp modes - //palette_offset >>= nc_bpp; - //palette_offset <<= nc_bpp; - - uint32_t bits_per_row = nc_bpp * w / 16; - uint32_t words_per_tile; - - if (addressing_mode == 1) - { - words_per_tile = bits_per_row * h; - } - else - { - words_per_tile = 8; // seems to be correct for sprites regardless of size / bpp on smartfp - } - - int x_max; - if (m_707f & 0x0010) - { - x_max = 0x400; - } - else - { - x_max = 0x200; - } - - - 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 > cliprect.max_y || yy < 0) - return; - - int y_index = yy * m_screen->width(); - - for (int32_t x = FlipX ? (w - 1) : 0; FlipX ? x >= 0 : x < w; FlipX ? x-- : x++) - { - int xx = xoff + x; - - bits <<= nc_bpp; - - if (nbits < nc_bpp) - { - uint16_t b = m_space_read_cb((m++)&0x7ffffff); // smartfp suggests either 0x7ffffff mask, or some bits are being set incorrectly, jak_s500 needs over 0x3ffffff at least - b = (b << 8) | (b >> 8); - bits |= b << (nc_bpp - nbits); - nbits += 16; - } - nbits -= nc_bpp; - - int pen = bits >> 16; - - int current_palette_offset = palette_offset; - - uint32_t pal = current_palette_offset + pen; - bits &= 0xffff; - - if (RowScroll) - xx -= 0;// (int16_t)m_scrollram[yy & 0x1ff]; - - xx &= (x_max-1); - if (xx >= (x_max-0x40)) - xx -= x_max; - - if (xx >= 0 && xx <= cliprect.max_x) - { - int pix_index = xx + y_index; - - uint16_t rgb = m_paletteram[pal]; - - if (!(rgb & 0x8000)) - { - if (Blend) - { - /* - 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])); - */ - m_screenbuf[pix_index] = m_rgb555_to_rgb888[rgb]; - } - else - { - m_screenbuf[pix_index] = m_rgb555_to_rgb888[rgb]; - } - } - } - } -} - -void gcm394_base_video_device::draw_page(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t bitmap_addr, uint16_t *regs, uint16_t *scroll, int which) -{ - uint32_t xscroll = scroll[0]; - uint32_t yscroll = scroll[1]; - uint32_t attr_reg = regs[0]; - uint32_t ctrl_reg = regs[1]; - uint32_t tilemap = regs[2]; - uint32_t palette_map = regs[3]; - address_space &space = m_cpu->space(AS_PROGRAM); - - // attr_reg bits - // -Bzz pppp hhww ffbb - // - // B = blend - // zz = depth - // pppp = palette - // ff = flips - // bb = bpp - // hh = height - // ww = width - - // ctrl_reg bits - // ---- ---B h--r ewRl - // - // e = enable - // l = bitmape/line mode - // r = rowscroll - // w = wallpaper mode - // R = regset mode - // h = high colour - // B = blend - - - if (!(ctrl_reg & 0x0008)) - { - return; - } - - if (((attr_reg & 0x3000) >> 12) != priority) - { - return; - } - - if (ctrl_reg & 0x0001) // bitmap mode jak_car2 and jak_s500 use for the ingame race sections, also have a bitmap test in test mode - { - if (0) - { - if (ctrl_reg & 0x0010) - popmessage("bitmap mode %08x with rowscroll\n", bitmap_addr); - else - popmessage("bitmap mode %08x\n", bitmap_addr); - } - - // note, in interlace modes it appears every other line is unused? (480 entry table, but with blank values) - // and furthermore the rowscroll and rowzoom tables only have 240 entries, not enough for every line - // the end of the rowscroll table (entries 240-255) contain something else, maybe garbage data as it's offscreen, maybe not - - uint32_t linebase = space.read_word(tilemap + scanline); // every other word is unused, but there are only enough entries for 240 lines then, sometimes to do with interlace mode? - uint16_t palette = space.read_word(palette_map + (scanline / 2)); - - if (scanline & 1) - palette >>= 8; - else - palette &= 0xff; - - if (!linebase) - return; - - linebase = linebase | (palette << 16); - - // this logic works for jak_s500 and the test modes to get the correct base, doesn't seem to work for jak_car2 ingame, maybe data is copied to wrong place? - int gfxbase = (bitmap_addr&0x7ffffff) + (linebase&0x7ffffff); - - for (int i = 0; i < 160; i++) // will have to be 320 for jak_car2 ingame, jak_s500 lines are wider than screen, and zoomed - { - uint16_t pix = m_space_read_cb((gfxbase++)&0x7ffffff); - int xx; - int y_index = scanline * m_screen->width(); - uint16_t pal; - - if ((scanline >= 0) && (scanline < 480)) - { - xx = i * 2; - - pal = (pix & 0xff) | 0x100; - - if (xx >= 0 && xx <= cliprect.max_x) - { - int pix_index = xx + y_index; - - uint16_t rgb = m_paletteram[pal]; - - if (!(rgb & 0x8000)) - { - m_screenbuf[pix_index] = m_rgb555_to_rgb888[rgb]; - } - } - - xx = (i * 2)+1; - pal = (pix >> 8) + 0x100; - - if (xx >= 0 && xx <= cliprect.max_x) - { - int pix_index = xx + y_index; - - uint16_t rgb = m_paletteram[pal]; - - if (!(rgb & 0x8000)) - { - m_screenbuf[pix_index] = m_rgb555_to_rgb888[rgb]; - } - } - } - } - } - else - { - uint32_t tile_h = 8 << ((attr_reg & 0x00c0) >> 6); - uint32_t tile_w = 8 << ((attr_reg & 0x0030) >> 4); - - int total_width; - int use_alt_drawmode = m_alt_tile_addressing; - int y_mask = 0; - - // just a guess based on this being set on the higher resolution tilemaps we've seen, could be 100% incorrect register - if ((attr_reg >> 15) & 0x1) - { - total_width = 1024; - y_mask = 0x1ff; - // use_alt_drawmode = 1; // probably doesn't control this - } - else - { - total_width = 512; - y_mask = 0xff; - // use_alt_drawmode = 0; // probably doesn't control this - } - - uint32_t tile_count_x = total_width / tile_w; - - uint32_t bitmap_y = (scanline + yscroll) & y_mask; - uint32_t y0 = bitmap_y / tile_h; - uint32_t tile_scanline = bitmap_y % tile_h; - uint32_t tile_address = tile_count_x * y0; - - for (uint32_t x0 = 0; x0 < tile_count_x; x0++, tile_address++) - { - uint32_t yy = ((tile_h * y0 - yscroll + 0x10) & y_mask) - 0x10; - uint32_t xx = (tile_w * x0 - xscroll) & (total_width-1); - uint32_t tile = (ctrl_reg & 0x0004) ? space.read_word(tilemap) : space.read_word(tilemap + tile_address); - - if (!tile) - continue; - - bool blend; - bool row_scroll; - bool flip_x; - uint32_t yflipmask; - uint32_t palette_offset; - - blend = (attr_reg & 0x4000 || ctrl_reg & 0x0100); - row_scroll = (ctrl_reg & 0x0010); - - if ((ctrl_reg & 0x0002) == 0) // RegSet:0 - { - uint16_t palette = (ctrl_reg & 0x0004) ? space.read_word(palette_map) : space.read_word(palette_map + tile_address / 2); - if (x0 & 1) - palette >>= 8; - - // 'palette' format - // --ff pppp - // - // f = flip bits - // p = palette - - flip_x = palette & 0x10; - yflipmask = (palette & 0x20) ? tile_h - 1 : 0; - palette_offset = (palette & 0x0f) << 4; - } - else // RegSet:1 - { - if (m_alt_tile_addressing == 0) - { - // smartfp needs the attribute table to contain extra tile bits even if regset is 1 - uint16_t palette = (ctrl_reg & 0x0004) ? space.read_word(palette_map) : space.read_word(palette_map + tile_address / 2); - if (x0 & 1) - palette >>= 8; - - // 'palette' format - // -- -ttt - // - // t = extra tile number bits - - tile |= (palette & 0x0007) << 16; - } - - flip_x = (attr_reg & 0x0004); - yflipmask = attr_reg & 0x0008 ? tile_h - 1 : 0; - palette_offset = (attr_reg & 0x0f00) >> 4; - } - - const uint8_t bpp = attr_reg & 0x0003; - - // HACKS - // There must be a select bit for the tilemap palettes somewhere, but where?! - - // the different games in paccon also expect a variety of different configs here, maybe a good place to look - - if (m_703a_palettebank & 1) // this actually seems to be the sprite palette bank enable, but for tkmag220 it gives us an easy way to ignore the logic below - { - if (which == 0) // tilemap 0 - { - if (ctrl_reg & 0x0002) // RegSet:1 - { - // smartfp has a conflict between the bootlogos and the first screen, it's in regset mode, no obvious difference in registers but needs palette from different places? - // not even m_707f changes here, which makes the m_707f case specific hacks for jak_s500 below very unlikely to actually be related - if ((bpp + 1) * 2 == 4) - if (m_alt_tile_addressing == 0) - palette_offset |= 0x200; - } - } - - if (which == 1) - { - // can't do this for jak_s500 logos - // jak_s500 also uses this tilemap in both 4 and 6bpp modes expecting the same palette base, so the hack used for smartfp on tilemap 0 is not applicable here - - // m_707f != 0x2d3 for jak_S500 main menu - if ((m_707f != 0x53) && (m_707f != 0x63) && (m_707f != 0x2d3)) - palette_offset |= 0x200; - } - - // jak_car2 screen transitions use layers 2 and 3 the same way, alternating each frame - if (which == 2) - { - // jak_s500 title screen + loading screen before race - if ((m_707f == 0x2d3) || (m_707f == 0x2db)) - palette_offset |= 0x200; - } - - } - //palette_offset |= m_pal_back; - - if (blend) - { - if (row_scroll) - { - if (flip_x) - draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); - else - draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); - } - else - { - if (flip_x) - draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); - else - draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); - } - } - else - { - if (row_scroll) - { - if (flip_x) - draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); - else - draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); - } - else - { - if (flip_x) - draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); - else - draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); - } - } - } - } -} - - -void gcm394_base_video_device::draw_sprite(const rectangle& cliprect, uint32_t scanline, int priority, uint32_t base_addr) -{ - uint32_t bitmap_addr = (m_sprite_702d_gfxbase_msb << 16) | m_sprite_7022_gfxbase_lsb; - uint32_t tile = m_spriteram[base_addr + 0]; - int16_t x = m_spriteram[base_addr + 1]; - int16_t y = m_spriteram[base_addr + 2]; - uint16_t attr = m_spriteram[base_addr + 3]; - - - if (!tile) // this check needs to come before the additional attribute bits are added in? (smartfp title) - { - return; - } - - int addressing_mode = 0; - - int screenwidth, screenheight, x_max; - if (m_707f & 0x0010) - { - screenwidth = 640; - screenheight = 480; - x_max = 0x400; - } - else - { - screenwidth = 320; - screenheight = 240; - x_max = 0x200; - } - - - // good for gormiti, smartfp, wrlshunt, paccon, jak_totm, jak_s500, jak_gtg - if ((m_7042_sprite & 0x0010) == 0x10) - addressing_mode = 0; // smartfp, paccon - else - addressing_mode = 1; - - if (m_alt_extrasprite_hack == 0) - if (addressing_mode == 0) // smartfp, paccon - tile |= m_spriteextra[base_addr / 4] << 16; - - if (m_alt_extrasprite_hack == 1) // jak_prft - tile |= (m_spriteextra[base_addr] & 0x000f) << 16; - - if (((attr & 0x3000) >> 12) != priority) - { - return; - } - - // attr PBzz pppp hhww ffdd - - // P = high palette bit - // b = blend enable - // zz = priority - // pppp = palette - // hh = height - // ww = width - // ff = flips - // dd = depth - - const uint32_t h = 8 << ((attr & 0x00c0) >> 6); - const uint32_t w = 8 << ((attr & 0x0030) >> 4); - - - if (!(m_7042_sprite & 0x0002)) - { - x = ((screenwidth / 2) + x) - w / 2; - y = ((screenheight / 2) - y) - (h / 2) + 8; - } - - x &= (x_max - 1); - y &= 0x01ff; - - uint32_t tile_line = ((scanline - y) + 0x200) % h; - int16_t test_y = (y + tile_line) & 0x1ff; - if (test_y >= 0x01c0) - test_y -= 0x0200; - - if (test_y != scanline) - { - return; - } - - bool blend = (attr & 0x4000); - - bool flip_x; - uint8_t bpp; - uint32_t yflipmask; - uint32_t palette_offset; - - // different attribute use? - if (screenwidth == 320) - { - if (m_alt_extrasprite_hack == 0) - { - flip_x = (attr & 0x0004); - yflipmask = attr & 0x0008 ? h - 1 : 0; - } - else - { - flip_x = 0; - yflipmask = 0; - } - - bpp = attr & 0x0003; - palette_offset = (attr & 0x0f00) >> 4; - } - else - { - flip_x = 0;// (attr & 0x0004); - yflipmask = 0;// attr& 0x0008 ? h - 1 : 0; - - bpp = attr & 0x0003; - palette_offset = (attr & 0x0f00) >> 4; - } - - if (m_703a_palettebank & 1) - palette_offset |= 0x100; - - if (attr & 0x8000) - palette_offset |= 0x200; - - if (blend) - { - if (flip_x) - draw(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, addressing_mode); - else - draw(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, addressing_mode); - } - else - { - if (flip_x) - draw(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, addressing_mode); - else - draw(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, addressing_mode); - } -} - -void gcm394_base_video_device::draw_sprites(const rectangle &cliprect, uint32_t scanline, int priority) -{ - // paccon suggests this, does older hardware have similar? - int numsprites = (m_7042_sprite & 0xff00) >> 8; - if (numsprites == 0) - numsprites = 0x100; - - for (uint32_t n = 0; n < numsprites; n++) - { - draw_sprite(cliprect, scanline, priority, 4 * n); - } + m_renderer->set_video_spaces(m_cpuspace, m_cs_space, m_csbase); } uint32_t gcm394_base_video_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) @@ -1021,48 +367,45 @@ uint32_t gcm394_base_video_device::screen_update(screen_device &screen, bitmap_r } //const uint16_t bgcol = 0x7c1f; // magenta - const uint16_t bgcol = 0x0000; // black - - +// const uint16_t bgcol = 0x0000; // black + bool highres; if (m_707f & 0x0010) { + highres = true; m_screen->set_visible_area(0, 640-1, 0, 480-1); } else { + highres = false; m_screen->set_visible_area(0, 320-1, 0, 240-1); } + address_space &mem = m_cpu->space(AS_PROGRAM); + + const uint32_t page0_addr = (m_page0_addr_msb << 16) | m_page0_addr_lsb; + const uint32_t page1_addr = (m_page1_addr_msb << 16) | m_page1_addr_lsb; + const uint32_t page2_addr = (m_page2_addr_msb << 16) | m_page2_addr_lsb; + const uint32_t page3_addr = (m_page3_addr_msb << 16) | m_page3_addr_lsb; + + const uint32_t sprites_addr = (m_sprite_702d_gfxbase_msb << 16) | m_sprite_7022_gfxbase_lsb; + + bitmap.fill(0, cliprect); + for (uint32_t scanline = (uint32_t)cliprect.min_y; scanline <= (uint32_t)cliprect.max_y; scanline++) { - uint32_t* bufferline = &m_screenbuf[scanline * m_screen->width()]; - - for (int x = 0; x < m_screen->width(); x++) - { - bufferline[x] = m_rgb555_to_rgb888[bgcol]; - } + uint32_t* dst = &bitmap.pix32(scanline, cliprect.min_x); for (int i = 0; i < 4; i++) { - const int draw_all = 1; - - if (1) - { - if ((!(machine().input().code_pressed(KEYCODE_Q))) || draw_all) draw_page(cliprect, scanline, i, (m_page0_addr_lsb | (m_page0_addr_msb<<16)), m_tmap0_regs, m_tmap0_scroll, 0); - if ((!(machine().input().code_pressed(KEYCODE_W))) || draw_all) draw_page(cliprect, scanline, i, (m_page1_addr_lsb | (m_page1_addr_msb<<16)), m_tmap1_regs, m_tmap1_scroll, 1); - if ((!(machine().input().code_pressed(KEYCODE_E))) || draw_all) draw_page(cliprect, scanline, i, (m_page2_addr_lsb | (m_page2_addr_msb<<16)), m_tmap2_regs, m_tmap2_scroll, 2); - if ((!(machine().input().code_pressed(KEYCODE_R))) || draw_all) draw_page(cliprect, scanline, i, (m_page3_addr_lsb | (m_page3_addr_msb<<16)), m_tmap3_regs, m_tmap3_scroll, 3); + m_renderer->draw_page(true, true, m_alt_tile_addressing ? false : true, m_703a_palettebank, cliprect, dst, scanline, i, page0_addr, m_tmap0_scroll, m_tmap0_regs, mem, m_paletteram, m_rowscroll, 0); + m_renderer->draw_page(true, true, m_alt_tile_addressing ? false : true, m_703a_palettebank, cliprect, dst, scanline, i, page1_addr, m_tmap1_scroll, m_tmap1_regs, mem, m_paletteram, m_rowscroll, 1); + m_renderer->draw_page(true, true, m_alt_tile_addressing ? false : true, m_703a_palettebank, cliprect, dst, scanline, i, page2_addr, m_tmap2_scroll, m_tmap2_regs, mem, m_paletteram, m_rowscroll, 2); + m_renderer->draw_page(true, true, m_alt_tile_addressing ? false : true, m_703a_palettebank, cliprect, dst, scanline, i, page3_addr, m_tmap3_scroll, m_tmap3_regs, mem, m_paletteram, m_rowscroll, 3); - } - if ((!(machine().input().code_pressed(KEYCODE_T))) || draw_all) draw_sprites(cliprect, scanline, i); + m_renderer->draw_sprites(true, true, m_alt_extrasprite_hack ? true : false, m_703a_palettebank, highres, cliprect, dst, scanline, i, sprites_addr, mem, m_paletteram, m_spriteram, -1); } - } - 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 + m_screen->width() * y]; - memcpy(dest, src, sizeof(uint32_t) * ((cliprect.max_x - cliprect.min_x) + 1)); + m_renderer->apply_saturation_and_fade(bitmap, cliprect, scanline); } return 0; @@ -1391,6 +734,8 @@ WRITE16_MEMBER(gcm394_base_video_device::sprite_7042_extra_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::sprite_7042_extra_w %04x\n", machine().describe_context(), data); m_7042_sprite = data; + m_renderer->set_video_reg_42(data); + //popmessage("extra modes %04x\n", data); } @@ -1470,7 +815,7 @@ READ16_MEMBER(gcm394_base_video_device::video_707c_r) READ16_MEMBER(gcm394_base_video_device::video_707f_r) { - uint16_t retdata = m_707f; + uint16_t retdata = m_renderer->get_video_reg_7f(); LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_707f_r (returning %04x)\n", machine().describe_context(), retdata); return retdata; } @@ -1496,7 +841,7 @@ WRITE16_MEMBER(gcm394_base_video_device::video_707f_w) } m_707f = data; - + m_renderer->set_video_reg_7f(data); //popmessage("707f is %04x\n", data); } @@ -1558,6 +903,7 @@ WRITE16_MEMBER(gcm394_base_video_device::video_702a_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_702a_w %04x\n", machine().describe_context(), data); m_702a = data; + m_renderer->set_video_reg_2a(data); } READ16_MEMBER(gcm394_base_video_device::video_curline_r) @@ -1582,15 +928,17 @@ WRITE16_MEMBER(gcm394_base_video_device::video_7030_brightness_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7030_brightness_w %04x\n", machine().describe_context(), data); m_7030_brightness = data; + m_renderer->set_video_reg_30(data); } void gcm394_base_video_device::update_raster_split_position() { // this might need updating to handle higher res modes LOGMASKED(LOG_GCM394_VIDEO, "update_raster_split_position: %04x,%04x\n", m_yirqpos, m_xirqpos); - if (m_xirqpos < 300 && m_yirqpos < 240) + if (m_xirqpos < 300 && m_yirqpos < 256) { - m_screenpos_timer->adjust(m_screen->time_until_pos(m_yirqpos, m_xirqpos)); + // where does -19 come from? needed for raster on paccon xevious to fire at correct line for bg scrolling to be seamless + m_screenpos_timer->adjust(m_screen->time_until_pos(m_yirqpos-19, m_xirqpos)); //printf("setting irq timer for y:%d x:%d", m_yirqpos, m_xirqpos); } else @@ -1623,6 +971,7 @@ WRITE16_MEMBER(gcm394_base_video_device::video_703c_tvcontrol1_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_703c_tvcontrol1_w %04x\n", machine().describe_context(), data); m_703c_tvcontrol1 = data; + m_renderer->set_video_reg_3c(data); } READ16_MEMBER(gcm394_base_video_device::video_7051_r) @@ -1668,7 +1017,7 @@ WRITE16_MEMBER(gcm394_base_video_device::spriteram_w) } else if (m_707e_spritebank == 0x0001) { - m_spriteextra[offset] = data; + m_spriteram[offset + 0x400] = data; } else { @@ -1684,7 +1033,7 @@ READ16_MEMBER(gcm394_base_video_device::spriteram_r) } else if (m_707e_spritebank == 0x0001) { - return m_spriteextra[offset]; + return m_spriteram[offset + 0x400]; } else { @@ -1705,13 +1054,9 @@ WRITE16_MEMBER(gcm394_base_video_device::palette_w) { offset |= (m_703a_palettebank & 0x000c) << 6; m_paletteram[offset] = data; - - uint32_t pal = m_rgb555_to_rgb888[data & 0x7fff]; - int r = (pal >> 16) & 0xff; - int g = (pal >> 8) & 0xff; - int b = (pal >> 0) & 0xff; - - m_palette->set_pen_color(offset, rgb_t(r, g, b)); + + // for debug + m_palette->set_pen_color(offset, rgb_t((((data >> 15) & 0x1f)<<3), (((data >> 10) & 0x1f)<<3), (((data >> 0) & 0x1f)<<3))); } } @@ -1731,16 +1076,19 @@ READ16_MEMBER(gcm394_base_video_device::palette_r) WRITE16_MEMBER(gcm394_base_video_device::video_701c_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_701c_w (unknown video reg?) %04x\n", machine().describe_context(), data); + m_renderer->set_video_reg_1c(data); } WRITE16_MEMBER(gcm394_base_video_device::video_701d_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_701d_w (unknown video reg?) %04x\n", machine().describe_context(), data); + m_renderer->set_video_reg_1d(data); } WRITE16_MEMBER(gcm394_base_video_device::video_701e_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_701e_w (unknown video reg?) %04x\n", machine().describe_context(), data); + m_renderer->set_video_reg_1e(data); } @@ -1787,7 +1135,7 @@ void gcm394_base_video_device::device_timer(emu_timer &timer, device_timer_id id m_screen->update_partial(m_screen->vpos()); // fire again, jak_dbz pinball needs this - m_screenpos_timer->adjust(m_screen->time_until_pos(m_yirqpos, m_xirqpos)); + m_screenpos_timer->adjust(m_screen->time_until_pos(m_yirqpos-19, m_xirqpos)); break; } } diff --git a/src/devices/machine/generalplus_gpl16250soc_video.h b/src/devices/machine/generalplus_gpl16250soc_video.h index 5edbbe76735..a04540dd5a1 100644 --- a/src/devices/machine/generalplus_gpl16250soc_video.h +++ b/src/devices/machine/generalplus_gpl16250soc_video.h @@ -36,6 +36,8 @@ public: void set_alt_extrasprite(int alt_extrasprite_hack) { m_alt_extrasprite_hack = alt_extrasprite_hack; } + void set_video_spaces(address_space& cpuspace, address_space& cs_space, int csbase) { m_cpuspace = &cpuspace; m_cs_space = &cs_space; m_csbase = csbase; } + //void set_pal_sprites(int pal_sprites) { m_pal_sprites = pal_sprites; } //void set_pal_back(int pal_back) { m_pal_back = pal_back; } @@ -147,37 +149,8 @@ protected: virtual void device_start() override; virtual void device_reset() override; - enum blend_enable_t : bool - { - BlendOff = false, - BlendOn = true - }; - - enum rowscroll_enable_t : bool - { - RowScrollOff = false, - RowScrollOn = true - }; - - enum flipx_t : bool - { - FlipXOff = false, - FlipXOn = true - }; - - template - void draw(const rectangle &cliprect, uint32_t line, uint32_t xoff, uint32_t yoff, uint32_t bitmap_addr, uint32_t tile, int32_t h, int32_t w, uint8_t bpp, uint32_t yflipmask, uint32_t palette_offset, int addressing_mode); - void draw_page(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t bitmap_addr, uint16_t *regs, uint16_t *scroll, int which); - void draw_sprites(const rectangle& cliprect, uint32_t scanline, int priority); - void draw_sprite(const rectangle& cliprect, uint32_t scanline, int priority, uint32_t base_addr); - - uint32_t m_screenbuf[640 * 480]; - uint8_t m_rgb5_to_rgb8[32]; - uint32_t m_rgb555_to_rgb888[0x8000]; - required_device m_cpu; required_device m_screen; -// required_shared_ptr m_scrollram; uint16_t m_page0_addr_lsb; uint16_t m_page0_addr_msb; @@ -242,8 +215,7 @@ protected: emu_timer *m_screenpos_timer; - uint16_t m_spriteram[0x400]; - uint16_t m_spriteextra[0x400]; + uint16_t m_spriteram[0x400*2]; uint16_t m_paletteram[0x100*0x10]; required_device m_palette; @@ -263,6 +235,10 @@ protected: int m_alt_tile_addressing; required_device m_renderer; + + address_space* m_cpuspace; + address_space* m_cs_space; + int m_csbase; }; class gcm394_video_device : public gcm394_base_video_device diff --git a/src/devices/machine/spg2xx_video.cpp b/src/devices/machine/spg2xx_video.cpp index b7615c76a38..d62e6998ea2 100644 --- a/src/devices/machine/spg2xx_video.cpp +++ b/src/devices/machine/spg2xx_video.cpp @@ -103,6 +103,8 @@ uint32_t spg2xx_video_device::screen_update(screen_device &screen, bitmap_rgb32 const uint32_t page1_addr = 0x40 * m_video_regs[0x20]; const uint32_t page2_addr = 0x40 * m_video_regs[0x21]; + const uint32_t sprite_addr = 0x40 * m_video_regs[0x22]; + uint16_t *page1_scroll = m_video_regs + 0x10; uint16_t *page2_scroll = m_video_regs + 0x16; uint16_t *page1_regs = m_video_regs + 0x12; @@ -116,9 +118,9 @@ uint32_t spg2xx_video_device::screen_update(screen_device &screen, bitmap_rgb32 for (int i = 0; i < 4; i++) { - m_renderer->draw_page(cliprect, dst, scanline, i, page1_addr, page1_scroll, page1_regs, mem, m_paletteram, m_scrollram); - m_renderer->draw_page(cliprect, dst, scanline, i, page2_addr, page2_scroll, page2_regs, mem, m_paletteram, m_scrollram); - m_renderer->draw_sprites(cliprect, dst, scanline, i, mem, m_paletteram, m_spriteram, m_sprlimit_read_cb()); + m_renderer->draw_page(false, false, false, 0, cliprect, dst, scanline, i, page1_addr, page1_scroll, page1_regs, mem, m_paletteram, m_scrollram, 0); + m_renderer->draw_page(false, false, false, 0, cliprect, dst, scanline, i, page2_addr, page2_scroll, page2_regs, mem, m_paletteram, m_scrollram, 1); + m_renderer->draw_sprites(false, false, false, 0, false, cliprect, dst, scanline, i, sprite_addr, mem, m_paletteram, m_spriteram, m_sprlimit_read_cb()); } m_renderer->apply_saturation_and_fade(bitmap, cliprect, scanline); @@ -177,7 +179,7 @@ READ16_MEMBER(spg2xx_video_device::video_r) case 0x22: // Sprite Segment Address LOGMASKED(LOG_PPU_READS, "video_r: Sprite Segment Address\n"); - return m_renderer->get_video_reg_22(); + return m_video_regs[offset]; case 0x2a: // Blend Level Control LOGMASKED(LOG_PPU_READS, "video_r: Blend Level Control\n"); @@ -334,7 +336,6 @@ WRITE16_MEMBER(spg2xx_video_device::video_w) case 0x22: // Sprite Segment Address LOGMASKED(LOG_PPU_WRITES, "video_w: Sprite Segment Address = %04x\n", data); m_video_regs[offset] = data; - m_renderer->set_video_reg_22(data); break; case 0x2a: // Blend Level Control diff --git a/src/devices/machine/spg_renderer.cpp b/src/devices/machine/spg_renderer.cpp index ded2c8ebe25..b2700968b72 100644 --- a/src/devices/machine/spg_renderer.cpp +++ b/src/devices/machine/spg_renderer.cpp @@ -7,7 +7,8 @@ DEFINE_DEVICE_TYPE(SPG_RENDERER, spg_renderer_device, "spg_renderer", "SunPlus / GeneralPlus video rendering") spg_renderer_device::spg_renderer_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, type, tag, owner, clock) + device_t(mconfig, type, tag, owner, clock), + m_space_read_cb(*this) { } @@ -18,6 +19,8 @@ spg_renderer_device::spg_renderer_device(const machine_config &mconfig, const ch void spg_renderer_device::device_start() { + m_space_read_cb.resolve_safe(0); + for (uint8_t i = 0; i < 32; i++) { m_rgb5_to_rgb8[i] = (i << 3) | (i >> 2); @@ -33,7 +36,6 @@ void spg_renderer_device::device_start() save_item(NAME(m_video_regs_1d)); save_item(NAME(m_video_regs_1e)); - save_item(NAME(m_video_regs_22)); save_item(NAME(m_video_regs_2a)); save_item(NAME(m_video_regs_30)); @@ -41,6 +43,8 @@ void spg_renderer_device::device_start() save_item(NAME(m_video_regs_42)); + save_item(NAME(m_video_regs_7f)); + save_item(NAME(m_ycmp_table)); } @@ -50,7 +54,6 @@ void spg_renderer_device::device_reset() m_video_regs_1d = 0x0000; m_video_regs_1e = 0x0000; - m_video_regs_22 = 0x0000; m_video_regs_2a = 0x0000; m_video_regs_30 = 0x0000; @@ -58,6 +61,8 @@ void spg_renderer_device::device_reset() m_video_regs_42 = 0x0001; + m_video_regs_7f = 0x0000; + for (int i = 0; i < 480; i++) { m_ycmp_table[i] = 0xffffffff; @@ -66,14 +71,13 @@ void spg_renderer_device::device_reset() // Perform a lerp between a and b -inline uint8_t spg_renderer_device::mix_channel(uint8_t bottom, uint8_t top) +inline uint8_t spg_renderer_device::mix_channel(uint8_t bottom, uint8_t top, uint8_t alpha) { - uint8_t alpha = (m_video_regs_2a & 3) << 6; return ((256 - alpha) * bottom + alpha * top) >> 8; } template -void spg_renderer_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 &spc, uint16_t* paletteram) +void spg_renderer_device::draw_tilestrip(bool read_from_csspace, uint32_t screenwidth, uint32_t drawwidthmask, const rectangle& cliprect, uint32_t* dst, uint32_t tile_h, uint32_t tile_w, uint32_t tilegfxdata_addr, uint32_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 &spc, uint16_t* paletteram, uint8_t blendlevel) { 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); @@ -82,23 +86,44 @@ void spg_renderer_device::draw_tilestrip(const rectangle& cliprect, uint32_t* ds for (int32_t x = FlipX ? (tile_w - 1) : 0; FlipX ? x >= 0 : x < tile_w; FlipX ? x-- : x++) { - int realdrawpos = (drawx + x) & 0x1ff; + int realdrawpos = (drawx + x) & drawwidthmask; bits <<= nc_bpp; if (nbits < nc_bpp) { - uint16_t b = spc.read_word(m++ & 0x3fffff); - b = (b << 8) | (b >> 8); - bits |= b << (nc_bpp - nbits); - nbits += 16; + if (!read_from_csspace) + { + uint16_t b = spc.read_word(m++ & 0x3fffff); + b = (b << 8) | (b >> 8); + bits |= b << (nc_bpp - nbits); + nbits += 16; + } + else + { + uint16_t b; + const int addr = m & 0x7ffffff; + if (addr < m_csbase) + { + b = m_cpuspace->read_word(addr); + } + else + { + b = m_cs_space->read_word(addr-m_csbase); + } + m++; + 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) + + if (realdrawpos >= 0 && realdrawpos < screenwidth) { uint16_t rgb = paletteram[pal]; @@ -106,9 +131,10 @@ void spg_renderer_device::draw_tilestrip(const rectangle& cliprect, uint32_t* ds { 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])); + + dst[realdrawpos] = (mix_channel((uint8_t)(dst[realdrawpos] >> 16), m_rgb5_to_rgb8[(rgb >> 10) & 0x1f], blendlevel) << 16) | + (mix_channel((uint8_t)(dst[realdrawpos] >> 8), m_rgb5_to_rgb8[(rgb >> 5) & 0x1f], blendlevel) << 8) | + (mix_channel((uint8_t)(dst[realdrawpos] >> 0), m_rgb5_to_rgb8[(rgb >> 0) & 0x1f], blendlevel) << 0); } else { @@ -120,122 +146,166 @@ void spg_renderer_device::draw_tilestrip(const rectangle& cliprect, uint32_t* ds } -void spg_renderer_device::draw_linemap(const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t* scrollregs, uint16_t* tilemapregs, address_space &spc, uint16_t* paletteram) +void spg_renderer_device::draw_linemap(bool has_extended_tilemaps, const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t* scrollregs, uint16_t* tilemapregs, address_space &spc, uint16_t* paletteram) { - if ((scanline < 0) || (scanline >= 240)) - return; + if (has_extended_tilemaps) + { + uint32_t ctrl = tilemapregs[1]; + + if (0) + { + if (ctrl & 0x0010) + popmessage("bitmap mode %08x with rowscroll\n", tilegfxdata_addr); + else + popmessage("bitmap mode %08x\n", tilegfxdata_addr); + } + // note, in interlace modes it appears every other line is unused? (480 entry table, but with blank values) + // and furthermore the rowscroll and rowzoom tables only have 240 entries, not enough for every line + // the end of the rowscroll table (entries 240-255) contain something else, maybe garbage data as it's offscreen, maybe not + uint32_t tilemap = tilemapregs[2]; + uint32_t palette_map = tilemapregs[3]; - uint32_t tilemap = tilemapregs[2]; - uint32_t palette_map = tilemapregs[3]; + uint32_t linebase = spc.read_word(tilemap + scanline); // every other word is unused, but there are only enough entries for 240 lines then, sometimes to do with interlace mode? + uint16_t palette = spc.read_word(palette_map + (scanline / 2)); - //printf("draw bitmap bases %04x %04x\n", tilemap, palette_map); + if (scanline & 1) + palette >>= 8; + else + palette &= 0xff; - //uint32_t xscroll = scrollregs[0]; - uint32_t yscroll = scrollregs[1]; + if (!linebase) + return; - int realline = (scanline + yscroll) & 0xff; + linebase = linebase | (palette << 16); + // this logic works for jak_s500 and the test modes to get the correct base, doesn't seem to work for jak_car2 ingame, maybe data is copied to wrong place? + int gfxbase = (tilegfxdata_addr&0x7ffffff) + (linebase&0x7ffffff); - uint16_t tile = spc.read_word(tilemap + realline); - uint16_t palette = 0; + for (int i = 0; i < 160; i++) // will have to be 320 for jak_car2 ingame, jak_s500 lines are wider than screen, and zoomed + { + uint16_t pix; + const int addr = gfxbase & 0x7ffffff; + if (addr < m_csbase) + { + pix = m_cpuspace->read_word(addr); + } + else + { + pix = m_cs_space->read_word(addr-m_csbase); + } + gfxbase++; - //if (!tile) - // continue; + int xx; + uint16_t pal; - palette = spc.read_word(palette_map + realline / 2); - if (scanline & 1) - palette >>= 8; - else - palette &= 0x00ff; + if ((scanline >= 0) && (scanline < 480)) + { + xx = i * 2; - //const int linewidth = 320 / 2; - int sourcebase = tile | (palette << 16); + pal = (pix & 0xff) | 0x100; - uint32_t ctrl = tilemapregs[1]; + if (xx >= 0 && xx <= cliprect.max_x) + { + uint16_t rgb = paletteram[pal]; - if (ctrl & 0x80) // HiColor mode (rad_digi) - { - for (int i = 0; i < 320; i++) - { - const uint16_t data = spc.read_word(sourcebase + i); + if (!(rgb & 0x8000)) + { + dst[xx] = m_rgb555_to_rgb888[rgb]; + } + } - if (!(data & 0x8000)) - { - dst[i] = m_rgb555_to_rgb888[data & 0x7fff]; + xx = (i * 2)+1; + pal = (pix >> 8) + 0x100; + + if (xx >= 0 && xx <= cliprect.max_x) + { + uint16_t rgb = paletteram[pal]; + + if (!(rgb & 0x8000)) + { + dst[xx] = m_rgb555_to_rgb888[rgb]; + } + } } } } - else + else // code used for spg2xx cases { - for (int i = 0; i < 320 / 2; i++) - { - uint8_t palette_entry; - uint16_t color; - const uint16_t data = spc.read_word(sourcebase + i); + if ((scanline < 0) || (scanline >= 240)) + return; - palette_entry = (data & 0x00ff); - color = paletteram[palette_entry]; + uint32_t tilemap = tilemapregs[2]; + uint32_t palette_map = tilemapregs[3]; - if (!(color & 0x8000)) - { - dst[(i * 2) + 0] = m_rgb555_to_rgb888[color & 0x7fff]; - } + popmessage("draw draw_linemap bases %04x %04x\n", tilemap, palette_map); - palette_entry = (data & 0xff00) >> 8; - color = paletteram[palette_entry]; + //uint32_t xscroll = scrollregs[0]; + uint32_t yscroll = scrollregs[1]; - if (!(color & 0x8000)) - { - dst[(i * 2) + 1] = m_rgb555_to_rgb888[color & 0x7fff]; - } - } - } -} + int realline = (scanline + yscroll) & 0xff; -bool spg_renderer_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, spg_renderer_device::blend_enable_t& blend, spg_renderer_device::flipx_t& flip_x, bool& flip_y, uint32_t& palette_offset, address_space &spc) -{ - uint32_t tile_address = x0 + (tile_count_x * y0); - - tile = (ctrl & 0x0004) ? spc.read_word(tilemap_rambase) : spc.read_word(tilemap_rambase + tile_address); + uint32_t tile = spc.read_word(tilemap + realline); + uint16_t palette = 0; - if (!tile) - return false; + //if (!tile) + // continue; - uint32_t tileattr = attr; - uint32_t tilectrl = ctrl; - if ((ctrl & 2) == 0) - { // -(1) bld(1) flip(2) pal(4) - - uint16_t palette = (ctrl & 0x0004) ? spc.read_word(palettemap_rambase) : spc.read_word(palettemap_rambase + tile_address / 2); - if (x0 & 1) + palette = spc.read_word(palette_map + realline / 2); + if (scanline & 1) palette >>= 8; else palette &= 0x00ff; + //const int linewidth = 320 / 2; + int sourcebase = tile | (palette << 16); - tileattr &= ~0x000c; - tileattr |= (palette >> 2) & 0x000c; // flip + uint32_t ctrl = tilemapregs[1]; - tileattr &= ~0x0f00; - tileattr |= (palette << 8) & 0x0f00; // palette + if (ctrl & 0x80) // HiColor mode (rad_digi) + { + for (int i = 0; i < 320; i++) + { + const uint16_t data = spc.read_word(sourcebase + i); - tilectrl &= ~0x0100; - tilectrl |= (palette << 2) & 0x0100; // blend - } + if (!(data & 0x8000)) + { + dst[i] = m_rgb555_to_rgb888[data & 0x7fff]; + } + } + } + else + { + for (int i = 0; i < 320 / 2; i++) + { + uint8_t palette_entry; + uint16_t color; + const uint16_t data = spc.read_word(sourcebase + i); - blend = ((tileattr & 0x4000 || tilectrl & 0x0100)) ? BlendOn : BlendOff; - flip_x = (tileattr & 0x0004) ? FlipXOn : FlipXOff; - flip_y= (tileattr & 0x0008); + palette_entry = (data & 0x00ff); + color = paletteram[palette_entry]; - palette_offset = (tileattr & 0x0f00) >> 4; + if (!(color & 0x8000)) + { + dst[(i * 2) + 0] = m_rgb555_to_rgb888[color & 0x7fff]; + } + palette_entry = (data & 0xff00) >> 8; + color = paletteram[palette_entry]; - return true; + if (!(color & 0x8000)) + { + dst[(i * 2) + 1] = m_rgb555_to_rgb888[color & 0x7fff]; + } + } + } + } } + + // this builds up a line table for the vcmp effect, this is not correct when step is used void spg_renderer_device::update_vcmp_table() { @@ -257,7 +327,7 @@ void spg_renderer_device::update_vcmp_table() } else { - if ((currentline >= 0) && (currentline < 240)) + if ((currentline >= 0) && (currentline < 256)) { m_ycmp_table[i] = currentline; } @@ -275,33 +345,33 @@ void spg_renderer_device::update_vcmp_table() } } -void spg_renderer_device::draw_tilestrip(spg_renderer_device::blend_enable_t blend, spg_renderer_device::flipx_t flip_x, 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& spc, uint16_t* paletteram) +void spg_renderer_device::draw_tilestrip(bool read_from_csspace, uint32_t screenwidth, uint32_t drawwidthmask, spg_renderer_device::blend_enable_t blend, spg_renderer_device::flipx_t flip_x, const rectangle& cliprect, uint32_t* dst, uint32_t tile_h, uint32_t tile_w, uint32_t tilegfxdata_addr, uint32_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& spc, uint16_t* paletteram, uint8_t blendlevel) { if (blend) { if (flip_x) { - draw_tilestrip(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, tile_scanline, drawx, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile, spc, paletteram); + draw_tilestrip(read_from_csspace, screenwidth, drawwidthmask, cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, tile_scanline, drawx, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile, spc, paletteram, blendlevel); } else { - draw_tilestrip(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, tile_scanline, drawx, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile, spc, paletteram); + draw_tilestrip(read_from_csspace, screenwidth, drawwidthmask, cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, tile_scanline, drawx, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile, spc, paletteram, blendlevel); } } else { if (flip_x) { - draw_tilestrip(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, tile_scanline, drawx, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile, spc, paletteram); + draw_tilestrip(read_from_csspace, screenwidth, drawwidthmask, cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, tile_scanline, drawx, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile, spc, paletteram, blendlevel); } else { - draw_tilestrip(cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, tile_scanline, drawx, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile, spc, paletteram); + draw_tilestrip(read_from_csspace, screenwidth, drawwidthmask, cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, tile_scanline, drawx, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile, spc, paletteram, blendlevel); } } } -void spg_renderer_device::draw_page(const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t* scrollregs, uint16_t* tilemapregs, address_space& spc, uint16_t* paletteram, uint16_t* scrollram) +void spg_renderer_device::draw_page(bool read_from_csspace, bool has_extended_tilemaps, bool use_alt_tile_addressing, uint32_t palbank, const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t* scrollregs, uint16_t* tilemapregs, address_space& spc, uint16_t* paletteram, uint16_t* scrollram, uint32_t which) { const uint32_t attr = tilemapregs[0]; const uint32_t ctrl = tilemapregs[1]; @@ -318,7 +388,7 @@ void spg_renderer_device::draw_page(const rectangle& cliprect, uint32_t* dst, ui if (ctrl & 0x0001) // Bitmap / Linemap mode! (basically screen width tile mode) { - draw_linemap(cliprect, dst, scanline, priority, tilegfxdata_addr, scrollregs, tilemapregs, spc, paletteram); + draw_linemap(has_extended_tilemaps, cliprect, dst, scanline, priority, tilegfxdata_addr, scrollregs, tilemapregs, spc, paletteram); return; } @@ -328,61 +398,186 @@ void spg_renderer_device::draw_page(const rectangle& cliprect, uint32_t* dst, ui { if (m_video_regs_1e != 0x0000) popmessage("vertical compression mode with non-0 step amount %04x offset %04x step %04x\n", m_video_regs_1c, m_video_regs_1d, m_video_regs_1e); - + logical_scanline = m_ycmp_table[scanline]; if (logical_scanline == 0xffffffff) return; } + uint32_t total_width; + uint32_t y_mask; + uint32_t screenwidth; + uint32_t drawwidthmask; + + if (read_from_csspace && ((attr >> 15) & 0x1)) + { + // just a guess based on this being set on the higher resolution tilemaps we've seen, could be 100% incorrect register + total_width = 1024; + y_mask = 0x1ff; + screenwidth = 640; + drawwidthmask = 0x400 - 1; + } + else + { + total_width = 512; + y_mask = 0xff; + screenwidth = 320; + drawwidthmask = 0x200 - 1; + } + + const uint32_t xscroll = scrollregs[0]; const uint32_t yscroll = scrollregs[1]; const uint32_t tilemap_rambase = tilemapregs[2]; - const uint32_t palettemap_rambase = tilemapregs[3]; + const uint32_t exattributemap_rambase = tilemapregs[3]; 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 = (logical_scanline + yscroll) & 0xff; // all tilemaps are 256 pixels high + const uint32_t tile_count_x = total_width / tile_w; // tilemaps are 512 or 1024 wide depending on screen mode? + const uint32_t bitmap_y = (logical_scanline + yscroll) & y_mask; // tilemaps are 256 or 512 high depending on screen mode? 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 uint32_t words_per_tile = bits_per_row * tile_h; const bool row_scroll = (ctrl & 0x0010); + uint8_t blendlevel = (m_video_regs_2a & 3) << 6; + + uint32_t words_per_tile; + + // good for gormiti, smartfp, wrlshunt, paccon, jak_totm, jak_s500, jak_gtg + if (has_extended_tilemaps && use_alt_tile_addressing) + { + words_per_tile = 8; + } + else + { + words_per_tile = bits_per_row * tile_h; + } int realxscroll = xscroll; if (row_scroll) { // Tennis in My Wireless Sports confirms the need to add the scroll value here rather than rowscroll being screen-aligned - realxscroll += (int16_t)scrollram[(logical_scanline+yscroll) & 0xff]; + realxscroll += (int16_t)scrollram[(logical_scanline + yscroll) & 0xff]; } const int upperscrollbits = (realxscroll >> (tile_width + 3)); - const int endpos = (320 + tile_w) / tile_w; + const int endpos = (screenwidth + tile_w) / tile_w; for (uint32_t x0 = 0; x0 < endpos; x0++) { spg_renderer_device::blend_enable_t blend; spg_renderer_device::flipx_t flip_x; bool flip_y; - uint16_t tile; + uint32_t tile; uint32_t palette_offset; - if (!get_tile_info(tilemap_rambase, palettemap_rambase, (x0 + upperscrollbits) & (tile_count_x-1) , y0, tile_count_x, ctrl, attr, tile, blend, flip_x, flip_y, palette_offset, spc)) + // get tile info + const int realx0 = (x0 + upperscrollbits) & (tile_count_x - 1); + uint32_t tile_address = realx0 + (tile_count_x * y0); + + tile = (ctrl & 0x0004) ? spc.read_word(tilemap_rambase) : spc.read_word(tilemap_rambase + tile_address); + + if (!tile) continue; + uint32_t tileattr = attr; + uint32_t tilectrl = ctrl; + + if (has_extended_tilemaps && use_alt_tile_addressing) + { + // in this mode what would be the 'palette' bits get used for extra tile bits (even if the usual 'extended table' mode is disabled?) + // used by smartfp + uint16_t exattribute = (ctrl & 0x0004) ? spc.read_word(exattributemap_rambase) : spc.read_word(exattributemap_rambase + tile_address / 2); + if (realx0 & 1) + exattribute >>= 8; + else + exattribute &= 0x00ff; + + tile |= (exattribute & 0x07) << 16; + //blendlevel = 0x1f; // hack + } + else if ((ctrl & 2) == 0) + { // -(1) bld(1) flip(2) pal(4) + + uint16_t exattribute = (ctrl & 0x0004) ? spc.read_word(exattributemap_rambase) : spc.read_word(exattributemap_rambase + tile_address / 2); + if (realx0 & 1) + exattribute >>= 8; + else + exattribute &= 0x00ff; + + + tileattr &= ~0x000c; + tileattr |= (exattribute >> 2) & 0x000c; // flip + + tileattr &= ~0x0f00; + tileattr |= (exattribute << 8) & 0x0f00; // palette + + tilectrl &= ~0x0100; + tilectrl |= (exattribute << 2) & 0x0100; // blend + } + + blend = ((tileattr & 0x4000 || tilectrl & 0x0100)) ? BlendOn : BlendOff; + flip_x = (tileattr & 0x0004) ? FlipXOn : FlipXOff; + flip_y = (tileattr & 0x0008); + + palette_offset = (tileattr & 0x0f00) >> 4; + // got tile info + + if (1) + { + // HACKS + // There must be a select bit for the tilemap palettes somewhere, but where?! + // the different games in paccon also expect a variety of different configs here, maybe a good place to look + if (palbank & 1) // this actually seems to be the sprite palette bank enable, but for myac220 / tkmag220 (where everything is from a single palette) it gives us an easy way to ignore the logic below + { + if (which == 0) // tilemap 0 + { + if (ctrl & 0x0002) // RegSet:1 + { + // smartfp has a conflict between the bootlogos and the first screen, it's in regset mode, no obvious difference in registers but needs palette from different places? + // not even m_video_regs_7f changes here, which makes the m_video_regs_7f case specific hacks for jak_s500 below very unlikely to actually be related + if ((bpp + 1) * 2 == 4) + if (use_alt_tile_addressing == true) + palette_offset |= 0x200; + } + } + + if (which == 1) + { + // can't do this for jak_s500 logos + // jak_s500 also uses this tilemap in both 4 and 6bpp modes expecting the same palette base, so the hack used for smartfp on tilemap 0 is not applicable here + + // m_video_regs_7f != 0x2d3 for jak_S500 main menu + if ((m_video_regs_7f != 0x53) && (m_video_regs_7f != 0x63) && (m_video_regs_7f != 0x2d3)) + palette_offset |= 0x200; + } + + // jak_car2 screen transitions use layers 2 and 3 the same way, alternating each frame + if (which == 2) + { + // jak_s500 title screen + loading screen before race + if ((m_video_regs_7f == 0x2d3) || (m_video_regs_7f == 0x2db)) + palette_offset |= 0x200; + } + + } + } + + palette_offset >>= nc_bpp; palette_offset <<= nc_bpp; - const int drawx = (x0 * tile_w) - (realxscroll & (tile_w-1)); - draw_tilestrip(blend,flip_x, cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, tile_scanline, drawx, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile, spc, paletteram); + const int drawx = (x0 * tile_w) - (realxscroll & (tile_w - 1)); + draw_tilestrip(read_from_csspace, screenwidth, drawwidthmask, blend, flip_x, cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, tile_scanline, drawx, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile, spc, paletteram, blendlevel); } } -void spg_renderer_device::draw_sprite(const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t base_addr, address_space &spc, uint16_t* paletteram, uint16_t* spriteram) +void spg_renderer_device::draw_sprite(bool read_from_csspace, bool has_extended_sprites, bool alt_extrasprite_hack, uint32_t palbank, bool highres, const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t spritegfxdata_addr, uint32_t base_addr, address_space &spc, uint16_t* paletteram, uint16_t* spriteram) { - uint32_t tilegfxdata_addr = 0x40 * m_video_regs_22; - uint16_t tile = spriteram[base_addr + 0]; + uint32_t tilegfxdata_addr = spritegfxdata_addr; + uint32_t tile = spriteram[base_addr + 0]; int16_t x = spriteram[base_addr + 1]; int16_t y = spriteram[base_addr + 2]; uint16_t attr = spriteram[base_addr + 3]; @@ -397,44 +592,108 @@ void spg_renderer_device::draw_sprite(const rectangle& cliprect, uint32_t* dst, return; } + + uint32_t screenwidth = 320; +// uint32_t screenheight = 240; + uint32_t screenheight = 256; + uint32_t xmask = 0x1ff; + uint32_t ymask = 0x1ff; + + if (highres) + { + screenwidth = 640; +// screenheight = 480; + screenheight = 512; + xmask = 0x3ff; + } + const uint32_t tile_h = 8 << ((attr & 0x00c0) >> 6); const uint32_t tile_w = 8 << ((attr & 0x0030) >> 4); if (!(m_video_regs_42 & 0x0002)) { - x = (160 + x) - tile_w / 2; - y = (120 - y) - (tile_h / 2) + 8; + x = ((screenwidth/2) + x) - tile_w / 2; +// y = ((screenheight/2) - y) - (tile_h / 2) + 8; + y = ((screenheight/2) - y) - (tile_h / 2); } - x &= 0x01ff; - y &= 0x01ff; + x &= xmask; + y &= ymask; int firstline = y; int lastline = y + (tile_h - 1); - lastline &= 0x1ff; + lastline &= ymask; const spg_renderer_device::blend_enable_t blend = (attr & 0x4000) ? BlendOn : BlendOff; - const spg_renderer_device::flipx_t flip_x = (attr & 0x0004) ? FlipXOn : FlipXOff; + spg_renderer_device::flipx_t flip_x = (attr & 0x0004) ? FlipXOn : FlipXOff; 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; + uint8_t blendlevel = (m_video_regs_2a & 3) << 6; + + uint32_t words_per_tile; + + // good for gormiti, smartfp, wrlshunt, paccon, jak_totm, jak_s500, jak_gtg + if (has_extended_sprites && ((m_video_regs_42 & 0x0010) == 0x10)) + { + // paccon and smartfp use this mode + words_per_tile = 8; + + if (!alt_extrasprite_hack) // 1 extra word for each sprite + { + // before or after the 0 tile check? + tile |= (spriteram[(base_addr / 4) + 0x400] & 0x01ff) << 16; + blendlevel = ((spriteram[(base_addr / 4) + 0x400] & 0x3e00) >> 9) << 3; + } + else // jak_prft - no /4 to offset in this mode - 4 extra words per sprite instead ? (or is RAM content incorrect for one of these cases?) + { + tile |= spriteram[(base_addr) + 0x400] << 16; + blendlevel = ((spriteram[(base_addr) + 0x400] & 0x3e00) >> 9) << 3; + } + } + else + { + words_per_tile = bits_per_row * tile_h; + } + bool flip_y = (attr & 0x0008); + + // various games don't want the flip bits in the usual place, wrlshunt for example, there's probably a bit to control this + // and likewise these bits probably now have a different meaning, so this shouldn't be trusted + if (has_extended_sprites) + { + if (highres || alt_extrasprite_hack) + { + flip_x = FlipXOff; + flip_y = 0; + } + } + uint32_t palette_offset = (attr & 0x0f00) >> 4; + if (has_extended_sprites) + { + // guess, tkmag220 / myac220 don't set this bit and expect all sprite palettes to be from the same bank as background palettes + if (palbank & 1) + palette_offset |= 0x100; + + // many other gpl16250 sets have this bit set when they want the upper 256 colours on a per-sprite basis, seems like an extended feature + if (attr & 0x8000) + palette_offset |= 0x200; + } + // the Circuit Racing game in PDC100 needs this or some graphics have bad colours at the edges when turning as it leaves stray lower bits set palette_offset >>= nc_bpp; palette_offset <<= nc_bpp; - if (firstline < lastline) { int scanx = scanline - firstline; if ((scanx >= 0) && (scanline <= lastline)) { - draw_tilestrip(blend, flip_x, cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile, spc, paletteram); + draw_tilestrip(read_from_csspace, screenwidth, xmask, blend, flip_x, cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile, spc, paletteram, blendlevel); } } else @@ -446,7 +705,7 @@ void spg_renderer_device::draw_sprite(const rectangle& cliprect, uint32_t* dst, if ((scanx >= 0) && (scanline <= templastline)) { - draw_tilestrip(blend, flip_x, cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile, spc, paletteram); + draw_tilestrip(read_from_csspace, screenwidth, xmask, blend, flip_x, cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile, spc, paletteram, blendlevel); } // clipped against the bottom tempfirstline = firstline; @@ -455,21 +714,29 @@ void spg_renderer_device::draw_sprite(const rectangle& cliprect, uint32_t* dst, if ((scanx >= 0) && (scanline <= templastline)) { - draw_tilestrip(blend, flip_x, cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile, spc, paletteram); + draw_tilestrip(read_from_csspace, screenwidth, xmask, blend, flip_x, cliprect, dst, tile_h, tile_w, tilegfxdata_addr, tile, scanx, x, flip_y, palette_offset, nc_bpp, bits_per_row, words_per_tile, spc, paletteram, blendlevel); } } } -void spg_renderer_device::draw_sprites(const rectangle &cliprect, uint32_t* dst, uint32_t scanline, int priority, address_space &spc, uint16_t* paletteram, uint16_t* spriteram, int sprlimit) +void spg_renderer_device::draw_sprites(bool read_from_csspace, bool has_extended_sprites, bool alt_extrasprite_hack, uint32_t palbank, bool highres, const rectangle &cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t spritegfxdata_addr, address_space &spc, uint16_t* paletteram, uint16_t* spriteram, int sprlimit) { if (!(m_video_regs_42 & 0x0001)) { return; } + // paccon suggests this, does older hardware have similar (if so, starting at what point?) or only GPL16250? + if (sprlimit == -1) + { + sprlimit = (m_video_regs_42 & 0xff00) >> 8; + if (sprlimit == 0) + sprlimit = 0x100; + } + for (uint32_t n = 0; n < sprlimit; n++) { - draw_sprite(cliprect, dst, scanline, priority, 4 * n, spc, paletteram, spriteram); + draw_sprite(read_from_csspace, has_extended_sprites, alt_extrasprite_hack, palbank, highres, cliprect, dst, scanline, priority, spritegfxdata_addr, 4 * n, spc, paletteram, spriteram); } } diff --git a/src/devices/machine/spg_renderer.h b/src/devices/machine/spg_renderer.h index cbdb7ccd8d2..50ecf6ff11c 100644 --- a/src/devices/machine/spg_renderer.h +++ b/src/devices/machine/spg_renderer.h @@ -14,14 +14,14 @@ public: spg_renderer_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); spg_renderer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - void draw_sprites(const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, address_space& spc, uint16_t* paletteram, uint16_t* spriteram, int sprlimit); - void draw_page(const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t* scrollregs, uint16_t* tilemapregs, address_space& spc, uint16_t* paletteram, uint16_t* scrollram); + void draw_sprites(bool read_from_csspace, bool has_extended_sprites, bool alt_extrasprite_hack, uint32_t palbank, bool highres, const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t spritegfxdata_addr, address_space& spc, uint16_t* paletteram, uint16_t* spriteram, int sprlimit); + void draw_page(bool read_from_csspace, bool has_extended_tilemaps, bool use_alt_tile_addressing, uint32_t palbank, const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t* scrollregs, uint16_t* tilemapregs, address_space& spc, uint16_t* paletteram, uint16_t* scrollram, uint32_t which); + void apply_saturation_and_fade(bitmap_rgb32& bitmap, const rectangle& cliprect, int scanline); void set_video_reg_1c(uint16_t val) { m_video_regs_1c = val; update_vcmp_table(); } void set_video_reg_1d(uint16_t val) { m_video_regs_1d = val; update_vcmp_table(); } void set_video_reg_1e(uint16_t val) { m_video_regs_1e = val; update_vcmp_table(); } - void set_video_reg_22(uint16_t val) { m_video_regs_22 = val; } void set_video_reg_2a(uint16_t val) { m_video_regs_2a = val; } void set_video_reg_30(uint16_t val) { m_video_regs_30 = val; } void set_video_reg_3c(uint16_t val) { m_video_regs_3c = val; } @@ -30,12 +30,18 @@ public: uint16_t get_video_reg_1c(void) { return m_video_regs_1c; } uint16_t get_video_reg_1d(void) { return m_video_regs_1d; } uint16_t get_video_reg_1e(void) { return m_video_regs_1e; } - uint16_t get_video_reg_22(void) { return m_video_regs_22; } uint16_t get_video_reg_2a(void) { return m_video_regs_2a; } uint16_t get_video_reg_30(void) { return m_video_regs_30; } uint16_t get_video_reg_3c(void) { return m_video_regs_3c; } uint16_t get_video_reg_42(void) { return m_video_regs_42; } + // used by some hack logic for the gpl16250 rendering for now + void set_video_reg_7f(uint16_t val) { m_video_regs_7f = val; } + uint16_t get_video_reg_7f(void) { return m_video_regs_7f; } + + auto space_read_callback() { return m_space_read_cb.bind(); } + void set_video_spaces(address_space* cpuspace, address_space* cs_space, int csbase) { m_cpuspace = cpuspace; m_cs_space = cs_space; m_csbase = csbase; } + protected: virtual void device_start() override; @@ -54,22 +60,21 @@ protected: }; template - 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, address_space &spc, uint16_t* palette); - - inline void draw_tilestrip(spg_renderer_device::blend_enable_t blend, spg_renderer_device::flipx_t flip_x, 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& spc, uint16_t* paletteram); + inline void draw_tilestrip(bool read_from_csspace, uint32_t screenwidth, uint32_t drawwidthmask, const rectangle& cliprect, uint32_t* dst, uint32_t tile_h, uint32_t tile_w, uint32_t tilegfxdata_addr, uint32_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 &spc, uint16_t* palette, uint8_t blendlevel); + inline void draw_tilestrip(bool read_from_csspace, uint32_t screenwidth, uint32_t drawwidthmask, spg_renderer_device::blend_enable_t blend, spg_renderer_device::flipx_t flip_x, const rectangle& cliprect, uint32_t* dst, uint32_t tile_h, uint32_t tile_w, uint32_t tilegfxdata_addr, uint32_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& spc, uint16_t* paletteram, uint8_t blendlevel); - void draw_sprite(const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t base_addr, address_space& spc, uint16_t* paletteram, uint16_t* spriteram); + inline void draw_sprite(bool read_from_csspace, bool has_extended_sprites, bool alt_extrasprite_hack, uint32_t palbank, bool highres, const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t spritegfxdata_addr, uint32_t base_addr, address_space& spc, uint16_t* paletteram, uint16_t* spriteram); - 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, spg_renderer_device::blend_enable_t& blend, spg_renderer_device::flipx_t& flip_x, bool& flip_y, uint32_t& palette_offset, address_space& spc); - inline void draw_linemap(const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t* scrollregs, uint16_t* tilemapregs, address_space& spc, uint16_t* paletteram); + inline void draw_linemap(bool has_extended_tilemaps, const rectangle& cliprect, uint32_t* dst, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t* scrollregs, uint16_t* tilemapregs, address_space& spc, uint16_t* paletteram); - uint8_t mix_channel(uint8_t a, uint8_t b); + inline uint8_t mix_channel(uint8_t a, uint8_t b, uint8_t alpha); uint8_t m_rgb5_to_rgb8[32]; uint32_t m_rgb555_to_rgb888[0x8000]; private: + void update_vcmp_table(); uint16_t m_video_regs_1c; @@ -77,14 +82,20 @@ private: uint16_t m_video_regs_1e; uint16_t m_video_regs_2a; - uint16_t m_video_regs_22; uint16_t m_video_regs_42; uint16_t m_video_regs_30; uint16_t m_video_regs_3c; + uint16_t m_video_regs_7f; uint32_t m_ycmp_table[480]; + + devcb_read16 m_space_read_cb; + + address_space* m_cpuspace; + address_space* m_cs_space; + int m_csbase; }; DECLARE_DEVICE_TYPE(SPG_RENDERER, spg_renderer_device) -- cgit v1.2.3