#include #include #include #include #include #include "game/init.h" #include extern unsigned char DemoStatEnable; // size: 0x1, address: 0x0 // .bss static struct _GXRenderModeObj rmodeobj; // size: 0x3C, address: 0x0 // .sdata static unsigned char DemoFirstFrame = 1; // size: 0x1, address: 0x0 // .sbss static void *DefaultFifo = NULL; // size: 0x4, address: 0x0 static GXFifoObj *DefaultFifoObj = NULL; // size: 0x4, address: 0x4 static struct _GXRenderModeObj *rmode; // size: 0x4, address: 0x8 static int BypassWorkaround; // size: 0x4, address: 0xC static unsigned long FrameCount; // size: 0x4, address: 0x10 static unsigned long FrameMissThreshold; // size: 0x4, address: 0x14 // functions static void __DEMOInitRenderMode(struct _GXRenderModeObj *mode); static void __DEMOInitMem(); static void __DEMOInitGX(); static void __DEMOInitVI(); static void __DEMOInitForEmu(); static void __BypassRetraceCallback(); static void LoadMemInfo(); void DEMOInit(struct _GXRenderModeObj *mode) { OSInit(); DVDInit(); VIInit(); DEMOPadInit(); __DEMOInitRenderMode(mode); __DEMOInitMem(); VIConfigure(rmode); DefaultFifo = OSAllocFromHeap(__OSCurrHeap, 0x40000); DefaultFifoObj = GXInit(DefaultFifo, 0x40000); __DEMOInitGX(); __DEMOInitVI(); } static void __DEMOInitRenderMode(struct _GXRenderModeObj *mode) { if (mode != NULL) { rmode = mode; return; } switch (VIGetTvFormat()) { case VI_NTSC: rmode = &GXNtsc480IntDf; break; case VI_PAL: rmode = &GXPal528IntDf; break; case VI_MPAL: rmode = &GXMpal480IntDf; break; default: OSPanic(__FILE__, 0x1A6, "DEMOInit: invalid TV format\n"); break; } GXAdjustForOverscan(rmode, &rmodeobj, 0, 0x10); rmode = &rmodeobj; } static void __DEMOInitMem() { void *arenaLo = OSGetArenaLo(); void *arenaHi = OSGetArenaHi(); unsigned long fbSize = ((u16)(rmode->fbWidth + 15) & 0xFFF0) * rmode->xfbHeight * 2; DemoFrameBuffer1 = (void *)(((u32)arenaLo + 0x1F) & 0xFFFFFFE0); DemoFrameBuffer2 = (void *)(((u32)DemoFrameBuffer1 + fbSize + 0x1F) & 0xFFFFFFE0); DemoCurrentBuffer = DemoFrameBuffer2; arenaLo = (void *)(((u32)DemoFrameBuffer2 + fbSize + 0x1F) & 0xFFFFFFE0); OSSetArenaLo(arenaLo); if (((OSGetConsoleType() + 0xF0000000) == 4U) && ((OSGetPhysicalMemSize() + 0xFFC00000) != 0U) && (OSGetConsoleSimulatedMemSize() < 0x01800000U)) { LoadMemInfo(); return; } arenaLo = OSGetArenaLo(); arenaHi = OSGetArenaHi(); arenaLo = OSInitAlloc(arenaLo, arenaHi, 1); OSSetArenaLo(arenaLo); arenaLo = (void *)(((u32)arenaLo + 0x1F) & 0xFFFFFFE0); arenaHi = (void *)((u32)arenaHi & 0xFFFFFFE0); OSSetCurrentHeap(OSCreateHeap((void *)(((u32)arenaLo)), arenaHi)); OSSetArenaLo((arenaLo = arenaHi)); } static void __DEMOInitGX() { GXSetViewport(0.0f, 0.0f, rmode->fbWidth, rmode->xfbHeight, 0.0f, 1.0f); GXSetScissor(0, 0, rmode->fbWidth, rmode->efbHeight); GXSetDispCopySrc(0, 0, rmode->fbWidth, rmode->efbHeight); GXSetDispCopyDst(rmode->fbWidth, rmode->xfbHeight); GXSetDispCopyYScale(((f32)rmode->xfbHeight / (f32)rmode->efbHeight)); GXSetCopyFilter(rmode->aa, rmode->sample_pattern, 1, rmode->vfilter); if (rmode->aa != 0) { GXSetPixelFmt(2, 0); } else { GXSetPixelFmt(0, 0); } GXCopyDisp(DemoCurrentBuffer, 1); GXSetDispCopyGamma(0); } static void __DEMOInitVI() { unsigned long nin; VISetNextFrameBuffer(DemoFrameBuffer1); DemoCurrentBuffer = DemoFrameBuffer2; VIFlush(); VIWaitForRetrace(); nin = rmode->viTVmode & 1; if (nin != 0) { VIWaitForRetrace(); } } static void __DEMOInitForEmu() { } void DEMOBeforeRender() { if (BypassWorkaround != 0) { GXSetDrawSync(0xFEEB); } if (rmode->field_rendering != 0) { GXSetViewportJitter(0.0f, 0.0f, rmode->fbWidth, rmode->xfbHeight, 0.0f, 1.0f, VIGetNextField()); } else { GXSetViewport(0.0f, 0.0f, rmode->fbWidth, rmode->xfbHeight, 0.0f, 1.0f); } GXInvalidateVtxCache(); GXInvalidateTexAll(); } void DEMOSwapBuffers() { VISetNextFrameBuffer(DemoCurrentBuffer); if (DemoFirstFrame != 0) { VISetBlack(0); DemoFirstFrame = 0; } VIFlush(); VIWaitForRetrace(); if ((u32)DemoCurrentBuffer == (u32)DemoFrameBuffer1) { DemoCurrentBuffer = DemoFrameBuffer2; return; } DemoCurrentBuffer = DemoFrameBuffer1; } struct _GXRenderModeObj *DEMOGetRenderModeObj() { return rmode; } u32 DEMOGetCurrentBuffer(void) { return (u32)DemoCurrentBuffer; } void DEMOEnableBypassWorkaround(unsigned long timeoutFrames) { BypassWorkaround = 1; FrameMissThreshold = timeoutFrames; VISetPreRetraceCallback(__BypassRetraceCallback); } static void __BypassRetraceCallback() { FrameCount += 1; } static void LoadMemInfo() { void *arenaHiOld; void *arenaLo; void *arenaHi; void *simMemEnd; struct DVDFileInfo fileInfo; unsigned long length; unsigned long transferLength; long offset; unsigned long i; unsigned long indexMax; char *buf[63]; struct { void *start; void *end; } *memEntry; OSReport("\nNow, try to find memory info file...\n\n"); if (!DVDOpen("/meminfo.bin", &fileInfo)) { OSReport("\nCan't find memory info file. Use /XXX toolname/ to maximize available\n"); OSReport("memory space. For now, we only use the first %dMB.\n", OSGetConsoleSimulatedMemSize() >> 0x14); arenaLo = OSGetArenaLo(); arenaHi = OSGetArenaHi(); arenaLo = OSInitAlloc(arenaLo, arenaHi, 1); OSSetArenaLo(arenaLo); arenaLo = (void *)(((u32)arenaLo + 0x1F) & 0xFFFFFFE0); arenaHi = (void *)((u32)arenaHi & 0xFFFFFFE0); OSSetCurrentHeap(OSCreateHeap((void *)(((u32)arenaLo)), arenaHi)); OSSetArenaLo((arenaLo = arenaHi)); return; } memEntry = (void *)((u32)buf + 0x1F & 0xFFFFFFE0); arenaHiOld = OSGetArenaHi(); simMemEnd = OSPhysicalToCached(OSGetConsoleSimulatedMemSize()); OSSetArenaHi(OSPhysicalToCached(OSGetPhysicalMemSize())); arenaLo = OSGetArenaLo(); arenaHi = OSGetArenaHi(); arenaLo = OSInitAlloc(arenaLo, arenaHi, 1); OSSetArenaLo(arenaLo); arenaLo = (void *)(((u32)arenaLo + 0x1F) & 0xFFFFFFE0); arenaHi = (void *)((u32)arenaHi & 0xFFFFFFE0); OSSetCurrentHeap(OSCreateHeap((void *)(arenaLo), arenaHi)); OSSetArenaLo((arenaLo = arenaHi)); OSAllocFixed(&arenaHiOld, &simMemEnd); length = fileInfo.length; offset = 0; while (length) { OSReport("loop\n"); transferLength = (length < 0x20) ? length : 0x20; if (DVDReadPrio(&fileInfo, memEntry, (transferLength + 0x1F) & 0xFFFFFFE0, offset, 2) < 0) { OSPanic(__FILE__, 0x49F, "An error occurred when issuing read to /meminfo.bin\n"); } indexMax = (transferLength / 8); for (i = 0; i < indexMax; i++) { OSReport("start: 0x%08x, end: 0x%08x\n", memEntry[i].start, memEntry[i].end); OSAllocFixed(&memEntry[i].start, &memEntry[i].end); OSReport("Removed 0x%08x - 0x%08x from the current heap\n", memEntry[i].start, (char *)memEntry[i].end - 1); } length -= transferLength; offset += transferLength; } DVDClose(&fileInfo); OSDumpHeap(__OSCurrHeap); }