summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author David Haywood <28625134+DavidHaywood@users.noreply.github.com>2020-06-04 21:09:03 +0100
committer GitHub <noreply@github.com>2020-06-04 16:09:03 -0400
commit370807115062124fd7304101665eb2d51a56f32f (patch)
tree62870766fa6a426947fa17fc4d013aaf3f6d2637
parent509a99b6c0d4774c064a72e4cb867985b388c3be (diff)
SunPlus refactoring checkpoint (nw) (#6793)
-rw-r--r--src/devices/machine/generalplus_gpl16250soc.cpp4
-rw-r--r--src/devices/machine/generalplus_gpl16250soc_video.cpp738
-rw-r--r--src/devices/machine/generalplus_gpl16250soc_video.h38
-rw-r--r--src/devices/machine/spg2xx_video.cpp11
-rw-r--r--src/devices/machine/spg_renderer.cpp519
-rw-r--r--src/devices/machine/spg_renderer.h35
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<gcm394_base_video_device::blend_enable_t Blend, gcm394_base_video_device::rowscroll_enable_t RowScroll, gcm394_base_video_device::flipx_t FlipX>
-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<BlendOn, RowScrollOn, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode);
- else
- draw<BlendOn, RowScrollOn, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode);
- }
- else
- {
- if (flip_x)
- draw<BlendOn, RowScrollOff, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode);
- else
- draw<BlendOn, RowScrollOff, FlipXOff>(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<BlendOff, RowScrollOn, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode);
- else
- draw<BlendOff, RowScrollOn, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode);
- }
- else
- {
- if (flip_x)
- draw<BlendOff, RowScrollOff, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode);
- else
- draw<BlendOff, RowScrollOff, FlipXOff>(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<BlendOn, RowScrollOff, FlipXOn>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, addressing_mode);
- else
- draw<BlendOn, RowScrollOff, FlipXOff>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, addressing_mode);
- }
- else
- {
- if (flip_x)
- draw<BlendOff, RowScrollOff, FlipXOn>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, addressing_mode);
- else
- draw<BlendOff, RowScrollOff, FlipXOff>(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<blend_enable_t Blend, rowscroll_enable_t RowScroll, flipx_t FlipX>
- 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<unsp_device> m_cpu;
required_device<screen_device> m_screen;
-// required_shared_ptr<uint16_t> 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<palette_device> m_palette;
@@ -263,6 +235,10 @@ protected:
int m_alt_tile_addressing;
required_device<spg_renderer_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<spg_renderer_device::blend_enable_t Blend, spg_renderer_device::flipx_t FlipX>
-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<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, spc, paletteram);
+ draw_tilestrip<BlendOn, FlipXOn>(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<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, spc, paletteram);
+ draw_tilestrip<BlendOn, FlipXOff>(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<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, spc, paletteram);
+ draw_tilestrip<BlendOff, FlipXOn>(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<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, spc, paletteram);
+ draw_tilestrip<BlendOff, FlipXOff>(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<spg_renderer_device::blend_enable_t Blend, spg_renderer_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, 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)