From 9d5ecbf980dc99a43d649862d1635945c28b25a0 Mon Sep 17 00:00:00 2001 From: MooglyGuy Date: Tue, 27 Jul 2021 19:09:38 +0200 Subject: N64 video adjustments: 8bpp mode, VI scan-out improvement (#8362) * -n64: Fixed handling of 8bpp framebuffer mode. Adjusted how VI scan-out functions. [Ryan Holtz, krom] * -rdp: Swapped 'magic matrix' dither pattern axes to match hardware tests. [Ryan Holtz, krom] * -n64: Removed unnecessary cast. --- src/mame/machine/n64.cpp | 17 +- src/mame/video/n64.cpp | 624 ++++++++++++++++++++++++++++---------------- src/mame/video/n64.h | 34 ++- src/mame/video/rdptpipe.cpp | 4 +- 4 files changed, 432 insertions(+), 247 deletions(-) diff --git a/src/mame/machine/n64.cpp b/src/mame/machine/n64.cpp index f157cb104ed..1db37e4fe72 100644 --- a/src/mame/machine/n64.cpp +++ b/src/mame/machine/n64.cpp @@ -998,14 +998,14 @@ void n64_periphs::vi_recalculate_resolution() int x_end = vi_hstart & 0x000003ff; int y_start = ((vi_vstart & 0x03ff0000) >> 16) >> 1; int y_end = (vi_vstart & 0x000003ff) >> 1; - int width = ((vi_xscale & 0x00000fff) * (x_end - x_start)) / 0x400; - int height = ((vi_yscale & 0x00000fff) * (y_end - y_start)) / 0x400; + int width = x_end - x_start; + int height = y_end - y_start; rectangle visarea = screen().visible_area(); // DACRATE is the quarter pixel clock and period will be for a field, not a frame attoseconds_t period = (vi_hsync & 0xfff) * (vi_vsync & 0xfff) * HZ_TO_ATTOSECONDS(DACRATE_NTSC) / 2; - if (width == 0 || height == 0 || (vi_control & 3) == 0) + if (width <= 0 || height <= 0 || (vi_control & 3) == 0) { vi_blank = 1; /* @@ -1115,12 +1115,15 @@ void n64_periphs::vi_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask) break; case 0x08/4: // VI_WIDTH_REG - if (vi_width != data && data > 0) { - vi_recalculate_resolution(); + uint32_t old_width = vi_width; + vi_width = data; + if (old_width != data && data > 0) + { + vi_recalculate_resolution(); + } + break; } - vi_width = data; - break; case 0x0c/4: // VI_INTR_REG vi_intr = data; diff --git a/src/mame/video/n64.cpp b/src/mame/video/n64.cpp index 1e4a0a75afe..5268e642323 100644 --- a/src/mame/video/n64.cpp +++ b/src/mame/video/n64.cpp @@ -171,7 +171,7 @@ WRITE_LINE_MEMBER(n64_state::screen_vblank_n64) void n64_periphs::video_update(bitmap_rgb32 &bitmap) { - if(vi_control & 0x40) /* Interlace */ + if (vi_control & 0x40) /* Interlace */ { field ^= 1; } @@ -180,7 +180,7 @@ void n64_periphs::video_update(bitmap_rgb32 &bitmap) field = 0; } - switch(vi_control & 0x3) + switch (vi_control & 0x3) { case PIXEL_SIZE_16BIT: video_update16(bitmap); @@ -210,58 +210,126 @@ void n64_periphs::video_update16(bitmap_rgb32 &bitmap) //uint32_t hb = ((n64->vi_origin & 0xffffff) >> 2) >> 1; //uint8_t* hidden_buffer = &m_hidden_bits[hb]; - int32_t hdiff = (vi_hstart & 0x3ff) - ((vi_hstart >> 16) & 0x3ff); + int32_t hend = vi_hstart & 0x3ff; + int32_t hstart = (vi_hstart >> 16) & 0x3ff; + int32_t hdiff = hend - hstart; float hcoeff = ((float)(vi_xscale & 0xfff) / (1 << 10)); uint32_t hres = ((float)hdiff * hcoeff); - int32_t invisiblewidth = vi_width - hres; - int32_t vdiff = ((vi_vstart & 0x3ff) - ((vi_vstart >> 16) & 0x3ff)) >> 1; + int32_t vend = (vi_vstart & 0x3ff) >> 1; + int32_t vstart = ((vi_vstart >> 16) & 0x3ff) >> 1; + int32_t vdiff = vend - vstart; float vcoeff = ((float)(vi_yscale & 0xfff) / (1 << 10)); uint32_t vres = ((float)vdiff * vcoeff); + fflush(stdout); + if (vdiff <= 0 || hdiff <= 0) { return; } - //if (hres > 640) // Needed by Top Gear Overdrive (E) - //{ - // invisiblewidth += (hres - 640); - // hres = 640; - //} - if (vres > bitmap.height()) // makes Perfect Dark boot w/o crashing { vres = bitmap.height(); } - uint32_t pixels = 0; - if (frame_buffer) { - for(int32_t j = 0; j < vres; j++) + const uint32_t aa_control = (vi_control >> 8) & 3; + float v0 = 0.0f; + if (aa_control < 3) // Resample pixels { - uint32_t *const d = &bitmap.pix(j); + for (int32_t j = 0; j < vdiff; j++, v0 += vcoeff) + { + uint32_t *const d = &bitmap.pix(j); + + float u0 = (float)0.0f; + + int iv0 = (int)v0; + int pix_v0_line = iv0 * vi_width; + + int iv1 = (iv0 >= (vres - 1) ? iv0 : (iv0 + 1)); + int pix_v1_line = iv1 * vi_width; + + for (int32_t i = 0; i < hdiff; i++) + { + int iu0 = (int)u0; + int iu1 = (iu0 >= (hres - 1) ? iu0 : (iu0 + 1)); + uint16_t pix00 = frame_buffer[(pix_v0_line + iu0) ^ WORD_ADDR_XOR]; + uint16_t pix10 = frame_buffer[(pix_v0_line + iu1) ^ WORD_ADDR_XOR]; + uint16_t pix01 = frame_buffer[(pix_v1_line + iu0) ^ WORD_ADDR_XOR]; + uint16_t pix11 = frame_buffer[(pix_v1_line + iu1) ^ WORD_ADDR_XOR]; + + const uint8_t r00 = ((pix00 >> 8) & 0xf8) | (pix00 >> 13); + const uint8_t g00 = ((pix00 >> 3) & 0xf8) | ((pix00 >> 8) & 0x07); + const uint8_t b00 = ((pix00 << 2) & 0xf8) | ((pix00 >> 3) & 0x07); + + const uint8_t r10 = ((pix10 >> 8) & 0xf8) | (pix10 >> 13); + const uint8_t g10 = ((pix10 >> 3) & 0xf8) | ((pix10 >> 8) & 0x07); + const uint8_t b10 = ((pix10 << 2) & 0xf8) | ((pix10 >> 3) & 0x07); + + const uint8_t r01 = ((pix01 >> 8) & 0xf8) | (pix01 >> 13); + const uint8_t g01 = ((pix01 >> 3) & 0xf8) | ((pix01 >> 8) & 0x07); + const uint8_t b01 = ((pix01 << 2) & 0xf8) | ((pix01 >> 3) & 0x07); - for(int32_t i = 0; i < hres; i++) + const uint8_t r11 = ((pix11 >> 8) & 0xf8) | (pix11 >> 13); + const uint8_t g11 = ((pix11 >> 3) & 0xf8) | ((pix11 >> 8) & 0x07); + const uint8_t b11 = ((pix11 << 2) & 0xf8) | ((pix11 >> 3) & 0x07); + + const float ut = u0 - (int)u0; + const float vt = v0 - (int)v0; + + float ur0 = (1.0f - ut) * r00 + ut * r10; + float ug0 = (1.0f - ut) * g00 + ut * g10; + float ub0 = (1.0f - ut) * b00 + ut * b10; + + float ur1 = (1.0f - ut) * r01 + ut * r11; + float ug1 = (1.0f - ut) * g01 + ut * g11; + float ub1 = (1.0f - ut) * b01 + ut * b11; + + float r = (1.0f - vt) * ur0 + vt * ur1; + float g = (1.0f - vt) * ug0 + vt * ug1; + float b = (1.0f - vt) * ub0 + vt * ub1; + + uint8_t r8 = std::clamp((uint8_t)r, (uint8_t)0, (uint8_t)255); + uint8_t g8 = std::clamp((uint8_t)g, (uint8_t)0, (uint8_t)255); + uint8_t b8 = std::clamp((uint8_t)b, (uint8_t)0, (uint8_t)255); + + d[i] = (r8 << 16) | (g8 << 8) | b8; + + u0 += hcoeff; + } + } + } + else // Replicate pixels + { + for (int32_t j = 0; j < vdiff; j++, v0 += vcoeff) { - uint16_t pix = frame_buffer[pixels ^ WORD_ADDR_XOR]; + uint32_t *const d = &bitmap.pix(j); + + int iv0 = (int)v0; + int pix_v0_line = iv0 * vi_width; - const uint8_t r = ((pix >> 8) & 0xf8) | (pix >> 13); - const uint8_t g = ((pix >> 3) & 0xf8) | ((pix >> 8) & 0x07); - const uint8_t b = ((pix << 2) & 0xf8) | ((pix >> 3) & 0x07); - d[i] = (r << 16) | (g << 8) | b; - pixels++; + for (int32_t i = 0; i < hdiff; i++) + { + int u0 = (int)(i * hcoeff); + uint16_t pix = frame_buffer[(pix_v0_line + u0) ^ WORD_ADDR_XOR]; + + const uint8_t r = ((pix >> 8) & 0xf8) | (pix >> 13); + const uint8_t g = ((pix >> 3) & 0xf8) | ((pix >> 8) & 0x07); + const uint8_t b = ((pix << 2) & 0xf8) | ((pix >> 3) & 0x07); + d[i] = (r << 16) | (g << 8) | b; + } } - pixels += invisiblewidth; } } } void n64_periphs::video_update32(bitmap_rgb32 &bitmap) { - int32_t gamma = (vi_control >> 3) & 1; - int32_t gamma_dither = (vi_control >> 2) & 1; + //int32_t gamma = (vi_control >> 3) & 1; + //int32_t gamma_dither = (vi_control >> 2) & 1; //int32_t vibuffering = ((n64->vi_control & 2) && fsaa && divot); uint32_t* frame_buffer32 = (uint32_t*)&m_rdram[(vi_origin & 0xffffff) >> 2]; @@ -269,7 +337,6 @@ void n64_periphs::video_update32(bitmap_rgb32 &bitmap) const int32_t hdiff = (vi_hstart & 0x3ff) - ((vi_hstart >> 16) & 0x3ff); const float hcoeff = ((float)(vi_xscale & 0xfff) / (1 << 10)); uint32_t hres = ((float)hdiff * hcoeff); - int32_t invisiblewidth = vi_width - hres; const int32_t vdiff = ((vi_vstart & 0x3ff) - ((vi_vstart >> 16) & 0x3ff)) >> 1; const float vcoeff = ((float)(vi_yscale & 0xfff) / (1 << 10)); @@ -280,60 +347,89 @@ void n64_periphs::video_update32(bitmap_rgb32 &bitmap) return; } - //if (hres > 640) // Needed by Top Gear Overdrive (E) - //{ - // invisiblewidth += (hres - 640); - // hres = 640; - //} - if (frame_buffer32) { - for (int32_t j = 0; j < vres; j++) + const uint32_t aa_control = (vi_control >> 8) & 3; + float v0 = 0.0f; + if (aa_control < 3) // Resample pixels { - uint32_t *const d = &bitmap.pix(j); - for (int32_t i = 0; i < hres; i++) + for (int32_t j = 0; j < vdiff; j++, v0 += vcoeff) { - uint32_t pix = *frame_buffer32++; - if (gamma || gamma_dither) + uint32_t *const d = &bitmap.pix(j); + + float u0 = 0.0f; + + int iv0 = (int)v0; + int pix_v0_line = iv0 * vi_width; + + int iv1 = (iv0 >= (vres - 1) ? iv0 : (iv0 + 1)); + int pix_v1_line = iv1 * vi_width; + + for (int32_t i = 0; i < hdiff; i++) { - int32_t r = (pix >> 24) & 0xff; - int32_t g = (pix >> 16) & 0xff; - int32_t b = (pix >> 8) & 0xff; - int32_t dith = 0; - if (gamma_dither) - { - dith = get_random() & 0x3f; - } - if (gamma) - { - if (gamma_dither) - { - r = m_gamma_dither_table[(r << 6)| dith]; - g = m_gamma_dither_table[(g << 6)| dith]; - b = m_gamma_dither_table[(b << 6)| dith]; - } - else - { - r = m_gamma_table[r]; - g = m_gamma_table[g]; - b = m_gamma_table[b]; - } - } - else if (gamma_dither) - { - if (r < 255) - r += (dith & 1); - if (g < 255) - g += (dith & 1); - if (b < 255) - b += (dith & 1); - } - pix = (r << 24) | (g << 16) | (b << 8); + int iu0 = (int)u0; + int iu1 = (iu0 >= (hres - 1) ? iu0 : (iu0 + 1)); + uint32_t pix00 = frame_buffer32[pix_v0_line + iu0]; + uint32_t pix10 = frame_buffer32[pix_v0_line + iu1]; + uint32_t pix01 = frame_buffer32[pix_v1_line + iu0]; + uint32_t pix11 = frame_buffer32[pix_v1_line + iu1]; + + const uint8_t r00 = (uint8_t)(pix00 >> 16); + const uint8_t g00 = (uint8_t)(pix00 >> 8); + const uint8_t b00 = (uint8_t)pix00; + + const uint8_t r10 = (uint8_t)(pix01 >> 16); + const uint8_t g10 = (uint8_t)(pix01 >> 8); + const uint8_t b10 = (uint8_t)pix01; + + const uint8_t r01 = (uint8_t)(pix10 >> 16); + const uint8_t g01 = (uint8_t)(pix10 >> 8); + const uint8_t b01 = (uint8_t)pix10; + + const uint8_t r11 = (uint8_t)(pix11 >> 16); + const uint8_t g11 = (uint8_t)(pix11 >> 8); + const uint8_t b11 = (uint8_t)pix11; + + const float ut = u0 - (int)u0; + const float vt = v0 - (int)v0; + + float ur0 = (1.0f - ut) * r00 + ut * r10; + float ug0 = (1.0f - ut) * g00 + ut * g10; + float ub0 = (1.0f - ut) * b00 + ut * b10; + + float ur1 = (1.0f - ut) * r01 + ut * r11; + float ug1 = (1.0f - ut) * g01 + ut * g11; + float ub1 = (1.0f - ut) * b01 + ut * b11; + + float r = (1.0f - vt) * ur0 + vt * ur1; + float g = (1.0f - vt) * ug0 + vt * ug1; + float b = (1.0f - vt) * ub0 + vt * ub1; + + uint8_t r8 = std::clamp((uint8_t)r, (uint8_t)0, (uint8_t)255); + uint8_t g8 = std::clamp((uint8_t)g, (uint8_t)0, (uint8_t)255); + uint8_t b8 = std::clamp((uint8_t)b, (uint8_t)0, (uint8_t)255); + + d[i] = (r8 << 16) | (g8 << 8) | b8; + + u0 += hcoeff; } + } + } + else // Replicate pixels + { + for (int32_t j = 0; j < vdiff; j++, v0 += vcoeff) + { + uint32_t *const d = &bitmap.pix(j); - d[i] = (pix >> 8); + int iv0 = (int)v0; + int pix_v0_line = iv0 * vi_width; + + for (int32_t i = 0; i < hdiff; i++) + { + int u0 = (int)(i * hcoeff); + d[i] = (frame_buffer32[pix_v0_line + u0] >> 8); + } } - frame_buffer32 += invisiblewidth; } } } @@ -603,18 +699,18 @@ void n64_rdp::set_blender_input(int32_t cycle, int32_t which, color_t** input_rg uint8_t const n64_rdp::s_bayer_matrix[16] = { /* Bayer matrix */ - 0, 4, 1, 5, - 6, 2, 7, 3, - 1, 5, 0, 4, - 7, 3, 6, 2 + 0, 4, 1, 5, + 6, 2, 7, 3, + 1, 5, 0, 4, + 7, 3, 6, 2 }; uint8_t const n64_rdp::s_magic_matrix[16] = { /* Magic square matrix */ - 0, 6, 1, 7, - 4, 2, 5, 3, - 3, 5, 2, 4, - 7, 1, 6, 0 + 0, 4, 3, 7, + 6, 2, 5, 1, + 1, 5, 2, 6, + 7, 3, 4, 0 }; z_decompress_entry_t const n64_rdp::m_z_dec_table[8] = @@ -3008,11 +3104,6 @@ void n64_rdp::cmd_set_color_image(uint64_t w1) m_misc_state.m_fb_size = uint32_t(w1 >> 51) & 0x3; m_misc_state.m_fb_width = (uint32_t(w1 >> 32) & 0x3ff) + 1; m_misc_state.m_fb_address = uint32_t(w1) & 0x01ffffff; - - if (m_misc_state.m_fb_format < 2 || m_misc_state.m_fb_format > 32) // Jet Force Gemini sets the format to 4, Intensity. Protection? - { - m_misc_state.m_fb_format = 2; - } } /*****************************************************************************/ @@ -3216,6 +3307,26 @@ n64_rdp::n64_rdp(n64_state &state, uint32_t* rdram, uint32_t* dmem) : poly_manag m_compute_cvg[0] = &n64_rdp::compute_cvg_noflip; m_compute_cvg[1] = &n64_rdp::compute_cvg_flip; + + m_write_pixel[0] = &n64_rdp::write_pixel4; + m_write_pixel[1] = &n64_rdp::write_pixel8; + m_write_pixel[2] = &n64_rdp::write_pixel16; + m_write_pixel[3] = &n64_rdp::write_pixel32; + + m_read_pixel[0] = &n64_rdp::read_pixel4; + m_read_pixel[1] = &n64_rdp::read_pixel8; + m_read_pixel[2] = &n64_rdp::read_pixel16; + m_read_pixel[3] = &n64_rdp::read_pixel32; + + m_copy_pixel[0] = &n64_rdp::copy_pixel4; + m_copy_pixel[1] = &n64_rdp::copy_pixel8; + m_copy_pixel[2] = &n64_rdp::copy_pixel16; + m_copy_pixel[3] = &n64_rdp::copy_pixel32; + + m_fill_pixel[0] = &n64_rdp::fill_pixel4; + m_fill_pixel[1] = &n64_rdp::fill_pixel8; + m_fill_pixel[2] = &n64_rdp::fill_pixel16; + m_fill_pixel[3] = &n64_rdp::fill_pixel32; } void n64_rdp::render_spans(int32_t start, int32_t end, int32_t tilenum, bool flip, extent_t* spans, bool rect, rdp_poly_state* object) @@ -3333,185 +3444,234 @@ void n64_rdp::rgbaz_correct_triangle(int32_t offx, int32_t offy, int32_t* r, int } } -inline void n64_rdp::write_pixel(uint32_t curpixel, color_t& color, rdp_span_aux* userdata, const rdp_poly_state &object) +void n64_rdp::write_pixel4(uint32_t curpixel, color_t& color, rdp_span_aux* userdata, const rdp_poly_state &object) { - if (object.m_misc_state.m_fb_size == 2) // 16-bit framebuffer - { - const uint32_t fb = (object.m_misc_state.m_fb_address >> 1) + curpixel; + // Not yet implemented +} - uint16_t finalcolor; - if (object.m_other_modes.color_on_cvg && !userdata->m_pre_wrap) - { - finalcolor = RREADIDX16(fb) & 0xfffe; - } - else - { - color.shr_imm(3); - finalcolor = (color.get_r() << 11) | (color.get_g() << 6) | (color.get_b() << 1); - } +void n64_rdp::write_pixel8(uint32_t curpixel, color_t& color, rdp_span_aux* userdata, const rdp_poly_state &object) +{ + const uint8_t c = (color.get_r() & 0xf8) | ((color.get_g() & 0xf8) >> 5); + if (c != 0) + RWRITEADDR8(object.m_misc_state.m_fb_address + curpixel, c); +} - switch (object.m_other_modes.cvg_dest) - { - case 0: - if (userdata->m_blend_enable) - { - uint32_t finalcvg = userdata->m_current_pix_cvg + userdata->m_current_mem_cvg; - if (finalcvg & 8) - { - finalcvg = 7; - } - RWRITEIDX16(fb, finalcolor | (finalcvg >> 2)); - HWRITEADDR8(fb, finalcvg & 3); - } - else +void n64_rdp::write_pixel16(uint32_t curpixel, color_t& color, rdp_span_aux* userdata, const rdp_poly_state &object) +{ + const uint32_t fb = (object.m_misc_state.m_fb_address >> 1) + curpixel; + + uint16_t finalcolor; + if (object.m_other_modes.color_on_cvg && !userdata->m_pre_wrap) + { + finalcolor = RREADIDX16(fb) & 0xfffe; + } + else + { + color.shr_imm(3); + finalcolor = (color.get_r() << 11) | (color.get_g() << 6) | (color.get_b() << 1); + } + + switch (object.m_other_modes.cvg_dest) + { + case 0: + if (userdata->m_blend_enable) + { + uint32_t finalcvg = userdata->m_current_pix_cvg + userdata->m_current_mem_cvg; + if (finalcvg & 8) { - const uint32_t finalcvg = (userdata->m_current_pix_cvg - 1) & 7; - RWRITEIDX16(fb, finalcolor | (finalcvg >> 2)); - HWRITEADDR8(fb, finalcvg & 3); + finalcvg = 7; } - break; - case 1: + RWRITEIDX16(fb, finalcolor | (finalcvg >> 2)); + HWRITEADDR8(fb, finalcvg & 3); + } + else { - const uint32_t finalcvg = (userdata->m_current_pix_cvg + userdata->m_current_mem_cvg) & 7; + const uint32_t finalcvg = (userdata->m_current_pix_cvg - 1) & 7; RWRITEIDX16(fb, finalcolor | (finalcvg >> 2)); HWRITEADDR8(fb, finalcvg & 3); - break; } - case 2: - RWRITEIDX16(fb, finalcolor | 1); - HWRITEADDR8(fb, 3); - break; - case 3: - RWRITEIDX16(fb, finalcolor | (userdata->m_current_mem_cvg >> 2)); - HWRITEADDR8(fb, userdata->m_current_mem_cvg & 3); - break; + break; + case 1: + { + const uint32_t finalcvg = (userdata->m_current_pix_cvg + userdata->m_current_mem_cvg) & 7; + RWRITEIDX16(fb, finalcolor | (finalcvg >> 2)); + HWRITEADDR8(fb, finalcvg & 3); + break; } + case 2: + RWRITEIDX16(fb, finalcolor | 1); + HWRITEADDR8(fb, 3); + break; + case 3: + RWRITEIDX16(fb, finalcolor | (userdata->m_current_mem_cvg >> 2)); + HWRITEADDR8(fb, userdata->m_current_mem_cvg & 3); + break; } - else // 32-bit framebuffer - { - const uint32_t fb = (object.m_misc_state.m_fb_address >> 2) + curpixel; +} - uint32_t finalcolor; - if (object.m_other_modes.color_on_cvg && !userdata->m_pre_wrap) - { - finalcolor = RREADIDX32(fb) & 0xffffff00; - } - else - { - finalcolor = (color.get_r() << 24) | (color.get_g() << 16) | (color.get_b() << 8); - } +void n64_rdp::write_pixel32(uint32_t curpixel, color_t& color, rdp_span_aux* userdata, const rdp_poly_state &object) +{ + const uint32_t fb = (object.m_misc_state.m_fb_address >> 2) + curpixel; - switch (object.m_other_modes.cvg_dest) - { - case 0: - if (userdata->m_blend_enable) - { - uint32_t finalcvg = userdata->m_current_pix_cvg + userdata->m_current_mem_cvg; - if (finalcvg & 8) - { - finalcvg = 7; - } + uint32_t finalcolor; + if (object.m_other_modes.color_on_cvg && !userdata->m_pre_wrap) + { + finalcolor = RREADIDX32(fb) & 0xffffff00; + } + else + { + finalcolor = (color.get_r() << 24) | (color.get_g() << 16) | (color.get_b() << 8); + } - RWRITEIDX32(fb, finalcolor | (finalcvg << 5)); - } - else + switch (object.m_other_modes.cvg_dest) + { + case 0: + if (userdata->m_blend_enable) + { + uint32_t finalcvg = userdata->m_current_pix_cvg + userdata->m_current_mem_cvg; + if (finalcvg & 8) { - RWRITEIDX32(fb, finalcolor | (((userdata->m_current_pix_cvg - 1) & 7) << 5)); + finalcvg = 7; } - break; - case 1: - RWRITEIDX32(fb, finalcolor | (((userdata->m_current_pix_cvg + userdata->m_current_mem_cvg) & 7) << 5)); - break; - case 2: - RWRITEIDX32(fb, finalcolor | 0xE0); - break; - case 3: - RWRITEIDX32(fb, finalcolor | (userdata->m_current_mem_cvg << 5)); - break; - } + + RWRITEIDX32(fb, finalcolor | (finalcvg << 5)); + } + else + { + RWRITEIDX32(fb, finalcolor | (((userdata->m_current_pix_cvg - 1) & 7) << 5)); + } + break; + case 1: + RWRITEIDX32(fb, finalcolor | (((userdata->m_current_pix_cvg + userdata->m_current_mem_cvg) & 7) << 5)); + break; + case 2: + RWRITEIDX32(fb, finalcolor | 0xE0); + break; + case 3: + RWRITEIDX32(fb, finalcolor | (userdata->m_current_mem_cvg << 5)); + break; } } -inline void n64_rdp::read_pixel(uint32_t curpixel, rdp_span_aux* userdata, const rdp_poly_state &object) +void n64_rdp::read_pixel4(uint32_t curpixel, rdp_span_aux* userdata, const rdp_poly_state &object) +{ + userdata->m_memory_color.set(0, 0, 0, 0); + userdata->m_current_mem_cvg = 7; +} + +void n64_rdp::read_pixel8(uint32_t curpixel, rdp_span_aux* userdata, const rdp_poly_state &object) +{ + const uint8_t fbyte = RREADADDR8(object.m_misc_state.m_fb_address + curpixel); + const uint8_t r8 = (fbyte & 0xf8) | (fbyte >> 5); + uint8_t g8 = (fbyte & 0x07); + g8 |= g8 << 3; + g8 |= g8 << 6; + userdata->m_memory_color.set(0, r8, g8, 0); + userdata->m_memory_color.set_a(0xff); + userdata->m_current_mem_cvg = 7; +} + +void n64_rdp::read_pixel16(uint32_t curpixel, rdp_span_aux* userdata, const rdp_poly_state &object) { - if (object.m_misc_state.m_fb_size == 2) // 16-bit framebuffer + const uint16_t fword = RREADIDX16((object.m_misc_state.m_fb_address >> 1) + curpixel); + + userdata->m_memory_color.set(0, GETHICOL(fword), GETMEDCOL(fword), GETLOWCOL(fword)); + if (object.m_other_modes.image_read_en) { - const uint16_t fword = RREADIDX16((object.m_misc_state.m_fb_address >> 1) + curpixel); + uint8_t hbyte = HREADADDR8((object.m_misc_state.m_fb_address >> 1) + curpixel); + userdata->m_memory_color.set_a(userdata->m_current_mem_cvg << 5); + userdata->m_current_mem_cvg = ((fword & 1) << 2) | (hbyte & 3); + } + else + { + userdata->m_memory_color.set_a(0xff); + userdata->m_current_mem_cvg = 7; + } +} - userdata->m_memory_color.set(0, GETHICOL(fword), GETMEDCOL(fword), GETLOWCOL(fword)); - if (object.m_other_modes.image_read_en) - { - uint8_t hbyte = HREADADDR8((object.m_misc_state.m_fb_address >> 1) + curpixel); - userdata->m_memory_color.set_a(userdata->m_current_mem_cvg << 5); - userdata->m_current_mem_cvg = ((fword & 1) << 2) | (hbyte & 3); - } - else - { - userdata->m_memory_color.set_a(0xff); - userdata->m_current_mem_cvg = 7; - } +void n64_rdp::read_pixel32(uint32_t curpixel, rdp_span_aux* userdata, const rdp_poly_state &object) +{ + const uint32_t mem = RREADIDX32((object.m_misc_state.m_fb_address >> 2) + curpixel); + userdata->m_memory_color.set(0, (mem >> 24) & 0xff, (mem >> 16) & 0xff, (mem >> 8) & 0xff); + if (object.m_other_modes.image_read_en) + { + userdata->m_memory_color.set_a(mem & 0xff); + userdata->m_current_mem_cvg = (mem >> 5) & 7; } - else // 32-bit framebuffer + else { - const uint32_t mem = RREADIDX32((object.m_misc_state.m_fb_address >> 2) + curpixel); - userdata->m_memory_color.set(0, (mem >> 24) & 0xff, (mem >> 16) & 0xff, (mem >> 8) & 0xff); - if (object.m_other_modes.image_read_en) - { - userdata->m_memory_color.set_a(mem & 0xff); - userdata->m_current_mem_cvg = (mem >> 5) & 7; - } - else - { - userdata->m_memory_color.set_a(0xff); - userdata->m_current_mem_cvg = 7; - } + userdata->m_memory_color.set_a(0xff); + userdata->m_current_mem_cvg = 7; } } -inline void n64_rdp::copy_pixel(uint32_t curpixel, color_t& color, const rdp_poly_state &object) +void n64_rdp::copy_pixel4(uint32_t curpixel, color_t& color, const rdp_poly_state &object) +{ + // Not yet implemented +} + +void n64_rdp::copy_pixel8(uint32_t curpixel, color_t& color, const rdp_poly_state &object) +{ + const uint8_t c = (color.get_r() & 0xf8) | ((color.get_g() & 0xf8) >> 5); + if (c != 0) + RWRITEADDR8(object.m_misc_state.m_fb_address + curpixel, c); +} + +void n64_rdp::copy_pixel16(uint32_t curpixel, color_t& color, const rdp_poly_state &object) { const uint32_t current_pix_cvg = color.get_a() ? 7 : 0; const uint8_t r = color.get_r(); // Vectorize me const uint8_t g = color.get_g(); const uint8_t b = color.get_b(); - if (object.m_misc_state.m_fb_size == 2) // 16-bit framebuffer - { - RWRITEIDX16((object.m_misc_state.m_fb_address >> 1) + curpixel, ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1) | ((current_pix_cvg >> 2) & 1)); - HWRITEADDR8((object.m_misc_state.m_fb_address >> 1) + curpixel, current_pix_cvg & 3); - } - else // 32-bit framebuffer - { - RWRITEIDX32((object.m_misc_state.m_fb_address >> 2) + curpixel, (r << 24) | (g << 16) | (b << 8) | (current_pix_cvg << 5)); - } + RWRITEIDX16((object.m_misc_state.m_fb_address >> 1) + curpixel, ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1) | ((current_pix_cvg >> 2) & 1)); + HWRITEADDR8((object.m_misc_state.m_fb_address >> 1) + curpixel, current_pix_cvg & 3); +} + +void n64_rdp::copy_pixel32(uint32_t curpixel, color_t& color, const rdp_poly_state &object) +{ + const uint32_t current_pix_cvg = color.get_a() ? 7 : 0; + const uint8_t r = color.get_r(); // Vectorize me + const uint8_t g = color.get_g(); + const uint8_t b = color.get_b(); + RWRITEIDX32((object.m_misc_state.m_fb_address >> 2) + curpixel, (r << 24) | (g << 16) | (b << 8) | (current_pix_cvg << 5)); +} + +void n64_rdp::fill_pixel4(uint32_t curpixel, const rdp_poly_state &object) +{ + // Not yet implemented } -inline void n64_rdp::fill_pixel(uint32_t curpixel, const rdp_poly_state &object) +void n64_rdp::fill_pixel8(uint32_t curpixel, const rdp_poly_state &object) { - if (object.m_misc_state.m_fb_size == 2) // 16-bit framebuffer + const uint8_t byte_shift = ((curpixel & 3) ^ BYTE_ADDR_XOR) << 3; + RWRITEADDR8(object.m_misc_state.m_fb_address + curpixel, (uint8_t)(object.m_fill_color >> byte_shift)); +} + +void n64_rdp::fill_pixel16(uint32_t curpixel, const rdp_poly_state &object) +{ + uint16_t val; + if (curpixel & 1) { - uint16_t val; - if (curpixel & 1) - { - val = object.m_fill_color & 0xffff; - } - else - { - val = (object.m_fill_color >> 16) & 0xffff; - } - RWRITEIDX16((object.m_misc_state.m_fb_address >> 1) + curpixel, val); - HWRITEADDR8((object.m_misc_state.m_fb_address >> 1) + curpixel, ((val & 1) << 1) | (val & 1)); + val = object.m_fill_color & 0xffff; } - else // 32-bit framebuffer + else { - RWRITEIDX32((object.m_misc_state.m_fb_address >> 2) + curpixel, object.m_fill_color); - HWRITEADDR8((object.m_misc_state.m_fb_address >> 1) + (curpixel << 1), (object.m_fill_color & 0x10000) ? 3 : 0); - HWRITEADDR8((object.m_misc_state.m_fb_address >> 1) + (curpixel << 1) + 1, (object.m_fill_color & 0x1) ? 3 : 0); + val = (object.m_fill_color >> 16) & 0xffff; } + RWRITEIDX16((object.m_misc_state.m_fb_address >> 1) + curpixel, val); + HWRITEADDR8((object.m_misc_state.m_fb_address >> 1) + curpixel, ((val & 1) << 1) | (val & 1)); +} + +void n64_rdp::fill_pixel32(uint32_t curpixel, const rdp_poly_state &object) +{ + RWRITEIDX32((object.m_misc_state.m_fb_address >> 2) + curpixel, object.m_fill_color); + HWRITEADDR8((object.m_misc_state.m_fb_address >> 1) + (curpixel << 1), (object.m_fill_color & 0x10000) ? 3 : 0); + HWRITEADDR8((object.m_misc_state.m_fb_address >> 1) + (curpixel << 1) + 1, (object.m_fill_color & 0x1) ? 3 : 0); } void n64_rdp::span_draw_1cycle(int32_t scanline, const extent_t &extent, const rdp_poly_state &object, int32_t threadid) { - assert(object.m_misc_state.m_fb_size >= 2 && object.m_misc_state.m_fb_size < 4); + assert(object.m_misc_state.m_fb_size < 4); const int32_t clipx1 = object.m_scissor.m_xh; const int32_t clipx2 = object.m_scissor.m_xl; @@ -3593,7 +3753,7 @@ void n64_rdp::span_draw_1cycle(int32_t scanline, const extent_t &extent, const r dzpix = object.m_span_base.m_span_dzpix; } - if (object.m_misc_state.m_fb_size < 2 || object.m_misc_state.m_fb_size > 4) + if (object.m_misc_state.m_fb_size > 4) fatalerror("unsupported m_fb_size %d\n", object.m_misc_state.m_fb_size); const int32_t blend_index = (object.m_other_modes.alpha_cvg_select ? 2 : 0) | ((object.m_other_modes.rgb_dither_sel < 3) ? 1 : 0); @@ -3669,7 +3829,7 @@ void n64_rdp::span_draw_1cycle(int32_t scanline, const extent_t &extent, const r const uint32_t zbcur = zb + curpixel; const uint32_t zhbcur = zhb + curpixel; - read_pixel(curpixel, userdata, object); + ((this)->*(m_read_pixel[object.m_misc_state.m_fb_size]))(curpixel, userdata, object); if(z_compare(zbcur, zhbcur, sz, dzpix, userdata, object)) { @@ -3682,7 +3842,7 @@ void n64_rdp::span_draw_1cycle(int32_t scanline, const extent_t &extent, const r if (rendered) { - write_pixel(curpixel, blended_pixel, userdata, object); + ((this)->*(m_write_pixel[object.m_misc_state.m_fb_size]))(curpixel, blended_pixel, userdata, object); if (object.m_other_modes.z_update_en) { z_store(object, zbcur, zhbcur, sz, userdata->m_dzpix_enc); @@ -3709,7 +3869,7 @@ void n64_rdp::span_draw_1cycle(int32_t scanline, const extent_t &extent, const r void n64_rdp::span_draw_2cycle(int32_t scanline, const extent_t &extent, const rdp_poly_state &object, int32_t threadid) { - assert(object.m_misc_state.m_fb_size >= 2 && object.m_misc_state.m_fb_size < 4); + assert(object.m_misc_state.m_fb_size < 4); const int32_t clipx1 = object.m_scissor.m_xh; const int32_t clipx2 = object.m_scissor.m_xl; @@ -3803,7 +3963,7 @@ void n64_rdp::span_draw_2cycle(int32_t scanline, const extent_t &extent, const r dzpix = object.m_span_base.m_span_dzpix; } - if (object.m_misc_state.m_fb_size < 2 || object.m_misc_state.m_fb_size > 4) + if (object.m_misc_state.m_fb_size > 4) fatalerror("unsupported m_fb_size %d\n", object.m_misc_state.m_fb_size); const int32_t blend_index = (object.m_other_modes.alpha_cvg_select ? 2 : 0) | ((object.m_other_modes.rgb_dither_sel < 3) ? 1 : 0); @@ -3928,7 +4088,7 @@ void n64_rdp::span_draw_2cycle(int32_t scanline, const extent_t &extent, const r const uint32_t zbcur = zb + curpixel; const uint32_t zhbcur = zhb + curpixel; - read_pixel(curpixel, userdata, object); + ((this)->*(m_read_pixel[object.m_misc_state.m_fb_size]))(curpixel, userdata, object); if(z_compare(zbcur, zhbcur, sz, dzpix, userdata, object)) { @@ -3939,7 +4099,7 @@ void n64_rdp::span_draw_2cycle(int32_t scanline, const extent_t &extent, const r if (rendered) { - write_pixel(curpixel, blended_pixel, userdata, object); + ((this)->*(m_write_pixel[object.m_misc_state.m_fb_size]))(curpixel, blended_pixel, userdata, object); if (object.m_other_modes.z_update_en) { z_store(object, zbcur, zhbcur, sz, userdata->m_dzpix_enc); @@ -4000,9 +4160,9 @@ void n64_rdp::span_draw_copy(int32_t scanline, const extent_t &extent, const rdp m_tex_pipe.copy(&userdata->m_texel0_color, sss, sst, tilenum, object, userdata); uint32_t curpixel = fb_index + x; - if ((userdata->m_texel0_color.get_a() != 0) || (!object.m_other_modes.alpha_compare_en)) + if (userdata->m_texel0_color.get_a() != 0 || !object.m_other_modes.alpha_compare_en || object.m_misc_state.m_fb_size == 1) { - copy_pixel(curpixel, userdata->m_texel0_color, object); + ((this)->*(m_copy_pixel[object.m_misc_state.m_fb_size]))(curpixel, userdata->m_texel0_color, object); } } @@ -4014,7 +4174,7 @@ void n64_rdp::span_draw_copy(int32_t scanline, const extent_t &extent, const rdp void n64_rdp::span_draw_fill(int32_t scanline, const extent_t &extent, const rdp_poly_state &object, int32_t threadid) { - assert(object.m_misc_state.m_fb_size >= 2 && object.m_misc_state.m_fb_size < 4); + assert(object.m_misc_state.m_fb_size < 4); const bool flip = object.flip; @@ -4036,7 +4196,7 @@ void n64_rdp::span_draw_fill(int32_t scanline, const extent_t &extent, const rdp { if (x >= clipx1 && x < clipx2) { - fill_pixel(fb_index + x, object); + ((this)->*(m_fill_pixel[object.m_misc_state.m_fb_size]))(fb_index + x, object); } x += xinc; diff --git a/src/mame/video/n64.h b/src/mame/video/n64.h index 6193514433c..9225c804b22 100644 --- a/src/mame/video/n64.h +++ b/src/mame/video/n64.h @@ -323,18 +323,40 @@ private: void compute_cvg_noflip(extent_t* spans, int32_t* majorx, int32_t* minorx, int32_t* majorxint, int32_t* minorxint, int32_t scanline, int32_t yh, int32_t yl, int32_t base); void compute_cvg_flip(extent_t* spans, int32_t* majorx, int32_t* minorx, int32_t* majorxint, int32_t* minorxint, int32_t scanline, int32_t yh, int32_t yl, int32_t base); - void write_pixel(uint32_t curpixel, color_t& color, rdp_span_aux* userdata, const rdp_poly_state &object); - void read_pixel(uint32_t curpixel, rdp_span_aux* userdata, const rdp_poly_state &object); - void copy_pixel(uint32_t curpixel, color_t& color, const rdp_poly_state &object); - void fill_pixel(uint32_t curpixel, const rdp_poly_state &object); + void write_pixel4(uint32_t curpixel, color_t& color, rdp_span_aux* userdata, const rdp_poly_state &object); + void write_pixel8(uint32_t curpixel, color_t& color, rdp_span_aux* userdata, const rdp_poly_state &object); + void write_pixel16(uint32_t curpixel, color_t& color, rdp_span_aux* userdata, const rdp_poly_state &object); + void write_pixel32(uint32_t curpixel, color_t& color, rdp_span_aux* userdata, const rdp_poly_state &object); + void read_pixel4(uint32_t curpixel, rdp_span_aux* userdata, const rdp_poly_state &object); + void read_pixel8(uint32_t curpixel, rdp_span_aux* userdata, const rdp_poly_state &object); + void read_pixel16(uint32_t curpixel, rdp_span_aux* userdata, const rdp_poly_state &object); + void read_pixel32(uint32_t curpixel, rdp_span_aux* userdata, const rdp_poly_state &object); + void copy_pixel4(uint32_t curpixel, color_t& color, const rdp_poly_state &object); + void copy_pixel8(uint32_t curpixel, color_t& color, const rdp_poly_state &object); + void copy_pixel16(uint32_t curpixel, color_t& color, const rdp_poly_state &object); + void copy_pixel32(uint32_t curpixel, color_t& color, const rdp_poly_state &object); + void fill_pixel4(uint32_t curpixel, const rdp_poly_state &object); + void fill_pixel8(uint32_t curpixel, const rdp_poly_state &object); + void fill_pixel16(uint32_t curpixel, const rdp_poly_state &object); + void fill_pixel32(uint32_t curpixel, const rdp_poly_state &object); void precalc_cvmask_derivatives(void); void z_build_com_table(void); typedef void (n64_rdp::*compute_cvg_t) (extent_t* spans, int32_t* majorx, int32_t* minorx, int32_t* majorxint, int32_t* minorxint, int32_t scanline, int32_t yh, int32_t yl, int32_t base); - compute_cvg_t m_compute_cvg[2]; + compute_cvg_t m_compute_cvg[2]; - running_machine* m_machine; + typedef void (n64_rdp::*write_pixel_t) (uint32_t curpixel, color_t& color, rdp_span_aux* userdata, const rdp_poly_state &object); + typedef void (n64_rdp::*read_pixel_t) (uint32_t curpixel, rdp_span_aux* userdata, const rdp_poly_state &object); + typedef void (n64_rdp::*copy_pixel_t) (uint32_t curpixel, color_t& color, const rdp_poly_state &object); + typedef void (n64_rdp::*fill_pixel_t) (uint32_t curpixel, const rdp_poly_state &object); + + write_pixel_t m_write_pixel[4]; + read_pixel_t m_read_pixel[4]; + copy_pixel_t m_copy_pixel[4]; + fill_pixel_t m_fill_pixel[4]; + + running_machine* m_machine; uint32_t* m_rdram; uint32_t* m_dmem; n64_periphs* m_n64_periphs; diff --git a/src/mame/video/rdptpipe.cpp b/src/mame/video/rdptpipe.cpp index c0b35da82bd..e4df83ec228 100644 --- a/src/mame/video/rdptpipe.cpp +++ b/src/mame/video/rdptpipe.cpp @@ -950,9 +950,9 @@ void n64_texture_pipe_t::fetch_i4_tlut0(rgbaint_t& out, int32_t s, int32_t t, in const uint8_t byteval = tc[taddr]; const uint8_t c = ((s & 1)) ? (byteval & 0xf) : ((byteval >> 4) & 0xf); - const uint16_t k = ((uint16_t*)(userdata->m_tmem + 0x800))[((tpal << 4) | c) << 2]; #if USE_64K_LUT + const uint16_t k = ((uint16_t*)(userdata->m_tmem + 0x800))[((tpal << 4) | c) << 2]; out.set(m_expand_16to32_table[k]); #else out.set((c & 1) * 0xff, GET_HI_RGBA16_TMEM(c), GET_MED_RGBA16_TMEM(c), GET_LOW_RGBA16_TMEM(c)); @@ -990,9 +990,9 @@ void n64_texture_pipe_t::fetch_i8_tlut0(rgbaint_t& out, int32_t s, int32_t t, in const int32_t taddr = (((tbase << 3) + s) ^ sTexAddrSwap8[t & 1]) & 0x7ff; const uint8_t c = tc[taddr]; - const uint16_t k = ((uint16_t*)(userdata->m_tmem + 0x800))[c << 2]; #if USE_64K_LUT + const uint16_t k = ((uint16_t*)(userdata->m_tmem + 0x800))[c << 2]; out.set(m_expand_16to32_table[k]); #else out.set((c & 1) * 0xff, GET_HI_RGBA16_TMEM(c), GET_MED_RGBA16_TMEM(c), GET_LOW_RGBA16_TMEM(c)); -- cgit v1.2.3