From f472e2904d8581e2b199fa73cb1c7a09d0c1212b Mon Sep 17 00:00:00 2001 From: ayuanx Date: Sat, 9 Jan 2010 17:11:59 +0000 Subject: [PATCH] Now Progressive Scan actually works for those games that really depend on this setting (Try Mario Kart Wii) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4798 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/Boot/Boot.cpp | 2 +- Source/Core/Core/Src/Core.cpp | 11 +- Source/Core/Core/Src/HW/HW.cpp | 7 - Source/Core/Core/Src/HW/HW.h | 1 - Source/Core/Core/Src/HW/SystemTimers.cpp | 4 +- Source/Core/Core/Src/HW/VideoInterface.cpp | 365 ++++-------------- Source/Core/Core/Src/HW/VideoInterface.h | 279 ++++++++++++- Source/Plugins/Plugin_VideoOGL/Src/main.cpp | 6 +- .../Plugin_Wiimote/Src/ConfigRecordingDlg.cpp | 6 +- .../Plugin_Wiimote/Src/ReadWiimote.cpp | 13 +- 10 files changed, 361 insertions(+), 333 deletions(-) diff --git a/Source/Core/Core/Src/Boot/Boot.cpp b/Source/Core/Core/Src/Boot/Boot.cpp index 4ddec1f750..3ecd781a8d 100644 --- a/Source/Core/Core/Src/Boot/Boot.cpp +++ b/Source/Core/Core/Src/Boot/Boot.cpp @@ -166,7 +166,7 @@ bool CBoot::BootUp() NOTICE_LOG(BOOT, "Booting %s", _StartupPara.m_strFilename.c_str()); g_symbolDB.Clear(); - VideoInterface::PreInit(_StartupPara.bNTSC); + VideoInterface::Preset(_StartupPara.bNTSC); switch (_StartupPara.m_BootType) { // GCM and Wii diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 806c93bce1..2c9975ce57 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -598,8 +598,7 @@ void VideoThrottle() // When frame limit is NOT off if (SConfig::GetInstance().m_Framelimit) { - // a full screen scan consists of 2 fields - u32 frametime = DrawnVideo * 2 * 1000 / TargetVPS; + u32 frametime = DrawnVideo * 1000 / TargetVPS; while ((u32)Timer.GetTimeDifference() < frametime) Common::YieldCPU(); //Common::SleepCurrentThread(1); @@ -612,7 +611,7 @@ void VideoThrottle() SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter; u32 FPS = Common::AtomicLoad(DrawnFrame) * 1000 / ElapseTime; - u32 VPS = DrawnVideo * 2 * 1000 / ElapseTime; + u32 VPS = DrawnVideo * 1000 / ElapseTime; u32 Speed = VPS * 100 / VideoInterface::TargetRefreshRate; // Settings are shown the same for both extended and summary info @@ -675,10 +674,8 @@ void VideoThrottle() Common::AtomicStore(DrawnFrame, 0); DrawnVideo = 0; } - else - { - DrawnVideo++; - } + + DrawnVideo++; } // Executed from GPU thread diff --git a/Source/Core/Core/Src/HW/HW.cpp b/Source/Core/Core/Src/HW/HW.cpp index 6a05409f76..4d00996630 100644 --- a/Source/Core/Core/Src/HW/HW.cpp +++ b/Source/Core/Core/Src/HW/HW.cpp @@ -106,11 +106,4 @@ namespace HW WII_IPC_HLE_Interface::DoState(p); } } - - // Restart Wiimote - void InitWiimote() - { - WII_IPCInterface::Init(); - WII_IPC_HLE_Interface::Init(); - } } diff --git a/Source/Core/Core/Src/HW/HW.h b/Source/Core/Core/Src/HW/HW.h index 1b7fbfff70..cd3375d3ac 100644 --- a/Source/Core/Core/Src/HW/HW.h +++ b/Source/Core/Core/Src/HW/HW.h @@ -26,7 +26,6 @@ namespace HW void Init(); void Shutdown(); void DoState(PointerWrap &p); - void InitWiimote(); } #endif diff --git a/Source/Core/Core/Src/HW/SystemTimers.cpp b/Source/Core/Core/Src/HW/SystemTimers.cpp index db4367b547..8661bd7408 100644 --- a/Source/Core/Core/Src/HW/SystemTimers.cpp +++ b/Source/Core/Core/Src/HW/SystemTimers.cpp @@ -184,7 +184,7 @@ void IPC_HLE_UpdateCallback(u64 userdata, int cyclesLate) void VICallback(u64 userdata, int cyclesLate) { VideoInterface::Update(); - CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine() - cyclesLate, et_VI); + CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame() - cyclesLate, et_VI); } void SICallback(u64 userdata, int cyclesLate) @@ -295,7 +295,7 @@ void Init() et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback); CoreTiming::ScheduleEvent(AI_PERIOD, et_AI); - CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine(), et_VI); + CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_VI); CoreTiming::ScheduleEvent(DSP_PERIOD, et_DSP); CoreTiming::ScheduleEvent(GetTicksPerSecond() / 60, et_SI); CoreTiming::ScheduleEvent(AUDIO_DMA_PERIOD, et_AudioDMA); diff --git a/Source/Core/Core/Src/HW/VideoInterface.cpp b/Source/Core/Core/Src/HW/VideoInterface.cpp index f9891a3bbd..64754e585c 100644 --- a/Source/Core/Core/Src/HW/VideoInterface.cpp +++ b/Source/Core/Core/Src/HW/VideoInterface.cpp @@ -30,277 +30,6 @@ namespace VideoInterface { -// VI Internal Hardware Addresses -enum -{ - VI_VERTICAL_TIMING = 0x00, - VI_CONTROL_REGISTER = 0x02, - VI_HORIZONTAL_TIMING_0_HI = 0x04, - VI_HORIZONTAL_TIMING_0_LO = 0x06, - VI_HORIZONTAL_TIMING_1_HI = 0x08, - VI_HORIZONTAL_TIMING_1_LO = 0x0a, - VI_VBLANK_TIMING_ODD_HI = 0x0c, - VI_VBLANK_TIMING_ODD_LO = 0x0e, - VI_VBLANK_TIMING_EVEN_HI = 0x10, - VI_VBLANK_TIMING_EVEN_LO = 0x12, - VI_BURST_BLANKING_ODD_HI = 0x14, - VI_BURST_BLANKING_ODD_LO = 0x16, - VI_BURST_BLANKING_EVEN_HI = 0x18, - VI_BURST_BLANKING_EVEN_LO = 0x1a, - VI_FB_LEFT_TOP_HI = 0x1c, // FB_LEFT_TOP is first half of XFB info - VI_FB_LEFT_TOP_LO = 0x1e, - VI_FB_RIGHT_TOP_HI = 0x20, // FB_RIGHT_TOP is only used in 3D mode - VI_FB_RIGHT_TOP_LO = 0x22, - VI_FB_LEFT_BOTTOM_HI = 0x24, // FB_LEFT_BOTTOM is second half of XFB info - VI_FB_LEFT_BOTTOM_LO = 0x26, - VI_FB_RIGHT_BOTTOM_HI = 0x28, // FB_RIGHT_BOTTOM is only used in 3D mode - VI_FB_RIGHT_BOTTOM_LO = 0x2a, - VI_VERTICAL_BEAM_POSITION = 0x2c, - VI_HORIZONTAL_BEAM_POSITION = 0x2e, - VI_PRERETRACE_HI = 0x30, - VI_PRERETRACE_LO = 0x32, - VI_POSTRETRACE_HI = 0x34, - VI_POSTRETRACE_LO = 0x36, - VI_DISPLAY_INTERRUPT_2_HI = 0x38, - VI_DISPLAY_INTERRUPT_2_LO = 0x3a, - VI_DISPLAY_INTERRUPT_3_HI = 0x3c, - VI_DISPLAY_INTERRUPT_3_LO = 0x3e, - VI_DISPLAY_LATCH_0_HI = 0x40, - VI_DISPLAY_LATCH_0_LO = 0x42, - VI_DISPLAY_LATCH_1_HI = 0x44, - VI_DISPLAY_LATCH_1_LO = 0x46, - VI_HSCALEW = 0x48, - VI_HSCALER = 0x4a, - VI_FILTER_COEF_0_HI = 0x4c, - VI_FILTER_COEF_0_LO = 0x4e, - VI_FILTER_COEF_1_HI = 0x50, - VI_FILTER_COEF_1_LO = 0x52, - VI_FILTER_COEF_2_HI = 0x54, - VI_FILTER_COEF_2_LO = 0x56, - VI_FILTER_COEF_3_HI = 0x58, - VI_FILTER_COEF_3_LO = 0x5a, - VI_FILTER_COEF_4_HI = 0x5c, - VI_FILTER_COEF_4_LO = 0x5e, - VI_FILTER_COEF_5_HI = 0x60, - VI_FILTER_COEF_5_LO = 0x62, - VI_FILTER_COEF_6_HI = 0x64, - VI_FILTER_COEF_6_LO = 0x66, - VI_UNK_AA_REG_HI = 0x68, - VI_UNK_AA_REG_LO = 0x6a, - VI_CLOCK = 0x6c, - VI_DTV_STATUS = 0x6e, - VI_FBWIDTH = 0x70, - VI_BORDER_BLANK_END = 0x72, // Only used in debug video mode - VI_BORDER_BLANK_START = 0x74, // Only used in debug video mode - VI_INTERLACE = 0x850, // ??? MYSTERY OLD CODE -}; - -union UVIVerticalTimingRegister -{ - u16 Hex; - struct - { - unsigned EQU : 4; // Equalization pulse in half lines - unsigned ACV : 10; // Active video in lines per field (TODO: Does it indicate half-lines in progressive mode or 54 MHz mode?) - unsigned : 2; - }; - UVIVerticalTimingRegister(u16 _hex) { Hex = _hex;} - UVIVerticalTimingRegister() { Hex = 0;} -}; - -union UVIDisplayControlRegister -{ - u16 Hex; - struct - { - unsigned ENB : 1; // Enables video timing generation and data request - unsigned RST : 1; // Clears all data requests and puts VI into its idle state - unsigned NIN : 1; // 0: Interlaced, 1: Non-Interlaced: top field drawn at field rate and bottom field is not displayed - unsigned DLR : 1; // Selects 3D Display Mode - unsigned LE0 : 2; // Display Latch; 0: Off, 1: On for 1 field, 2: On for 2 fields, 3: Always on - unsigned LE1 : 2; - unsigned FMT : 2; // 0: NTSC, 1: PAL, 2: MPAL, 3: Debug - unsigned : 6; - }; - UVIDisplayControlRegister(u16 _hex) { Hex = _hex;} - UVIDisplayControlRegister() { Hex = 0;} -}; - -union UVIHorizontalTiming0 -{ - u32 Hex; - struct { u16 Lo, Hi; }; - struct - { - unsigned HLW : 9; // Halfline Width (W*16 = Width (720)) - unsigned : 7; - unsigned HCE : 7; // Horizontal Sync Start to Color Burst End - unsigned : 1; - unsigned HCS : 7; // Horizontal Sync Start to Color Burst Start - unsigned : 1; - }; -}; - -union UVIHorizontalTiming1 -{ - u32 Hex; - struct { u16 Lo, Hi; }; - struct - { - unsigned HSY : 7; // Horizontal Sync Width - unsigned HBE640 : 9; // Horizontal Sync Start to horizontal blank end - unsigned : 1; - unsigned HBS640 : 9; // Half line to horizontal blanking start - unsigned : 6; - }; -}; - -// Exists for both odd and even fields -union UVIVBlankTimingRegister -{ - u32 Hex; - struct { u16 Lo, Hi; }; - struct - { - unsigned PRB : 10; // Pre-blanking in half lines - unsigned : 6; - unsigned PSB : 10; // Post blanking in half lines - unsigned : 6; - }; -}; - -// Exists for both odd and even fields -union UVIBurstBlankingRegister -{ - u32 Hex; - struct { u16 Lo, Hi; }; - struct - { - unsigned BS0 : 5; // Field x start to burst blanking start in halflines - unsigned BE0 : 11; // Field x start to burst blanking end in halflines - unsigned BS2 : 5; // Field x+2 start to burst blanking start in halflines - unsigned BE2 : 11; // Field x+2 start to burst blanking end in halflines - }; -}; - -union UVIFBInfoRegister -{ - u32 Hex; - struct { u16 Lo, Hi; }; - struct - { - // TODO: mask out lower 9bits/align to 9bits??? - unsigned FBB : 24; // Base address of the framebuffer in external mem - // POFF only seems to exist in the top reg. XOFF, unknown. - unsigned XOFF : 4; // Horizontal Offset of the left-most pixel within the first word of the fetched picture - unsigned POFF : 1; // Page offest: 1: fb address is (address>>5) - unsigned CLRPOFF : 3; // ? setting bit 31 clears POFF - }; -}; - -// VI Interrupt Register -union UVIInterruptRegister -{ - u32 Hex; - struct { u16 Lo, Hi; }; - struct - { - unsigned HCT : 11; // Horizontal Position - unsigned : 5; - unsigned VCT : 11; // Vertical Position - unsigned : 1; - unsigned IR_MASK : 1; // Interrupt Enable Bit - unsigned : 2; - unsigned IR_INT : 1; // Interrupt Status (1=Active) (Read to clear) - }; -}; - -union UVILatchRegister -{ - u32 Hex; - struct { u16 Lo, Hi; }; - struct - { - unsigned HCT : 11; // Horizontal Count - unsigned : 5; - unsigned VCT : 11; // Vertical Count - unsigned : 4; - unsigned TRG : 1; // Trigger Flag - }; -}; - -union UVIHorizontalStepping -{ - u16 Hex; - struct - { - unsigned FbSteps : 8; - unsigned FieldSteps : 8; - }; -}; - -union UVIHorizontalScaling -{ - u16 Hex; - struct - { - unsigned STP : 9; // Horizontal stepping size (U1.8 Scaler Value) (0x160 Works for 320) - unsigned : 3; - unsigned HS_EN : 1; // Enable Horizontal Scaling - unsigned : 3; - }; - UVIHorizontalScaling(u16 _hex) { Hex = _hex;} - UVIHorizontalScaling() { Hex = 0;} -}; - -// Used for tables 0-2 -union UVIFilterCoefTable3 -{ - u32 Hex; - struct { u16 Lo, Hi; }; - struct - { - unsigned Tap0 : 10; - unsigned Tap1 : 10; - unsigned Tap2 : 10; - unsigned : 2; - }; -}; - -// Used for tables 3-6 -union UVIFilterCoefTable4 -{ - u32 Hex; - struct { u16 Lo, Hi; }; - struct - { - unsigned Tap0 : 8; - unsigned Tap1 : 8; - unsigned Tap2 : 8; - unsigned Tap3 : 8; - }; -}; - -struct SVIFilterCoefTables -{ - UVIFilterCoefTable3 Tables02[3]; - UVIFilterCoefTable4 Tables36[4]; -}; - -// Debug video mode only, probably never used in dolphin... -union UVIBorderBlankRegister -{ - u32 Hex; - struct { u16 Lo, Hi; }; - struct - { - unsigned HBE656 : 10; // Border Horizontal Blank End - unsigned : 11; - unsigned HBS656 : 10; // Border Horizontal Blank start - unsigned BRDR_EN : 1; // Border Enable - }; -}; - // STATE_TO_SAVE // Registers listed in order: @@ -316,8 +45,8 @@ static UVIFBInfoRegister m_XFBInfoTop; static UVIFBInfoRegister m_XFBInfoBottom; static UVIFBInfoRegister m_3DFBInfoTop; // Start making your stereoscopic demos! :p static UVIFBInfoRegister m_3DFBInfoBottom; -static u16 m_VBeamPos = 0; -static u16 m_HBeamPos = 0; +static u16 m_VBeamPos = 0; // 0: Inactive +static u16 m_HBeamPos = 0; // 0: Inactive static UVIInterruptRegister m_InterruptRegister[4]; static UVILatchRegister m_LatchRegister[2]; static UVIHorizontalStepping m_HorizontalStepping; @@ -325,7 +54,7 @@ static UVIHorizontalScaling m_HorizontalScaling; static SVIFilterCoefTables m_FilterCoefTables; static u32 m_UnkAARegister = 0;// ??? 0x00FF0000 static u16 m_Clock = 0; // 0: 27MHz, 1: 54MHz -static u16 m_DTVStatus = 0; // Region char and component cable bit (only low 2bits are used?) +static u16 m_DTVStatus = 0; // Region char and component cable bit static u16 m_FBWidth = 0; // Only correct when scaling is enabled? static UVIBorderBlankRegister m_BorderHBlank; // 0xcc002076 - 0xcc00207f is full of 0x00FF: unknown @@ -371,7 +100,8 @@ void DoState(PointerWrap &p) p.Do(s_lowerFieldBegin); } -void PreInit(bool _bNTSC) +// Executed after Init, before game boot +void Preset(bool _bNTSC) { m_VerticalTimingRegister.EQU = 6; @@ -411,12 +141,16 @@ void PreInit(bool _bNTSC) m_HorizontalStepping.FbSteps = 40; m_HorizontalStepping.FieldSteps = 40; - m_Clock = 0; + m_HBeamPos = 1; + m_VBeamPos = 1; + + // 54MHz, capable of progressive scan + m_Clock = 1; // Say component cable is plugged m_DTVStatus = 1; - UpdateTiming(); + UpdateParameters(); } void SetRegionReg(char _region) @@ -430,8 +164,7 @@ void Init() m_InterruptRegister[i].Hex = 0; m_DisplayControlRegister.Hex = 0; - - UpdateTiming(); + UpdateParameters(); } void Read8(u8& _uReturnValue, const u32 _iAddress) @@ -547,8 +280,6 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) // RETRACE STUFF ... case VI_PRERETRACE_HI: _uReturnValue = m_InterruptRegister[0].Hi; - m_InterruptRegister[0].IR_INT = 0; - UpdateInterrupts(); return; case VI_PRERETRACE_LO: _uReturnValue = m_InterruptRegister[0].Lo; @@ -556,8 +287,6 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) case VI_POSTRETRACE_HI: _uReturnValue = m_InterruptRegister[1].Hi; - m_InterruptRegister[1].IR_INT = 0; - UpdateInterrupts(); return; case VI_POSTRETRACE_LO: _uReturnValue = m_InterruptRegister[1].Lo; @@ -565,8 +294,6 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) case VI_DISPLAY_INTERRUPT_2_HI: _uReturnValue = m_InterruptRegister[2].Hi; - m_InterruptRegister[2].IR_INT = 0; - UpdateInterrupts(); return; case VI_DISPLAY_INTERRUPT_2_LO: _uReturnValue = m_InterruptRegister[2].Lo; @@ -574,8 +301,6 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) case VI_DISPLAY_INTERRUPT_3_HI: _uReturnValue = m_InterruptRegister[3].Hi; - m_InterruptRegister[3].IR_INT = 0; - UpdateInterrupts(); return; case VI_DISPLAY_INTERRUPT_3_LO: _uReturnValue = m_InterruptRegister[3].Lo; @@ -714,7 +439,7 @@ void Write16(const u16 _iValue, const u32 _iAddress) UpdateInterrupts(); } - UpdateTiming(); + UpdateParameters(); } break; @@ -803,6 +528,7 @@ void Write16(const u16 _iValue, const u32 _iAddress) // RETRACE STUFF ... case VI_PRERETRACE_HI: m_InterruptRegister[0].Hi = _iValue; + UpdateInterrupts(); break; case VI_PRERETRACE_LO: m_InterruptRegister[0].Lo = _iValue; @@ -810,6 +536,7 @@ void Write16(const u16 _iValue, const u32 _iAddress) case VI_POSTRETRACE_HI: m_InterruptRegister[1].Hi = _iValue; + UpdateInterrupts(); break; case VI_POSTRETRACE_LO: m_InterruptRegister[1].Lo = _iValue; @@ -817,6 +544,7 @@ void Write16(const u16 _iValue, const u32 _iAddress) case VI_DISPLAY_INTERRUPT_2_HI: m_InterruptRegister[2].Hi = _iValue; + UpdateInterrupts(); break; case VI_DISPLAY_INTERRUPT_2_LO: m_InterruptRegister[2].Lo = _iValue; @@ -824,6 +552,7 @@ void Write16(const u16 _iValue, const u32 _iAddress) case VI_DISPLAY_INTERRUPT_3_HI: m_InterruptRegister[3].Hi = _iValue; + UpdateInterrupts(); break; case VI_DISPLAY_INTERRUPT_3_LO: m_InterruptRegister[3].Lo = _iValue; @@ -981,25 +710,25 @@ u32 GetXFBAddressBottom() return m_XFBInfoBottom.FBB; } -void UpdateTiming() +void UpdateParameters() { switch (m_DisplayControlRegister.FMT) { case 0: // NTSC - case 2: // PAL-M + case 2: // PAL-M // AyuanX: LineCount doesn't look right for PAL-M TargetRefreshRate = NTSC_FIELD_RATE; - TicksPerFrame = SystemTimers::GetTicksPerSecond() / (NTSC_FIELD_RATE / 2); - s_lineCount = m_DisplayControlRegister.NIN ? (NTSC_LINE_COUNT+1)/2 : NTSC_LINE_COUNT; - s_upperFieldBegin = NTSC_UPPER_BEGIN; - s_lowerFieldBegin = NTSC_LOWER_BEGIN; + TicksPerFrame = SystemTimers::GetTicksPerSecond() / NTSC_FIELD_RATE; + s_lineCount = m_DisplayControlRegister.NIN ? NTSC_LINE_COUNT : (NTSC_LINE_COUNT+1)/2; + //s_upperFieldBegin = NTSC_UPPER_BEGIN; + //s_lowerFieldBegin = NTSC_LOWER_BEGIN; break; case 1: // PAL TargetRefreshRate = PAL_FIELD_RATE; - TicksPerFrame = SystemTimers::GetTicksPerSecond() / (PAL_FIELD_RATE / 2); - s_lineCount = m_DisplayControlRegister.NIN ? (PAL_LINE_COUNT+1)/2 : PAL_LINE_COUNT; - s_upperFieldBegin = PAL_UPPER_BEGIN; - s_lowerFieldBegin = PAL_LOWER_BEGIN; + TicksPerFrame = SystemTimers::GetTicksPerSecond() / PAL_FIELD_RATE; + s_lineCount = m_DisplayControlRegister.NIN ? PAL_LINE_COUNT : (PAL_LINE_COUNT+1)/2; + //s_upperFieldBegin = PAL_UPPER_BEGIN; + //s_lowerFieldBegin = PAL_LOWER_BEGIN; break; case 3: // Debug @@ -1016,7 +745,8 @@ int GetTicksPerLine() { if (s_lineCount == 0) return 100000; - return TicksPerFrame / s_lineCount; + else + return TicksPerFrame / s_lineCount; } int GetTicksPerFrame() @@ -1053,8 +783,44 @@ static void EndField() if (video->IsValid()) video->Video_EndField(); } +// AyuanX: No need to update per scan line, update per frame is good enough, and faster +// Purpose: Send VI interrupt when triggered +// Run when: When a frame is scaned (progressive/interlace) +void Update() +{ + u16 NewVBeamPos; + if (m_DisplayControlRegister.NIN) + { + // Progressive + NewVBeamPos = s_lineCount + 1; + BeginField(FIELD_PROGRESSIVE); + } + else if (m_VBeamPos == s_lineCount) + { + // Interlace Upper + NewVBeamPos = s_lineCount * 2; + BeginField(FIELD_UPPER); + } + else + { + // Interlace Lower + NewVBeamPos = s_lineCount; + BeginField(FIELD_LOWER); + } + for (int i = 0; i < 4; i++) + { + if (m_VBeamPos <= m_InterruptRegister[i].VCT && m_InterruptRegister[i].VCT < NewVBeamPos) + m_InterruptRegister[i].IR_INT = 1; + } + UpdateInterrupts(); + m_VBeamPos = (NewVBeamPos > s_lineCount) ? 1 : NewVBeamPos; + + Core::VideoThrottle(); +} + +/* // Purpose: Send VI interrupt when triggered // Run when: When a line is scaned void Update() @@ -1088,5 +854,6 @@ void Update() BeginField(m_DisplayControlRegister.NIN ? FIELD_PROGRESSIVE : FIELD_LOWER); } +*/ } // namespace diff --git a/Source/Core/Core/Src/HW/VideoInterface.h b/Source/Core/Core/Src/HW/VideoInterface.h index 9964ee499b..0b97369451 100644 --- a/Source/Core/Core/Src/HW/VideoInterface.h +++ b/Source/Core/Core/Src/HW/VideoInterface.h @@ -41,14 +41,285 @@ namespace VideoInterface #define PAL_LINE_COUNT 625 // These line numbers indicate the beginning of the "active video" in a frame. // A PAL frame has the upper field first followed by the lower field. -#define PAL_UPPER_BEGIN 23 // TODO: Actually 23.5! +#define PAL_UPPER_BEGIN 23 #define PAL_LOWER_BEGIN 336 +// VI Internal Hardware Addresses +enum +{ + VI_VERTICAL_TIMING = 0x00, + VI_CONTROL_REGISTER = 0x02, + VI_HORIZONTAL_TIMING_0_HI = 0x04, + VI_HORIZONTAL_TIMING_0_LO = 0x06, + VI_HORIZONTAL_TIMING_1_HI = 0x08, + VI_HORIZONTAL_TIMING_1_LO = 0x0a, + VI_VBLANK_TIMING_ODD_HI = 0x0c, + VI_VBLANK_TIMING_ODD_LO = 0x0e, + VI_VBLANK_TIMING_EVEN_HI = 0x10, + VI_VBLANK_TIMING_EVEN_LO = 0x12, + VI_BURST_BLANKING_ODD_HI = 0x14, + VI_BURST_BLANKING_ODD_LO = 0x16, + VI_BURST_BLANKING_EVEN_HI = 0x18, + VI_BURST_BLANKING_EVEN_LO = 0x1a, + VI_FB_LEFT_TOP_HI = 0x1c, // FB_LEFT_TOP is first half of XFB info + VI_FB_LEFT_TOP_LO = 0x1e, + VI_FB_RIGHT_TOP_HI = 0x20, // FB_RIGHT_TOP is only used in 3D mode + VI_FB_RIGHT_TOP_LO = 0x22, + VI_FB_LEFT_BOTTOM_HI = 0x24, // FB_LEFT_BOTTOM is second half of XFB info + VI_FB_LEFT_BOTTOM_LO = 0x26, + VI_FB_RIGHT_BOTTOM_HI = 0x28, // FB_RIGHT_BOTTOM is only used in 3D mode + VI_FB_RIGHT_BOTTOM_LO = 0x2a, + VI_VERTICAL_BEAM_POSITION = 0x2c, + VI_HORIZONTAL_BEAM_POSITION = 0x2e, + VI_PRERETRACE_HI = 0x30, + VI_PRERETRACE_LO = 0x32, + VI_POSTRETRACE_HI = 0x34, + VI_POSTRETRACE_LO = 0x36, + VI_DISPLAY_INTERRUPT_2_HI = 0x38, + VI_DISPLAY_INTERRUPT_2_LO = 0x3a, + VI_DISPLAY_INTERRUPT_3_HI = 0x3c, + VI_DISPLAY_INTERRUPT_3_LO = 0x3e, + VI_DISPLAY_LATCH_0_HI = 0x40, + VI_DISPLAY_LATCH_0_LO = 0x42, + VI_DISPLAY_LATCH_1_HI = 0x44, + VI_DISPLAY_LATCH_1_LO = 0x46, + VI_HSCALEW = 0x48, + VI_HSCALER = 0x4a, + VI_FILTER_COEF_0_HI = 0x4c, + VI_FILTER_COEF_0_LO = 0x4e, + VI_FILTER_COEF_1_HI = 0x50, + VI_FILTER_COEF_1_LO = 0x52, + VI_FILTER_COEF_2_HI = 0x54, + VI_FILTER_COEF_2_LO = 0x56, + VI_FILTER_COEF_3_HI = 0x58, + VI_FILTER_COEF_3_LO = 0x5a, + VI_FILTER_COEF_4_HI = 0x5c, + VI_FILTER_COEF_4_LO = 0x5e, + VI_FILTER_COEF_5_HI = 0x60, + VI_FILTER_COEF_5_LO = 0x62, + VI_FILTER_COEF_6_HI = 0x64, + VI_FILTER_COEF_6_LO = 0x66, + VI_UNK_AA_REG_HI = 0x68, + VI_UNK_AA_REG_LO = 0x6a, + VI_CLOCK = 0x6c, + VI_DTV_STATUS = 0x6e, + VI_FBWIDTH = 0x70, + VI_BORDER_BLANK_END = 0x72, // Only used in debug video mode + VI_BORDER_BLANK_START = 0x74, // Only used in debug video mode + //VI_INTERLACE = 0x850, // ??? MYSTERY OLD CODE +}; + +union UVIVerticalTimingRegister +{ + u16 Hex; + struct + { + unsigned EQU : 4; // Equalization pulse in half lines + unsigned ACV : 10; // Active video in lines per field (seems always zero) + unsigned : 2; + }; + UVIVerticalTimingRegister(u16 _hex) { Hex = _hex;} + UVIVerticalTimingRegister() { Hex = 0;} +}; + +union UVIDisplayControlRegister +{ + u16 Hex; + struct + { + unsigned ENB : 1; // Enables video timing generation and data request + unsigned RST : 1; // Clears all data requests and puts VI into its idle state + unsigned NIN : 1; // 0: Interlaced, 1: Non-Interlaced: top field drawn at field rate and bottom field is not displayed + unsigned DLR : 1; // Selects 3D Display Mode + unsigned LE0 : 2; // Display Latch; 0: Off, 1: On for 1 field, 2: On for 2 fields, 3: Always on + unsigned LE1 : 2; + unsigned FMT : 2; // 0: NTSC, 1: PAL, 2: MPAL, 3: Debug + unsigned : 6; + }; + UVIDisplayControlRegister(u16 _hex) { Hex = _hex;} + UVIDisplayControlRegister() { Hex = 0;} +}; + +union UVIHorizontalTiming0 +{ + u32 Hex; + struct { u16 Lo, Hi; }; + struct + { + unsigned HLW : 9; // Halfline Width (W*16 = Width (720)) + unsigned : 7; + unsigned HCE : 7; // Horizontal Sync Start to Color Burst End + unsigned : 1; + unsigned HCS : 7; // Horizontal Sync Start to Color Burst Start + unsigned : 1; + }; +}; + +union UVIHorizontalTiming1 +{ + u32 Hex; + struct { u16 Lo, Hi; }; + struct + { + unsigned HSY : 7; // Horizontal Sync Width + unsigned HBE640 : 9; // Horizontal Sync Start to horizontal blank end + unsigned : 1; + unsigned HBS640 : 9; // Half line to horizontal blanking start + unsigned : 6; + }; +}; + +// Exists for both odd and even fields +union UVIVBlankTimingRegister +{ + u32 Hex; + struct { u16 Lo, Hi; }; + struct + { + unsigned PRB : 10; // Pre-blanking in half lines + unsigned : 6; + unsigned PSB : 10; // Post blanking in half lines + unsigned : 6; + }; +}; + +// Exists for both odd and even fields +union UVIBurstBlankingRegister +{ + u32 Hex; + struct { u16 Lo, Hi; }; + struct + { + unsigned BS0 : 5; // Field x start to burst blanking start in halflines + unsigned BE0 : 11; // Field x start to burst blanking end in halflines + unsigned BS2 : 5; // Field x+2 start to burst blanking start in halflines + unsigned BE2 : 11; // Field x+2 start to burst blanking end in halflines + }; +}; + +union UVIFBInfoRegister +{ + u32 Hex; + struct { u16 Lo, Hi; }; + struct + { + // TODO: mask out lower 9bits/align to 9bits??? + unsigned FBB : 24; // Base address of the framebuffer in external mem + // POFF only seems to exist in the top reg. XOFF, unknown. + unsigned XOFF : 4; // Horizontal Offset of the left-most pixel within the first word of the fetched picture + unsigned POFF : 1; // Page offest: 1: fb address is (address>>5) + unsigned CLRPOFF : 3; // ? setting bit 31 clears POFF + }; +}; + +// VI Interrupt Register +union UVIInterruptRegister +{ + u32 Hex; + struct { u16 Lo, Hi; }; + struct + { + unsigned HCT : 11; // Horizontal Position + unsigned : 5; + unsigned VCT : 11; // Vertical Position + unsigned : 1; + unsigned IR_MASK : 1; // Interrupt Mask Bit + unsigned : 2; + unsigned IR_INT : 1; // Interrupt Status (1=Active, 0=Clear) + }; +}; + +union UVILatchRegister +{ + u32 Hex; + struct { u16 Lo, Hi; }; + struct + { + unsigned HCT : 11; // Horizontal Count + unsigned : 5; + unsigned VCT : 11; // Vertical Count + unsigned : 4; + unsigned TRG : 1; // Trigger Flag + }; +}; + +union UVIHorizontalStepping +{ + u16 Hex; + struct + { + unsigned FbSteps : 8; + unsigned FieldSteps : 8; + }; +}; + +union UVIHorizontalScaling +{ + u16 Hex; + struct + { + unsigned STP : 9; // Horizontal stepping size (U1.8 Scaler Value) (0x160 Works for 320) + unsigned : 3; + unsigned HS_EN : 1; // Enable Horizontal Scaling + unsigned : 3; + }; + UVIHorizontalScaling(u16 _hex) { Hex = _hex;} + UVIHorizontalScaling() { Hex = 0;} +}; + +// Used for tables 0-2 +union UVIFilterCoefTable3 +{ + u32 Hex; + struct { u16 Lo, Hi; }; + struct + { + unsigned Tap0 : 10; + unsigned Tap1 : 10; + unsigned Tap2 : 10; + unsigned : 2; + }; +}; + +// Used for tables 3-6 +union UVIFilterCoefTable4 +{ + u32 Hex; + struct { u16 Lo, Hi; }; + struct + { + unsigned Tap0 : 8; + unsigned Tap1 : 8; + unsigned Tap2 : 8; + unsigned Tap3 : 8; + }; +}; + +struct SVIFilterCoefTables +{ + UVIFilterCoefTable3 Tables02[3]; + UVIFilterCoefTable4 Tables36[4]; +}; + +// Debug video mode only, probably never used in dolphin... +union UVIBorderBlankRegister +{ + u32 Hex; + struct { u16 Lo, Hi; }; + struct + { + unsigned HBE656 : 10; // Border Horizontal Blank End + unsigned : 11; + unsigned HBS656 : 10; // Border Horizontal Blank start + unsigned BRDR_EN : 1; // Border Enable + }; +}; + // urgh, ugly externs. extern u32 TargetRefreshRate; // For BS2 HLE - void PreInit(bool _bNTSC); + void Preset(bool _bNTSC); void SetRegionReg(char _region); void Init(); @@ -65,14 +336,14 @@ namespace VideoInterface u8* GetXFBPointerTop(); u8* GetXFBPointerBottom(); - // Update and draw framebuffer(s) + // Update and draw framebuffer void Update(); // UpdateInterrupts: check if we have to generate a new VI Interrupt void UpdateInterrupts(); // Change values pertaining to video mode - void UpdateTiming(); + void UpdateParameters(); int GetTicksPerLine(); int GetTicksPerFrame(); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index 43c19489d1..c6d771b937 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -539,16 +539,14 @@ void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight) s_beginFieldArgs.field = field; s_beginFieldArgs.fbWidth = fbWidth; s_beginFieldArgs.fbHeight = fbHeight; + + Common::AtomicStoreRelease(s_swapRequested, TRUE); } } // Run from the CPU thread (from VideoInterface.cpp) void Video_EndField() { - if (s_PluginInitialized) - { - Common::AtomicStoreRelease(s_swapRequested, TRUE); - } } static struct diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigRecordingDlg.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigRecordingDlg.cpp index f1366b6b31..538e3f0c3d 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigRecordingDlg.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigRecordingDlg.cpp @@ -97,8 +97,10 @@ void WiimoteRecordingConfigDialog::CloseClick(wxCommandEvent& event) switch(event.GetId()) { case ID_CLOSE: - SetEvent(WiiMoteReal::g_StopThreadTemporary); //direct closing will result in crash @ReadWiimote, also dont try to waitforobject here, it will result in deadlock! because this thread is still needed to progress in the Readwiimote to get to the waitingobject @readwiimote itself..... - Close(); //Problem lies mainly in Readwiimote(), closing here leaves the thread readWiimote thread, trying to access vars which aint there anymore. + if (g_RealWiiMoteInitialized) + SetEvent(WiiMoteReal::g_StopThreadTemporary); //WiiMoteReal::SafecloseRemoteFunc over takes the closing of the Dlg + else + Close(); break; case ID_APPLY: SaveFile(); diff --git a/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp b/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp index 266406e4ec..2b588905e5 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp @@ -200,9 +200,10 @@ void handle_event(struct wiimote_t* wm) m_RecordingConfigFrame->m_GaugeAccel[1]->SetValue(wm->accel.y); m_RecordingConfigFrame->m_GaugeAccel[2]->SetValue(wm->accel.z); + int GNCx, GNCy, GNCz; + if(wm->exp.type == EXP_NUNCHUK) // Updating Nunchuck Gauges - { - + { m_RecordingConfigFrame->m_GaugeGForceNunchuk[0]->SetValue((int)floor((nc->gforce.x * 300) + 100.5)); m_RecordingConfigFrame->m_GaugeGForceNunchuk[1]->SetValue((int)floor((nc->gforce.y * 300) + 100.5)); m_RecordingConfigFrame->m_GaugeGForceNunchuk[2]->SetValue((int)floor((nc->gforce.z * 300) + 100.5)); @@ -217,9 +218,9 @@ void handle_event(struct wiimote_t* wm) float _GNCz = (float)(nc->accel.z - nc->accel_calib.cal_zero.z) / (float)nc->accel_calib.cal_g.z; // Conver the data to integers - int GNCx = (int)(_GNCx * 100); - int GNCy = (int)(_GNCy * 100); - int GNCz = (int)(_GNCz * 100); + GNCx = (int)(_GNCx * 100); + GNCy = (int)(_GNCy * 100); + GNCz = (int)(_GNCz * 100); } @@ -230,7 +231,7 @@ void handle_event(struct wiimote_t* wm) // wxT("Current: %03u %03u %03u"), Gx, Gy, Gz)); if(m_RecordingConfigFrame->m_bRecording) { - if(wm->exp.type == EXP_NUNCHUK) { + if(wm->exp.type != EXP_NUNCHUK) { DEBUG_LOG(WIIMOTE, "Wiiuse Recorded accel x, y, z: %03i %03i %03i", Gx, Gy, Gz); } else {