diff --git a/port/fast3d/gfx_pc.cpp b/port/fast3d/gfx_pc.cpp index 478b7215e..235b037ce 100644 --- a/port/fast3d/gfx_pc.cpp +++ b/port/fast3d/gfx_pc.cpp @@ -150,20 +150,22 @@ static struct RDP { struct { const uint8_t* addr; uint32_t orig_size_bytes; - uint32_t size_bytes; + uint32_t full_size_bytes; // full_image_line_size_bytes * height + uint32_t size_bytes; // line_size_bytes * height uint32_t full_image_line_size_bytes; uint32_t line_size_bytes; uint32_t tex_flags; struct RawTexMetadata raw_tex_metadata; bool masked; bool blended; - } loaded_texture[2]; + } loaded_texture[8]; struct { uint8_t fmt; uint8_t siz; uint8_t cms, cmt; uint8_t shifts, shiftt; uint16_t uls, ult, lrs, lrt; // U10.2 + uint16_t width, height; // in texels uint16_t tmem; // 0-511, in 64-bit word units uint32_t line_size_bytes; uint8_t palette; @@ -568,18 +570,20 @@ static void import_texture_rgba16(int tile, bool importReplacement) { const uint32_t full_image_line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes; const uint32_t line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes; - // SUPPORT_CHECK(full_image_line_size_bytes == line_size_bytes); - for (uint32_t i = 0; i < size_bytes / 2; i++) { - const uint16_t col16 = (addr[2 * i] << 8) | addr[2 * i + 1]; - const uint8_t a = col16 & 1; - const uint8_t r = col16 >> 11; - const uint8_t g = (col16 >> 6) & 0x1f; - const uint8_t b = (col16 >> 1) & 0x1f; - tex_upload_buffer[4 * i + 0] = SCALE_5_8(r); - tex_upload_buffer[4 * i + 1] = SCALE_5_8(g); - tex_upload_buffer[4 * i + 2] = SCALE_5_8(b); - tex_upload_buffer[4 * i + 3] = a ? 255 : 0; + uint8_t *dst = tex_upload_buffer; + for (uint32_t k = 0; k < size_bytes; k += line_size_bytes, addr += full_image_line_size_bytes) { + for (uint32_t i = 0; i < line_size_bytes / 2; i++, dst += 4) { + const uint16_t col16 = (addr[2 * i] << 8) | addr[2 * i + 1]; + const uint8_t a = col16 & 1; + const uint8_t r = col16 >> 11; + const uint8_t g = (col16 >> 6) & 0x1f; + const uint8_t b = (col16 >> 1) & 0x1f; + dst[0] = SCALE_5_8(r); + dst[1] = SCALE_5_8(g); + dst[2] = SCALE_5_8(b); + dst[3] = a ? 255 : 0; + } } const uint32_t width = rdp.texture_tile[tile].line_size_bytes / 2; @@ -639,16 +643,18 @@ static void import_texture_ia8(int tile, bool importReplacement) { const uint32_t full_image_line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes; const uint32_t line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes; - SUPPORT_CHECK(full_image_line_size_bytes == line_size_bytes); - for (uint32_t i = 0; i < size_bytes; i++) { - const uint8_t intensity = addr[i] >> 4; - const uint8_t alpha = addr[i] & 0xf; - const uint8_t c = SCALE_4_8(intensity); - tex_upload_buffer[4 * i + 0] = c; - tex_upload_buffer[4 * i + 1] = c; - tex_upload_buffer[4 * i + 2] = c; - tex_upload_buffer[4 * i + 3] = SCALE_4_8(alpha); + uint8_t *dst = tex_upload_buffer; + for (uint32_t k = 0; k < size_bytes; k += line_size_bytes, addr += full_image_line_size_bytes) { + for (uint32_t i = 0; i < line_size_bytes; i++, dst += 4) { + const uint8_t intensity = addr[i] >> 4; + const uint8_t alpha = addr[i] & 0xf; + const uint8_t c = SCALE_4_8(intensity); + dst[0] = c; + dst[1] = c; + dst[2] = c; + dst[3] = SCALE_4_8(alpha); + } } const uint32_t width = rdp.texture_tile[tile].line_size_bytes; @@ -690,16 +696,18 @@ static void import_texture_i4(int tile, bool importReplacement) { const uint32_t full_image_line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes; const uint32_t line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes; - // SUPPORT_CHECK(full_image_line_size_bytes == line_size_bytes); - for (uint32_t i = 0; i < size_bytes * 2; i++) { - const uint8_t byte = addr[i / 2]; - const uint8_t part = (byte >> (4 - (i % 2) * 4)) & 0xf; - const uint8_t intensity = SCALE_4_8(part); - tex_upload_buffer[4 * i + 0] = intensity; - tex_upload_buffer[4 * i + 1] = intensity; - tex_upload_buffer[4 * i + 2] = intensity; - tex_upload_buffer[4 * i + 3] = 255; // can be intensity + uint8_t *dst = tex_upload_buffer; + for (uint32_t k = 0; k < size_bytes; k += line_size_bytes, addr += full_image_line_size_bytes) { + for (uint32_t i = 0; i < line_size_bytes * 2; i++, dst += 4) { + const uint8_t byte = addr[i / 2]; + const uint8_t part = (byte >> (4 - (i % 2) * 4)) & 0xf; + const uint8_t intensity = SCALE_4_8(part); + dst[0] = intensity; + dst[1] = intensity; + dst[2] = intensity; + dst[3] = 255; // can be intensity + } } const uint32_t width = rdp.texture_tile[tile].line_size_bytes * 2; @@ -713,17 +721,22 @@ static void import_texture_i8(int tile, bool importReplacement) { const RawTexMetadata* metadata = &rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].raw_tex_metadata; const uint8_t* addr = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].addr; const uint32_t size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].size_bytes; - const uint32_t full_image_line_size_bytes = + uint32_t full_image_line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes; const uint32_t line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes; - // SUPPORT_CHECK(full_image_line_size_bytes == line_size_bytes); - for (uint32_t i = 0; i < size_bytes; i++) { - const uint8_t intensity = addr[i]; - tex_upload_buffer[4 * i + 0] = intensity; - tex_upload_buffer[4 * i + 1] = intensity; - tex_upload_buffer[4 * i + 2] = intensity; - tex_upload_buffer[4 * i + 3] = 255; // can be intensity + // FIXME: for some fucking reason this only works correctly if you IGNORE the alignment + full_image_line_size_bytes = line_size_bytes; + + uint8_t *dst = tex_upload_buffer; + for (uint32_t k = 0; k < size_bytes; k += line_size_bytes, addr += full_image_line_size_bytes) { + for (uint32_t i = 0; i < line_size_bytes; i++, dst += 4) { + const uint8_t intensity = addr[i]; + dst[0] = intensity; + dst[1] = intensity; + dst[2] = intensity; + dst[3] = 255; // can be intensity instead? + } } const uint32_t width = rdp.texture_tile[tile].line_size_bytes; @@ -764,12 +777,14 @@ static void import_texture_ci4(int tile, bool importReplacement) { const uint32_t line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes; const uint32_t pal_idx = rdp.texture_tile[tile].palette; // 0-15 const uint16_t* palette = (const uint16_t *)(rdp.palette + pal_idx * 16); // 16 pixel entries, 16 bits each - SUPPORT_CHECK(full_image_line_size_bytes == line_size_bytes); - for (uint32_t i = 0; i < size_bytes * 2; i++) { - const uint8_t byte = addr[i / 2]; - const uint8_t idx = (byte >> (4 - (i % 2) * 4)) & 0xf; - palette_to_rgba32(palette[idx], tex_upload_buffer + 4 * i); + uint8_t *dst = tex_upload_buffer; + for (uint32_t k = 0; k < size_bytes; k += line_size_bytes, addr += full_image_line_size_bytes) { + for (uint32_t i = 0; i < line_size_bytes * 2; i++, dst += 4) { + const uint8_t byte = addr[i / 2]; + const uint8_t idx = (byte >> (4 - (i % 2) * 4)) & 0xf; + palette_to_rgba32(palette[idx], dst); + } } uint32_t result_line_size = rdp.texture_tile[tile].line_size_bytes; @@ -811,18 +826,22 @@ static void import_texture_ci8(int tile, bool importReplacement) { } static void import_texture(int i, int tile, bool importReplacement) { - if (rdp.tex_lod) { - // import the base level, don't care about the mips - // FIXME: this shouldn't even get here in that case, what the fuck? - tile = rdp.first_tile_index; - } - const uint8_t fmt = rdp.texture_tile[tile].fmt; const uint8_t siz = rdp.texture_tile[tile].siz; const uint32_t texFlags = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].tex_flags; const uint32_t tmem_index = rdp.texture_tile[tile].tmem_index; const uint8_t palette_index = rdp.texture_tile[tile].palette; + if (rdp.tex_lod && !tmem_index) { + // set up miplevel 0 + rdp.loaded_texture[0].line_size_bytes = rdp.texture_tile[tile].width << siz >> 1; + rdp.loaded_texture[0].full_image_line_size_bytes = rdp.texture_tile[tile].line_size_bytes; + rdp.loaded_texture[0].full_size_bytes = rdp.loaded_texture[0].full_image_line_size_bytes * rdp.texture_tile[tile].height; + rdp.loaded_texture[0].size_bytes = rdp.loaded_texture[0].line_size_bytes * rdp.texture_tile[tile].height; + rdp.loaded_texture[0].orig_size_bytes = rdp.loaded_texture[0].size_bytes; + rdp.loaded_texture[0].addr = rdp.texture_to_load.addr; + } + const RawTexMetadata* metadata = &rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].raw_tex_metadata; const uint8_t* orig_addr = rdp.loaded_texture[tmem_index].addr; SUPPORT_CHECK(orig_addr); @@ -1273,7 +1292,8 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo uint32_t tex_width[2], tex_height[2], tex_width2[2], tex_height2[2]; for (int i = 0; i < 2; i++) { - uint32_t tile = rdp.first_tile_index + i; + // TODO: fix this; for now just ignore smaller mips + const uint32_t tile = rdp.first_tile_index + (rdp.tex_lod ? 0 : i); if (comb->used_textures[i]) { if (rdp.textures_changed[i]) { gfx_flush(); @@ -1373,11 +1393,15 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo if (!used_textures[t]) { continue; } + + // TODO: fix this; for now just ignore smaller mips + const uint32_t tile = (rdp.tex_lod ? 0 : t); + float u = v_arr[i]->u / 32.0f; float v = v_arr[i]->v / 32.0f; - int shifts = rdp.texture_tile[rdp.first_tile_index + t].shifts; - int shiftt = rdp.texture_tile[rdp.first_tile_index + t].shiftt; + int shifts = rdp.texture_tile[rdp.first_tile_index + tile].shifts; + int shiftt = rdp.texture_tile[rdp.first_tile_index + tile].shiftt; if (shifts != 0) { if (shifts <= 10) { u /= 1 << shifts; @@ -1393,8 +1417,8 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo } } - u -= rdp.texture_tile[rdp.first_tile_index + t].uls / 4.0f; - v -= rdp.texture_tile[rdp.first_tile_index + t].ult / 4.0f; + u -= rdp.texture_tile[rdp.first_tile_index + tile].uls / 4.0f; + v -= rdp.texture_tile[rdp.first_tile_index + tile].ult / 4.0f; if ((rdp.other_mode_h & (3U << G_MDSFT_TEXTFILT)) != G_TF_POINT) { // Linear filter adds 0.5f to the coordinates @@ -1747,7 +1771,7 @@ static void gfx_dp_set_tile(uint8_t fmt, uint32_t siz, uint32_t line, uint32_t t // assume one texture is loaded at address 0 and another texture at any other address rdp.texture_tile[tile].tmem = tmem; - rdp.texture_tile[tile].tmem_index = tmem / 256; + rdp.texture_tile[tile].tmem_index = (rdp.tex_lod && tile < 6) ? tile : 6 + (tmem > 0); rdp.textures_changed[0] = true; rdp.textures_changed[1] = true; } @@ -1757,6 +1781,8 @@ static void gfx_dp_set_tile_size(uint8_t tile, uint16_t uls, uint16_t ult, uint1 rdp.texture_tile[tile].ult = ult; rdp.texture_tile[tile].lrs = lrs; rdp.texture_tile[tile].lrt = lrt; + rdp.texture_tile[tile].width = (lrs - uls + 4) / 4; + rdp.texture_tile[tile].height = (lrt - ult + 4) / 4; rdp.textures_changed[0] = true; rdp.textures_changed[1] = true; } @@ -1802,22 +1828,7 @@ static void gfx_dp_load_block(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t SUPPORT_CHECK(ult == 0); // The lrs field rather seems to be number of pixels to load - uint32_t word_size_shift = 0; - switch (rdp.texture_to_load.siz) { - case G_IM_SIZ_4b: - word_size_shift = 0; // Or -1? It's unused in SM64 anyway. - break; - case G_IM_SIZ_8b: - word_size_shift = 0; - break; - case G_IM_SIZ_16b: - word_size_shift = 1; - break; - case G_IM_SIZ_32b: - word_size_shift = 2; - break; - } - uint32_t orig_size_bytes = (lrs + 1) << word_size_shift; + uint32_t orig_size_bytes = (lrs + 1) << rdp.texture_to_load.siz >> 1; uint32_t size_bytes = orig_size_bytes; if (rdp.texture_to_load.raw_tex_metadata.h_byte_scale != 1 || rdp.texture_to_load.raw_tex_metadata.v_pixel_scale != 1) { @@ -1826,6 +1837,7 @@ static void gfx_dp_load_block(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t } rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].orig_size_bytes = orig_size_bytes; rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].size_bytes = size_bytes; + rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_size_bytes = size_bytes; rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes = size_bytes; rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes = size_bytes; // assert(size_bytes <= 4096 && "bug: too big texture"); @@ -1836,37 +1848,25 @@ static void gfx_dp_load_block(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].masked = false; rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].blended = false; - rdp.textures_changed[rdp.texture_tile[tile].tmem_index] = true; + if (rdp.tex_lod) { + rdp.textures_changed[0] = rdp.textures_changed[1] = true; + } else { + rdp.textures_changed[rdp.texture_tile[tile].tmem_index > 6] = true; + } } static void gfx_dp_load_tile(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t lrs, uint32_t lrt) { SUPPORT_CHECK(tile == G_TX_LOADTILE); - uint32_t word_size_shift = 0; - switch (rdp.texture_to_load.siz) { - case G_IM_SIZ_4b: - word_size_shift = 0; - break; - case G_IM_SIZ_8b: - word_size_shift = 0; - break; - case G_IM_SIZ_16b: - word_size_shift = 1; - break; - case G_IM_SIZ_32b: - word_size_shift = 2; - break; - } - uint32_t offset_x = uls >> G_TEXTURE_IMAGE_FRAC; uint32_t offset_y = ult >> G_TEXTURE_IMAGE_FRAC; uint32_t tile_width = ((lrs - uls) >> G_TEXTURE_IMAGE_FRAC) + 1; uint32_t tile_height = ((lrt - ult) >> G_TEXTURE_IMAGE_FRAC) + 1; uint32_t full_image_width = rdp.texture_to_load.width + 1; - uint32_t offset_x_in_bytes = offset_x << word_size_shift; - uint32_t tile_line_size_bytes = tile_width << word_size_shift; - uint32_t full_image_line_size_bytes = full_image_width << word_size_shift; + uint32_t offset_x_in_bytes = offset_x << rdp.texture_to_load.siz >> 1; + uint32_t tile_line_size_bytes = tile_width << rdp.texture_to_load.siz >> 1; + uint32_t full_image_line_size_bytes = full_image_width << rdp.texture_to_load.siz >> 1; uint32_t orig_size_bytes = tile_line_size_bytes * tile_height; uint32_t size_bytes = orig_size_bytes; @@ -1884,6 +1884,7 @@ static void gfx_dp_load_tile(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].orig_size_bytes = orig_size_bytes; rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].size_bytes = size_bytes; + rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_size_bytes = full_image_line_size_bytes * tile_height; rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes = full_image_line_size_bytes; rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes = tile_line_size_bytes; @@ -1899,8 +1900,14 @@ static void gfx_dp_load_tile(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t rdp.texture_tile[tile].ult = ult; rdp.texture_tile[tile].lrs = lrs; rdp.texture_tile[tile].lrt = lrt; + rdp.texture_tile[tile].width = ((lrs - uls) >> G_TEXTURE_IMAGE_FRAC) + 1; + rdp.texture_tile[tile].height = ((lrt - ult) >> G_TEXTURE_IMAGE_FRAC) + 1; - rdp.textures_changed[rdp.texture_tile[tile].tmem_index] = true; + if (rdp.tex_lod) { + rdp.textures_changed[0] = rdp.textures_changed[1] = true; + } else { + rdp.textures_changed[rdp.texture_tile[tile].tmem_index > 6] = true; + } } /*static uint8_t color_comb_component(uint32_t v) { diff --git a/src/game/texdecompress.c b/src/game/texdecompress.c index 96c6fe2f1..5ff6a2d80 100644 --- a/src/game/texdecompress.c +++ b/src/game/texdecompress.c @@ -1909,7 +1909,7 @@ s32 texInflateLookupFromBuffer(u8 *src, s32 width, s32 height, u8 *dst, u8 *look */ void texSwapAltRowBytes(u8 *dst, s32 width, s32 height, s32 format) { -#ifdef PLATFORM_N64 // I'm assuming this is required on N64 because the GPU reads them in words +#ifdef PLATFORM_N64 // the N64 GPU wants interleaved data, we don't s32 x; s32 y; s32 alignedwidth;