Link ks_nes_draw

Co-authored-by: GRAnimated <23510999+GRAnimated@users.noreply.github.com>
This commit is contained in:
Cuyler36
2026-07-15 21:00:58 -04:00
parent 3239cfb683
commit 8e4bff4d53
2 changed files with 102 additions and 100 deletions
+1 -1
View File
@@ -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"),
],
+101 -99
View File
@@ -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) {