From d42d13b81ee32ded159c852b2874231da6228089 Mon Sep 17 00:00:00 2001 From: Sandro Ronco Date: Sun, 21 Aug 2022 14:19:43 +0200 Subject: Hyperscan: various updates * Fixed hang in X-Men. * Fixed some graphical issues. * Implemented the TVE framebuffer (used in some homebrew demos). --- hash/hyperscan.xml | 2 -- src/devices/cpu/score/score.cpp | 61 ++++++++++++++++++++++++-------------- src/devices/cpu/score/scoredsm.cpp | 9 ++++-- src/devices/machine/spg290_ppu.cpp | 6 ++-- src/mame/tvgames/spg29x.cpp | 34 +++++++++++++++++++-- 5 files changed, 79 insertions(+), 33 deletions(-) diff --git a/hash/hyperscan.xml b/hash/hyperscan.xml index fb247fb7c20..9e656b00334 100644 --- a/hash/hyperscan.xml +++ b/hash/hyperscan.xml @@ -2,8 +2,6 @@ diff --git a/src/devices/cpu/score/score.cpp b/src/devices/cpu/score/score.cpp index 71fad96d0a1..ffa95aee8c7 100644 --- a/src/devices/cpu/score/score.cpp +++ b/src/devices/cpu/score/score.cpp @@ -560,31 +560,34 @@ void score7_cpu_device::op_specialform() } break; case 0x18: // sll - m_gpr[rd] = m_gpr[ra] << (m_gpr[rb] & 0x1f); + r = m_gpr[ra] << (m_gpr[rb] & 0x1f); if (cu) { - CHECK_Z(m_gpr[rd]); - CHECK_N(m_gpr[rd]); + CHECK_Z(r); + CHECK_N(r); SET_C(BIT(m_gpr[ra], 32 - (m_gpr[rb] & 0x1f))); } + m_gpr[rd] = r; break; case 0x1a: // srl - m_gpr[rd] = m_gpr[ra] >> (m_gpr[rb] & 0x1f); + r = m_gpr[ra] >> (m_gpr[rb] & 0x1f); if (cu) { - CHECK_Z(m_gpr[rd]); - CHECK_N(m_gpr[rd]); + CHECK_Z(r); + CHECK_N(r); SET_C(BIT(m_gpr[ra], (m_gpr[rb] & 0x1f) - 1)); } + m_gpr[rd] = r; break; case 0x1b: // sra - m_gpr[rd] = sign_extend(m_gpr[ra] >> (m_gpr[rb] & 0x1f), 32 - (m_gpr[rb] & 0x1f)); + r = sign_extend(m_gpr[ra] >> (m_gpr[rb] & 0x1f), 32 - (m_gpr[rb] & 0x1f)); if (cu) { - CHECK_Z(m_gpr[rd]); - CHECK_N(m_gpr[rd]); + CHECK_Z(r); + CHECK_N(r); SET_C(BIT(m_gpr[ra], (m_gpr[rb] & 0x1f) - 1)); } + m_gpr[rd] = r; break; case 0x1c: // ror unemulated_op("ror"); @@ -661,10 +664,14 @@ void score7_cpu_device::op_specialform() case 0x28: // mfsr if (rb < 3) m_gpr[rd] = m_sr[rb]; + else + logerror("%s: mfsr accessing sr%d (PC=0x%08x)\n", tag(), rb, m_ppc); break; case 0x29: // mtsr if (rb < 3) m_sr[rb] = m_gpr[ra]; + else + logerror("%s: mtsr accessing sr%d (PC=0x%08x)\n", tag(), rb, m_ppc); break; case 0x2a: // t SET_T(check_condition(rb)); @@ -710,31 +717,34 @@ void score7_cpu_device::op_specialform() unemulated_op("sce"); break; case 0x38: // slli - m_gpr[rd] = m_gpr[ra] << rb; + r = m_gpr[ra] << rb; if (cu) { - CHECK_Z(m_gpr[rd]); - CHECK_N(m_gpr[rd]); + CHECK_Z(r); + CHECK_N(r); SET_C(BIT(m_gpr[ra], 32 - rb)); } + m_gpr[rd] = r; break; case 0x3a: // srli - m_gpr[rd] = m_gpr[ra] >> rb; + r = m_gpr[ra] >> rb; if (cu) { - CHECK_Z(m_gpr[rd]); - CHECK_N(m_gpr[rd]); + CHECK_Z(r); + CHECK_N(r); SET_C(BIT(m_gpr[ra], rb - 1)); } + m_gpr[rd] = r; break; case 0x3b: // srai - m_gpr[rd] = sign_extend(m_gpr[ra] >> rb, 32 - rb); + r = sign_extend(m_gpr[ra] >> rb, 32 - rb); if (cu) { - CHECK_Z(m_gpr[rd]); - CHECK_N(m_gpr[rd]); + CHECK_Z(r); + CHECK_N(r); SET_C(BIT(m_gpr[ra], rb - 1)); } + m_gpr[rd] = r; break; case 0x3c: // rori unemulated_op("rori"); @@ -1196,11 +1206,12 @@ void score7_cpu_device::op_rform2() m_gpr[rd] = r; break; case 0x02: // neg! - m_gpr[rd] = 0 - m_gpr[ra]; - CHECK_Z(m_gpr[rd]); - CHECK_N(m_gpr[rd]); - CHECK_V_SUB(0, m_gpr[ra], m_gpr[rd]); + r = 0 - m_gpr[ra]; + CHECK_Z(r); + CHECK_N(r); + CHECK_V_SUB(0, m_gpr[ra], r); CHECK_C_SUB(0, m_gpr[ra]); + m_gpr[rd] = r; break; case 0x03: // cmp! r = m_gpr[rd] - m_gpr[ra]; @@ -1290,9 +1301,12 @@ void score7_cpu_device::op_iform1a() else m_gpr[rd] += 1 << (imm5 & 0xf); - // condition flags are invalid after this instruction + // according to the datasheet, the flags are undefined after this instruction, but xmen expects the Z flag to be valid. + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); break; case 0x01: // slli! + SET_C(BIT(m_gpr[rd], 32 - imm5)); m_gpr[rd] <<= imm5; CHECK_Z(m_gpr[rd]); CHECK_N(m_gpr[rd]); @@ -1301,6 +1315,7 @@ void score7_cpu_device::op_iform1a() unemulated_op("sdbbp!"); break; case 0x03: // srli! + SET_C(BIT(m_gpr[rd], imm5 - 1)); m_gpr[rd] >>= imm5; CHECK_Z(m_gpr[rd]); CHECK_N(m_gpr[rd]); diff --git a/src/devices/cpu/score/scoredsm.cpp b/src/devices/cpu/score/scoredsm.cpp index 257d0416811..074c28a90f5 100644 --- a/src/devices/cpu/score/scoredsm.cpp +++ b/src/devices/cpu/score/scoredsm.cpp @@ -125,7 +125,7 @@ void score7_disassembler::disasm32(std::ostream &stream, offs_t pc, uint32_t opc util::stream_format(stream, "j%s 0x%08x", GET_J_LK(opcode) ? "l": "", (pc & 0xfc000000) | (GET_J_DISP24(opcode) << 1)); break; case 0x03: // RIX-form-1 - util::stream_format(stream, "%s r%d, [R%d, %d]+", m_rix1_op[GET_RIX_FUNC3(opcode)], GET_RIX_RD(opcode), GET_RIX_RA(opcode), sign_extend(GET_RIX_IMM12(opcode), 12)); + util::stream_format(stream, "%s r%d, [r%d, %d]+", m_rix1_op[GET_RIX_FUNC3(opcode)], GET_RIX_RD(opcode), GET_RIX_RA(opcode), sign_extend(GET_RIX_IMM12(opcode), 12)); break; case 0x04: util::stream_format(stream, "b%s%s 0x%08x", m_cond[GET_BC_BC(opcode) & 0x0f], GET_BC_LK(opcode) ? "l": "", pc + (sign_extend(GET_BC_DISP19(opcode), 19) << 1)); @@ -158,7 +158,7 @@ void score7_disassembler::disasm32(std::ostream &stream, offs_t pc, uint32_t opc } break; case 0x07: // RIX-form-2 - util::stream_format(stream, "%s r%d, [R%d]+, %d", m_rix2_op[GET_RIX_FUNC3(opcode)], GET_RIX_RD(opcode), GET_RIX_RA(opcode), sign_extend(GET_RIX_IMM12(opcode), 12)); + util::stream_format(stream, "%s r%d, [r%d]+, %d", m_rix2_op[GET_RIX_FUNC3(opcode)], GET_RIX_RD(opcode), GET_RIX_RA(opcode), sign_extend(GET_RIX_IMM12(opcode), 12)); break; case 0x08: util::stream_format(stream, "addri%s r%d, r%d, %d", GET_RI_CU(opcode) ? ".c": "", GET_RI_RD(opcode), GET_RI_RA(opcode), sign_extend(GET_RI_IMM14(opcode), 14)); @@ -234,7 +234,10 @@ void score7_disassembler::disasm16(std::ostream &stream, offs_t pc, uint16_t opc util::stream_format(stream, "ldiu! r%d, 0x%02x", GET_I2_RD(opcode), GET_I2_IMM8(opcode)); break; case 0x06: // I-form-1a - util::stream_format(stream, "%s! r%d, %d", m_i1a_op[GET_I16_FUNC3(opcode)], GET_I16_RD(opcode), GET_I16_IMM5(opcode)); + if (GET_I16_FUNC3(opcode) == 0) + util::stream_format(stream, "%s! r%d, %d", (GET_I16_IMM5(opcode) & 0x10) ? "subei" : "addei", GET_I16_RD(opcode), GET_I16_IMM5(opcode) & 0x0f); + else + util::stream_format(stream, "%s! r%d, %d", m_i1a_op[GET_I16_FUNC3(opcode)], GET_I16_RD(opcode), GET_I16_IMM5(opcode)); break; case 0x07: // I-form-1b switch(GET_I16_FUNC3(opcode)) diff --git a/src/devices/machine/spg290_ppu.cpp b/src/devices/machine/spg290_ppu.cpp index 19ff7ccb1d2..37f0def0f84 100644 --- a/src/devices/machine/spg290_ppu.cpp +++ b/src/devices/machine/spg290_ppu.cpp @@ -335,14 +335,14 @@ inline rgb_t spg290_ppu_device::blend_colors(const rgb_t &c0, const rgb_t &c1, u if (m_blend_mode & 1) { int r = (c0.r() * level / 63) - (c1.r() * (63 - level) / 63); - int g = (c0.b() * level / 63) - (c1.b() * (63 - level) / 63); + int g = (c0.g() * level / 63) - (c1.g() * (63 - level) / 63); int b = (c0.b() * level / 63) - (c1.b() * (63 - level) / 63); return rgb_t(r, g, b); } else { int r = (c0.r() * level / 63) + (c1.r() * (63 - level) / 63); - int g = (c0.b() * level / 63) + (c1.b() * (63 - level) / 63); + int g = (c0.g() * level / 63) + (c1.g() * (63 - level) / 63); int b = (c0.b() * level / 63) + (c1.b() * (63 - level) / 63); return rgb_t(r, g, b); } @@ -382,7 +382,7 @@ void spg290_ppu_device::blit_sprite(bitmap_rgb32 &bitmap, const rectangle &clipr uint8_t bit_pixel = ((attribute & 3) + 1) << 1; uint8_t sprite_flip = (attribute >> 2) & 0x03; uint16_t pen_bank = ((attribute >> 8) & 0x1f) * 0x10; - uint8_t blend = (attribute & 0x8000) ? (attribute >> 26) & 0x3f : 0; + uint8_t blend = (attribute & 0x8000) ? 0x3f - ((attribute >> 26) & 0x3f) : 0; uint8_t pixel_word = 32 / bit_pixel; uint8_t pixel_byte = 8 / bit_pixel; uint8_t word_line = sprite_hsize / pixel_word; diff --git a/src/mame/tvgames/spg29x.cpp b/src/mame/tvgames/spg29x.cpp index 955c50173b2..76272368592 100644 --- a/src/mame/tvgames/spg29x.cpp +++ b/src/mame/tvgames/spg29x.cpp @@ -9,7 +9,6 @@ HyperScan TODO: - Various graphics glitches - Sound - - X-Men hangs after the first match - USB Hyperscan has a hidden test menu that can be accessed with a specific inputs sequence: @@ -133,6 +132,9 @@ private: uint16_t m_tve_control = 0; uint8_t m_tve_fade_offset = 0; + uint16_t m_timers_clk_sel = 0; + uint8_t m_tve_buffer_ctrl = 3 ; + uint32_t m_tv_start_addr[3] = { 0 }; uint16_t m_gpio_out = 0; }; @@ -176,6 +178,8 @@ private: void spg29x_game_state::timers_clk_sel_w(offs_t offset, uint32_t data, uint32_t mem_mask) { + COMBINE_DATA(&m_timers_clk_sel); + auto clock = 27_MHz_XTAL / ((data & 0xff) + 1); uint32_t mask = 0x100; @@ -239,6 +243,23 @@ uint32_t spg29x_game_state::spg290_screen_update(screen_device &screen, bitmap_r { m_ppu->screen_update(screen, bitmap, cliprect); + // TVE frame buffer + if (m_tve_buffer_ctrl < 3) + { + auto &space = m_maincpu->space(AS_PROGRAM); + const bool interlaced = m_tve_control & 1; + for (int y = cliprect.min_y; y <= cliprect.max_y; y += (interlaced ? 1 : 2)) + for (int x = cliprect.min_x; x <= cliprect.max_x; x++) + { + const uint16_t rgb = space.read_word(m_tv_start_addr[m_tve_buffer_ctrl] + (y * cliprect.width() + x) * 2); + const rgb_t pix = rgb_t(pal5bit(rgb >> 11), pal6bit(rgb >> 5), pal5bit(rgb >> 0)); + + bitmap.pix(y, x) = pix; + if (!interlaced && cliprect.contains(x, y + 1)) + bitmap.pix(y + 1, x) = pix; + } + } + if (m_tve_fade_offset) { int fade_offset = 255 - m_tve_fade_offset; @@ -260,9 +281,12 @@ void spg29x_game_state::spg290_mem(address_map &map) map(0x08030000, 0x08030003).w(FUNC(spg29x_game_state::tve_control_w)).lr32(NAME([this](uint32_t data) { return m_tve_control; })); map(0x0803000c, 0x0803000f).lw32(NAME([this](uint32_t data) { m_tve_fade_offset = data & 0xff; })); + map(0x08070000, 0x0807000b).lr32(NAME([this](offs_t offset) { return m_tv_start_addr[offset]; })); + map(0x08070000, 0x0807000b).lw32(NAME([this](offs_t offset, uint32_t data, uint32_t mem_mask) { COMBINE_DATA(&m_tv_start_addr[offset]); })); + map(0x08090020, 0x08090023).lw32(NAME([this](uint32_t data) { m_tve_buffer_ctrl = data & 3; })); map(0x0807006c, 0x0807006f).lr32(NAME([]() { return 0x01;})); // MUI Status: SDRAM is in the self-refresh mode //map(0x08150000, 0x08150000).lw8(NAME([this](uint8_t data) { printf("%c", data); })); // UART - map(0x082100e4, 0x082100e7).w(FUNC(spg29x_game_state::timers_clk_sel_w)); // Timer Source Clock Selection + map(0x082100e4, 0x082100e7).w(FUNC(spg29x_game_state::timers_clk_sel_w)).lr32(NAME([this]() { return m_timers_clk_sel; })); // Timer Source Clock Selection map(0x08240000, 0x0824000f).noprw(); //map(0x08000000, 0x0800ffff); // CSI @@ -338,6 +362,9 @@ void spg29x_game_state::machine_start() save_item(NAME(m_tve_control)); save_item(NAME(m_tve_fade_offset)); + save_item(NAME(m_timers_clk_sel)); + save_item(NAME(m_tve_buffer_ctrl)); + save_item(NAME(m_tv_start_addr)); save_item(NAME(m_gpio_out)); } @@ -345,6 +372,9 @@ void spg29x_game_state::machine_reset() { m_tve_control = 0; m_tve_fade_offset = 0; + m_timers_clk_sel = 0; + m_tve_buffer_ctrl = 3; + m_tv_start_addr[0] = m_tv_start_addr[1] = m_tv_start_addr[2] = 0; m_gpio_out = 0; // disable JTAG -- cgit v1.2.3