summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author David Haywood <mamehaze@gmail.com>2019-03-29 21:58:02 +0000
committer R. Belmont <rb6502@users.noreply.github.com>2019-03-29 17:58:02 -0400
commitaec15f1f3842e68cbafbccb1f908cce3aaeac89b (patch)
treed7b6040208464063b96d946200314596e91edb4e
parentb9b2a6dd7d64ebe072495b7c596862c3e7d50e6c (diff)
jak_capb - sprite and input improvements (nw) (#4820)
* jak_capb - sprite and input improvements (nw) * use buttons * use a callback here (nw) * shuffle code, refactor slightly (nw) * (nw) * start to make video IRQ logic a bit closer to spg2xx (nw) * spiderman research (nw) * sprite fixes (nw) * different hacks (nw) * flippin' flip bits (nw) * I don't like colour conversion from weird HSL formats (nw) * better transpen (nw) * more flipping (nw)
-rw-r--r--src/devices/machine/spg110.cpp9
-rw-r--r--src/devices/machine/spg110.h1
-rw-r--r--src/devices/machine/spg110_video.cpp284
-rw-r--r--src/devices/machine/spg110_video.h21
-rw-r--r--src/mame/drivers/spg110.cpp80
5 files changed, 227 insertions, 168 deletions
diff --git a/src/devices/machine/spg110.cpp b/src/devices/machine/spg110.cpp
index ddb672233d9..68032a973d5 100644
--- a/src/devices/machine/spg110.cpp
+++ b/src/devices/machine/spg110.cpp
@@ -39,7 +39,10 @@ spg110_device::spg110_device(const machine_config &mconfig, const char *tag, dev
{
}
-
+WRITE_LINE_MEMBER(spg110_device::videoirq_w)
+{
+ m_cpu->set_state_unsynced(UNSP_IRQ0_LINE, state);
+}
void spg110_device::configure_spg_io(spg2xx_io_device* io)
{
@@ -66,6 +69,7 @@ void spg110_device::device_add_mconfig(machine_config &config)
configure_spg_io(m_spg_io);
SPG110_VIDEO(config, m_spg_video, DERIVED_CLOCK(1, 1), m_cpu, m_screen);
+ m_spg_video->write_video_irq_callback().set(FUNC(spg110_device::videoirq_w));
}
WRITE16_MEMBER(spg110_device::spg110_3100_w) { }
@@ -91,7 +95,7 @@ void spg110_device::map(address_map &map)
map(0x002010, 0x002015).rw(m_spg_video, FUNC(spg110_video_device::tmap0_regs_r), FUNC(spg110_video_device::tmap0_regs_w));
map(0x002016, 0x00201b).rw(m_spg_video, FUNC(spg110_video_device::tmap1_regs_r), FUNC(spg110_video_device::tmap1_regs_w));
-#if 0 // more vregs?
+#if 1 // more vregs?
map(0x00201c, 0x00201c).w(m_spg_video, FUNC(spg110_video_device::spg110_201c_w));
map(0x002020, 0x002020).w(m_spg_video, FUNC(spg110_video_device::spg110_2020_w));
@@ -131,6 +135,7 @@ void spg110_device::map(address_map &map)
map(0x002067, 0x002067).w(m_spg_video, FUNC(spg110_video_device::dma_unk_2067_w));
map(0x002068, 0x002068).w(m_spg_video, FUNC(spg110_video_device::dma_src_step_w));
+ map(0x002100, 0x0021ff).ram(); // jak_spdmo only
map(0x002200, 0x0022ff).ram(); // looks like per-pen brightness or similar? strange because palette isn't memory mapped here (maybe rowscroll?)
#if 1 // sound registers? seems to be 8 long entries, only uses up to 0x7f? (register mapping seems similar to spg2xx, maybe with less channels?)
diff --git a/src/devices/machine/spg110.h b/src/devices/machine/spg110.h
index 1cdfc2e19e9..91a715fc755 100644
--- a/src/devices/machine/spg110.h
+++ b/src/devices/machine/spg110.h
@@ -96,6 +96,7 @@ private:
DECLARE_READ16_MEMBER(get_pal_r) { return 0; /*m_pal_flag;*/ }
void configure_spg_io(spg2xx_io_device* io);
+ DECLARE_WRITE_LINE_MEMBER(videoirq_w);
};
DECLARE_DEVICE_TYPE(SPG110, spg110_device)
diff --git a/src/devices/machine/spg110_video.cpp b/src/devices/machine/spg110_video.cpp
index ea5b2dfcb11..799e0653c8a 100644
--- a/src/devices/machine/spg110_video.cpp
+++ b/src/devices/machine/spg110_video.cpp
@@ -19,6 +19,7 @@ spg110_video_device::spg110_video_device(const machine_config &mconfig, device_t
, m_sprtileno(*this, "sprtileno")
, m_sprattr1(*this, "sprattr1")
, m_sprattr2(*this, "sprattr2")
+ , m_video_irq_cb(*this)
{
}
@@ -28,12 +29,10 @@ spg110_video_device::spg110_video_device(const machine_config &mconfig, const ch
}
template<spg110_video_device::flipx_t FlipX>
-void spg110_video_device::draw(const rectangle &cliprect, uint32_t line, uint32_t xoff, uint32_t yoff, uint32_t ctrl, uint32_t bitmap_addr, uint16_t tile, uint8_t pal, int32_t h, int32_t w, uint8_t bpp)
+void spg110_video_device::draw(const rectangle &cliprect, uint32_t line, uint32_t xoff, uint32_t yoff, uint32_t ctrl, uint32_t bitmap_addr, uint16_t tile, uint8_t yflipmask, uint8_t pal, int32_t h, int32_t w, uint8_t bpp)
{
address_space &space = m_cpu->space(AS_PROGRAM);
- uint32_t yflipmask = 0; //attr & TILE_Y_FLIP ? h - 1 : 0;
-
uint32_t nc = (bpp + 1) << 1;
uint32_t palette_offset = pal;
@@ -80,15 +79,17 @@ void spg110_video_device::draw(const rectangle &cliprect, uint32_t line, uint32_
if (xx >= 0 && xx < 320)
{
- // TODO, this is completely wrong for this palette system
int pix_index = xx + y_index;
- //uint16_t rawpal = m_palram[pal];
const pen_t *pens = m_palette->pens();
uint32_t paldata = pens[pal];
- int penword = (pal >> 4) & 0xf;
- int penbit = (pal & 0xf);
- int trans = m_palctrlswapped[penword] & (1 << penbit);
+ int transmap = m_palctrlram[(pal & 0xf0)>>4];
+
+ bool trans = false;
+
+ if (transmap & 0x10) // maybe values other than 0x010 have other meanings, like blending?
+ if ((pal & 0x0f) == (transmap & 0xf))
+ trans = true;
if (!trans)
{
@@ -142,21 +143,21 @@ void spg110_video_device::draw_page(const rectangle &cliprect, uint32_t scanline
extra_attribute = space2.read_word((palette_map*2) + tile_address);
if (x0 & 1)
- extra_attribute = (extra_attribute & 0xff00) >> 8;
- else
extra_attribute = (extra_attribute & 0x00ff);
+ else
+ extra_attribute = (extra_attribute & 0xff00) >> 8;
uint8_t pal = extra_attribute & 0x0f;
- uint8_t pri = (extra_attribute & 0x30)>>4;
+ uint8_t pri = (extra_attribute & 0x30) >> 4;
+ bool flip_x = extra_attribute & 0x40;
if (pri == priority)
{
- bool flip_x = 0;//(tileattr & TILE_X_FLIP);
if (flip_x)
- draw<FlipXOn>(cliprect, tile_scanline, xx, yy, ctrl, bitmap_addr, tile, pal, tile_h, tile_w, bpp);
+ draw<FlipXOn>(cliprect, tile_scanline, xx, yy, ctrl, bitmap_addr, tile, 0, pal, tile_h, tile_w, bpp);
else
- draw<FlipXOff>(cliprect, tile_scanline, xx, yy, ctrl, bitmap_addr, tile, pal, tile_h, tile_w, bpp);
+ draw<FlipXOff>(cliprect, tile_scanline, xx, yy, ctrl, bitmap_addr, tile, 0, pal, tile_h, tile_w, bpp);
}
}
@@ -165,34 +166,33 @@ void spg110_video_device::draw_page(const rectangle &cliprect, uint32_t scanline
void spg110_video_device::draw_sprite(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t base_addr)
{
- uint32_t bitmap_addr = 0;//0x40 * m_video_regs[0x22];
- uint16_t tile = m_sprtileno[base_addr];
- uint16_t attr1 = m_sprattr1[base_addr];
- uint16_t attr2 = m_sprattr2[base_addr];
-
- int x = (attr1 >> 8) & 0xff;
- int y = (attr1) & 0xff;
- uint8_t pri = (attr2 & 0x3000)>>12;
// m_sprtileno tttt tttt tttt tttt t = tile number (all bits?)
// m_sprattr1 xxxx xxxx yyyy yyyy x = low x bits, y = low y bits
- // m_sprattr2 -Xzz pppp hhww --bb X = high x bit z = priority, p = palette h = height w = width b = bpp
+ // m_sprattr2 YXzz pppp hhww fFbb X = high x bit, z = priority, p = palette, h = height, w = width, f = flipy, F = flipx, b = bpp, Y = high y bit
-
- if (!(attr2 & 0x4000))
- x+= 0x100;
+ uint16_t tile = m_sprtileno[base_addr];
if (!tile)
{
return;
}
- // if ((priority==0) && (scanline==128)) printf("%02x, drawing sprite %04x %04x %04x\n", base_addr, tile, attr1, attr2);
+ uint32_t bitmap_addr = 0x40 * m_tilebase;
+ uint16_t attr1 = m_sprattr1[base_addr];
+ uint16_t attr2 = m_sprattr2[base_addr];
- // if (((attr & PAGE_PRIORITY_FLAG_MASK) >> PAGE_PRIORITY_FLAG_SHIFT) != priority)
- // {
- // return;
- // }
+ int x = (attr1 >> 8) & 0xff;
+ int y = (attr1) & 0xff;
+ uint8_t pri = (attr2 & 0x3000)>>12;
+ bool flip_x = (attr2 & 0x0004)>>2;
+ bool flip_y = (attr2 & 0x0008)>>3;
+
+ if (!(attr2 & 0x4000))
+ x+= 0x100;
+
+ if (!(attr2 & 0x8000))
+ y+= 0x100;
const uint32_t h = 8 << ((attr2 & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT);
const uint32_t w = 8 << ((attr2 & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT);
@@ -203,8 +203,11 @@ void spg110_video_device::draw_sprite(const rectangle &cliprect, uint32_t scanli
// y = (120 - y) - (h / 2) + 8;
// }
- y = 0xff - y;
- x = x - 128;
+ y = 0x1ff - y - 128 + 1;
+ x = x - 128 + 32;
+
+ x -= (w / 2);
+ y -= (h / 2);
x &= 0x01ff;
y &= 0x01ff;
@@ -220,17 +223,16 @@ void spg110_video_device::draw_sprite(const rectangle &cliprect, uint32_t scanli
}
//bool blend = (attr & 0x4000);
- bool flip_x = 0;//(attr & TILE_X_FLIP);
const uint8_t bpp = attr2 & 0x0003;
- //const uint32_t yflipmask = attr & TILE_Y_FLIP ? h - 1 : 0;
+ const uint32_t yflipmask = flip_y ? h - 1 : 0;
const uint32_t palette_offset = (attr2 & 0x0f00) >> 8;
if (pri == priority)
{
if (flip_x)
- draw<FlipXOn>(cliprect, tile_line, x, y, 0, bitmap_addr, tile, palette_offset, h, w, bpp);
+ draw<FlipXOn>(cliprect, tile_line, x, y, 0, bitmap_addr, tile, yflipmask, palette_offset, h, w, bpp);
else
- draw<FlipXOff>(cliprect, tile_line, x, y, 0, bitmap_addr, tile, palette_offset, h, w, bpp);
+ draw<FlipXOff>(cliprect, tile_line, x, y, 0, bitmap_addr, tile, yflipmask, palette_offset, h, w, bpp);
}
}
@@ -307,7 +309,7 @@ GFXDECODE_END
void spg110_video_device::device_add_mconfig(machine_config &config)
{
- PALETTE(config, m_palette, palette_device::BLACK, 256);
+ PALETTE(config, m_palette).set_entries(0x100);
GFXDECODE(config, m_gfxdecode, m_palette, gfx);
}
@@ -325,53 +327,62 @@ device_memory_interface::space_config_vector spg110_video_device::memory_space_c
READ16_MEMBER(spg110_video_device::spg110_2063_r)
{
// checks for bits 0x20 and 0x08 in the IRQ function (all IRQs point to the same place)
- return 0x0008;
+
+ // HACK! jak_spdo checks for 0x400 or 0x200 starting some of the games
+ return m_video_irq_status | 0x600;
}
WRITE16_MEMBER(spg110_video_device::spg110_2063_w)
{
// writes 0x28, probably clears the IRQ / IRQ sources? 0x63 is the same offset for this in spg2xx but bits used seem to be different
- m_cpu->set_state_unsynced(UNSP_IRQ0_LINE, CLEAR_LINE);
+ const uint16_t old = m_video_irq_enable & m_video_irq_status;
+ m_video_irq_status &= ~data;
+ const uint16_t changed = old ^ (m_video_irq_enable & m_video_irq_status);
+ if (changed)
+ check_video_irq();
}
-WRITE16_MEMBER(spg110_video_device::spg110_201c_w) { }
-WRITE16_MEMBER(spg110_video_device::spg110_2020_w) { }
-WRITE16_MEMBER(spg110_video_device::spg110_2042_w) { }
-WRITE16_MEMBER(spg110_video_device::spg110_2031_w) { }
-WRITE16_MEMBER(spg110_video_device::spg110_2032_w) { }
-WRITE16_MEMBER(spg110_video_device::spg110_2033_w) { }
-WRITE16_MEMBER(spg110_video_device::spg110_2034_w) { }
-WRITE16_MEMBER(spg110_video_device::spg110_2035_w) { }
-WRITE16_MEMBER(spg110_video_device::spg110_2036_w) { COMBINE_DATA(&m_2036_scroll); }
-WRITE16_MEMBER(spg110_video_device::spg110_2039_w) { }
-WRITE16_MEMBER(spg110_video_device::spg110_2037_w) { }
-WRITE16_MEMBER(spg110_video_device::spg110_203c_w) { }
-WRITE16_MEMBER(spg110_video_device::spg110_203d_w) { }
-WRITE16_MEMBER(spg110_video_device::spg110_2045_w) { }
-
-
-WRITE16_MEMBER(spg110_video_device::spg110_2028_w) { }
-WRITE16_MEMBER(spg110_video_device::spg110_2029_w) { }
+WRITE16_MEMBER(spg110_video_device::spg110_201c_w) { logerror("%s: 201c: %04x\n", machine().describe_context(), data); } // during startup text only
+WRITE16_MEMBER(spg110_video_device::spg110_2020_w) { COMBINE_DATA(&m_tilebase); logerror("%s: 2020: %04x\n", machine().describe_context(), data); } // confirmed as tile base, seems to apply to both layers and sprites, unlike spg2xx which has separate registers
+WRITE16_MEMBER(spg110_video_device::spg110_2028_w) { logerror("%s: 2028: %04x\n", machine().describe_context(), data); } // startup
READ16_MEMBER(spg110_video_device::spg110_2028_r) { return 0x0000; }
+
+WRITE16_MEMBER(spg110_video_device::spg110_2029_w) { logerror("%s: 2029: %04x\n", machine().describe_context(), data); } // 0006, 0008 on startup
READ16_MEMBER(spg110_video_device::spg110_2029_r) { return 0x0000; }
+WRITE16_MEMBER(spg110_video_device::spg110_2031_w) { logerror("%s: 2031: %04x\n", machine().describe_context(), data); } // 014a or 0000 when ball is in trap
+WRITE16_MEMBER(spg110_video_device::spg110_2032_w) { logerror("%s: 2032: %04x\n", machine().describe_context(), data); } // 014a most of the time, 0000 very rarely
+WRITE16_MEMBER(spg110_video_device::spg110_2033_w) { logerror("%s: 2033: %04x\n", machine().describe_context(), data); } // changes, situational, eg when pausing
+WRITE16_MEMBER(spg110_video_device::spg110_2034_w) { logerror("%s: 2034: %04x\n", machine().describe_context(), data); } // 0141 on every scene transition
+WRITE16_MEMBER(spg110_video_device::spg110_2035_w) { logerror("%s: 2035: %04x\n", machine().describe_context(), data); } // 0141 on every scene transition
+WRITE16_MEMBER(spg110_video_device::spg110_2036_w) { logerror("%s: 2036: %04x\n", machine().describe_context(), data); COMBINE_DATA(&m_2036_scroll); } // seems related to ball y position, not scrolling (possibly shadow sprite related?)
+
+READ16_MEMBER(spg110_video_device::spg110_2037_r) { return 0x0000; } // added to something from the PRNG
+WRITE16_MEMBER(spg110_video_device::spg110_2037_w) { logerror("%s: 2037: %04x\n", machine().describe_context(), data); } // 0126 (always?)
+
+WRITE16_MEMBER(spg110_video_device::spg110_2039_w) { logerror("%s: 2039: %04x\n", machine().describe_context(), data); } // 0803 on every scene transition
+
+WRITE16_MEMBER(spg110_video_device::spg110_203c_w) { logerror("%s: 203c: %04x\n", machine().describe_context(), data); } // 0006 on startup, twice
+
+WRITE16_MEMBER(spg110_video_device::spg110_203d_w) { logerror("%s: 203d: %04x\n", machine().describe_context(), data); } // changes, usually between scenes
+
+READ16_MEMBER(spg110_video_device::spg110_2042_r) { return 0x0000; }
+WRITE16_MEMBER(spg110_video_device::spg110_2042_w) { logerror("%s: 2042: %04x\n", machine().describe_context(), data); } // sets bit 0x0004, masks with 0xfffb etc.
+
+WRITE16_MEMBER(spg110_video_device::spg110_2045_w) { logerror("%s: 2045: %04x\n", machine().describe_context(), data); } // 0006 on startup, once
+
WRITE16_MEMBER(spg110_video_device::spg110_205x_w)
{
COMBINE_DATA(&m_palctrlram[offset]);
-
- uint16_t temp = m_palctrlram[offset];
-
- // 0x0010 to 0x0001 - complete guess that this could be pen transparency
- m_palctrlswapped[offset] = bitswap<16>(temp, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2, 1, 0, 7, 6, 5, 4);
}
WRITE16_MEMBER(spg110_video_device::dma_unk_2061_w) { COMBINE_DATA(&m_dma_unk_2061); }
WRITE16_MEMBER(spg110_video_device::dma_dst_step_w) { COMBINE_DATA(&m_dma_dst_step); }
-WRITE16_MEMBER(spg110_video_device::dma_unk_2067_w) { COMBINE_DATA(&m_dma_unk_2067); }
+WRITE16_MEMBER(spg110_video_device::dma_unk_2067_w) { COMBINE_DATA(&m_dma_src_high); }
WRITE16_MEMBER(spg110_video_device::dma_src_step_w) { COMBINE_DATA(&m_dma_src_step); }
WRITE16_MEMBER(spg110_video_device::dma_dst_w) { COMBINE_DATA(&m_dma_dst); }
@@ -382,12 +393,14 @@ WRITE16_MEMBER(spg110_video_device::dma_len_trigger_w)
int length = data & 0x1fff;
// this is presumably a counter that underflows to 0x1fff, because that's what the wait loop waits for?
- logerror("%s: (trigger len) %04x with values (unk) %04x (dststep) %04x (unk) %04x (src step) %04x | (dst) %04x (src) %04x\n", machine().describe_context(), data, m_dma_unk_2061, m_dma_dst_step, m_dma_unk_2067, m_dma_src_step, m_dma_dst, m_dma_src);
+ logerror("%s: (trigger len) %04x with values (unk) %04x (dststep) %04x (unk) %04x (src step) %04x | (dst) %04x (src) %04x\n", machine().describe_context(), data, m_dma_unk_2061, m_dma_dst_step, m_dma_src_high, m_dma_src_step, m_dma_dst, m_dma_src);
- if ((m_dma_unk_2061!=0x0000) || (m_dma_unk_2067 != 0x0000))
- fatalerror("unknown DMA params are not zero!\n");
+ if (m_dma_src_high != 0x0000)
+ {
+ logerror("unknown DMA params are not zero!\n");
+ }
- int source = m_dma_src;
+ int source = m_dma_src | m_dma_src_high << 16;
int dest = m_dma_dst;
for (int i = 0; i < length; i++)
@@ -400,6 +413,26 @@ WRITE16_MEMBER(spg110_video_device::dma_len_trigger_w)
source+=m_dma_src_step;
dest+=m_dma_dst_step;
}
+
+ // not sure, spiderman would suggest that some of these need to reset (unless a missing IRQ clears them)
+ m_dma_unk_2061 = 0;
+ m_dma_dst_step = 0;
+ m_dma_src_high = 0;
+ m_dma_src_step = 0;
+ m_dma_dst = 0;
+ m_dma_src = 0;
+
+ // HACK: it really seems this interrupt status is related to the DMA, but jak_capb doesn't ack it, so must also be a way to disable it?
+ if (m_is_spiderman)
+ {
+ const int i = 0x0002;
+
+ if (m_video_irq_enable & 1)
+ {
+ m_video_irq_status |= i;
+ check_video_irq();
+ }
+ }
}
READ16_MEMBER(spg110_video_device::dma_len_status_r)
@@ -407,8 +440,6 @@ READ16_MEMBER(spg110_video_device::dma_len_status_r)
return 0x1fff; // DMA related?
}
-READ16_MEMBER(spg110_video_device::spg110_2037_r) { return 0x0000; }
-READ16_MEMBER(spg110_video_device::spg110_2042_r) { return 0x0000; }
READ16_MEMBER(spg110_video_device::tmap0_regs_r) { return tmap0_regs[offset]; }
READ16_MEMBER(spg110_video_device::tmap1_regs_r) { return tmap1_regs[offset]; }
@@ -475,7 +506,7 @@ void spg110_video_device::map_video(address_map &map)
map(0x04200, 0x043ff).ram().share("sprattr1");
map(0x04400, 0x045ff).ram().share("sprattr2");
- map(0x08000, 0x081ff).ram().share("palram"); // palette format unknown
+ map(0x08000, 0x081ff).ram().w(FUNC(spg110_video_device::palette_w)).share("palram"); // palette format unknown
}
void spg110_video_device::device_start()
@@ -483,12 +514,19 @@ void spg110_video_device::device_start()
save_item(NAME(m_dma_src_step));
save_item(NAME(m_dma_dst_step));
save_item(NAME(m_dma_unk_2061));
- save_item(NAME(m_dma_unk_2067));
+ save_item(NAME(m_dma_src_high));
save_item(NAME(m_dma_dst));
save_item(NAME(m_dma_src));
save_item(NAME(m_bg_scrollx));
save_item(NAME(m_bg_scrolly));
save_item(NAME(m_2036_scroll));
+
+ m_video_irq_cb.resolve();
+
+ if (!strcmp(machine().system().name, "jak_spdmo"))
+ m_is_spiderman = true;
+ else
+ m_is_spiderman = false;
}
void spg110_video_device::device_reset()
@@ -496,12 +534,16 @@ void spg110_video_device::device_reset()
m_dma_src_step = 0;
m_dma_dst_step = 0;
m_dma_unk_2061 = 0;
- m_dma_unk_2067 = 0;
+ m_dma_src_high = 0;
m_dma_dst = 0;
m_dma_src = 0;
m_bg_scrollx = 0;
m_bg_scrolly = 0;
m_2036_scroll = 0;
+
+ // is there actually an enable register here?
+ m_video_irq_enable = 0xffff;
+ m_video_irq_status = 0x0000;
}
double spg110_video_device::hue2rgb(double p, double q, double t)
@@ -514,46 +556,58 @@ double spg110_video_device::hue2rgb(double p, double q, double t)
return p;
}
-uint32_t spg110_video_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+
+// wrong format!
+WRITE16_MEMBER(spg110_video_device::palette_w)
{
- // Palette, this is still wrong!
- int offs = 0;
- for (int index = 0;index < 256; index++)
- {
- uint16_t dat = m_palram[offs++];
-
- // llll lsss sshh hhhh
- int l_raw = (dat & 0xf800) >> 11;
- int sl_raw = (dat & 0x07c0) >> 6;
- int h_raw = (dat & 0x003f) >> 0;
-
- double l = (double)l_raw / 31.0f;
- double s = (double)sl_raw / 31.0f;
- double h = (double)h_raw / 47.0f;
-
- double r, g, b;
-
- if (s == 0) {
- r = g = b = l; // greyscale
- } else {
- double q = l < 0.5f ? l * (1 + s) : l + s - l * s;
- double p = 2 * l - q;
- r = hue2rgb(p, q, h + 1/3.0f);
- g = hue2rgb(p, q, h);
- b = hue2rgb(p, q, h - 1/3.0f);
- }
+ // probably not
+ const double h_add = 0.65f;
+ const double h_divide = 43.2f;
+
+ COMBINE_DATA(&m_palram[offset]);
+
+ uint16_t dat = m_palram[offset];
+
+ // llll lsss sshh hhhh
+ int l_raw = (dat & 0xfe00) >> 10;
+ int sl_raw = (dat & 0x03c0) >> 6;
+ int h_raw = (dat & 0x003f) >> 0;
- int r_real = r * 255.0f;
- int g_real = g * 255.0f;
- int b_real = b * 255.0f;
+ double l = (double)l_raw / 63.0f;
+ double s = (double)sl_raw / 15.0f;
+ double h = (double)h_raw / h_divide;
- m_palette->set_pen_color(index, r_real, g_real, b_real);
+ // probably not
+ h += h_add;
+
+ if (h>1.0f)
+ h-= 1.0f;
+
+ double r, g, b;
+
+ if (s == 0) {
+ r = g = b = l; // greyscale
+ } else {
+ double q = l < 0.5f ? l * (1 + s) : l + s - l * s;
+ double p = 2 * l - q;
+ r = hue2rgb(p, q, h + 1/3.0f);
+ g = hue2rgb(p, q, h);
+ b = hue2rgb(p, q, h - 1/3.0f);
}
+ int r_real = r * 255.0f;
+ int g_real = g * 255.0f;
+ int b_real = b * 255.0f;
+
+ m_palette->set_pen_color(offset, r_real, g_real, b_real);
+}
+
+uint32_t spg110_video_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
memset(&m_screenbuf[320 * cliprect.min_y], 0, 4 * 320 * ((cliprect.max_y - cliprect.min_y) + 1));
- const uint32_t page1_addr = 0;//0x40 * m_video_regs[0x20];
- const uint32_t page2_addr = 0;//0x40 * m_video_regs[0x21];
+ const uint32_t page1_addr = 0x40 * m_tilebase;//0x40 * m_video_regs[0x20];
+ const uint32_t page2_addr = 0x40 * m_tilebase;//0x40 * m_video_regs[0x21];
uint16_t *page1_regs = tmap0_regs;
uint16_t *page2_regs = tmap1_regs;
@@ -579,9 +633,23 @@ uint32_t spg110_video_device::screen_update(screen_device &screen, bitmap_rgb32
WRITE_LINE_MEMBER(spg110_video_device::vblank)
{
+ const int i = 0x0008;
+
if (!state)
{
- m_cpu->set_state_unsynced(UNSP_IRQ0_LINE, ASSERT_LINE);
+ m_video_irq_status &= ~i;
+ check_video_irq();
+ return;
+ }
+
+ if (m_video_irq_enable & 1)
+ {
+ m_video_irq_status |= i;
+ check_video_irq();
}
- return;
}
+
+void spg110_video_device::check_video_irq()
+{
+ m_video_irq_cb((m_video_irq_status & m_video_irq_enable) ? ASSERT_LINE : CLEAR_LINE);
+} \ No newline at end of file
diff --git a/src/devices/machine/spg110_video.h b/src/devices/machine/spg110_video.h
index e8117ed6e1b..1b8743de54d 100644
--- a/src/devices/machine/spg110_video.h
+++ b/src/devices/machine/spg110_video.h
@@ -9,6 +9,7 @@
#include "cpu/unsp/unsp.h"
#include "emupal.h"
#include "screen.h"
+//#include "machine/timer.h"
class spg110_video_device : public device_t, public device_memory_interface
@@ -80,6 +81,8 @@ public:
DECLARE_WRITE16_MEMBER(tmap0_regs_w);
DECLARE_WRITE16_MEMBER(tmap1_regs_w);
+ auto write_video_irq_callback() { return m_video_irq_cb.bind(); };
+
protected:
virtual void device_start() override;
virtual void device_reset() override;
@@ -123,10 +126,7 @@ private:
required_shared_ptr<uint16_t> m_sprattr1;
required_shared_ptr<uint16_t> m_sprattr2;
-
- uint16_t m_palctrlswapped[0x10];
-
-
+ DECLARE_WRITE16_MEMBER(palette_w);
uint16_t tmap0_regs[0x6];
uint16_t tmap1_regs[0x6];
@@ -134,7 +134,7 @@ private:
uint16_t m_dma_src_step;
uint16_t m_dma_dst_step;
uint16_t m_dma_unk_2061;
- uint16_t m_dma_unk_2067;
+ uint16_t m_dma_src_high;
uint16_t m_dma_dst;
uint16_t m_dma_src;
@@ -143,15 +143,24 @@ private:
uint16_t m_bg_scrolly;
uint16_t m_2036_scroll;
+ uint16_t m_tilebase;
+
+ uint16_t m_video_irq_enable;
+ uint16_t m_video_irq_status;
+ void check_video_irq();
+
void tilemap_write_regs(int which, uint16_t* regs, int regno, uint16_t data);
template<flipx_t FlipX>
- void draw(const rectangle &cliprect, uint32_t line, uint32_t xoff, uint32_t yoff, uint32_t ctrl, uint32_t bitmap_addr, uint16_t tile, uint8_t pal, int32_t h, int32_t w, uint8_t bpp);
+ void draw(const rectangle &cliprect, uint32_t line, uint32_t xoff, uint32_t yoff, uint32_t ctrl, uint32_t bitmap_addr, uint16_t tile, uint8_t yflipmask, uint8_t pal, int32_t h, int32_t w, uint8_t bpp);
void draw_page(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t bitmap_addr, uint16_t *regs);
void draw_sprite(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t base_addr);
void draw_sprites(const rectangle &cliprect, uint32_t scanline, int priority);
uint32_t m_screenbuf[320 * 240];
+ bool m_is_spiderman;
+
+ devcb_write_line m_video_irq_cb;
};
DECLARE_DEVICE_TYPE(SPG110_VIDEO, spg110_video_device)
diff --git a/src/mame/drivers/spg110.cpp b/src/mame/drivers/spg110.cpp
index c05be2940c9..27bfebe6475 100644
--- a/src/mame/drivers/spg110.cpp
+++ b/src/mame/drivers/spg110.cpp
@@ -32,6 +32,8 @@ public:
void spg110_base(machine_config &config);
+ DECLARE_CUSTOM_INPUT_MEMBER(plunger_r);
+
protected:
required_device<unsp_device> m_maincpu;
@@ -78,9 +80,9 @@ static INPUT_PORTS_START( jak_capb )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0080, DEF_STR( On ) )
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Menu")
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_NAME("Left Flipper")
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Nudge")// nudge (motion control)
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_NAME("Right Flipper")
+ PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Left Flipper") // there are 2 physical buttons connected to this
+ PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Nudge")// nudge (motion control)
+ PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Right Flipper") // there are 2 physical buttons connected to this
PORT_DIPNAME( 0x1000, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x1000, DEF_STR( On ) )
@@ -198,59 +200,33 @@ static INPUT_PORTS_START( jak_capb )
PORT_BIT( 0xffff, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("JOYY")
- PORT_BIT(0x0fff, 0x0000, IPT_PEDAL ) PORT_SENSITIVITY(100) PORT_KEYDELTA(100) PORT_MINMAX(0x00,0x0fff) PORT_NAME("Plunger")
+ PORT_BIT( 0x03ff, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(DEVICE_SELF, spg110_game_state, plunger_r, nullptr)
+
+ PORT_START("JOYY_REAL")
+ PORT_BIT(0x00ff, 0x0000, IPT_PEDAL ) PORT_SENSITIVITY(100) PORT_KEYDELTA(100) PORT_MINMAX(0x00,0x00ff) PORT_NAME("Plunger") PORT_CENTERDELTA(255)
INPUT_PORTS_END
+
+CUSTOM_INPUT_MEMBER(spg110_game_state::plunger_r)
+{
+ // this is only needed because our PORT_CENTERDELTA doesn't work if set > 255 (and is limited in the menu to that) such a value that doesn't center quickly enough for the plunger to be effective
+ return ioport("JOYY_REAL")->read()<<2;
+}
+
+
static INPUT_PORTS_START( jak_spdmo )
PORT_START("PA")
- PORT_DIPNAME( 0x0001, 0x0000, "PA" )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x0001, DEF_STR( On ) )
- PORT_DIPNAME( 0x0002, 0x0000, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x0002, DEF_STR( On ) )
- PORT_DIPNAME( 0x0004, 0x0000, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x0004, DEF_STR( On ) )
- PORT_DIPNAME( 0x0008, 0x0000, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x0008, DEF_STR( On ) )
- PORT_DIPNAME( 0x0010, 0x0000, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x0010, DEF_STR( On ) )
- PORT_DIPNAME( 0x0020, 0x0000, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x0020, DEF_STR( On ) )
- PORT_DIPNAME( 0x0040, 0x0000, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x0040, DEF_STR( On ) )
- PORT_DIPNAME( 0x0080, 0x0000, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x0080, DEF_STR( On ) )
- PORT_DIPNAME( 0x0100, 0x0000, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x0100, DEF_STR( On ) )
- PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x0200, DEF_STR( On ) )
- PORT_DIPNAME( 0x0400, 0x0000, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x0400, DEF_STR( On ) )
- PORT_DIPNAME( 0x0800, 0x0000, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x0800, DEF_STR( On ) )
- PORT_DIPNAME( 0x1000, 0x0000, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x1000, DEF_STR( On ) )
- PORT_DIPNAME( 0x2000, 0x0000, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x2000, DEF_STR( On ) )
- PORT_DIPNAME( 0x4000, 0x0000, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x4000, DEF_STR( On ) )
- PORT_DIPNAME( 0x8000, 0x0000, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x8000, DEF_STR( On ) )
+ PORT_BIT( 0x001f, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Menu / Pause")
+ PORT_BIT( 0x00c0, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_BUTTON4 )
+ PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_BUTTON3 )
+ PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_BUTTON2 )
+ PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_BUTTON1 )
+ PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_NAME("Joypad Right")
+ PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_NAME("Joypad Left")
+ PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_NAME("Joypad Down")
+ PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_NAME("Joypad Up")
PORT_START("PB")
PORT_DIPNAME( 0x0001, 0x0000, "PB" )