From 5b88f3f508dc0238642dbcf983bc82e01e112fb8 Mon Sep 17 00:00:00 2001 From: Shiz Date: Wed, 24 Jan 2024 16:32:57 +0100 Subject: [PATCH 1/4] video: refactor magic register writes into named functions --- libogc/video.c | 151 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 120 insertions(+), 31 deletions(-) diff --git a/libogc/video.c b/libogc/video.c index 4ec14f74..f059cc9a 100644 --- a/libogc/video.c +++ b/libogc/video.c @@ -2240,30 +2240,75 @@ static void __VIWriteI2CRegisterBuf(u8 reg, int size, u8 *data) udelay(2); } -static void __VISetOverSampling(u8 mode) + +static void __VISetTiming(u8 mode) { - __VIWriteI2CRegister8(0x65, mode); + __VIWriteI2CRegister8(0x00, mode); } -static void __VISetYUVSEL(u8 dtvstatus) +static void __VISetOutputMode(u8 dtvstatus) { - if(currTvMode==VI_NTSC) vdacFlagRegion = 0x0000; - else if(currTvMode==VI_PAL || currTvMode==VI_EURGB60) vdacFlagRegion = 0x0002; - else if(currTvMode==VI_MPAL) vdacFlagRegion = 0x0001; - else vdacFlagRegion = 0x0000; + switch (currTvMode) + { + case VI_NTSC: + default: + vdacFlagRegion = 0; break; + case VI_MPAL: + vdacFlagRegion = 1; break; + case VI_PAL: + case VI_EURGB60: + vdacFlagRegion = 2; break; + case VI_DEBUG: + case VI_DEBUG_PAL: + vdacFlagRegion = 3; break; + } __VIWriteI2CRegister8(0x01, _SHIFTL(dtvstatus,5,3)|(vdacFlagRegion&0x1f)); } -static void __VISetFilterEURGB60(u8 enable) +static void __VISetVBlankData(bool cgms, bool wss, bool captions) { - __VIWriteI2CRegister8(0x6e, enable); + u8 data = (captions ? 0 : 1) | (cgms ? 0 : 1) << 1 | (cgms ? 0 : 1) << 2; + __VIWriteI2CRegister8(0x02, data); } -static void __VISetupEncoder(void) +static void __VISetTrapFilter(bool enable) { - u8 macrobuf[0x1a]; + __VIWriteI2CRegister8(0x03, enable ? 1 : 0); +} + +static void __VISetOutputEnable(bool enable) +{ + __VIWriteI2CRegister8(0x04, enable ? 1 : 0); +} + +static void __VISetCGMSData(u8 param1, u8 param2, u8 param3) +{ + __VIWriteI2CRegister16(0x05, (param1 & 3) << 8 | (param2 & 0xf) << 10 | param3); +} + +static void __VIResetCGMSData(void) +{ + __VISetCGMSData(0, 0, 0); +} +static void __VISetWSSData(u8 param1, u8 param2, u8 param3, u8 param4) +{ + __VIWriteI2CRegister16(0x08, (param1 & 0xf) << 8 | (param2 & 0xf) << 12 | (param3 & 0x7) << 3 | (param4 & 0x7)); +} + +static void __VIResetWSSData(void) +{ + __VISetWSSData(0, 0, 0, 0); +} + +static void __VISetOverDrive(bool enable, u8 level) +{ + __VIWriteI2CRegister8(0x0A, (level << 1) | (enable ? 1 : 0)); +} + +static void __VISetGamma(void) +{ u8 gamma[0x21] = { 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x20, 0x40, 0x60, @@ -2271,6 +2316,54 @@ static void __VISetupEncoder(void) 0x00, 0x60, 0x00, 0x80, 0x00, 0xa0, 0x00, 0xeb, 0x00 }; + __VIWriteI2CRegisterBuf(0x10, sizeof(gamma), gamma); +} + +static void __VISetMacroVision(u8 tv) +{ + u8 macrobuf[0x1a]; + + memset(macrobuf, 0, sizeof(macrobuf)); + __VIWriteI2CRegisterBuf(0x40, sizeof(macrobuf), macrobuf); +} + +static void __VISetOverSampling(u8 mode) +{ + __VIWriteI2CRegister8(0x65, mode); +} + +static void __VISetClosedCaptionMode(u8 mode) +{ + __VIWriteI2CRegister8(0x6A, mode); +} + +static void __VISetRGBFilter(bool enable) +{ + __VIWriteI2CRegister8(0x6e, enable ? 1 : 0); +} + +static void __VISetAudioVolume(u8 left_chan, u8 right_chan) +{ + u16 data = (left_chan << 8) | right_chan; + __VIWriteI2CRegister16(0x71, data); +} + +static void __VISetClosedCaptionData(u8 param1, u8 param2, u8 param3, u8 param4) +{ + u32 data = (param1 & 0x7f) << 24 | (param2 & 0x7f) << 16 | (param3 & 0x7f) << 8 | (param4 & 0x7f); + __VIWriteI2CRegister32(0x7A, data); +} + +static void __VIResetClosedCaptionData(void) +{ + __VISetClosedCaptionData(0, 0, 0, 0); +} + +static u32 __VISetupEncoder(void) +{ + if (!shdw_changeEncoder) + return 0; + shdw_changeEncoder = 0; u8 dtv, tv; @@ -2278,34 +2371,30 @@ static void __VISetupEncoder(void) dtv = (_viReg[55]&0x01); oldDtvStatus = dtv; - // SetRevolutionModeSimple - - memset(macrobuf, 0, 0x1a); - - __VIWriteI2CRegister8(0x6a, 1); + __VISetClosedCaptionMode(1); __VISetOverSampling(3); - __VISetYUVSEL(dtv); - __VIWriteI2CRegister8(0x00, 0); - __VIWriteI2CRegister16(0x71, 0x8e8e); - __VIWriteI2CRegister8(0x02, 7); - __VIWriteI2CRegister16(0x05, 0x0000); - __VIWriteI2CRegister16(0x08, 0x0000); - __VIWriteI2CRegister32(0x7A, 0x00000000); + __VISetOutputMode(dtv); + __VISetTiming(0); + __VISetAudioVolume(0x8e, 0x8e); + __VISetVBlankData(false, false, false); + __VIResetCGMSData(); + __VIResetWSSData(); + __VIResetClosedCaptionData(); // Macrovision crap - __VIWriteI2CRegisterBuf(0x40, sizeof(macrobuf), macrobuf); + __VISetMacroVision(); // Sometimes 1 in RGB mode? (reg 1 == 3) - __VIWriteI2CRegister8(0x0A, 0); + __VISetOverDrive(false, 0); - __VIWriteI2CRegister8(0x03, 1); + __VISetTrapFilter(true); - __VIWriteI2CRegisterBuf(0x10, sizeof(gamma), gamma); + __VISetGamma(); - __VIWriteI2CRegister8(0x04, 1); + __VISetOutputEnable(true); - if(tv==VI_EURGB60) __VISetFilterEURGB60(1); - else __VISetFilterEURGB60(0); + if(tv==VI_EURGB60) __VISetRGBFilter(true); + else __VISetRGBFilter(false); oldTvStatus = tv; } @@ -2508,7 +2597,7 @@ static void __VIRetraceHandler(u32 nIrq,void *pCtx) #if defined(HW_RVL) tv = VIDEO_GetCurrentTvMode(); dtv = (_viReg[55]&0x01); - if(dtv!=oldDtvStatus || tv!=oldTvStatus) __VISetYUVSEL(dtv); + if(dtv!=oldDtvStatus || tv!=oldTvStatus) __VISetOutputMode(dtv); oldDtvStatus = dtv; if(tv!=oldTvStatus) { From 322788f04cbc53b14f4bcf12e72e5bab7fde7847 Mon Sep 17 00:00:00 2001 From: Shiz Date: Sun, 28 Jan 2024 13:40:12 +0100 Subject: [PATCH 2/4] video: add generic RGB mode flag and allow re-configuring encoder Previously, the encoder was configured only once during VIDEO_Init(), and would not be re-configured when VIDEO_Configure(mode) was called. Since we can switch from a non-RGB to an RGB mode, we need to be able to reconfigure the encoder at configure-time. This commit extends the mode-switching mechanism to also allow scheduling for encoder setting changes at run-time. Moreover, since there are more RGB video modes than EURGB60, we extend the mode struct with a flag to indicate whether the mode is RGB or not or not for easy internal use. Adding it to the VI_TVMODE enumeration was also considered, but decided against since it would break the VIDEO_GetCurrentTvMode() ABI for EURGB60 modes. --- gc/ogc/gx_struct.h | 1 + libogc/video.c | 86 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 74 insertions(+), 13 deletions(-) diff --git a/gc/ogc/gx_struct.h b/gc/ogc/gx_struct.h index 107e7a7b..4bd7af6b 100644 --- a/gc/ogc/gx_struct.h +++ b/gc/ogc/gx_struct.h @@ -65,6 +65,7 @@ typedef struct _gx_rmodeobj { u16 viWidth; u16 viHeight; u32 xfbMode; + u8 rgb; u8 field_rendering; u8 aa; u8 sample_pattern[12][2]; diff --git a/libogc/video.c b/libogc/video.c index f059cc9a..cd248817 100644 --- a/libogc/video.c +++ b/libogc/video.c @@ -72,6 +72,7 @@ typedef struct _horVer { u32 fbMode; u32 nonInter; u32 tv; + u8 rgb; u8 wordPerLine; u8 std; u8 wpl; @@ -98,6 +99,7 @@ GXRModeObj TVNtsc240Ds = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -132,6 +134,7 @@ GXRModeObj TVNtsc240DsAa = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_TRUE, // aa @@ -166,6 +169,7 @@ GXRModeObj TVNtsc240Int = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_TRUE, // field_rendering GX_FALSE, // aa @@ -200,6 +204,7 @@ GXRModeObj TVNtsc240IntAa = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_TRUE, // field_rendering GX_TRUE, // aa @@ -234,6 +239,7 @@ GXRModeObj TVNtsc480Int = 640, // viWidth 480, // viHeight VI_XFBMODE_DF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -268,6 +274,7 @@ GXRModeObj TVNtsc480IntDf = 640, // viWidth 480, // viHeight VI_XFBMODE_DF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -302,6 +309,7 @@ GXRModeObj TVNtsc480IntAa = 640, // viWidth 480, // viHeight VI_XFBMODE_DF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_TRUE, // aa @@ -337,6 +345,7 @@ GXRModeObj TVNtsc480Prog = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -371,6 +380,7 @@ GXRModeObj TVNtsc480ProgSoft = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -405,6 +415,7 @@ GXRModeObj TVNtsc480ProgAa = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_TRUE, // aa @@ -439,6 +450,7 @@ GXRModeObj TVMpal240Ds = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -473,6 +485,7 @@ GXRModeObj TVMpal240DsAa = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_TRUE, // aa @@ -507,6 +520,7 @@ GXRModeObj TVMpal240Int = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_TRUE, // field_rendering GX_FALSE, // aa @@ -541,6 +555,7 @@ GXRModeObj TVMpal240IntAa = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_TRUE, // field_rendering GX_TRUE, // aa @@ -575,6 +590,7 @@ GXRModeObj TVMpal480Int = 640, // viWidth 480, // viHeight VI_XFBMODE_DF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -609,6 +625,7 @@ GXRModeObj TVMpal480IntDf = 640, // viWidth 480, // viHeight VI_XFBMODE_DF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -643,6 +660,7 @@ GXRModeObj TVMpal480IntAa = 640, // viWidth 480, // viHeight VI_XFBMODE_DF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_TRUE, // aa @@ -677,6 +695,7 @@ GXRModeObj TVMpal480Prog = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -711,6 +730,7 @@ GXRModeObj TVMpal480ProgSoft = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -745,6 +765,7 @@ GXRModeObj TVMpal480ProgAa = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_TRUE, // aa @@ -779,6 +800,7 @@ GXRModeObj TVPal264Ds = 640, // viWidth 528, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -813,6 +835,7 @@ GXRModeObj TVPal264DsAa = 640, // viWidth 528, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_TRUE, // aa @@ -847,6 +870,7 @@ GXRModeObj TVPal264Int = 640, // viWidth 528, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_TRUE, // field_rendering GX_FALSE, // aa @@ -881,6 +905,7 @@ GXRModeObj TVPal264IntAa = 640, // viWidth 528, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_TRUE, // field_rendering GX_TRUE, // aa @@ -915,6 +940,7 @@ GXRModeObj TVPal528Int = 640, // viWidth 528, // viHeight VI_XFBMODE_DF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -949,6 +975,7 @@ GXRModeObj TVPal528IntDf = 640, // viWidth 528, // viHeight VI_XFBMODE_DF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -982,6 +1009,7 @@ GXRModeObj TVPal524IntAa = 640, // viWidth 524, // viHeight VI_XFBMODE_DF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_TRUE, // aa @@ -1016,6 +1044,7 @@ GXRModeObj TVPal576IntDfScale = 640, // viWidth 576, // viHeight VI_XFBMODE_DF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -1049,6 +1078,7 @@ GXRModeObj TVPal528Prog = 640, // viWidth 528, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -1083,6 +1113,7 @@ GXRModeObj TVPal528ProgSoft = 640, // viWidth 528, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -1116,6 +1147,7 @@ GXRModeObj TVPal524ProgAa = 640, // viWidth 524, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_TRUE, // aa @@ -1150,6 +1182,7 @@ GXRModeObj TVPal576ProgScale = 640, // viWidth 576, // viHeight VI_XFBMODE_SF, // xFBmode + GX_FALSE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -1183,6 +1216,7 @@ GXRModeObj TVEurgb60Hz240Ds = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_TRUE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -1216,6 +1250,7 @@ GXRModeObj TVEurgb60Hz240DsAa = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_TRUE, // rgb GX_FALSE, // field_rendering GX_TRUE, // aa @@ -1249,6 +1284,7 @@ GXRModeObj TVEurgb60Hz240Int = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_TRUE, // rgb GX_TRUE, // field_rendering GX_FALSE, // aa @@ -1282,6 +1318,7 @@ GXRModeObj TVEurgb60Hz240IntAa = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_TRUE, // rgb GX_TRUE, // field_rendering GX_TRUE, // aa @@ -1315,6 +1352,7 @@ GXRModeObj TVEurgb60Hz480Int = 640, // viWidth 480, // viHeight VI_XFBMODE_DF, // xFBmode + GX_TRUE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -1348,6 +1386,7 @@ GXRModeObj TVEurgb60Hz480IntDf = 640, // viWidth 480, // viHeight VI_XFBMODE_DF, // xFBmode + GX_TRUE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -1381,6 +1420,7 @@ GXRModeObj TVEurgb60Hz480IntAa = 640, // viWidth 480, // viHeight VI_XFBMODE_DF, // xFBmode + GX_TRUE, // rgb GX_FALSE, // field_rendering GX_TRUE, // aa @@ -1414,6 +1454,7 @@ GXRModeObj TVEurgb60Hz480Prog = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_TRUE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -1447,6 +1488,7 @@ GXRModeObj TVEurgb60Hz480ProgSoft = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_TRUE, // rgb GX_FALSE, // field_rendering GX_FALSE, // aa @@ -1480,6 +1522,7 @@ GXRModeObj TVEurgb60Hz480ProgAa = 640, // viWidth 480, // viHeight VI_XFBMODE_SF, // xFBmode + GX_TRUE, // rgb GX_FALSE, // field_rendering GX_TRUE, // aa @@ -1610,8 +1653,8 @@ static u16 shdw_regs[60]; static u32 fbSet = 0; static s16 displayOffsetH; static s16 displayOffsetV; -static u32 currTvMode,changeMode; -static u32 shdw_changeMode,flushFlag; +static u32 currTvMode,currRgb,changeMode,changeEncoder; +static u32 shdw_changeMode,shdw_changeEncoder,flushFlag; static u64 changed,shdw_changed; static vu32 retraceCount; static const struct _timing *currTiming; @@ -1685,6 +1728,7 @@ static void printDebugCalculations(void) printf("HorVer.fbMode = %d\n",HorVer.fbMode); printf("HorVer.nonInter = %d\n",HorVer.nonInter); printf("HorVer.tv = %d\n",HorVer.tv); + printf("HorVer.rgb = %d\n",HorVer.rgb); printf("HorVer.wordPerLine = %d\n",HorVer.wordPerLine); printf("HorVer.wpl = %d\n",HorVer.wpl); printf("HorVer.std = %d\n",HorVer.std); @@ -2365,10 +2409,15 @@ static u32 __VISetupEncoder(void) return 0; shdw_changeEncoder = 0; - u8 dtv, tv; + u8 dtv, tv, rgb; + + if (!shdw_changeEncoder) + return 0; + shdw_changeEncoder = 0; tv = VIDEO_GetCurrentTvMode(); dtv = (_viReg[55]&0x01); + rgb = currRgb; oldDtvStatus = dtv; __VISetClosedCaptionMode(1); @@ -2393,10 +2442,10 @@ static u32 __VISetupEncoder(void) __VISetOutputEnable(true); - if(tv==VI_EURGB60) __VISetRGBFilter(true); - else __VISetRGBFilter(false); + __VISetRGBFilter(rgb ? true : false); oldTvStatus = tv; + return 1; } #endif @@ -2458,6 +2507,7 @@ static inline u32 __VISetRegs(void) shdw_changeMode = 0; currTiming = HorVer.timing; currTvMode = HorVer.tv; + currRgb = HorVer.rgb; currentFb = nextFb; @@ -2589,7 +2639,11 @@ static void __VIRetraceHandler(u32 nIrq,void *pCtx) preRetraceCB(retraceCount); if(flushFlag) { - if(__VISetRegs()) { + u32 flushed = __VISetRegs(); +#if defined(HW_RVL) + flushed |= __VISetupEncoder(); +#endif + if(flushed) { flushFlag = 0; SI_RefreshSamplingRate(); } @@ -2599,11 +2653,6 @@ static void __VIRetraceHandler(u32 nIrq,void *pCtx) dtv = (_viReg[55]&0x01); if(dtv!=oldDtvStatus || tv!=oldTvStatus) __VISetOutputMode(dtv); oldDtvStatus = dtv; - - if(tv!=oldTvStatus) { - if(tv==VI_EURGB60) __VISetFilterEURGB60(1); - else __VISetFilterEURGB60(0); - } oldTvStatus = tv; #endif if(postRetraceCB) @@ -2635,6 +2684,7 @@ void VIDEO_Init(void) changed = 0; shdw_changed = 0; shdw_changeMode = 0; + shdw_changeEncoder = 1; flushFlag = 0; _viReg[38] = ((taps[1]>>6)|(taps[2]<<4)); @@ -2662,6 +2712,7 @@ void VIDEO_Init(void) if(HorVer.tv!=VI_DEBUG) vimode += (HorVer.tv<<2); currTiming = __gettiming(vimode); currTvMode = HorVer.tv; + currRgb = HorVer.rgb; regs[1] = _viReg[1]; HorVer.timing = currTiming; @@ -2710,6 +2761,7 @@ void VIDEO_Configure(GXRModeObj *rmode) { u16 dcr; u32 nonint,vimode,level; + u8 rgb; const struct _timing *curtiming; #ifdef _VIDEO_DEBUG if(rmode->viHeight&0x0001) printf("VIDEO_Configure(): Odd number(%d) is specified to viHeight\n",rmode->viHeight); @@ -2719,12 +2771,18 @@ void VIDEO_Configure(GXRModeObj *rmode) && (rmode->xfbHeight<<1)!=rmode->viHeight) printf("VIDEO_Configure(): xfbHeight(%d) is not as twice as viHeight(%d) when SF XFB mode is specified\n",rmode->xfbHeight,rmode->viHeight); #endif _CPU_ISR_Disable(level); - nonint = (rmode->viTVMode&0x0003); + nonint = _SHIFTR(rmode->viTVMode,0,2); if(nonint!=HorVer.nonInter) { changeMode = 1; HorVer.nonInter = nonint; } HorVer.tv = _SHIFTR(rmode->viTVMode,2,3); + rgb = rmode->rgb; + if(rgb!=HorVer.rgb) { + changeEncoder = 1; + changeMode = 1; + HorVer.rgb = rgb; + } HorVer.dispPosX = rmode->viXOrigin; HorVer.dispPosY = rmode->viYOrigin; if(HorVer.nonInter==VI_NON_INTERLACE) HorVer.dispPosY = HorVer.dispPosY<<1; @@ -2761,7 +2819,7 @@ void VIDEO_Configure(GXRModeObj *rmode) dcr |= _SHIFTL(HorVer.threeD,3,1); if(HorVer.nonInter==VI_PROGRESSIVE || HorVer.nonInter==(VI_NON_INTERLACE|VI_PROGRESSIVE)) dcr |= 0x0004; else dcr |= _SHIFTL(HorVer.nonInter,2,1); - if(!(HorVer.tv==VI_EURGB60)) dcr |= _SHIFTL(HorVer.tv,8,2); + if(!HorVer.rgb) dcr |= _SHIFTL(HorVer.tv,8,2); regs[1] = dcr; changed |= VI_REGCHANGE(1); @@ -2853,6 +2911,8 @@ void VIDEO_Flush(void) _CPU_ISR_Disable(level); shdw_changeMode |= changeMode; changeMode = 0; + shdw_changeEncoder |= changeEncoder; + changeEncoder = 0; shdw_changed |= changed; while(changed) { From b61db131c7ff69f1698ac51d21c25262a976cd81 Mon Sep 17 00:00:00 2001 From: Shiz Date: Sun, 28 Jan 2024 13:14:57 +0100 Subject: [PATCH 3/4] video: fix encoder setup for RGB video modes --- libogc/video.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/libogc/video.c b/libogc/video.c index cd248817..8b54e1f3 100644 --- a/libogc/video.c +++ b/libogc/video.c @@ -2363,12 +2363,18 @@ static void __VISetGamma(void) __VIWriteI2CRegisterBuf(0x10, sizeof(gamma), gamma); } -static void __VISetMacroVision(u8 tv) +static void __VISetMacroVision(u8 rgb) { u8 macrobuf[0x1a]; memset(macrobuf, 0, sizeof(macrobuf)); __VIWriteI2CRegisterBuf(0x40, sizeof(macrobuf), macrobuf); + if (rgb) __VIWriteI2CRegister8(0x59, 1); +} + +static void __VISetRGBChannelSwap(bool enable) +{ + __VIWriteI2CRegister8(0x62, enable ? 1 : 0); } static void __VISetOverSampling(u8 mode) @@ -2411,17 +2417,16 @@ static u32 __VISetupEncoder(void) u8 dtv, tv, rgb; - if (!shdw_changeEncoder) - return 0; - shdw_changeEncoder = 0; - tv = VIDEO_GetCurrentTvMode(); dtv = (_viReg[55]&0x01); rgb = currRgb; oldDtvStatus = dtv; + __VISetOutputEnable(false); + + __VISetRGBChannelSwap(rgb ? true : false); __VISetClosedCaptionMode(1); - __VISetOverSampling(3); + __VISetOverSampling(rgb ? 1 : 3); __VISetOutputMode(dtv); __VISetTiming(0); __VISetAudioVolume(0x8e, 0x8e); @@ -2431,18 +2436,18 @@ static u32 __VISetupEncoder(void) __VIResetClosedCaptionData(); // Macrovision crap - __VISetMacroVision(); + __VISetMacroVision(rgb); - // Sometimes 1 in RGB mode? (reg 1 == 3) - __VISetOverDrive(false, 0); + __VISetOverDrive(rgb ? true : false, 0); __VISetTrapFilter(true); __VISetGamma(); - __VISetOutputEnable(true); - __VISetRGBFilter(rgb ? true : false); + if (rgb) __VIWriteI2CRegister8(0x67, 1); + + __VISetOutputEnable(true); oldTvStatus = tv; return 1; From 2f09ca1f05d16783b3028bc5b1dd1a57634c9888 Mon Sep 17 00:00:00 2001 From: Shiz Date: Wed, 24 Jan 2024 16:33:56 +0100 Subject: [PATCH 4/4] video: add RGB 480p progressive mode This mode was used in the Wii arcade board (RVA-001). Detecting it for use with VIDEO_GetPreferredMode() would require some logic involving reading /title/00000001/00000002/data/RVA.txt since that is the main method used to detect the board instead of SC. Due to the relative clumsiness involved I decided to leave it out for now. --- gc/ogc/video_types.h | 7 +++ libogc/video.c | 122 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 117 insertions(+), 12 deletions(-) diff --git a/gc/ogc/video_types.h b/gc/ogc/video_types.h index ad5371f4..b7baef13 100644 --- a/gc/ogc/video_types.h +++ b/gc/ogc/video_types.h @@ -107,6 +107,9 @@ distribution. #define VI_MAX_WIDTH_EURGB60 VI_MAX_WIDTH_NTSC #define VI_MAX_HEIGHT_EURGB60 VI_MAX_HEIGHT_NTSC +#define VI_MAX_WIDTH_DEBUG VI_MAX_WIDTH_NTSC +#define VI_MAX_HEIGHT_DEBUG VI_MAX_HEIGHT_NTSC + #define VIDEO_PadFramebufferWidth(width) ((u16)(((u16)(width) + 15) & ~15)) /*!< macro to pad the width to a multiple of 16 */ /*! @@ -133,6 +136,7 @@ distribution. #define VI_TVMODE_MPAL_PROG VI_TVMODE(VI_MPAL, VI_PROGRESSIVE) #define VI_TVMODE_DEBUG_INT VI_TVMODE(VI_DEBUG, VI_INTERLACE) +#define VI_TVMODE_DEBUG_PROG VI_TVMODE(VI_DEBUG, VI_PROGRESSIVE) #define VI_TVMODE_DEBUG_PAL_INT VI_TVMODE(VI_DEBUG_PAL, VI_INTERLACE) #define VI_TVMODE_DEBUG_PAL_DS VI_TVMODE(VI_DEBUG_PAL, VI_NON_INTERLACE) @@ -191,6 +195,9 @@ extern GXRModeObj TVEurgb60Hz480IntAa; extern GXRModeObj TVEurgb60Hz480Prog; extern GXRModeObj TVEurgb60Hz480ProgSoft; extern GXRModeObj TVEurgb60Hz480ProgAa; +extern GXRModeObj TVRgb480Prog; /*!< Video and render mode configuration for 480 lines,progressive,singlefield RGB mode */ +extern GXRModeObj TVRgb480ProgSoft; +extern GXRModeObj TVRgb480ProgAa; /*! * @} diff --git a/libogc/video.c b/libogc/video.c index 8b54e1f3..1731c991 100644 --- a/libogc/video.c +++ b/libogc/video.c @@ -1545,6 +1545,111 @@ GXRModeObj TVEurgb60Hz480ProgAa = } }; +GXRModeObj TVRgb480Prog = +{ + VI_TVMODE_DEBUG_PROG, // viDisplayMode + 640, // fbWidth + 480, // efbHeight + 480, // xfbHeight + (VI_MAX_WIDTH_DEBUG - 640)/2, // viXOrigin + (VI_MAX_HEIGHT_DEBUG - 480)/2, // viYOrigin + 640, // viWidth + 480, // viHeight + VI_XFBMODE_SF, // xFBmode + GX_TRUE, // rgb + GX_FALSE, // field_rendering + GX_FALSE, // aa + + // sample points arranged in increasing Y order + { + {6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each + {6,6},{6,6},{6,6}, // pix 1 + {6,6},{6,6},{6,6}, // pix 2 + {6,6},{6,6},{6,6} // pix 3 + }, + + // vertical filter[7], 1/64 units, 6 bits each + { + 0, // line n-1 + 0, // line n-1 + 21, // line n + 22, // line n + 21, // line n + 0, // line n+1 + 0 // line n+1 + } +}; + +GXRModeObj TVRgb480ProgSoft = +{ + VI_TVMODE_DEBUG_PROG, // viDisplayMode + 640, // fbWidth + 480, // efbHeight + 480, // xfbHeight + (VI_MAX_WIDTH_DEBUG - 640)/2, // viXOrigin + (VI_MAX_HEIGHT_DEBUG - 480)/2, // viYOrigin + 640, // viWidth + 480, // viHeight + VI_XFBMODE_SF, // xFBmode + GX_TRUE, // rgb + GX_FALSE, // field_rendering + GX_FALSE, // aa + + // sample points arranged in increasing Y order + { + {6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each + {6,6},{6,6},{6,6}, // pix 1 + {6,6},{6,6},{6,6}, // pix 2 + {6,6},{6,6},{6,6} // pix 3 + }, + + // vertical filter[7], 1/64 units, 6 bits each + { + 8, // line n-1 + 8, // line n-1 + 10, // line n + 12, // line n + 10, // line n + 8, // line n+1 + 8 // line n+1 + } +}; + +GXRModeObj TVRgb480ProgAa = +{ + VI_TVMODE_DEBUG_PROG, // viDisplayMode + 640, // fbWidth + 480, // efbHeight + 480, // xfbHeight + (VI_MAX_WIDTH_DEBUG - 640)/2, // viXOrigin + (VI_MAX_HEIGHT_DEBUG - 480)/2, // viYOrigin + 640, // viWidth + 480, // viHeight + VI_XFBMODE_SF, // xFBmode + GX_TRUE, // rgb + GX_FALSE, // field_rendering + GX_TRUE, // aa + + // sample points arranged in increasing Y order + { + {3,2},{9,6},{3,10}, // pix 0, 3 sample points, 1/12 units, 4 bits each + {3,2},{9,6},{3,10}, // pix 1 + {9,2},{3,6},{9,10}, // pix 2 + {9,2},{3,6},{9,10} // pix 3 + }, + + // vertical filter[7], 1/64 units, 6 bits each + { + 4, // line n-1 + 8, // line n-1 + 12, // line n + 16, // line n + 12, // line n + 8, // line n+1 + 4 // line n+1 + } +}; + static const u16 taps[26] = { 0x01F0,0x01DC,0x01AE,0x0174,0x0129,0x00DB, @@ -1762,9 +1867,11 @@ static const struct _timing* __gettiming(u32 vimode) { switch(vimode) { case VI_TVMODE_NTSC_INT: + case VI_TVMODE_EURGB60_INT: return &video_timing[0]; break; case VI_TVMODE_NTSC_DS: + case VI_TVMODE_EURGB60_DS: return &video_timing[1]; break; case VI_TVMODE_PAL_INT: @@ -1773,12 +1880,6 @@ static const struct _timing* __gettiming(u32 vimode) case VI_TVMODE_PAL_DS: return &video_timing[3]; break; - case VI_TVMODE_EURGB60_INT: - return &video_timing[0]; - break; - case VI_TVMODE_EURGB60_DS: - return &video_timing[1]; - break; case VI_TVMODE_MPAL_INT: return &video_timing[4]; break; @@ -1786,17 +1887,14 @@ static const struct _timing* __gettiming(u32 vimode) return &video_timing[5]; break; case VI_TVMODE_NTSC_PROG: + case VI_TVMODE_EURGB60_PROG: + case VI_TVMODE_MPAL_PROG: + case VI_TVMODE_DEBUG_PROG: return &video_timing[6]; break; case VI_TVMODE_PAL_PROG: return &video_timing[7]; break; - case VI_TVMODE_EURGB60_PROG: - return &video_timing[6]; - break; - case VI_TVMODE_MPAL_PROG: - return &video_timing[6]; - break; default: return NULL; }