From 8e4bff4d5373aa40bac2a4e84b9ce460c178b4fa Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Wed, 15 Jul 2026 21:00:58 -0400 Subject: [PATCH] Link ks_nes_draw Co-authored-by: GRAnimated <23510999+GRAnimated@users.noreply.github.com> --- configure.py | 2 +- src/static/Famicom/ks_nes_draw.cpp | 200 +++++++++++++++-------------- 2 files changed, 102 insertions(+), 100 deletions(-) diff --git a/configure.py b/configure.py index caa35619..a65ed8a7 100644 --- a/configure.py +++ b/configure.py @@ -836,7 +836,7 @@ config.libs = [ "src_dir": "src/static", "objects": [ Object(Matching, "Famicom/ks_nes_core.cpp"), - Object(NonMatching, "Famicom/ks_nes_draw.cpp"), + Object(Matching, "Famicom/ks_nes_draw.cpp"), Object(Matching, "Famicom/famicom.cpp"), Object(Matching, "Famicom/famicom_nesinfo.cpp"), ], diff --git a/src/static/Famicom/ks_nes_draw.cpp b/src/static/Famicom/ks_nes_draw.cpp index b5189a5f..10073c50 100644 --- a/src/static/Famicom/ks_nes_draw.cpp +++ b/src/static/Famicom/ks_nes_draw.cpp @@ -885,30 +885,16 @@ loop_condition: } void ksNesDrawOBJMMC5(ksNesCommonWorkObj* wp, ksNesStateObj* sp, u32 sprite_priority_pass) { - static const GXColor color_thres = { 255, 1, 0, 0 }; - // clang-format off + GXTexObj obj3; + GXTexObj obj; + GXTexObj obj2; + u32 j; static f32 indtexmtx_obj[2][3] = { { 0.5f, 0.0f, 0.0f }, { 0.0f, 0.0625f, 0.0f }, }; - // clang-format on - - GXTexObj obj3; - GXTexObj obj; - GXTexObj obj2; + static const GXColor color_thres = { 255, 1, 0, 0 }; size_t var_r25 = wp->chr_to_i8_buf_size; - u32 sft; - u32 var_r3; - u32 i, j; - u32 var_r15; - u32 var_r24; - u32 x; - u32 x1, x2, y1, y2; - u32 u1, u2, v; - u32 clr; - u32 oam_attrs; - u8 *work; - ksNesScanlineYCoords* coords_p; GXSetNumChans(1); GXSetNumTexGens(2); @@ -958,14 +944,16 @@ void ksNesDrawOBJMMC5(ksNesCommonWorkObj* wp, ksNesStateObj* sp, u32 sprite_prio GXSetIndTexOrder(GX_INDTEXSTAGE1, GX_TEXCOORD1, GX_TEXMAP2); GXSetIndTexCoordScale(GX_INDTEXSTAGE1, GX_ITS_8, GX_ITS_1); - sft = 0; - while (var_r25 > (0x8000 << sft)) { - sft++; - } + { + u32 shift = 0; + while (var_r25 > (0x8000 << shift)) { + shift++; + } - indtexmtx_obj[0][0] = 0.5f / (sft >= 4 ? (1 << (sft - 3)) : 1); - indtexmtx_obj[1][1] = 0.5f / (sft <= 2 ? (1 << (3 - sft)) : 1); - GXSetIndTexMtx(GX_ITM_0, indtexmtx_obj, 36 + (sft < 4 ? 0 : sft - 3)); + indtexmtx_obj[0][0] = 0.5f / (shift >= 4 ? (1 << (shift - 3)) : 1); + indtexmtx_obj[1][1] = 0.5f / (shift <= 2 ? (1 << (3 - shift)) : 1); + GXSetIndTexMtx(GX_ITM_0, indtexmtx_obj, 36 + (shift < 4 ? 0 : shift - 3)); + } GXSetTevIndirect(GX_TEVSTAGE1, GX_INDTEXSTAGE1, GX_ITF_8, GX_ITB_NONE, GX_ITM_0, GX_ITW_OFF, GX_ITW_0, GX_TRUE, GX_FALSE, GX_ITBA_OFF); GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP0, GX_COLOR_NULL); @@ -983,107 +971,125 @@ void ksNesDrawOBJMMC5(ksNesCommonWorkObj* wp, ksNesStateObj* sp, u32 sprite_prio GXSetTevAlphaOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_ALWAYS, 0); - var_r24 = 0; - for (i = 0; i < ARRAY_COUNT(wp->draw_ctx.OAMTable); i++) { - if (sprite_priority_pass == 0 || (wp->draw_ctx.OAMTable[i].attributes & KS_NES_OAM_ATTR_PRIORITY) != 0) { - var_r24 += (wp->draw_ctx.ppu_scanline_regs[wp->draw_ctx.OAMTable[i].y_pos].ppu_ctrl & KS_NES_PPU_CTRL_SPRITE_SIZE) ? 8 : 4; + u32 i; + u32 v; + u32 y1; + u32 y2; + u8 scanline; + u32 size_mode; + u32 u1; + u32 u2; + u32 clr; + u32 x2; + u32 x1; + u32 flip_vertical; + u32 tile_idx; + u32 palette_bits; + u32 tmp; + u32 x; + u32 bank; + u32 color_base; + u32 oam_offset; + + i = 0; + for (oam_offset = 0; oam_offset < sizeof(wp->draw_ctx.OAMTable); oam_offset += sizeof(ksNesOAMEntry)) { + if (sprite_priority_pass == 0 || (ksNesGetOAMEntry(wp, oam_offset).attributes & KS_NES_OAM_ATTR_PRIORITY) != 0) { + i += (wp->draw_ctx.ppu_scanline_regs[ksNesGetOAMEntry(wp, oam_offset).y_pos].ppu_ctrl & KS_NES_PPU_CTRL_SPRITE_SIZE) ? 8 : 4; } } - for (i = 0; i < 8; i += 4) { - GXInitTexObj(&obj3, &wp->chr_to_u8_bufp[(var_r25 >> 3) * i], 1024, var_r25 >> 11, GX_TF_I8, GX_MIRROR, GX_CLAMP, 0); + for (bank = 0; bank < 8; bank += 4) { + GXInitTexObj(&obj3, &wp->chr_to_u8_bufp[(var_r25 >> 3) * bank], 1024, var_r25 >> 11, GX_TF_I8, GX_MIRROR, GX_CLAMP, 0); GXInitTexObjLOD(&obj3, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1); GXLoadTexObj(&obj3, GX_TEXMAP0); // why is this loop value loaded here??? j = (ARRAY_COUNT(wp->draw_ctx.OAMTable) - 1) * sizeof(wp->draw_ctx.OAMTable[0]); - GXBegin(GX_QUADS, GX_VTXFMT0, var_r24); + GXBegin(GX_QUADS, GX_VTXFMT0, i); while (TRUE) { - ksNesOAMEntry* oam_p = KS_NES_TYPE_FROM_DRAW_CTX_SCANLINE_BUF_OFS(ksNesOAMEntry, wp->draw_ctx, j); - u8 scanline = oam_p->y_pos; - u32 tile_idx = oam_p->tile_index; // loading tile index & bank - u32 size_mode = (wp->draw_ctx.ppu_scanline_regs[scanline].ppu_ctrl >> 5) & 1; // sprite size mode, 0 = 8x8, 1 = 8x16 - u32 palette_bits; - u32 tmp; + tile_idx = ksNesGetOAMEntry(wp, j).tile_index; // loading tile index & bank + scanline = ksNesGetOAMEntry(wp, j).y_pos; + size_mode = (wp->draw_ctx.ppu_scanline_regs[scanline].ppu_ctrl >> 5) & 1; // sprite size mode, 0 = 8x8, 1 = 8x16 if (size_mode != 0) { // 8x16 sprite - palette_bits = (tile_idx >> 6) | ((tile_idx & KS_NES_OAM_TILE_BANK) << 2); - palette_bits = ((wp->draw_ctx.ppu_scanline_regs[scanline].chr_bank_ext_upper_sprite << (palette_bits + 1)) & 0x100) | ((wp->draw_ctx.ppu_scanline_regs[scanline].chr_bank_sprite[palette_bits])); + tmp = (tile_idx >> 6) | ((tile_idx & KS_NES_OAM_TILE_BANK) << 2); + palette_bits = ((wp->draw_ctx.ppu_scanline_regs[scanline].chr_bank_ext_upper_sprite << (tmp + 1)) & 0x100) | wp->draw_ctx.ppu_scanline_regs[scanline].chr_bank_sprite[tmp]; tile_idx &= KS_NES_OAM_TILE_IDX; } else { // 8x8 sprite - palette_bits = (tile_idx >> 6) | (wp->draw_ctx.ppu_scanline_regs[scanline].ppu_ctrl >> 1) & 4; - palette_bits = ((wp->draw_ctx.ppu_scanline_regs[scanline].chr_bank_ext_upper_sprite << (palette_bits + 1)) & 0x100) | ((wp->draw_ctx.ppu_scanline_regs[scanline].chr_bank_sprite[palette_bits])); + tmp = (tile_idx >> 6) | (wp->draw_ctx.ppu_scanline_regs[scanline].ppu_ctrl >> 1) & 4; + palette_bits = ((wp->draw_ctx.ppu_scanline_regs[scanline].chr_bank_ext_upper_sprite << (tmp + 1)) & 0x100) | wp->draw_ctx.ppu_scanline_regs[scanline].chr_bank_sprite[tmp]; } - - - oam_attrs = oam_p->attributes; // OAM attributes - x1 = oam_p->x_pos + 128; // OAM X position - x2 = oam_p->x_pos + 128 + 8; // OAM X position + 8 - clr = ((((oam_attrs & KS_NES_OAM_ATTR_PALETTE_MASK) * 16) + 4) | (wp->draw_ctx.ppu_scanline_regs[scanline].ppu_ctrl & (KS_NES_PPU_CTRL_NMI_ENABLE | KS_NES_PPU_CTRL_MASTER_SLAVE))) << 24; + // clr = ; + color_base = ((ksNesGetOAMEntry(wp, j).attributes << 4) & 0x30) + 4; + clr = (color_base | (wp->draw_ctx.ppu_scanline_regs[scanline].ppu_ctrl & (KS_NES_PPU_CTRL_NMI_ENABLE | KS_NES_PPU_CTRL_MASTER_SLAVE))) << 24; + x = ksNesGetOAMEntry(wp, j).x_pos; + x2 = x + 128; // OAM X position + x1 = x + 128 + 8; // OAM X position + 8 if (sprite_priority_pass != 0) { - if ((oam_attrs & KS_NES_OAM_ATTR_PRIORITY) == 0) { + if ((ksNesGetOAMEntry(wp, j).attributes & KS_NES_OAM_ATTR_PRIORITY) == 0) { goto loop_point; } - } else if ((oam_attrs & KS_NES_OAM_ATTR_PRIORITY) != 0) { + } else if ((ksNesGetOAMEntry(wp, j).attributes & KS_NES_OAM_ATTR_PRIORITY) != 0) { clr |= 0xFF010000; } v = (palette_bits << 1) & 0x3FC; tmp = ((tile_idx << 5) & 0x7E0) | ((palette_bits << 0xB) & 0x800 & ~0x7E0); - if (oam_attrs & KS_NES_OAM_ATTR_FLIP_HORIZONTAL) { + if (ksNesGetOAMEntry(wp, j).attributes & KS_NES_OAM_ATTR_FLIP_HORIZONTAL) { u2 = tmp; u1 = tmp + 0x20; } else { u1 = tmp; u2 = tmp + 0x20; } - if ((oam_attrs & KS_NES_OAM_ATTR_FLIP_VERTICAL) != 0) { - tmp = (-0x81 - scanline) + i; + flip_vertical = ksNesGetOAMEntry(wp, j).attributes & KS_NES_OAM_ATTR_FLIP_VERTICAL; + if (flip_vertical != 0) { + tmp = (-0x81 - scanline) + bank; y1 = tmp - 8; y2 = tmp - 4; - if (var_r24 != 0) { + if (size_mode != 0) { u1 += 0x20; u2 += 0x20; } } else { - tmp = (-0x81 - scanline) - i; + tmp = (-0x81 - scanline) - bank; y1 = tmp; y2 = tmp - 4; } do { - GXPosition2s16(x1, y1); + GXPosition2s16(x2, y1); GXColor1u32(clr); GXTexCoord2u16(0, v); GXTexCoord2u16(u1, 0); - GXPosition2s16(x2, y1); + GXPosition2s16(x1, y1); GXColor1u32(clr); GXTexCoord2u16(0, v); GXTexCoord2u16(u2, 0); - GXPosition2s16(x2, y2); + GXPosition2s16(x1, y2); GXColor1u32(clr); GXTexCoord2u16(0, v); GXTexCoord2u16(u2, 0x10); - GXPosition2s16(x1, y2); + GXPosition2s16(x2, y2); GXColor1u32(clr); GXTexCoord2u16(0, v); GXTexCoord2u16(u1, 0x10); y1 -= 8; y2 -= 8; - if ((oam_attrs & KS_NES_OAM_ATTR_FLIP_VERTICAL) != 0) { + if (flip_vertical != 0) { u1 -= 0x20; u2 -= 0x20; } else { u1 += 0x20; u2 += 0x20; } - } while (var_r24-- != 0); + } while (size_mode-- != 0); loop_point: if (j == 0) break; @@ -1093,50 +1099,46 @@ loop_point: GXEnd(); } - if (sprite_priority_pass == 0) return; + if (sprite_priority_pass != 0) { + u32 n = ksNesDrawMakeOBJBlankVtxList(wp); - u32 quads = ksNesDrawMakeOBJBlankVtxList(wp); - if (quads == 0) return; + if (n != 0) { + GXSetNumChans(1); + GXSetNumTexGens(0); + GXSetNumTevStages(1); + GXSetNumIndStages(0); + GXSetBlendMode(GX_BM_LOGIC, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_COPY); - GXSetNumChans(1); - GXSetNumTexGens(0); - GXSetNumTevStages(1); - GXSetNumIndStages(0); - GXSetBlendMode(GX_BM_LOGIC, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_COPY); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT); - GXClearVtxDesc(); - GXSetVtxDesc(GX_VA_POS, GX_DIRECT); - GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_S16, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_S16, 0); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); - - GXSetTevDirect(GX_TEVSTAGE0); - GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); - GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_VTX, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE); - GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR); - - GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); + GXSetTevDirect(GX_TEVSTAGE0); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); + GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); + GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR); - GXBegin(GX_QUADS, GX_VTXFMT0, quads << 1); - for (i = 0; i < quads; i += 2) { - ksNesScanlineYCoords* coords_p = KS_NES_TYPE_FROM_DRAW_CTX_SCANLINE_BUF_OFS(ksNesScanlineYCoords, wp->draw_ctx, i); - u8 scanline_top = (u8)KS_NES_TYPE_FROM_DRAW_CTX_SCANLINE_BUF_OFS(ksNesScanlineYCoords, wp->draw_ctx, i)->top; - // work = (u8*)wp + i; // wp->draw_ctx.scanline_y_coords[i, i + 1] (top & bottom) - x = 384; - if ((wp->draw_ctx.ppu_scanline_regs[scanline_top].ppumask_flags & KS_NES_PPU_MASK_SPRITES_COMBINED) == KS_NES_PPU_MASK_SHOW_SPRITES) { - x = 136; + GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); + + GXBegin(GX_QUADS, GX_VTXFMT0, n * 2); + for (u32 i = 0; i < n; i += 2) { + s16 x1 = (wp->draw_ctx.ppu_scanline_regs[wp->draw_ctx.scanline_y_coords[i]].ppumask_flags & KS_NES_PPU_MASK_SPRITES_COMBINED) == KS_NES_PPU_MASK_SHOW_SPRITES ? 136 : 384; + + GXPosition2s16(128, -128 - wp->draw_ctx.scanline_y_coords[i]); + GXColor1u32(0x00000000); + GXPosition2s16(x1, -128 - wp->draw_ctx.scanline_y_coords[i]); + GXColor1u32(0x00000000); + GXPosition2s16(x1, -128 - wp->draw_ctx.scanline_y_coords[i] - wp->draw_ctx.scanline_y_coords[i + 1]); + GXColor1u32(0x00000000); + GXPosition2s16(128, -128 - wp->draw_ctx.scanline_y_coords[i] - wp->draw_ctx.scanline_y_coords[i + 1]); + GXColor1u32(0x00000000); + } + GXEnd(); } - GXPosition2s16(128, -128 - x); - GXColor1u32(0); - GXPosition2s16(x, -128 - coords_p->top); - GXColor1u32(0); - GXPosition2s16(x, -128 - coords_p->top - coords_p->bottom); - GXColor1u32(0); - GXPosition2s16(128, -128 - coords_p->top - coords_p->bottom); - GXColor1u32(0); } - GXEnd(); } void ksNesDrawFlushEFBToRed8(u8* buf) {