diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index a5783a5a..8a91ba1f 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -22146,7 +22146,7 @@ VISetPreRetraceCallback = .text:0x803B3E50; // type:function size:0x44 fn_803B3EA0 = .text:0x803B3EA0; // type:function size:0x44 fn_803B3EF0 = .text:0x803B3EF0; // type:function size:0x118 fn_803B4010 = .text:0x803B4010; // type:function size:0x200 -fn_803B4210 = .text:0x803B4210; // type:function size:0x548 +VIInit = .text:0x803B4210; // type:function size:0x548 VIWaitForRetrace = .text:0x803B4760; // type:function size:0x54 fn_803B47C0 = .text:0x803B47C0; // type:function size:0x2A8 fn_803B4A70 = .text:0x803B4A70; // type:function size:0xE0 @@ -22161,7 +22161,7 @@ VIGetRetraceCount = .text:0x803B5940; // type:function size:0x8 fn_803B5950 = .text:0x803B5950; // type:function size:0x9C fn_803B59F0 = .text:0x803B59F0; // type:function size:0x90 VIGetTvFormat = .text:0x803B5A80; // type:function size:0x60 scope:global -fn_803B5AE0 = .text:0x803B5AE0; // type:function size:0x3C +VIGetDTVStatus = .text:0x803B5AE0; // type:function size:0x3C fn_803B5B20 = .text:0x803B5B20; // type:function size:0x234 fn_803B5D60 = .text:0x803B5D60; // type:function size:0x54 fn_803B5DC0 = .text:0x803B5DC0; // type:function size:0xF8 @@ -22731,12 +22731,12 @@ fn_803D5E60 = .text:0x803D5E60; // type:function size:0x104 fn_803D5F70 = .text:0x803D5F70; // type:function size:0xC fn_803D5F80 = .text:0x803D5F80; // type:function size:0x21C fn_803D61A0 = .text:0x803D61A0; // type:function size:0x338 -fn_803D64E0 = .text:0x803D64E0; // type:function size:0x54 +SCGetAspectRatio = .text:0x803D64E0; // type:function size:0x54 fn_803D6540 = .text:0x803D6540; // type:function size:0x74 -fn_803D65C0 = .text:0x803D65C0; // type:function size:0x54 +SCGetEuRgb60Mode = .text:0x803D65C0; // type:function size:0x54 fn_803D6620 = .text:0x803D6620; // type:function size:0xC SCGetLanguage = .text:0x803D6630; // type:function size:0x6C scope:global -fn_803D66A0 = .text:0x803D66A0; // type:function size:0x54 +SCGetProgressiveMode = .text:0x803D66A0; // type:function size:0x54 fn_803D6700 = .text:0x803D6700; // type:function size:0x54 fn_803D6760 = .text:0x803D6760; // type:function size:0x54 fn_803D67C0 = .text:0x803D67C0; // type:function size:0x40 @@ -26301,7 +26301,7 @@ initialize__Q23EGG5VideoFP16_GXRenderModeObjPCQ33EGG5Video16RenderModeObjSet = . configure__Q23EGG5VideoFP16_GXRenderModeObjPCQ33EGG5Video16RenderModeObjSet = .text:0x804986F0; // type:function size:0x104 getTickPerVRetrace__Q23EGG5VideoFUi = .text:0x80498800; // type:function size:0x60 getTickPerVRetrace__Q23EGG5VideoFv = .text:0x80498860; // type:function size:0x24 -getStandardRenderModeObj__Q23EGG5VideoFv = .text:0x80498890; // type:function size:0x148 +getStandardRenderModeObj__Q23EGG5VideoFPCQ33EGG5Video16RenderModeObjSet = .text:0x80498890; // type:function size:0x148 init__Q23EGG3XfbFUsUsPQ23EGG4Heap = .text:0x804989E0; // type:function size:0x74 __ct__Q23EGG3XfbFPQ23EGG4Heap = .text:0x80498A60; // type:function size:0x64 calcBufferSize__Q23EGG3XfbFUsUs = .text:0x80498AD0; // type:function size:0x14 diff --git a/configure.py b/configure.py index 4f4dabe2..06285a60 100644 --- a/configure.py +++ b/configure.py @@ -365,7 +365,7 @@ config.libs = [ Object(Matching, "egg/core/eggDisplay.cpp"), Object(Matching, "egg/core/eggColorFader.cpp"), Object(Matching, "egg/core/eggAsyncDisplay.cpp"), - Object(NonMatching, "egg/core/eggVideo.cpp"), + Object(Matching, "egg/core/eggVideo.cpp"), Object(NonMatching, "egg/core/eggXfb.cpp"), Object(NonMatching, "egg/core/eggXfbManager.cpp"), Object(NonMatching, "egg/core/eggGraphicsFifo.cpp"), diff --git a/include/egg/core/eggVideo.h b/include/egg/core/eggVideo.h index fb56d66f..0a282516 100644 --- a/include/egg/core/eggVideo.h +++ b/include/egg/core/eggVideo.h @@ -11,21 +11,21 @@ namespace EGG { class Video { public: struct RenderModeObjSet { - GXRenderModeObj *table[10]; + const GXRenderModeObj *table[10]; }; public: - /* 0x00 */ GXRenderModeObj const *pRenderMode; + /* 0x00 */ GXRenderModeObj *pRenderMode; /* 0x04 */ TBitFlag mFlag; /* 0x08 */ u32 mConfiguredTime; public: /* inline */ Video() : pRenderMode(0), mFlag(), mConfiguredTime(){}; /* 80498690 */ void initialize(GXRenderModeObj *, const RenderModeObjSet *); - /* 804986f0 */ void configure(GXRenderModeObj *, const RenderModeObjSet *); + /* 804986f0 */ GXRenderModeObj *configure(GXRenderModeObj *, const RenderModeObjSet *); /* 80498800 */ static u32 getTickPerVRetrace(u32 tvFormat); /* 80498860 */ static u32 getTickPerVRetrace(); - /* 80498890 */ static GXRenderModeObj *getStandardRenderModeObj(RenderModeObjSet *); + /* 80498890 */ static const GXRenderModeObj *getStandardRenderModeObj(const RenderModeObjSet *); public: /* inline */ void setBlack(bool b) { diff --git a/include/rvl/GX/GXFrameBuf.h b/include/rvl/GX/GXFrameBuf.h index 376007e5..f21de91f 100644 --- a/include/rvl/GX/GXFrameBuf.h +++ b/include/rvl/GX/GXFrameBuf.h @@ -24,6 +24,10 @@ typedef struct _GXRenderModeObj { void GXSetCopyFilter(u8, const u8[12][2], u8, const u8[7]); void GXSetCopyClear(GXColor, u32 zClear); void GXSetDispCopySrc(u16 left, u16 top, u16 width, u16 height); +f32 GXGetYScaleFactor(u16 height, u16 width); +u16 GXGetNumXfbLines(u16 height, f32 scale); +void GXSetDispCopyDst(u16 width, u16 height); +u32 GXSetDispCopyYScale(f32 scale); extern GXRenderModeObj GXNtsc480IntDf; extern GXRenderModeObj GXMpal480IntDf; diff --git a/src/egg/core/eggVideo.cpp b/src/egg/core/eggVideo.cpp new file mode 100644 index 00000000..76479432 --- /dev/null +++ b/src/egg/core/eggVideo.cpp @@ -0,0 +1,406 @@ +#include +#include +#include +#include + +namespace { + +const GXRenderModeObj gRMO_Pal60_640x456Prog_16x9 = { + 0, // tvInfo + 640, // fbWidth + 456, // efbHeight + 456, // xfbHeight + 25, // viXOrigin + 12, // viYOrigin + 670, // viWidth + 456, // viHeight + 1, // xfbMode + 0, // field_rendering + 0, // aa + { + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + }, // sample_pattern + {7, 7, 12, 12, 12, 7, 7} // vFilter +}; + +const GXRenderModeObj gRMO_Pal60_640x456IntDf_16x9 = { + 2, // tvInfo + 640, // fbWidth + 456, // efbHeight + 456, // xfbHeight + 25, // viXOrigin + 12, // viYOrigin + 670, // viWidth + 456, // viHeight + 0, // xfbMode + 0, // field_rendering + 0, // aa + { + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + }, // sample_pattern + {0, 0, 21, 22, 21, 0, 0} // vFilter +}; + +const GXRenderModeObj gRMO_Pal50_640x456IntDf_16x9 = { + 4, // tvInfo + 640, // fbWidth + 456, // efbHeight + 542, // xfbHeight + 27, // viXOrigin + 16, // viYOrigin + 666, // viWidth + 542, // viHeight + 1, // xfbMode + 0, // field_rendering + 0, // aa + { + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + }, // sample_pattern + {7, 7, 12, 12, 12, 7, 7} // vFilter +}; + +const GXRenderModeObj gRMO_Ntsc_640x456Prog_16x9 = { + 20, // tvInfo + 640, // fbWidth + 456, // efbHeight + 456, // xfbHeight + 25, // viXOrigin + 12, // viYOrigin + 670, // viWidth + 456, // viHeight + 1, // xfbMode + 0, // field_rendering + 0, // aa + { + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + }, // sample_pattern + {7, 7, 12, 12, 12, 7, 7} // vFilter +}; + +const GXRenderModeObj gRMO_Ntsc_640x456IntDf_16x9 = { + 22, // tvInfo + 640, // fbWidth + 456, // efbHeight + 456, // xfbHeight + 25, // viXOrigin + 12, // viYOrigin + 670, // viWidth + 456, // viHeight + 0, // xfbMode + 0, // field_rendering + 0, // aa + { + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + }, // sample_pattern + {0, 0, 21, 22, 21, 0, 0} // vFilter +}; + +const GXRenderModeObj gRMO_Pal60_640x456Prog_4x3 = { + 0, // tvInfo + 640, // fbWidth + 456, // efbHeight + 456, // xfbHeight + 17, // viXOrigin + 12, // viYOrigin + 686, // viWidth + 456, // viHeight + 1, // xfbMode + 0, // field_rendering + 0, // aa + { + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + }, // sample_pattern + {7, 7, 12, 12, 12, 7, 7} // vFilter +}; + +const GXRenderModeObj gRMO_Pal60_640x456IntDf_4x3 = { + 2, // tvInfo + 640, // fbWidth + 456, // efbHeight + 456, // xfbHeight + 17, // viXOrigin + 12, // viYOrigin + 686, // viWidth + 456, // viHeight + 0, // xfbMode + 0, // field_rendering + 0, // aa + { + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + }, // sample_pattern + {0, 0, 21, 22, 21, 0, 0} // vFilter +}; + +const GXRenderModeObj gRMO_Pal50_640x456IntDf_4x3 = { + 4, // tvInfo + 640, // fbWidth + 456, // efbHeight + 542, // xfbHeight + 19, // viXOrigin + 16, // viYOrigin + 682, // viWidth + 542, // viHeight + 1, // xfbMode + 0, // field_rendering + 0, // aa + { + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + }, // sample_pattern + {7, 7, 12, 12, 12, 7, 7} // vFilter +}; + +const GXRenderModeObj gRMO_Ntsc_640x456Prog_4x3 = { + 20, // tvInfo + 640, // fbWidth + 456, // efbHeight + 456, // xfbHeight + 17, // viXOrigin + 12, // viYOrigin + 686, // viWidth + 456, // viHeight + 1, // xfbMode + 0, // field_rendering + 0, // aa + { + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + }, // sample_pattern + {7, 7, 12, 12, 12, 7, 7} // vFilter +}; + +const GXRenderModeObj gRMO_Ntsc_640x456IntDf_4x3 = { + 22, // tvInfo + 640, // fbWidth + 456, // efbHeight + 456, // xfbHeight + 17, // viXOrigin + 12, // viYOrigin + 686, // viWidth + 456, // viHeight + 0, // xfbMode + 0, // field_rendering + 0, // aa + { + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + {6, 6}, + }, // sample_pattern + {0, 0, 21, 22, 21, 0, 0} // vFilter +}; + +} // namespace + +namespace EGG { + +const EGG::Video::RenderModeObjSet renderModes = {{&gRMO_Pal60_640x456Prog_16x9, &gRMO_Pal60_640x456IntDf_16x9, + &gRMO_Pal50_640x456IntDf_16x9, &gRMO_Ntsc_640x456Prog_16x9, &gRMO_Ntsc_640x456IntDf_16x9, + &gRMO_Pal60_640x456Prog_4x3, &gRMO_Pal60_640x456IntDf_4x3, &gRMO_Pal50_640x456IntDf_4x3, + &gRMO_Ntsc_640x456Prog_4x3, &gRMO_Ntsc_640x456IntDf_4x3}}; + +/* 80498690 */ void Video::initialize(GXRenderModeObj *obj, const RenderModeObjSet *set) { + VIInit(); + configure(obj, set); +} + +/* 804986f0 */ GXRenderModeObj *Video::configure(GXRenderModeObj *obj, const RenderModeObjSet *set) { + GXRenderModeObj *oldMode = pRenderMode; + if (set == nullptr) { + set = &renderModes; + } + if (obj == nullptr) { + // Cast away constness. In an incredibly cursed way, adding proper + // const correctness to this class changes regalloc + obj = (GXRenderModeObj *)getStandardRenderModeObj(set); + } + if (pRenderMode != obj) { + pRenderMode = obj; + VISetBlack(true); + VIConfigure(obj); + VIFlush(); + mConfiguredTime = OSGetTick(); + mFlag.setBit(0); + u16 efbWidth = obj->fbWidth; + u16 efbHeight = obj->efbHeight; + f32 factor = GXGetYScaleFactor(efbHeight, obj->xfbHeight); + u16 lines = GXGetNumXfbLines(efbHeight, factor); + GXSetDispCopySrc(0, 0, efbWidth, efbHeight); + GXSetDispCopyDst(efbWidth, lines); + GXSetDispCopyYScale(factor); + VIWaitForRetrace(); + VIWaitForRetrace(); + } + + return oldMode; +} + +// Random function that pretends to do an int to float +// cast here, for float ordering issues +f32 itof(u32 n) { + return n; +} +// TODO VITvFormat +/* 80498800 */ u32 Video::getTickPerVRetrace(u32 tvFormat) { + f32 val = tvFormat - 1 <= VI_TV_FMT_PAL ? 50.0f : 59.94f; + return (u32)((OS_BUS_CLOCK_SPEED >> 2) / val); +} +/* 80498860 */ u32 Video::getTickPerVRetrace() { + return getTickPerVRetrace(VIGetTvFormat()); +} +/* 80498890 */ const GXRenderModeObj *Video::getStandardRenderModeObj(const RenderModeObjSet *set) { + bool pmode = SCGetProgressiveMode() == 1; + bool rbg60mode = SCGetEuRgb60Mode() == 1; + bool aspect = SCGetAspectRatio() == 0; + bool dtvstatus = VIGetDTVStatus() == 1; + u32 tvFormat = VIGetTvFormat(); + + bool isNtscLike; + switch (tvFormat) { + case VI_TV_FMT_NTSC: + isNtscLike = true; + break; + case VI_TV_FMT_PAL: + case VI_TV_FMT_EURGB60: + isNtscLike = false; + break; + default: + isNtscLike = true; + } + + if (dtvstatus && pmode) { + if (isNtscLike) { + if (aspect) { + return set->table[1]; + } else { + return set->table[6]; + } + } else if (aspect) { + return set->table[4]; + } else { + return set->table[9]; + } + } else if (isNtscLike) { + if (aspect) { + return set->table[0]; + } else { + return set->table[5]; + } + } else if (rbg60mode) { + if (aspect) { + return set->table[3]; + } else { + return set->table[8]; + } + } else if (aspect) { + return set->table[2]; + } + return set->table[7]; +} + +} // namespace EGG