// license:BSD-3-Clause // copyright-holders:Ryan Holtz /****************************************************************************** * * Sony Playstation 2 Graphics Synthesizer device skeleton * * To Do: * Everything * */ #include "emu.h" #include "ps2gs.h" DEFINE_DEVICE_TYPE(SONYPS2_GS, ps2_gs_device, "ps2gs", "Playstation 2 GS") /*static*/ size_t const ps2_gs_device::FORMAT_PIXEL_WIDTHS[] = { 32, 24, 16, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 8, 4, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 32, 24, 16, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0 }; /*static*/ char const *const ps2_gs_device::FORMAT_NAMES[] = { "PSMCT32", "PSMCT24", "PSMCT16", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "PCMCT16S", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "PSMT8", "PSMT4", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "PSMT8H", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "PSMT4HL", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "PSMT4HH", "Unknown", "Unknown", "Unknown", "PSMZ32", "PSMZ24", "PSMZ16", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "PSMZ16S", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown" }; /*static*/ uint32_t const ps2_gs_device::KICK_COUNTS[] = { 1, 2, 2, 3, 3, 3, 2, 1 }; ps2_gs_device::ps2_gs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, SONYPS2_GS, tag, owner, clock) , m_intc(*this, finder_base::DUMMY_TAG) , m_vu1(*this, finder_base::DUMMY_TAG) , m_gif(*this, "gif") { } ps2_gs_device::~ps2_gs_device() { } void ps2_gs_device::device_add_mconfig(machine_config &config) { SONYPS2_GIF(config, m_gif, clock(), DEVICE_SELF, m_vu1); } void ps2_gs_device::device_start() { save_item(NAME(m_bitbltbuf)); save_item(NAME(m_src_buf_base)); save_item(NAME(m_src_buf_width)); save_item(NAME(m_src_buf_fmt)); save_item(NAME(m_dst_buf_base)); save_item(NAME(m_dst_buf_width)); save_item(NAME(m_dst_buf_fmt)); save_item(NAME(m_trx_pos)); save_item(NAME(m_src_ul_x)); save_item(NAME(m_src_ul_y)); save_item(NAME(m_dst_ul_x)); save_item(NAME(m_dst_ul_y)); save_item(NAME(m_copy_dir)); save_item(NAME(m_trx_reg)); save_item(NAME(m_trx_width)); save_item(NAME(m_trx_height)); save_item(NAME(m_trx_dir)); save_item(NAME(m_base_regs)); save_item(NAME(m_pmode)); save_item(NAME(m_read_circuit_enable)); save_item(NAME(m_use_fixed_alpha)); save_item(NAME(m_alpha_out_select)); save_item(NAME(m_blend_to_background)); save_item(NAME(m_fixed_alpha)); save_item(NAME(m_smode2)); save_item(NAME(m_interlace)); save_item(NAME(m_frame_interlace)); save_item(NAME(m_dpms_mode)); save_item(NAME(m_dispfb)); save_item(NAME(m_dispfb_base)); save_item(NAME(m_dispfb_width)); save_item(NAME(m_dispfb_format)); save_item(NAME(m_dispfb_x)); save_item(NAME(m_dispfb_y)); save_item(NAME(m_display)); save_item(NAME(m_display_xpos)); save_item(NAME(m_display_ypos)); save_item(NAME(m_magh)); save_item(NAME(m_magv)); save_item(NAME(m_display_width)); save_item(NAME(m_display_height)); save_item(NAME(m_bgcolor)); save_item(NAME(m_bg_r)); save_item(NAME(m_bg_g)); save_item(NAME(m_bg_b)); save_item(NAME(m_csr)); save_item(NAME(m_imr)); save_item(NAME(m_busdir)); save_item(NAME(m_sig_label_id)); save_item(NAME(m_vertex_count)); save_item(NAME(m_kick_count)); save_item(NAME(m_context[0].m_xyoffset)); save_item(NAME(m_context[0].m_offset_x)); save_item(NAME(m_context[0].m_offset_y)); save_item(NAME(m_context[0].m_scissor)); save_item(NAME(m_context[0].m_scissor_x0)); save_item(NAME(m_context[0].m_scissor_x1)); save_item(NAME(m_context[0].m_scissor_y0)); save_item(NAME(m_context[0].m_scissor_y1)); save_item(NAME(m_context[0].m_test)); save_item(NAME(m_context[0].m_alpha_test)); save_item(NAME(m_context[0].m_alpha_func)); save_item(NAME(m_context[0].m_alpha_ref)); save_item(NAME(m_context[0].m_alpha_fail)); save_item(NAME(m_context[0].m_dstalpha_test)); save_item(NAME(m_context[0].m_dstalpha_pass1)); save_item(NAME(m_context[0].m_depth_test)); save_item(NAME(m_context[0].m_depth_func)); save_item(NAME(m_context[0].m_frame)); save_item(NAME(m_context[0].m_fb_base)); save_item(NAME(m_context[0].m_fb_format)); save_item(NAME(m_context[0].m_fb_width)); save_item(NAME(m_context[0].m_fb_mask)); save_item(NAME(m_context[0].m_zbuf)); save_item(NAME(m_context[0].m_z_base)); save_item(NAME(m_context[0].m_z_format)); save_item(NAME(m_context[0].m_z_mask)); save_item(NAME(m_context[1].m_xyoffset)); save_item(NAME(m_context[1].m_offset_x)); save_item(NAME(m_context[1].m_offset_y)); save_item(NAME(m_context[1].m_scissor)); save_item(NAME(m_context[1].m_scissor_x0)); save_item(NAME(m_context[1].m_scissor_x1)); save_item(NAME(m_context[1].m_scissor_y0)); save_item(NAME(m_context[1].m_scissor_y1)); save_item(NAME(m_context[1].m_test)); save_item(NAME(m_context[1].m_alpha_test)); save_item(NAME(m_context[1].m_alpha_func)); save_item(NAME(m_context[1].m_alpha_ref)); save_item(NAME(m_context[1].m_alpha_fail)); save_item(NAME(m_context[1].m_dstalpha_test)); save_item(NAME(m_context[1].m_dstalpha_pass1)); save_item(NAME(m_context[1].m_depth_test)); save_item(NAME(m_context[1].m_depth_func)); save_item(NAME(m_context[1].m_frame)); save_item(NAME(m_context[1].m_fb_base)); save_item(NAME(m_context[1].m_fb_format)); save_item(NAME(m_context[1].m_fb_width)); save_item(NAME(m_context[1].m_fb_mask)); save_item(NAME(m_context[1].m_zbuf)); save_item(NAME(m_context[1].m_z_base)); save_item(NAME(m_context[1].m_z_format)); save_item(NAME(m_context[1].m_z_mask)); m_ram = std::make_unique(0x400000/4); m_vertices = std::make_unique(0x10000); // Arbitrary count } void ps2_gs_device::device_reset() { m_bitbltbuf = 0; m_src_buf_base = 0; m_src_buf_width = 0; m_src_buf_fmt = PSMCT32; m_dst_buf_base = 0; m_dst_buf_width = 0; m_dst_buf_fmt = PSMCT32; m_trx_pos = 0; m_src_ul_x = 0; m_src_ul_y = 0; m_dst_ul_x = 0; m_dst_ul_y = 0; m_copy_dir = 0; m_trx_reg = 0; m_trx_width = 0; m_trx_height = 0; m_trx_dir = 0; memset(m_base_regs, 0, sizeof(uint64_t) * 15); m_pmode = 0; memset(m_read_circuit_enable, 0, 2); m_use_fixed_alpha = 0; m_alpha_out_select = 0; m_blend_to_background = 0; m_fixed_alpha = 0; m_smode2 = 0; m_interlace = 0; m_frame_interlace = 0; m_dpms_mode = 0; memset(m_dispfb, 0, sizeof(uint64_t) * 2); memset(m_dispfb_base, 0, sizeof(uint32_t) * 2); memset(m_dispfb_width, 0, sizeof(uint32_t) * 2); memset(m_dispfb_format, 0, sizeof(uint8_t) * 2); memset(m_dispfb_x, 0, sizeof(uint32_t) * 2); memset(m_dispfb_y, 0, sizeof(uint32_t) * 2); memset(m_display, 0, sizeof(uint64_t) * 2); memset(m_display_xpos, 0, sizeof(uint32_t) * 2); memset(m_display_ypos, 0, sizeof(uint32_t) * 2); memset(m_magh, 0, sizeof(uint8_t) * 2); memset(m_magv, 0, sizeof(uint8_t) * 2); memset(m_display_width, 0, sizeof(uint32_t) * 2); memset(m_display_height, 0, sizeof(uint32_t) * 2); m_bgcolor = 0; m_bg_r = 0; m_bg_g = 0; m_bg_b = 0; m_csr = 0; m_imr = 0; m_busdir = 0; m_sig_label_id = 0; memset(m_context, 0, sizeof(context_t) * 2); m_vertex_count = 0; m_kick_count = 0; } READ64_MEMBER(ps2_gs_device::priv_regs0_r) { uint64_t ret = m_base_regs[offset >> 1]; switch (offset) { case 0x00: ret = m_pmode; logerror("%s: regs0_r: PMODE (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; case 0x04: ret = m_smode2; logerror("%s: regs0_r: SMODE2 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; case 0x0e: case 0x12: ret = m_dispfb[(offset - 0x0e) / 4]; logerror("%s: regs0_r: DISPFB2 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; case 0x10: case 0x14: ret = m_display[(offset - 0x10) / 4]; logerror("%s: regs0_r: DISPLAY2 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; case 0x1c: ret = m_bgcolor; logerror("%s: regs0_r: BGCOLOR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; case 0x02: logerror("%s: regs0_r: SMODE1 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; case 0x06: logerror("%s: regs0_r: SRFSH (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; case 0x08: logerror("%s: regs0_r: SYNCH1 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; case 0x0a: logerror("%s: regs0_r: SYNCH2 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; case 0x0c: logerror("%s: regs0_r: SYNCV (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; case 0x16: logerror("%s: regs0_r: EXTBUF (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; case 0x18: logerror("%s: regs0_r: EXTDATA (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; case 0x1a: logerror("%s: regs0_r: EXTWRITE (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; default: logerror("%s: regs0_r: Unknown (%08x)\n", machine().describe_context(), 0x12000000 + (offset << 3)); break; } return ret; } WRITE64_MEMBER(ps2_gs_device::priv_regs0_w) { switch (offset) { case 0x00: // PMODE m_pmode = data; m_read_circuit_enable[0] = BIT(data, 0); m_read_circuit_enable[1] = BIT(data, 1); m_use_fixed_alpha = BIT(data, 5); m_alpha_out_select = BIT(data, 6); m_blend_to_background = BIT(data, 7); m_fixed_alpha = (data >> 8) & 0xff; logerror("%s: regs0_w: PMODE = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break; case 0x04: // SMODE2 m_smode2 = data; m_interlace = BIT(data, 0); m_frame_interlace = BIT(data, 1); m_dpms_mode = (data >> 2) & 3; logerror("%s: regs0_w: SMODE2 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break; case 0x0e: // DISPFB1 case 0x12: // DISPFB2 { const uint8_t index = (offset - 0x0e) / 4; m_dispfb[index] = data; m_dispfb_base[index] = (data & 0x1ff) << 11; m_dispfb_width[index] = (data & 0x7e00) >> 3; m_dispfb_format[index] = (data >> 15) & 0x1f; m_dispfb_x[index] = (data >> 32) & 0x7ff; m_dispfb_y[index] = (data >> 42) & 0x7ff; logerror("%s: regs0_w: DISPFB%d = %08x%08x\n", machine().describe_context(), index + 1, (uint32_t)(data >> 32), (uint32_t)data); break; } case 0x10: // DISPLAY1 case 0x14: // DISPLAY2 { const uint8_t index = (offset - 0x10) / 4; m_display[index] = data; m_display_xpos[index] = data & 0xfff; m_display_ypos[index] = (data >> 12) & 0x7ff; m_magh[index] = (data >> 23) & 0xf; m_magv[index] = (data >> 27) & 3; m_display_width[index] = (data >> 32) & 0xfff; m_display_height[index] = (data >> 44) & 0x7ff; logerror("%s: regs0_w: DISPLAY%d = %08x%08x\n", machine().describe_context(), index + 1, (uint32_t)(data >> 32), (uint32_t)data); break; } case 0x1c: // BGCOLOR m_bgcolor = data; m_bg_r = data & 0xff; m_bg_g = (data >> 8) & 0xff; m_bg_b = (data >> 16) & 0xff; logerror("%s: regs0_w: BGCOLOR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break; case 0x02: logerror("%s: regs0_w: SMODE1 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break; case 0x06: logerror("%s: regs0_w: SRFSH = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break; case 0x08: logerror("%s: regs0_w: SYNCH1 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break; case 0x0a: logerror("%s: regs0_w: SYNCH2 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break; case 0x0c: logerror("%s: regs0_w: SYNCV = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break; case 0x16: logerror("%s: regs0_w: EXTBUF = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break; case 0x18: logerror("%s: regs0_w: EXTDATA = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break; case 0x1a: logerror("%s: regs0_w: EXTWRITE = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break; default: logerror("%s: regs0_w: Unknown %08x = %08x%08x\n", machine().describe_context(), 0x12000000 + (offset << 3), (uint32_t)(data >> 32), (uint32_t)data); break; } m_base_regs[offset >> 1] = data; } READ64_MEMBER(ps2_gs_device::priv_regs1_r) { uint64_t ret = 0; switch (offset) { case 0x00: ret = m_csr | (CSR_REV | CSR_ID | CSR_FIFO_EMPTY); logerror("%s: regs1_r: CSR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; case 0x02: ret = m_imr; logerror("%s: regs1_r: IMR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; case 0x08: ret = m_busdir; logerror("%s: regs1_r: BUSDIR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; case 0x10: ret = m_sig_label_id; logerror("%s: regs1_r: SIGLBLID (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; default: logerror("%s: regs1_r: Unknown (%08x)\n", machine().describe_context(), 0x12000000 + (offset << 3)); break; } return ret; } WRITE64_MEMBER(ps2_gs_device::priv_regs1_w) { switch (offset) { case 0x00: logerror("%s: regs1_w: CSR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); m_csr = data &~ (CSR_RESET | CSR_SIGNAL | CSR_HSINT | CSR_VSINT | CSR_EDWINT | CSR_FLUSH); //m_csr |= (CSR_SIGNAL | CSR_HSINT | CSR_VSINT | CSR_EDWINT | CSR_FLUSH); break; case 0x02: logerror("%s: regs1_w: IMR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); m_imr = data; break; case 0x08: logerror("%s: regs1_w: BUSDIR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); m_busdir = data; break; case 0x10: logerror("%s: regs1_w: SIGLBLID = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); m_sig_label_id = data; break; default: logerror("%s: regs1_w: Unknown %08x = %08x%08x\n", machine().describe_context(), 0x12000000 + (offset << 3), (uint32_t)(data >> 32), (uint32_t)data); break; } } void ps2_gs_device::write_packed(const uint8_t reg, const uint64_t hi, const uint64_t lo) { switch (reg) { case 0x0e: regs_w(machine().dummy_space(), (uint32_t)hi, lo, ~0ULL); break; default: logerror("%s: write_packed: Unknown register %02x = %08x%08x%08x%08x\n", machine().describe_context(), reg, (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo); break; } } WRITE64_MEMBER(ps2_gs_device::regs_w) { static char const *const dir_strs[4] = { "Host->Local", "Local->Host", "Local->Local", "None" }; static char const *const prim_strs[8] = { "Point", "Line", "Line Strip", "Tri", "Tri Strip", "Tri Fan", "Sprite", "Invalid" }; switch (offset) { case 0x00: // PRIM m_prim = data; m_prim_type = data & 7; m_gouraud_enable = BIT(data, 3); m_texture_enable = BIT(data, 4); m_fog_enable = BIT(data, 5); m_blend_enable = BIT(data, 6); m_aa_enable = BIT(data, 7); m_no_perspective = BIT(data, 8); m_curr_context = (data >> 9) & 1; m_fix_fragments = BIT(data, 10); m_kick_count = KICK_COUNTS[m_prim_type]; logerror("%s: regs_w: PRIM = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); logerror("%s TYPE=%s GOUR=%d TEX=%d FOG=%d BLEND=%d\n", machine().describe_context(), prim_strs[m_prim_type], BIT(data, 3), BIT(data, 4), BIT(data, 5), BIT(data, 6)); logerror("%s AA=%d NOPERSP=%d CONTEXT=%d FIXFRAG=%d\n", machine().describe_context(), BIT(data, 7), BIT(data, 8), BIT(data, 9), BIT(data, 10)); break; case 0x01: // RGBAQ { m_rgbaq = data; m_vc_r = data & 0xff; m_vc_g = (data >> 8) & 0xff; m_vc_b = (data >> 16) & 0xff; m_vc_a = (data >> 24) & 0xff; uint32_t q = (uint32_t)(data >> 32); m_q = *reinterpret_cast(&q); logerror("%s: regs_w: RGBAQ = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); logerror("%s R=%02x G=%02x B=%02x A=%02x Q=%f\n", machine().describe_context(), m_vc_r, m_vc_g, m_vc_b, m_vc_a, m_q); break; } case 0x05: // XYZ2 { uint16_t x = (uint16_t)data; uint16_t y = (uint16_t)(data >> 16); uint32_t z = (uint32_t)(data >> 32); m_vertices[m_vertex_count] = { x, y, z, m_vc_r, m_vc_g, m_vc_b, m_vc_a, m_q, 0, 0, 0 // TODO: U/S, V/T, fog }; m_vertex_count++; logerror("%s: regs_w: XYZ2 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); logerror("%s: X=%f Y=%f Z=%08x\n", machine().describe_context(), x / 16.0f, y / 16.0f, z); if (m_vertex_count >= m_kick_count) { logerror("%s: Should begin primitive drawing...\n", machine().describe_context()); switch (m_prim_type & 7) { case PRIM_TYPE_LINE_STRIP: m_vertices[0] = m_vertices[m_vertex_count - 1]; m_vertex_count = 1; m_kick_count = 1; break; case PRIM_TYPE_TRI_STRIP: case PRIM_TYPE_TRI_FAN: m_vertices[0] = m_vertices[m_vertex_count - 2]; m_vertices[1] = m_vertices[m_vertex_count - 1]; m_vertex_count = 2; m_kick_count = 1; break; case PRIM_TYPE_POINT: case PRIM_TYPE_LINE: case PRIM_TYPE_TRI: case PRIM_TYPE_SPRITE: case PRIM_TYPE_INVALID: default: m_vertex_count = 0; m_kick_count = 0; break; } } break; } case 0x18: // XYOFFSET1 case 0x19: // XYOFFSET2 { const uint8_t index = offset - 0x18; m_context[index].m_xyoffset = data; m_context[index].m_offset_x = data & 0xffff; m_context[index].m_offset_y = (data >> 32) & 0xffff; logerror("%s: regs_w: XYFOFFSET%d = %08x%08x\n", machine().describe_context(), index + 1, (uint32_t)(data >> 32), (uint32_t)data); logerror("%s X=%f Y=%f\n", machine().describe_context(), m_context[index].m_offset_x / 16.0f, m_context[index].m_offset_y / 16.0f); break; } case 0x1a: // PRMODECONT m_prmodecont = data; m_use_prim_for_attrs = BIT(data, 0); logerror("%s: regs_w: PRMODECONT = %08x%08x, %s\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data, m_use_prim_for_attrs ? "Use PRIM" : "Use PRMODE"); break; case 0x40: // SCISSOR1 case 0x41: // SCISSOR2 { const uint8_t index = offset - 0x40; m_context[index].m_scissor = data; m_context[index].m_scissor_x0 = data & 0x7ff; m_context[index].m_scissor_x1 = (data >> 16) & 0x7ff; m_context[index].m_scissor_y0 = (data >> 32) & 0x7ff; m_context[index].m_scissor_y1 = (data >> 48) & 0x7ff; logerror("%s: regs_w: SCISSOR%d = %08x%08x\n", machine().describe_context(), index + 1, (uint32_t)(data >> 32), (uint32_t)data); logerror("%s X0=d Y0=%d X1=%d Y1=%d\n", machine().describe_context(), m_context[index].m_scissor_x0, m_context[index].m_scissor_y0, m_context[index].m_scissor_x1, m_context[index].m_scissor_y1); break; } case 0x45: // DTHE m_dthe = data; m_dither = BIT(data, 0); logerror("%s: regs_w: DTHE = %08x%08x, %s\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data, m_clamp_color ? "Dither" : "No Dither"); break; case 0x46: // COLCLAMP m_colclamp = data; m_clamp_color = BIT(data, 0); logerror("%s: regs_w: COLCLAMP = %08x%08x, %s\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data, m_clamp_color ? "Clamp Color" : "Wrap Color"); break; case 0x47: // TEST1 case 0x48: // TEST2 { const uint8_t index = offset - 0x47; m_context[index].m_test = data; m_context[index].m_alpha_test = BIT(data, 0); m_context[index].m_alpha_func = (data >> 1) & 7; m_context[index].m_alpha_ref = (data >> 4) & 0xff; m_context[index].m_alpha_fail = (data >> 12) & 3; m_context[index].m_dstalpha_test = BIT(data, 14); m_context[index].m_dstalpha_pass1 = BIT(data, 15); m_context[index].m_depth_test = BIT(data, 16); m_context[index].m_depth_func = (data >> 17) & 3; logerror("%s: regs_w: SCISSOR%d = %08x%08x\n", machine().describe_context(), index + 1, (uint32_t)(data >> 32), (uint32_t)data); logerror("%s X0=d Y0=%d X1=%d Y1=%d\n", machine().describe_context(), m_context[index].m_scissor_x0, m_context[index].m_scissor_y0, m_context[index].m_scissor_x1, m_context[index].m_scissor_y1); break; } case 0x4c: // FRAME1 case 0x4d: // FRAME2 { const uint8_t index = offset - 0x4c; m_context[index].m_frame = data; m_context[index].m_fb_base = (data & 0x1ff) << 11; m_context[index].m_fb_width = (data >> 10) & 0xfc0; m_context[index].m_fb_format = (data >> 24) & 0x3f; m_context[index].m_fb_mask = (uint32_t)(data >> 32); logerror("%s: regs_w: FRAME%d = %08x%08x\n", machine().describe_context(), index + 1, (uint32_t)(data >> 32), (uint32_t)data); logerror("%s BASE=%08x WIDTH=%d FORMAT=%d MASK=%08x\n", machine().describe_context(), m_context[index].m_fb_base, m_context[index].m_fb_width, m_context[index].m_fb_format, m_context[index].m_fb_mask); break; } case 0x4e: // ZBUF1 case 0x4f: // ZBUF2 { const uint8_t index = offset - 0x4e; m_context[index].m_zbuf = data; m_context[index].m_z_base = (data & 0x1ff) << 11; m_context[index].m_z_format = (data >> 24) & 0xf; m_context[index].m_z_mask = BIT(data, 32); logerror("%s: regs_w: ZBUF%d = %08x%08x\n", machine().describe_context(), index + 1, (uint32_t)(data >> 32), (uint32_t)data); logerror("%s BASE=%08x FORMAT=%d MASK=%d\n", machine().describe_context(), m_context[index].m_z_base, m_context[index].m_z_format, BIT(data, 32)); break; } case 0x50: // BITBLTBUF m_bitbltbuf = data; m_src_buf_base = ((uint32_t)m_bitbltbuf & 0x7fff) << 6; m_src_buf_width = ((uint32_t)(m_bitbltbuf >> 16) & 0x3f) << 6; m_src_buf_fmt = (uint8_t)((m_bitbltbuf >> 24) & 0x3f); m_dst_buf_base = ((uint32_t)(m_bitbltbuf >> 32) & 0x7fff) << 6; m_dst_buf_width = ((uint32_t)(m_bitbltbuf >> 48) & 0x3f) << 6; m_dst_buf_fmt = (uint8_t)((m_bitbltbuf >> 56) & 0x3f); logerror("%s: regs_w: BITBLTBUF = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); logerror("%s: SRCBASE=%08x SRCWIDTH=%d SRCFMT=%s\n", machine().describe_context(), m_src_buf_base, m_src_buf_width, FORMAT_NAMES[m_src_buf_fmt]); logerror("%s: DSTBASE=%08x DSTWIDTH=%d DSTFMT=%s\n", machine().describe_context(), m_dst_buf_base, m_dst_buf_width, FORMAT_NAMES[m_dst_buf_fmt]); break; case 0x51: // TRXPOS m_trx_pos = data; m_src_ul_x = (uint32_t)m_trx_pos & 0x7ff; m_src_ul_y = (uint32_t)(m_trx_pos >> 16) & 0x7ff; m_dst_ul_x = (uint32_t)(m_trx_pos >> 32) & 0x7ff; m_dst_ul_y = (uint32_t)(m_trx_pos >> 48) & 0x7ff; m_copy_dir = (uint8_t)(m_trx_pos >> 59) & 3; logerror("%s: regs_w: TRXPOS = %08x%08x, SRCUL=%d,%d DSTUL=%d,%d, DIR=%d\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data, m_src_ul_x, m_src_ul_y, m_dst_ul_x, m_dst_ul_y, m_copy_dir); break; case 0x52: // TRXREG m_trx_reg = data; m_trx_width = (uint32_t)m_trx_reg & 0xfff; m_trx_height = (uint32_t)(m_trx_reg >> 32) & 0xfff; logerror("%s: regs_w: TRXREG = %08x%08x, DIMS=%dx%d\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data, m_trx_width, m_trx_height); break; case 0x53: // TRXDIR m_trx_dir = data & 3; logerror("%s: regs_w: TRXDIR = %08x%08x, %s\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data, dir_strs[m_trx_dir]); break; case 0x54: // HWREG logerror("%s: regs_w: HWREG = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); copy_dword_from_host(data); break; default: logerror("%s: regs_w: Unknown register %02x = %08x%08x\n", machine().describe_context(), offset, (uint32_t)(data >> 32), (uint32_t)data); break; } } void ps2_gs_device::copy_dword_from_host(uint64_t data) { if (m_src_buf_fmt == PSMCT24 || m_src_buf_fmt == PSMZ24) { // Special-case for unevenly-sized data. // TODO: What do we do with leftover data, if any, when an IMAGE transfer finishes? logerror("%s: Unsupported src format: PSMCT24/PSMZ24\n", machine().describe_context()); return; } const size_t bpp = FORMAT_PIXEL_WIDTHS[m_src_buf_fmt]; offs_t dst_offset = (m_dst_buf_base + m_dst_ul_y * m_dst_buf_width + m_dst_ul_x) >> 2; for (size_t shift = 0, index = 0; shift < 64; shift += bpp, index++) { uint64_t src = (data >> shift) & ((1ULL << bpp) - 1ULL); switch (m_dst_buf_fmt) { case PSMCT32: case PSMZ32: { m_ram[dst_offset + index] = (uint32_t)src; break; } case PSMCT24: case PSMZ24: logerror("%s: Unsupported dst format: PSMCT24/PSMZ24\n", machine().describe_context()); break; case PSMCT16: case PSMCT16S: case PSMZ16: case PSMZ16S: { const offs_t dst_shift = ((index & 1) << 4); m_ram[dst_offset + (index >> 1)] &= ~(0x0000ffff << dst_shift); m_ram[dst_offset + (index >> 1)] |= (uint32_t)src << dst_shift; break; } case PSMT8: { const offs_t dst_shift = ((index & 3) << 3); m_ram[dst_offset + (index >> 2)] &= ~(0x000000ff << dst_shift); m_ram[dst_offset + (index >> 2)] |= (uint32_t)src << dst_shift; break; } case PSMT8H: { m_ram[dst_offset + index] &= 0x00ffffff; m_ram[dst_offset + index] |= (uint32_t)src << 24; break; } case PSMT4: { const offs_t dst_shift = ((index & 7) << 2); m_ram[dst_offset + (index >> 3)] &= ~(0x0000000f << dst_shift); m_ram[dst_offset + (index >> 3)] |= (uint32_t)src << dst_shift; break; } case PSMT4HL: m_ram[dst_offset + index] &= 0xf0ffffff; m_ram[dst_offset + index] |= (uint32_t)src << 24; break; case PSMT4HH: m_ram[dst_offset + index] &= 0x0fffffff; m_ram[dst_offset + index] |= (uint32_t)src << 28; break; default: logerror("%s: copy_dword_from_host: Unknown format %02x\n", machine().describe_context(), m_dst_buf_fmt); return; } } } void ps2_gs_device::vblank_start() { } void ps2_gs_device::vblank_end() { m_curr_field ^= 1; if (m_curr_field) m_csr &= ~CSR_FIELD_ODD; else m_csr |= CSR_FIELD_ODD; } ps2_gif_device* ps2_gs_device::interface() { return m_gif.target(); } READ32_MEMBER(ps2_gs_device::gif_r) { return m_gif->read(space, offset, mem_mask); } WRITE32_MEMBER(ps2_gs_device::gif_w) { m_gif->write(space, offset, data, mem_mask); }