diff --git a/include/Famicom/ks_nes_common.h b/include/Famicom/ks_nes_common.h index 1f760170..9776186f 100644 --- a/include/Famicom/ks_nes_common.h +++ b/include/Famicom/ks_nes_common.h @@ -30,12 +30,26 @@ extern "C" { #define KS_NES_BYTES_PER_KB (1024) #define KS_NES_TO_KB(b) ((f32)b * (1.0f / (f32)KS_NES_BYTES_PER_KB)) +typedef struct _0B40_struct { + u8* _00; + u8* _04; + u8* _08; + u32 _0C; + u32 _10; + u32 _14; + u8 _18; + u8 _19; + u8 pad2[0x6]; +} B40_struct; // size == 0x20 + typedef struct ksNesCommonWorkPriv { /* 0x0000 */ u8 wram[KS_NES_WRAM_SIZE]; /* 0x0800 */ u8 _0800[0x340]; - /* 0x0B40 */ u8* _0B40[0x7c0]; + /* 0x0B40 */ B40_struct _0B40[0xf0]; + /* 0x2940 */ u8 _2940[0x100]; /* 0x2A40 */ u8 _2A40[0x800]; - /* 0x3240 */ u8 _3240[0x5c00]; + /* 0x3240 */ u8 _3240[0x4800]; + /* 0x7840 */ u8 _7840[0x1400]; /* 0x8E40 */ u8 _8E40[0x80]; /* 0x8EC0 */ u8 _8EC0[0x28]; /* 0x8EE8 */ Mtx34 draw_mtx; diff --git a/include/MSL_C/w_math.h b/include/MSL_C/w_math.h index eb024284..d7880a22 100644 --- a/include/MSL_C/w_math.h +++ b/include/MSL_C/w_math.h @@ -3,7 +3,7 @@ #include "MSL_C/MSL_Common/float.h" -#ifndef BUGFIXES +#if !defined(BUGFIXES) && !defined(FIX_SQRT_LINKAGE) #define SQRTF_LINKAGE extern #else // making the function static instead of extern resolves the bug diff --git a/include/dolphin/gx/GXTexture.h b/include/dolphin/gx/GXTexture.h index e9343cf0..af5561ad 100644 --- a/include/dolphin/gx/GXTexture.h +++ b/include/dolphin/gx/GXTexture.h @@ -9,27 +9,28 @@ extern "C" { #endif typedef GXTexRegion* (*GXTexRegionCallback)(const GXTexObj* obj, GXTexMapID id); -typedef GXTlutRegion *(*GXTlutRegionCallback)(u32 idx); +typedef GXTlutRegion* (*GXTlutRegionCallback)(u32 idx); -void GXInitTexObj(GXTexObj *obj, void *image_ptr, u16 width, u16 height, GXTexFmt format, GXTexWrapMode wrap_s, GXTexWrapMode wrap_t, u8 mipmap); -void GXInitTexObjCI(GXTexObj *obj, void *image_ptr, u16 width, u16 height, GXCITexFmt format, GXTexWrapMode wrap_s, GXTexWrapMode wrap_t, u8 mipmap, u32 tlut_name); -void GXInitTexObjData(GXTexObj *obj, void *image_ptr); -void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter min_filt, GXTexFilter mag_filt, f32 min_lod, - f32 max_lod, f32 lod_bias, GXBool bias_clamp, GXBool do_edge_lod, - GXAnisotropy max_aniso); +void GXInitTexObj(GXTexObj* obj, void* image_ptr, u16 width, u16 height, GXTexFmt format, GXTexWrapMode wrap_s, + GXTexWrapMode wrap_t, u8 mipmap); +void GXInitTexObjCI(GXTexObj* obj, void* image_ptr, u16 width, u16 height, GXCITexFmt format, GXTexWrapMode wrap_s, + GXTexWrapMode wrap_t, u8 mipmap, u32 tlut_name); +void GXInitTexObjData(GXTexObj* obj, void* image_ptr); +void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter min_filt, GXTexFilter mag_filt, f32 min_lod, f32 max_lod, f32 lod_bias, + GXBool bias_clamp, GXBool do_edge_lod, GXAnisotropy max_aniso); void GXLoadTexObj(GXTexObj* obj, GXTexMapID id); u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, GXBool mipmap, u8 max_lod); void GXInvalidateTexAll(); void GXInitTexObjWrapMode(GXTexObj* obj, GXTexWrapMode s, GXTexWrapMode t); -void GXInitTlutObj(GXTlutObj *tlut_obj, void *lut, GXTlutFmt fmt, u16 n_entries); +void GXInitTlutObj(GXTlutObj* tlut_obj, void* lut, GXTlutFmt fmt, u16 n_entries); void GXLoadTlut(GXTlutObj* obj, u32 idx); void GXSetTexCoordScaleManually(GXTexCoordID coord, GXBool enable, u16 ss, u16 ts); -void GXInitTexCacheRegion(GXTexRegion* region, GXBool is_32b_mipmap, u32 tmem_even, - GXTexCacheSize size_even, u32 tmem_odd, GXTexCacheSize size_odd); +void GXInitTexCacheRegion(GXTexRegion* region, GXBool is_32b_mipmap, u32 tmem_even, GXTexCacheSize size_even, + u32 tmem_odd, GXTexCacheSize size_odd); GXTexRegionCallback GXSetTexRegionCallback(GXTexRegionCallback callback); void GXInvalidateTexRegion(GXTexRegion* region); -void GXInitTlutRegion(GXTlutRegion *region, u32 tmem_addr, GXTlutSize tlut_size); - +void GXInitTlutRegion(GXTlutRegion* region, u32 tmem_addr, GXTlutSize tlut_size); +void GXSetTexCoordBias(GXTexCoordID coord, u8 s_enable, u8 t_enable); #ifdef __cplusplus } #endif diff --git a/src/static/Famicom/ks_nes_core.cpp b/src/static/Famicom/ks_nes_core.cpp index ee9341cf..d297c47e 100644 --- a/src/static/Famicom/ks_nes_core.cpp +++ b/src/static/Famicom/ks_nes_core.cpp @@ -2354,16 +2354,15 @@ void ksNesConvertChrToI8(ksNesCommonWorkObj* wp, const u8* data, u32 flags) { u32 j; u32 d; u32 mask; - + bufSize = (wp->chr_to_i8_buf_size > CHR_TO_I8_BUF_SIZE ? 0x100 : wp->chr_to_i8_buf_size >> 12); idx = (flags >> 9) & 0x1f; - + a = (flags & 0x40) << 5; b = (flags >> 4) & 0x18; c = (flags & 0x3f) << 5; abc = c + a + b; - for (i = 0; i < 8; i++) { if (i & 1) { d = (data[7 - (i >> 1)]) | (data[0xf - (i >> 1)] << 8); @@ -2373,7 +2372,8 @@ void ksNesConvertChrToI8(ksNesCommonWorkObj* wp, const u8* data, u32 flags) { mask = 0x8080; for (j = 0; j < 8; j++) { - wp->chr_to_u8_bufp[abc + (flags & 0x3e00) * 8 + (i * (bufSize >> 3)) * 0x1000 + j] = (((d & mask) & 0xff00) != 0 ? 2 : 0) | (((u16)(d & mask) & 0x00FF) != 0 ? 1 : 0); + wp->chr_to_u8_bufp[abc + (flags & 0x3e00) * 8 + (i * (bufSize >> 3)) * 0x1000 + j] = + (((d & mask) & 0xff00) != 0 ? 2 : 0) | (((u16)(d & mask) & 0x00FF) != 0 ? 1 : 0); mask >>= 1; } DCStoreRangeNoSync(wp->chr_to_u8_bufp + (((idx) + (i * (bufSize >> 3))) * 0x1000 + b + a + c), 0x20); @@ -2405,7 +2405,8 @@ void ksNesConvertChrToI8MMC5(ksNesCommonWorkObj* wp, const u8* ptr, u32 flag) { mask = 0x8080; for (j = 0; j < 8; j++) { - wp->chr_to_u8_bufp[abc + (flag & (0x3F << 9)) * 8 + (i * (adj >> 3)) * 0x1000 + j] = (((v & mask) & 0xFF00) != 0 ? 2 : 0) | ((((u16)(v & mask)) & 0x00FF) != 0 ? 1 : 0); + wp->chr_to_u8_bufp[abc + (flag & (0x3F << 9)) * 8 + (i * (adj >> 3)) * 0x1000 + j] = + (((v & mask) & 0xFF00) != 0 ? 2 : 0) | ((((u16)(v & mask)) & 0x00FF) != 0 ? 1 : 0); mask >>= 1; } @@ -2477,8 +2478,8 @@ int ksNesQDFastLoad(ksNesCommonWorkObj* wp, ksNesStateObj* sp) { } memset(sp->wram + 0x200, 0, 0x600); - boot_file_no = search_p[25]; // boot file number - file_count = search_p[QD_BLOCK_DISKINFO_SZ + 1]; // amount->file_amount + boot_file_no = search_p[25]; // boot file number + file_count = search_p[QD_BLOCK_DISKINFO_SZ + 1]; // amount->file_amount search_p += QD_BLOCK_DISKINFO_SZ + QD_BLOCK_AMOUNT_SZ; // skip immediately to first file info block while (file_count != 0 && search_p < disk_end_p) { @@ -2496,7 +2497,9 @@ int ksNesQDFastLoad(ksNesCommonWorkObj* wp, ksNesStateObj* sp) { if (load_ofs < KS_NES_CHRRAM_SIZE && size <= KS_NES_CHRRAM_SIZE) { memcpy(sp->chrramp + load_ofs, &search_p[QD_BLOCK_FILEHEADER_SZ + 1], size); } - } else if (((load_ofs < KS_NES_WRAM_SIZE || load_ofs > (0x6000-1)) && (load_ofs < 0xE000 && ((load_ofs + size) <= KS_NES_WRAM_SIZE || (load_ofs + size) > 0x6000))) && (load_ofs + size) <= 0xE000 && (size <= KS_NES_BBRAM_SIZE && size != 0)) { + } else if (((load_ofs < KS_NES_WRAM_SIZE || load_ofs > (0x6000 - 1)) && + (load_ofs < 0xE000 && ((load_ofs + size) <= KS_NES_WRAM_SIZE || (load_ofs + size) > 0x6000))) && + (load_ofs + size) <= 0xE000 && (size <= KS_NES_BBRAM_SIZE && size != 0)) { if (load_ofs < KS_NES_WRAM_SIZE) { memcpy(sp->wram + load_ofs, &search_p[QD_BLOCK_FILEHEADER_SZ + 1], size); } else { @@ -2562,7 +2565,7 @@ search_start: return -1; } - search_p[0] = 3; // write file header block code? (3) + search_p[0] = 3; // write file header block code? (3) search_p[1] = sp->wram[14]; // write file number? memcpy(search_p + 2, sp->_176E + 10, 14); @@ -2571,7 +2574,7 @@ search_start: search_p += 19; // write data - + j = 0; for (j = 0; j < save_len; j++) { u8* read_p = (&sp->cpu_0000_1fff)[ksNes_ADDR2BANK(read_ofs + j)] + j; @@ -2635,9 +2638,9 @@ int ksNesReset(ksNesCommonWorkObj* wp, ksNesStateObj* sp, u32 flags, u8* chrramp u8* nesromp; OSTick os_tick; uint uVar4; - int iVar4; size_t count; u8 bVar1; + int i; // 0x40XX values appear to be NES APU addresses // 0x5015 could be the address of the MMC5's audio status register @@ -2659,23 +2662,17 @@ int ksNesReset(ksNesCommonWorkObj* wp, ksNesStateObj* sp, u32 flags, u8* chrramp if ((flags & 0x40) == 0) { Sound_SetC000(sp->wram); Sound_SetE000(sp->wram); - count = 0; - uVar4 = 0; - do { - if (!(count & 7) && 0x40 <= count && count < 0x90) { + for (u32 i = 0; i < 0x106; i++) { + if (!(i & 7) && 0x40 <= i && i < 0x90) { - uVar1 = count - 0x40 >> 3 & 0x3fffffff; + uVar1 = i - 0x40 >> 3 & 0x3fffffff; - Sound_Write((u16)sound_init_data[uVar1], (u8)sound_init_data[uVar1 + 1], uVar4); + Sound_Write((u16)sound_init_data[uVar1], (u8)sound_init_data[uVar1 + 1], i * 0x72); } - Sound_Write(0, 0, uVar4); - - count++; - uVar4 += 0x72; - - } while (count < 0x106); + Sound_Write(0, 0, i * 0x72); + } } if (flags & 1) { @@ -2692,32 +2689,23 @@ int ksNesReset(ksNesCommonWorkObj* wp, ksNesStateObj* sp, u32 flags, u8* chrramp } else { // fill ram with a predetermined pattern. - iVar2 = 0; - - for (count = 0x200; count; count--) { + for (i = 0, iVar2 = 0; i < 0x200; iVar2 += 4, i++) { wramp = &sp->wram[iVar2]; wramp[0] = 0x0f; wramp[1] = 0xef; wramp[2] = 0xfe; wramp[3] = 0x7d; - - iVar2 += 4; } } // zero out the private work struct memset(&wp->work_priv, 0, sizeof(ksNesCommonWorkPriv)); - iVar4 = 0; - iVar2 = 0; - // the state struct is (mostly) zeroed out. // this sets up some self referential pointer in the state struct for an unknown reason. - for (count = 0x18; count; count--) { - sp->_186C[iVar2] = &sp->_0800[table[iVar4 & 0xf] * 0x100]; - iVar4++; - iVar2++; + for (i = 0; i < 0x18; i++) { + sp->_186C[i] = &sp->_0800[table[i & 0xf] * 0x100]; } sp->nesromp = wp->nesromp; @@ -2775,34 +2763,21 @@ int ksNesReset(ksNesCommonWorkObj* wp, ksNesStateObj* sp, u32 flags, u8* chrramp memcpy(sp->palette_normal, &ksNesPaletteNormal, 0x80); } - iVar2 = 0; - - for (count = 0x80; count; count--) { - sp->_16CC[iVar2] = 0x0f; - iVar2++; + for (i = 0; i < 0x80; i++) { + sp->_16CC[i] = 0x0f; } - iVar2 = 0; - - for (count = 8; count; count--) { - sp->_16A0[iVar2] = 0x20; - iVar2++; + for (i = 0; i < 8; i++) { + sp->_16A0[i] = 0x20; } - iVar2 = 0; - - // i think we're dealing a new type of struct here. - for (count = 0xf0; count; count--) { - wp->work_priv._0B40[iVar2] = sp->_1810[0]; - wp->work_priv._0B40[iVar2 + 1] = sp->_1810[1]; - iVar2 += 8; + for (i = 0; i < 0xf0; i++) { + wp->work_priv._0B40[i]._00 = sp->_1810[0]; + wp->work_priv._0B40[i]._04 = sp->_1810[1]; } - iVar2 = 0; - - for (count = 8; count; count--) { - sp->_17FC[iVar2] = (u8)iVar2; - iVar2++; + for (i = 0; i < 8; i++) { + sp->_17FC[i] = (u8)i; } memset(wp->chr_to_u8_bufp, 0, wp->chr_to_i8_buf_size); diff --git a/src/static/Famicom/ks_nes_draw.cpp b/src/static/Famicom/ks_nes_draw.cpp index 5f36ff29..7f7f2671 100644 --- a/src/static/Famicom/ks_nes_draw.cpp +++ b/src/static/Famicom/ks_nes_draw.cpp @@ -1,5 +1,8 @@ - +#define FIX_SQRT_LINKAGE #include "Famicom/ks_nes_draw.h" +#include "dolphin/gx.h" +#include "dolphin/PPCArch.h" +#include "_mem.h" u8 ksNesPaletteNormal[] = { 0xc2, 0x10, 0x80, 0x17, 0x98, 0x17, 0xc0, 0x14, 0xdc, 0x0d, 0xd8, 0x03, 0xd8, 0x00, 0xc8, 0x80, 0xbc, 0xa0, 0x80, @@ -10,3 +13,351 @@ u8 ksNesPaletteNormal[] = { 0x00, 0xff, 0xff, 0xc2, 0xff, 0xde, 0xff, 0xea, 0xff, 0xfe, 0xfd, 0xfe, 0xf9, 0xff, 0x16, 0xff, 0x35, 0xff, 0x74, 0xe7, 0x93, 0xd7, 0xb6, 0xd7, 0xdd, 0xdb, 0xbf, 0xef, 0x7b, 0x80, 0x00, 0x80, 0x00, }; + +void ksNesDrawInit(ksNesCommonWorkObj* wp) { + Mtx44 mtx; + Vec v1 = { 0.f, 0.f, 800.f }; + Vec v3 = { 0.f, 0.f, -100.f }; + Vec v2 = { 0.f, 1.f, 0.f }; + GXInvalidateTexAll(); + GXInvalidateVtxCache(); + GXSetClipMode(GX_CLIP_DISABLE); + GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); + GXSetCopyFilter(GX_FALSE, NULL, GX_FALSE, NULL); + GXSetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE); + GXSetZTexture(GX_ZT_DISABLE, GX_TF_Z8, 0); + GXSetZCompLoc(GX_FALSE); + GXSetColorUpdate(GX_TRUE); + GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA); + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0); + GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0); + GXSetTevSwapMode(GX_TEVSTAGE2, GX_TEV_SWAP0, GX_TEV_SWAP0); + GXSetTevSwapMode(GX_TEVSTAGE3, GX_TEV_SWAP0, GX_TEV_SWAP0); + C_MTXOrtho(mtx, 0, -480.f, 0.f, 640.f, 0.f, 2000.f); + GXSetProjection(mtx, GX_ORTHOGRAPHIC); + C_MTXLookAt(wp->work_priv.draw_mtx, &v1, &v2, &v3); +} + +void ksNesDrawEnd() { + GXSetClipMode(GX_CLIP_ENABLE); + GXSetZCompLoc(GX_TRUE); + GXSetNumIndStages(0); + GXSetTevDirect(GX_TEVSTAGE0); + GXSetTevDirect(GX_TEVSTAGE1); + GXSetTevDirect(GX_TEVSTAGE2); + GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); + GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA); + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0); + GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0); + GXSetTevSwapMode(GX_TEVSTAGE2, GX_TEV_SWAP0, GX_TEV_SWAP0); + GXSetTevSwapMode(GX_TEVSTAGE3, GX_TEV_SWAP0, GX_TEV_SWAP0); + GXSetTexCoordScaleManually(GX_TEXCOORD0, GX_FALSE, 0, 0); + GXSetTexCoordScaleManually(GX_TEXCOORD1, GX_FALSE, 0, 0); +} + +void ksNesDrawClearEFBFirst(ksNesCommonWorkObj* wp) { + DCFlushRange(&wp->work_priv._2A40, sizeof(wp->work_priv._2A40)); + GXSetNumChans(1); + GXSetNumTexGens(0); + GXSetNumTevStages(1); + GXSetNumIndStages(0); + GXSetTevDirect(GX_TEVSTAGE0); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); + GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR); + GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE); + GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 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); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGB, GX_RGBA4, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GXSetCurrentMtx(0); + GXLoadPosMtxImm(wp->work_priv.draw_mtx, 0); + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + { + GXPosition2s16(0x80, -0x80); + GXColor1u32(0x00ff0000); + + GXPosition2s16(0x180, -0x80); + GXColor1u32(0x00000000); + + GXPosition2s16(0x180, -0x180); + GXColor1u32(0x0000ff00); + + GXPosition2s16(0x80, -0x180); + GXColor1u32(0x00000000); + } + GXEnd(); +} + +void ksNesDrawMakeBGIndTex(ksNesCommonWorkObj* wp, u32 ind) { + u32 myInd = 0x7fff; + u8 myInd2 = 0x80; + if (ind) { + myInd = 9; + } + if (wp->chr_to_i8_buf_size <= 0x1000000) { + myInd2 = wp->chr_to_i8_buf_size >> 0xd; + } + DCFlushRangeNoSync(wp->work_priv._3240, sizeof(wp->work_priv._3240)); + DCFlushRangeNoSync(wp->work_priv._7840, sizeof(wp->work_priv._7840)); +} + +void ksNesDrawMakeBGIndTexMMC5(ksNesCommonWorkObj*, ksNesStateObj*) { +} + +void ksNesDrawMakeBGIndTexMMC2(ksNesCommonWorkObj*, u32) { +} + +void ksNesDrawOBJSetupMMC2(ksNesCommonWorkObj*) { +} + +void ksNesDrawBG(ksNesCommonWorkObj*, ksNesStateObj*) { +} + +u32 ksNesDrawMakeOBJBlankVtxList(ksNesCommonWorkObj* wp) { + u32 ret = 0; + u32 comparison_mask = 20; + int i; + + for (i = 8; i < 0xf0; i++) { + int bMask = wp->work_priv._0B40[i]._19 & 0x14; + if (bMask != comparison_mask && ((bMask != 0) || (comparison_mask != 4)) && + (bMask != 4 || comparison_mask != 0)) { + if (ret & 1 != 0) { + wp->work_priv.wram[ret] = i - wp->_004C[ret + 0x13]; + ret++; + } + if ((comparison_mask == 20) || (wp->work_priv._0B40[i]._19 & 0x10) == 0) { + wp->work_priv.wram[ret++] = i; + } + comparison_mask = wp->work_priv._0B40[i]._19 & 0x14; + } + } + + if (ret & 1) { + wp->work_priv.wram[ret] = i - wp->_004C[ret + 0x13]; + ret++; + } + return ret; +} + +u32 ksNesDrawMakeOBJAppearVtxList(ksNesCommonWorkObj* wp) { + u32 ret = 0; + u32 comparison_mask = 0; + int i; + + for (i = 8; i < 0xf0; i++) { + int bMask = wp->work_priv._0B40[i]._19 & 0x14; + if (bMask != comparison_mask && ((bMask != 0) || (comparison_mask != 4)) && + (bMask != 4 || comparison_mask != 0)) { + if (ret & 1 != 0) { + wp->work_priv.wram[ret] = i - wp->_004C[ret + 0x13]; + ret++; + } + if ((wp->work_priv._0B40[i]._19 & 0x10)) { + wp->work_priv.wram[ret++] = i; + } + comparison_mask = wp->work_priv._0B40[i]._19 & 0x14; + } + } + + if (ret & 1) { + wp->work_priv.wram[ret] = i - wp->_004C[ret + 0x13]; + ret++; + } + return ret; +} + +void ksNesDrawOBJ(ksNesCommonWorkObj* wp, ksNesStateObj* state, u32 c) { + u32 size = 0x100000; + int i; + GXTexObj GStack_7c; + GXTexObj GStack_9c; + GXTexObj GStack_bc; + if (wp->chr_to_i8_buf_size <= 0x100000) { + size = wp->chr_to_i8_buf_size; + } + if (c == 0) { + for (u32 i = 0; i < 0x110; i++) { + u32 v; + if (i < 0xf0) { + v = 8; + if (state->frame_flags & 0x2000) { + v = 255; + } + } else { + v = 0; + } + wp->work_priv.wram[i] = v; + if ((wp->work_priv._0B40[i]._19 & 0x10) == 0) { + wp->work_priv.wram[i] = 0; + } + } + if (state->prg_size == 0x40000 && memcmp(state->prgromp + 0x3ffe9, "MARIO 3", 7) == 0) { + for (i = 0; i < 0xf0; i++) { + if (wp->work_priv._0B40[i]._0C == 0x7e7e7e7e) { + wp->work_priv.wram[i] = 0; + } + } + } + memset(&wp->work_priv.wram[0x340], 0, 0x800); + u8* uVar6 = &wp->work_priv.wram[0x340]; + int a; + for (u32 i = 0; i < 0x100; i++) { + int _j = 8; + if (wp->work_priv._0B40[wp->work_priv._2940[i]]._18 & 0x20) { + _j = 0x10; + } + a = 0; + int b, _c; + if (wp->work_priv._2940[i + 2] & 0x80) { + b = _j << 2; + _c = -4; + } else { + b = 0; + _c = 4; + } + u32 j, val; + for (j = 0; j < _j; j++) { + int ind = j + wp->work_priv._2940[i]; + val = wp->work_priv.wram[ind]; + if (val) { + wp->work_priv.wram[ind]--; + if ((a & 2) == 0) { + uVar6[a] = wp->work_priv._2940[i] + j; + uVar6[a + 1] = b; + a += 2; + } + } else if ((a & 2) != 0) { + uVar6[a] = wp->work_priv._2940[i] + j; + uVar6[a + 1] = b; + a += 2; + } + b += _c; + val = b; + } + if ((a & 2) != 0) { + uVar6[a] = wp->work_priv._2940[i] + j; + uVar6[a + 1] = val; + a += 2; + } + wp->work_priv.wram[0x300 + (i / 4)] = a; + } + } + GXSetNumChans(1); + GXSetNumTexGens(2); + GXSetNumTevStages(3); + GXSetNumIndStages(2); + 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); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX1, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGB, GX_RGBA4, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGBX8, 10); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX1, GX_CLR_RGBA, GX_RGBX8, 10); + GXInitTexObj(&GStack_7c, wp->chr_to_u8_bufp, 0x400, (u16)(size >> 10), GX_TF_I8, GX_MIRROR, GX_CLAMP, 0); + GXInitTexObjLOD(&GStack_7c, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1); + GXLoadTexObj(&GStack_7c, GX_TEXMAP0); + GXInitTexObj(&GStack_9c, wp->work_priv._8EC0, 8, 4, GX_TF_IA8, GX_CLAMP, GX_CLAMP, 0); + GXInitTexObjLOD(&GStack_9c, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1); + GXLoadTexObj(&GStack_9c, GX_TEXMAP1); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c); + GXSetTexCoordScaleManually(GX_TEXCOORD0, GX_TRUE, 0x100, 0x101); + GXSetTexCoordBias(GX_TEXCOORD0, 0, 0); + GXSetIndTexOrder(GX_INDTEXSTAGE0, GX_TEXCOORD0, GX_TEXMAP1); + GXSetIndTexCoordScale(GX_INDTEXSTAGE0, GX_ITS_8, GX_ITS_1); + GXSetTevIndirect(GX_TEVSTAGE0, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_OFF, GX_ITW_OFF, GX_FALSE, + GX_FALSE, GX_ITBA_OFF); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEX_DISABLE, GX_COLOR0A0); + GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_VTX, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVREG2); + GXInitTexObj(&GStack_bc, wp->work_priv._8E40, 4, 0x10, GX_TF_IA8, GX_CLAMP, GX_CLAMP, 0); + GXInitTexObjLOD(&GStack_bc, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1); + GXLoadTexObj(&GStack_bc, GX_TEXMAP2); + GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, 0x3c); + GXSetTexCoordScaleManually(GX_TEXCOORD1, GX_TRUE, 0x100, 0x101); + GXSetTexCoordBias(GX_TEXCOORD1, 0, 0); + GXSetIndTexOrder(GX_INDTEXSTAGE1, GX_TEXCOORD1, GX_TEXMAP2); + GXSetIndTexCoordScale(GX_INDTEXSTAGE1, GX_ITS_8, GX_ITS_1); + { + u32 i; + for (i = 0; size > (0x8000 << i); i++) {} + + static f32 indtexmtx_obj[2][3] = { { 0.5f, 0.f, 0.f }, { 0.f, 0.0625f, 0.f } }; + indtexmtx_obj[0][0] = 0.5f / (i >= 4 ? (1 << i - 3) : 1); + indtexmtx_obj[1][1] = 0.5f / (i <= 2 ? (1 << 3 - i) : 1); + GXSetIndTexMtx(GX_ITM_0, indtexmtx_obj, 36 + (i < 4 ? 0 : i - 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); + GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_C2, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC); + GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA); + GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevDirect(GX_TEVSTAGE2); + GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + const static GXColor color_thres = { 0xff, 1, 0, 0 }; + GXSetTevColor(GX_TEVREG0, color_thres); + GXSetTevColorIn(GX_TEVSTAGE2, GX_CC_C0, GX_CC_C2, GX_CC_CPREV, GX_CC_ZERO); + GXSetTevColorOp(GX_TEVSTAGE2, GX_TEV_COMP_GR16_GT, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE2, GX_CA_APREV, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO); + 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); +} + +void ksNesDrawOBJMMC5(ksNesCommonWorkObj*, ksNesStateObj*, u32) { +} + +void ksNesDrawFlushEFBToRed8(u8* buf) { + static const GXColor black = { 0, 0, 0, 0 }; + GXSetTexCopySrc(0x80, 0x88, 0x100, 0xe4); + GXSetTexCopyDst(0x100, 0xe4, GX_CTF_R8, GX_FALSE); + GXSetCopyClear(black, 0xffffff); + GXCopyTex(buf, GX_FALSE); + GXPixModeSync(); + GXInvalidateTexAll(); +} + +void ksNesDrawOBJI8ToEFB(ksNesCommonWorkObj* wp, u8* buf) { +} + +void ksNesDrawEmuResult(ksNesCommonWorkObj*) { +} + +void ksNesDraw(ksNesCommonWorkObj* wp, ksNesStateObj* state) { + ksNesDrawInit(wp); + ksNesDrawClearEFBFirst(wp); + if (state->mapper == 9 || state->mapper == 10) { + ksNesDrawMakeBGIndTexMMC2(wp, state->mapper == 9 ? TRUE : FALSE); + ksNesDrawOBJSetupMMC2(wp); + } else if (state->mapper == 5) { + ksNesDrawMakeBGIndTexMMC5(wp, state); + } else { + ksNesDrawMakeBGIndTex(wp, state->mapper == 4 ? TRUE : FALSE); + } + PPCSync(); + if (state->mapper == 5) { + ksNesDrawOBJMMC5(wp, state, 0); + } else { + ksNesDrawOBJ(wp, state, 0); + } + ksNesDrawFlushEFBToRed8(wp->result_bufp); + if (state->mapper == 5) { + ksNesDrawOBJMMC5(wp, state, 1); + } else { + ksNesDrawOBJ(wp, state, 1); + } + + ksNesDrawBG(wp, state); + ksNesDrawOBJI8ToEFB(wp, wp->result_bufp); + ksNesDrawFlushEFBToRed8(wp->result_bufp); + ksNesDrawEmuResult(wp); + ksNesDrawEnd(); +}