diff --git a/cmake/targets/dolphin.cmake b/cmake/targets/dolphin.cmake index a20b9d81..98e342bf 100644 --- a/cmake/targets/dolphin.cmake +++ b/cmake/targets/dolphin.cmake @@ -16,6 +16,9 @@ target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} PUBLIC DOL=1 ISO=2 DUSK_DOLPHIN_BUILD_TYPE=${DUSK_DOLPHIN_BUILD_TYPE} + # GameCube/Wii PowerPC is always big-endian; declare it at compile time + # like every other target instead of relying on endian.h's runtime probe. + DUSK_PLATFORM_ENDIAN_BIG ) # Custom compiler flags diff --git a/src/dusk/asset/loader/chunk/assetchunkloader.c b/src/dusk/asset/loader/chunk/assetchunkloader.c index 505126c6..4046ef12 100644 --- a/src/dusk/asset/loader/chunk/assetchunkloader.c +++ b/src/dusk/asset/loader/chunk/assetchunkloader.c @@ -115,6 +115,11 @@ errorret_t assetChunkLoaderSync(assetloading_t *loading) { memoryCopy(out->tiles, data + offset, tileSize); offset += tileSize; + for(size_t t = 0; t < CHUNK_TILE_COUNT; t++) { + uint32_t *shape = (uint32_t *)&out->tiles[t].shape; + *shape = endianLittleToHost32(*shape); + } + out->meshCount = data[offset]; offset += sizeof(uint8_t); assertTrue( @@ -136,6 +141,9 @@ errorret_t assetChunkLoaderSync(assetloading_t *loading) { memoryCopy(out->meshOffsets[m], data + offset, sizeof(vec3)); offset += sizeof(vec3); + out->meshOffsets[m][0] = endianLittleToHostFloat(out->meshOffsets[m][0]); + out->meshOffsets[m][1] = endianLittleToHostFloat(out->meshOffsets[m][1]); + out->meshOffsets[m][2] = endianLittleToHostFloat(out->meshOffsets[m][2]); } memoryFree(data); diff --git a/src/dusk/asset/loader/dmf/assetmeshloader.c b/src/dusk/asset/loader/dmf/assetmeshloader.c index a4c5bcaf..de40a622 100644 --- a/src/dusk/asset/loader/dmf/assetmeshloader.c +++ b/src/dusk/asset/loader/dmf/assetmeshloader.c @@ -48,8 +48,20 @@ errorret_t assetMeshLoaderAsync(assetloading_t *loading) { uint32_t vertCount = endianLittleToHost32(*(uint32_t *)(raw + 8)); meshvertex_t *vertices = NULL; if(vertCount > 0) { - vertices = memoryAllocate(vertCount * sizeof(meshvertex_t)); + // 32-byte (cache-line) aligned: GX_SetArray + DCFlushRange on Dolphin + // require this for the DMA'd vertex data to actually reach the GPU + // coherently. Static compiled-in vertex arrays happen to get this from + // the linker; a plain memoryAllocate here would not. + vertices = memoryAlign(32, vertCount * sizeof(meshvertex_t)); memoryCopy(vertices, raw + 12, vertCount * sizeof(meshvertex_t)); + + for(uint32_t v = 0; v < vertCount; v++) { + vertices[v].uv[0] = endianLittleToHostFloat(vertices[v].uv[0]); + vertices[v].uv[1] = endianLittleToHostFloat(vertices[v].uv[1]); + vertices[v].pos[0] = endianLittleToHostFloat(vertices[v].pos[0]); + vertices[v].pos[1] = endianLittleToHostFloat(vertices[v].pos[1]); + vertices[v].pos[2] = endianLittleToHostFloat(vertices[v].pos[2]); + } } memoryFree(raw); @@ -103,18 +115,22 @@ errorret_t assetMeshLoaderSync(assetloading_t *loading) { out->vertices = NULL; errorChain(ret); } + out->meshInitialized = true; ret = meshFlush(&out->mesh, 0, (int32_t)vertCount); if(errorIsNotOk(ret)) { loading->entry->state = ASSET_ENTRY_STATE_ERROR; meshDispose(&out->mesh); + out->meshInitialized = false; memoryFree(out->vertices); out->vertices = NULL; errorChain(ret); } - #ifndef DUSK_OPENGL_LEGACY - // VBO owns the data now; CPU copy is no longer needed. + #if defined(DUSK_OPENGL) && !defined(DUSK_OPENGL_LEGACY) + // VBO owns the data now; CPU copy is no longer needed. The platform + // mesh object itself still needs meshDispose later - tracked via + // out->meshInitialized, independent of the CPU buffer's lifetime. memoryFree(out->vertices); out->vertices = NULL; #endif @@ -129,8 +145,11 @@ errorret_t assetMeshDispose(assetentry_t *entry) { assertIsMainThread("Must be called from the main thread."); assetmeshoutput_t *out = &entry->data.mesh; - if(out->vertices != NULL) { + if(out->meshInitialized) { errorChain(meshDispose(&out->mesh)); + out->meshInitialized = false; + } + if(out->vertices != NULL) { memoryFree(out->vertices); out->vertices = NULL; } diff --git a/src/dusk/asset/loader/dmf/assetmeshloader.h b/src/dusk/asset/loader/dmf/assetmeshloader.h index 5f906efe..ebe66cdd 100644 --- a/src/dusk/asset/loader/dmf/assetmeshloader.h +++ b/src/dusk/asset/loader/dmf/assetmeshloader.h @@ -30,6 +30,7 @@ typedef struct { typedef struct { mesh_t mesh; + bool_t meshInitialized; meshvertex_t *vertices; } assetmeshoutput_t; diff --git a/src/duskdolphin/display/displaydolphin.c b/src/duskdolphin/display/displaydolphin.c index 90c352f6..7980dca9 100644 --- a/src/duskdolphin/display/displaydolphin.c +++ b/src/duskdolphin/display/displaydolphin.c @@ -78,6 +78,12 @@ errorret_t displayInitDolphin(void) { GX_SetDispCopyGamma(GX_GM_1_0); GX_SetColorUpdate(GX_TRUE); + // Without this, the EFB's Z-buffer format/compression is left at whatever + // GX_Init() defaulted to, so depth testing and the GX_MAX_Z24 clear value + // used every frame in frameBufferClearDolphin aren't guaranteed to line up + // with the actual EFB Z format. + GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); + // Describe mesh vertex format. GX_ClearVtxDesc(); GX_SetVtxDesc(GX_VA_POS, GX_INDEX16); @@ -101,7 +107,7 @@ errorret_t displaySetStateDolphin(displaystate_t state) { } if(state.flags & DISPLAY_STATE_FLAG_DEPTH_TEST) { - GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_FALSE); } else { GX_SetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE); }