diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/Config.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/Config.cpp index 81b5941df0..5aaf2f3fcf 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/Config.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/Config.cpp @@ -1,59 +1,59 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Common.h" -#include "IniFile.h" -#include "Config.h" - -CConfig g_Config; - -CConfig::CConfig() -{ - Load(); -} - -void CConfig::LoadDefaults() -{ - m_EnableHLEAudio = true; - m_EnableDTKMusic = true; - m_Interpolation = true; -} - -void CConfig::Load() -{ - // first load defaults - LoadDefaults(); - - IniFile file; - file.Load(FULL_CONFIG_DIR "DSP.ini"); - file.Get("Config", "EnableHLEAudio", &m_EnableHLEAudio, true); // Sound Settings - file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true); - file.Get("Config", "EnableThrottle", &m_EnableThrottle, true); - file.Get("Config", "Interpolation", &m_Interpolation, true); -} - -void CConfig::Save() -{ - IniFile file; - file.Load(FULL_CONFIG_DIR "DSP.ini"); - file.Set("Config", "EnableHLEAudio", m_EnableHLEAudio); // Sound Settings - file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic); - file.Set("Config", "EnableThrottle", m_EnableThrottle); - file.Set("Config", "Interpolation", m_Interpolation); - - file.Save(FULL_CONFIG_DIR "DSP.ini"); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "IniFile.h" +#include "Config.h" + +CConfig g_Config; + +CConfig::CConfig() +{ + Load(); +} + +void CConfig::LoadDefaults() +{ + m_EnableHLEAudio = true; + m_EnableDTKMusic = true; + m_Interpolation = true; +} + +void CConfig::Load() +{ + // first load defaults + LoadDefaults(); + + IniFile file; + file.Load(FULL_CONFIG_DIR "DSP.ini"); + file.Get("Config", "EnableHLEAudio", &m_EnableHLEAudio, true); // Sound Settings + file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true); + file.Get("Config", "EnableThrottle", &m_EnableThrottle, true); + file.Get("Config", "Interpolation", &m_Interpolation, true); +} + +void CConfig::Save() +{ + IniFile file; + file.Load(FULL_CONFIG_DIR "DSP.ini"); + file.Set("Config", "EnableHLEAudio", m_EnableHLEAudio); // Sound Settings + file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic); + file.Set("Config", "EnableThrottle", m_EnableThrottle); + file.Set("Config", "Interpolation", m_Interpolation); + + file.Save(FULL_CONFIG_DIR "DSP.ini"); +} diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/ConfigDlg.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/ConfigDlg.cpp index b24412117f..5e060db838 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/ConfigDlg.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/ConfigDlg.cpp @@ -1,85 +1,85 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "resource.h" - -#include "Config.h" -#include "ConfigDlg.h" - -LRESULT -CConfigDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) -{ - // Load config settings - g_Config.Load(); - - // Center window - //CenterWindow(this->GetParent()); - CenterWindow(GetParent()); - - // Get button handles - m_buttonEnableHLEAudio = GetDlgItem(IDC_ENABLE_HLE_AUDIO); - m_buttonEnableDTKMusic = GetDlgItem(IDC_ENABLE_DTK_MUSIC); - m_buttonEnableThrottle = GetDlgItem(IDC_ENABLE_THROTTLE); - m_comboSampleRate = GetDlgItem(IDC_SAMPLERATE); - - // Update checkboxes - m_buttonEnableHLEAudio.SetCheck(g_Config.m_EnableHLEAudio ? BST_CHECKED : BST_UNCHECKED); - m_buttonEnableDTKMusic.SetCheck(g_Config.m_EnableDTKMusic ? BST_CHECKED : BST_UNCHECKED); - m_buttonEnableThrottle.SetCheck(g_Config.m_EnableThrottle ? BST_CHECKED : BST_UNCHECKED); - m_comboSampleRate.AddString("44100"); - m_comboSampleRate.AddString("48000"); - m_comboSampleRate.SetCurSel(g_Config.m_SampleRate == 44100 ? 0 : 1); - - // Add tooltips - CToolTipCtrl ToolTips; - ToolTips.Create(m_hWnd); - ToolTips.Activate(true); - ToolTips.SetMaxTipWidth(220); // limit the width - ToolTips.SetDelayTime(TTDT_AUTOPOP, 20 * 1000); // give us time to read it - CToolInfo tiHLE(TTF_SUBCLASS, m_buttonEnableHLEAudio, 0, NULL, - "This is the most common sound type"); - CToolInfo tiDTK(TTF_SUBCLASS, m_buttonEnableDTKMusic, 0, NULL, - "This is sometimes used to play music tracks from the disc"); - CToolInfo tiOther(TTF_SUBCLASS, m_buttonEnableThrottle, 0, NULL, - "This is sometimes used together with pre-rendered movies. Disabling this" - " also disables the speed throttle that is causes. Meaning that" - " there will be no upper limit on your FPS."); - ToolTips.AddTool(tiHLE); - ToolTips.AddTool(tiDTK); - ToolTips.AddTool(tiOther); - - return(TRUE); -} - - -LRESULT -CConfigDlg::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) -{ - // Save settings - if (wID == IDOK) - { - g_Config.m_EnableHLEAudio = (m_buttonEnableHLEAudio.GetCheck() == BST_CHECKED) ? true : false; - g_Config.m_EnableDTKMusic = (m_buttonEnableDTKMusic.GetCheck() == BST_CHECKED) ? true : false; - g_Config.m_EnableThrottle = (m_buttonEnableThrottle.GetCheck() == BST_CHECKED) ? true : false; - g_Config.m_SampleRate = (m_comboSampleRate.GetCurSel() == 0 ? 44100 : 48000); - g_Config.Save(); - } - - EndDialog(wID); - g_Config.Save(); - return(0); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "resource.h" + +#include "Config.h" +#include "ConfigDlg.h" + +LRESULT +CConfigDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) +{ + // Load config settings + g_Config.Load(); + + // Center window + //CenterWindow(this->GetParent()); + CenterWindow(GetParent()); + + // Get button handles + m_buttonEnableHLEAudio = GetDlgItem(IDC_ENABLE_HLE_AUDIO); + m_buttonEnableDTKMusic = GetDlgItem(IDC_ENABLE_DTK_MUSIC); + m_buttonEnableThrottle = GetDlgItem(IDC_ENABLE_THROTTLE); + m_comboSampleRate = GetDlgItem(IDC_SAMPLERATE); + + // Update checkboxes + m_buttonEnableHLEAudio.SetCheck(g_Config.m_EnableHLEAudio ? BST_CHECKED : BST_UNCHECKED); + m_buttonEnableDTKMusic.SetCheck(g_Config.m_EnableDTKMusic ? BST_CHECKED : BST_UNCHECKED); + m_buttonEnableThrottle.SetCheck(g_Config.m_EnableThrottle ? BST_CHECKED : BST_UNCHECKED); + m_comboSampleRate.AddString("44100"); + m_comboSampleRate.AddString("48000"); + m_comboSampleRate.SetCurSel(g_Config.m_SampleRate == 44100 ? 0 : 1); + + // Add tooltips + CToolTipCtrl ToolTips; + ToolTips.Create(m_hWnd); + ToolTips.Activate(true); + ToolTips.SetMaxTipWidth(220); // limit the width + ToolTips.SetDelayTime(TTDT_AUTOPOP, 20 * 1000); // give us time to read it + CToolInfo tiHLE(TTF_SUBCLASS, m_buttonEnableHLEAudio, 0, NULL, + "This is the most common sound type"); + CToolInfo tiDTK(TTF_SUBCLASS, m_buttonEnableDTKMusic, 0, NULL, + "This is sometimes used to play music tracks from the disc"); + CToolInfo tiOther(TTF_SUBCLASS, m_buttonEnableThrottle, 0, NULL, + "This is sometimes used together with pre-rendered movies. Disabling this" + " also disables the speed throttle that is causes. Meaning that" + " there will be no upper limit on your FPS."); + ToolTips.AddTool(tiHLE); + ToolTips.AddTool(tiDTK); + ToolTips.AddTool(tiOther); + + return(TRUE); +} + + +LRESULT +CConfigDlg::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) +{ + // Save settings + if (wID == IDOK) + { + g_Config.m_EnableHLEAudio = (m_buttonEnableHLEAudio.GetCheck() == BST_CHECKED) ? true : false; + g_Config.m_EnableDTKMusic = (m_buttonEnableDTKMusic.GetCheck() == BST_CHECKED) ? true : false; + g_Config.m_EnableThrottle = (m_buttonEnableThrottle.GetCheck() == BST_CHECKED) ? true : false; + g_Config.m_SampleRate = (m_comboSampleRate.GetCurSel() == 0 ? 44100 : 48000); + g_Config.Save(); + } + + EndDialog(wID); + g_Config.Save(); + return(0); +} diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.cpp index e999a34d19..31254c8e81 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.cpp @@ -1,90 +1,90 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifdef _WIN32 -#include "PCHW/DSoundStream.h" -#endif - -#include "DSPHandler.h" - -CDSPHandler* CDSPHandler::m_pInstance = NULL; - -CDSPHandler::CDSPHandler() - : m_pUCode(NULL), - m_bHalt(false), - m_bAssertInt(false) -{ - SetUCode(UCODE_ROM); - m_DSPControl.DSPHalt = 1; - m_DSPControl.DSPInit = 1; -} - -CDSPHandler::~CDSPHandler() -{ - delete m_pUCode; - m_pUCode = NULL; -} - -void CDSPHandler::Update() -{ - if (m_pUCode != NULL) - m_pUCode->Update(); -} - -unsigned short CDSPHandler::WriteControlRegister(unsigned short _Value) -{ - UDSPControl Temp(_Value); - if (Temp.DSPReset) - { - SetUCode(UCODE_ROM); - Temp.DSPReset = 0; - } - if (Temp.DSPInit == 0) - { - // copy 128 byte from ARAM 0x000000 to IMEM - SetUCode(UCODE_INIT_AUDIO_SYSTEM); - Temp.DSPInitCode = 0; - // MessageBox(NULL, "UCODE_INIT_AUDIO_SYSTEM", "DSP-HLE", MB_OK); - } - - m_DSPControl.Hex = Temp.Hex; - return m_DSPControl.Hex; -} - -unsigned short CDSPHandler::ReadControlRegister() -{ - return m_DSPControl.Hex; -} - -void CDSPHandler::SendMailToDSP(u32 _uMail) -{ - if (m_pUCode != NULL) - m_pUCode->HandleMail(_uMail); -} - -IUCode* CDSPHandler::GetUCode() -{ - return m_pUCode; -} - -void CDSPHandler::SetUCode(u32 _crc) -{ - delete m_pUCode; - m_pUCode = NULL; - m_MailHandler.Clear(); - m_pUCode = UCodeFactory(_crc, m_MailHandler); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifdef _WIN32 +#include "PCHW/DSoundStream.h" +#endif + +#include "DSPHandler.h" + +CDSPHandler* CDSPHandler::m_pInstance = NULL; + +CDSPHandler::CDSPHandler() + : m_pUCode(NULL), + m_bHalt(false), + m_bAssertInt(false) +{ + SetUCode(UCODE_ROM); + m_DSPControl.DSPHalt = 1; + m_DSPControl.DSPInit = 1; +} + +CDSPHandler::~CDSPHandler() +{ + delete m_pUCode; + m_pUCode = NULL; +} + +void CDSPHandler::Update() +{ + if (m_pUCode != NULL) + m_pUCode->Update(); +} + +unsigned short CDSPHandler::WriteControlRegister(unsigned short _Value) +{ + UDSPControl Temp(_Value); + if (Temp.DSPReset) + { + SetUCode(UCODE_ROM); + Temp.DSPReset = 0; + } + if (Temp.DSPInit == 0) + { + // copy 128 byte from ARAM 0x000000 to IMEM + SetUCode(UCODE_INIT_AUDIO_SYSTEM); + Temp.DSPInitCode = 0; + // MessageBox(NULL, "UCODE_INIT_AUDIO_SYSTEM", "DSP-HLE", MB_OK); + } + + m_DSPControl.Hex = Temp.Hex; + return m_DSPControl.Hex; +} + +unsigned short CDSPHandler::ReadControlRegister() +{ + return m_DSPControl.Hex; +} + +void CDSPHandler::SendMailToDSP(u32 _uMail) +{ + if (m_pUCode != NULL) + m_pUCode->HandleMail(_uMail); +} + +IUCode* CDSPHandler::GetUCode() +{ + return m_pUCode; +} + +void CDSPHandler::SetUCode(u32 _crc) +{ + delete m_pUCode; + m_pUCode = NULL; + m_MailHandler.Clear(); + m_pUCode = UCodeFactory(_crc, m_MailHandler); +} diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/Debugger/Blocks.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/Debugger/Blocks.cpp index 94a050bdca..34e351e820 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/Debugger/Blocks.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/Debugger/Blocks.cpp @@ -1,85 +1,85 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// -// Licensetype: GNU General Public License (GPL) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. -// -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ -// -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ -// -////////////////////////////////////////////////////////////////////////////////////////// - -// includes -#include -#include -#include - -#ifndef _WIN32 -#include -#endif - -#include "Debugger.h" -#include "PBView.h" -#include "IniFile.h" -#include "FileUtil.h" -#include "StringUtil.h" -#include "FileSearch.h" -#include "../Logging/Console.h" // open and close console - - -// Make the wxTextCtrls scroll with each other -void CDebugger::DoScrollBlocks() -{ - // ShowPosition = in letters - // GetScrollPos = number of lines from the top - // GetLineLength = letters in one line - // SetScrollPos = only set the scrollbar, doesn't update the text, - // Update() or Refresh() doesn't help - - double pos = m_bl95->GetScrollPos(wxVERTICAL)*(m_bl95->GetLineLength(0)+12.95); // annoying :( - m_bl0->ShowPosition((int)pos); - - /* - if(GetAsyncKeyState(VK_NUMPAD1)) - A -= 0.1; - else if(GetAsyncKeyState(VK_NUMPAD2)) - A += 0.11; - - wprintf("GetScrollPos:%i GetScrollRange:%i GetPosition:%i GetLastPosition:%i GetMaxWidth:%i \ - GetLineLength:%i XYToPosition:%i\n \ - GetScrollPos * GetLineLength + GetScrollRange:%i A:%f\n", - m_bl95->GetScrollPos(wxVERTICAL), m_bl95->GetScrollRange(wxVERTICAL), - m_bl95->GetPosition().y, m_bl95->GetLastPosition(), m_bl95->GetMaxWidth(), - m_bl95->GetLineLength(0), m_bl95->XYToPosition(0,25), - pos, A - ); - - for (int i = 0; i < 127; ++i) - { - m_bl0->AppendText(wxString::Format("%02i|68 : 01a70144\n", i)); - m_bl95->AppendText(wxString::Format("%i Mouse\n", i)); - }*/ -} - -void CDebugger::ScrollBlocksMouse(wxMouseEvent& event) -{ - DoScrollBlocks(); - event.Skip(); // otherwise we remove the regular behavior, for example scrolling -} - -void CDebugger::ScrollBlocksCursor(wxScrollWinEvent& event) -{ - DoScrollBlocks(); - event.Skip(); // otherwise we remove the regular behavior, for example scrolling -} -// ============== +////////////////////////////////////////////////////////////////////////////////////////// +// +// Licensetype: GNU General Public License (GPL) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. +// +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ +// +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +// +////////////////////////////////////////////////////////////////////////////////////////// + +// includes +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +#include "Debugger.h" +#include "PBView.h" +#include "IniFile.h" +#include "FileUtil.h" +#include "StringUtil.h" +#include "FileSearch.h" +#include "../Logging/Console.h" // open and close console + + +// Make the wxTextCtrls scroll with each other +void CDebugger::DoScrollBlocks() +{ + // ShowPosition = in letters + // GetScrollPos = number of lines from the top + // GetLineLength = letters in one line + // SetScrollPos = only set the scrollbar, doesn't update the text, + // Update() or Refresh() doesn't help + + double pos = m_bl95->GetScrollPos(wxVERTICAL)*(m_bl95->GetLineLength(0)+12.95); // annoying :( + m_bl0->ShowPosition((int)pos); + + /* + if(GetAsyncKeyState(VK_NUMPAD1)) + A -= 0.1; + else if(GetAsyncKeyState(VK_NUMPAD2)) + A += 0.11; + + wprintf("GetScrollPos:%i GetScrollRange:%i GetPosition:%i GetLastPosition:%i GetMaxWidth:%i \ + GetLineLength:%i XYToPosition:%i\n \ + GetScrollPos * GetLineLength + GetScrollRange:%i A:%f\n", + m_bl95->GetScrollPos(wxVERTICAL), m_bl95->GetScrollRange(wxVERTICAL), + m_bl95->GetPosition().y, m_bl95->GetLastPosition(), m_bl95->GetMaxWidth(), + m_bl95->GetLineLength(0), m_bl95->XYToPosition(0,25), + pos, A + ); + + for (int i = 0; i < 127; ++i) + { + m_bl0->AppendText(wxString::Format("%02i|68 : 01a70144\n", i)); + m_bl95->AppendText(wxString::Format("%i Mouse\n", i)); + }*/ +} + +void CDebugger::ScrollBlocksMouse(wxMouseEvent& event) +{ + DoScrollBlocks(); + event.Skip(); // otherwise we remove the regular behavior, for example scrolling +} + +void CDebugger::ScrollBlocksCursor(wxScrollWinEvent& event) +{ + DoScrollBlocks(); + event.Skip(); // otherwise we remove the regular behavior, for example scrolling +} +// ============== diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/Debugger/Debugger.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/Debugger/Debugger.cpp index fcd69bc3d7..0b7326871a 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/Debugger/Debugger.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/Debugger/Debugger.cpp @@ -1,691 +1,691 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// -// Licensetype: GNU General Public License (GPL) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. -// -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ -// -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ -// -////////////////////////////////////////////////////////////////////////////////////////// - -// includes -#include -#include -#include - -#ifndef _WIN32 -#include -#endif - -#include "Debugger.h" -#include "PBView.h" -#include "IniFile.h" -#include "FileUtil.h" -#include "StringUtil.h" -#include "FileSearch.h" -#include "../Logging/Console.h" // open and close console - - -// externals that are needed even in Release builds -bool gSSBM = true; -bool gSSBMremedy1 = true; -bool gSSBMremedy2 = true; -bool gSequenced = true; -bool gVolume = true; -bool gReset = false; - - -// ======================================================================================= -// Declare events -BEGIN_EVENT_TABLE(CDebugger,wxDialog) - EVT_CLOSE(CDebugger::OnClose) // on close event - - EVT_BUTTON(ID_UPD,CDebugger::OnUpdate) // buttons - - // left cotrols - EVT_CHECKLISTBOX(IDC_CHECKLIST5, CDebugger::OnOptions) // options - EVT_CHECKLISTBOX(IDC_CHECKLIST6, CDebugger::OnShowAll) - EVT_RADIOBOX(IDC_RADIO0,CDebugger::ShowBase) // update frequency - - // right cotrols - EVT_RADIOBOX(IDC_RADIO0,CDebugger::ShowBase) - EVT_RADIOBOX(IDC_RADIO1,CDebugger::ChangeFrequency) // update frequency - EVT_RADIOBOX(IDC_RADIO2,CDebugger::ChangePreset) // presets - EVT_CHECKLISTBOX(IDC_CHECKLIST1, CDebugger::OnSettingsCheck) // settings - - EVT_NOTEBOOK_PAGE_CHANGED(ID_NOTEBOOK, CDebugger::UpdateMail) // mails - EVT_RADIOBOX(IDC_RADIO3,CDebugger::ChangeMail) - EVT_CHECKLISTBOX(IDC_CHECKLIST2, CDebugger::OnGameChange) // gc - EVT_CHECKLISTBOX(IDC_CHECKLIST3, CDebugger::OnGameChange) // wii - EVT_CHECKLISTBOX(IDC_CHECKLIST4, CDebugger::MailSettings) // settings - - //EVT_RIGHT_DOWN(CDebugger::ScrollBlocks) - //EVT_LEFT_DOWN(CDebugger::ScrollBlocks) - //EVT_MOUSE_EVENTS(CDebugger::ScrollBlocks) - //EVT_MOTION(CDebugger::ScrollBlocks) - - //EVT_SCROLL(CDebugger::ScrollBlocks) - //EVT_SCROLLWIN(CDebugger::ScrollBlocks) -END_EVENT_TABLE() -// ======================================================================================= - - -CDebugger::CDebugger(wxWindow *parent, wxWindowID id, const wxString &title, - const wxPoint &position, const wxSize& size, long style) - : wxDialog(parent, id, title, position, size, style) - , m_GPRListView(NULL) - //, gUpdFreq(5) // loaded from file - , giShowAll(-1) - , gPreset(0) - - - , upd95(false) // block view settings - , upd94(false) - , upd93(false) - , upd92(false) -{ - CreateGUIControls(); - - // load ini... - IniFile file; - file.Load(DEBUGGER_CONFIG_FILE); - this->Load(file); - - // append block names - PBn.resize(266/2); - PBn[10] = "mixer"; - PBn[34] = "initial_time_delay"; - PBn[41] = "updates"; - PBn[46] = "dpop"; - PBn[58] = "vol_env"; - PBn[60] = "audio_addr"; - PBn[68] = "adpcm"; - PBn[88] = "src"; - PBn[95] = "adpcm_loop_info"; - PBn[98] = "lpf"; - PBn[102] = "hpf"; - PBn[106] = "pad"; - - PBp.resize(266/2); - PBp[10] = "volume_left, unknown"; - - PBp[58] = "cur_volume, cur_volume_delta"; // PBVolumeEnvelope - - - PBp[60] = "looping, sample_format"; // PBAudioAddr - PBp[62] = "loop_addr_hi, loop_addr_lo"; - PBp[64] = "end_addr_hi, end_addr_lo"; - PBp[66] = "cur_addr_hi, cur_addr_lo"; - - PBp[68] = "coef[0], coef[1]"; // PBADPCMInfo - - PBp[94] = "cur_addr_frac, last_samples[0]"; - - PBp[94] = "last_samples[3], pred_scale"; - PBp[96] = "yn1, yn2"; - - //wxEVT_RIGHT_DOWN, wxEVT_MOUSEWHEEL, wxEVT_LEFT_UP, - //m_bl95, m_PageBlock, sBlock - - m_bl95->Connect(wxID_ANY, wxEVT_SCROLLWIN_THUMBTRACK, - wxScrollWinEventHandler(CDebugger::ScrollBlocksCursor), (wxObject*)NULL, this); - m_bl95->Connect(wxID_ANY, wxEVT_SCROLLWIN_THUMBRELEASE, - wxScrollWinEventHandler(CDebugger::ScrollBlocksCursor), (wxObject*)NULL, this); - m_bl95->Connect(wxID_ANY, wxEVT_MOTION, - wxMouseEventHandler(CDebugger::ScrollBlocksMouse), (wxObject*)NULL, this); - m_bl95->Connect(wxID_ANY, wxEVT_MOUSEWHEEL, - wxMouseEventHandler(CDebugger::ScrollBlocksMouse), (wxObject*)NULL, this); -} - -CDebugger::~CDebugger() -{ - // empty - IniFile file; - file.Load(DEBUGGER_CONFIG_FILE); - this->Save(file); - file.Save(DEBUGGER_CONFIG_FILE); -} - -void CDebugger::Save(IniFile& _IniFile) const -{ - // TODO2: get the screen resolution and make limits from that - if(GetPosition().x < 1000 && GetPosition().y < 1000 - && GetSize().GetWidth() < 1000 && GetSize().GetHeight() < 1000 - ) - { - _IniFile.Set("SoundWindow", "x", GetPosition().x); - _IniFile.Set("SoundWindow", "y", GetPosition().y); - _IniFile.Set("SoundWindow", "w", GetSize().GetWidth()); - _IniFile.Set("SoundWindow", "h", GetSize().GetHeight()); - } - _IniFile.Set("SoundWindow", "Console", m_options->IsChecked(3)); // save settings - _IniFile.Set("SoundWindow", "UpdateFrequency", m_RadioBox[1]->GetSelection()); - _IniFile.Set("SoundWindow", "ScanMails", m_gcwiiset->IsChecked(0)); - _IniFile.Set("SoundWindow", "StoreMails", m_gcwiiset->IsChecked(1)); - _IniFile.Set("SoundWindow", "ShowBase", m_RadioBox[0]->GetSelection() ? false : true); -} - - -void CDebugger::Load(IniFile& _IniFile) -{ - int x,y,w,h; - _IniFile.Get("SoundWindow", "x", &x, GetPosition().x); - _IniFile.Get("SoundWindow", "y", &y, GetPosition().y); - _IniFile.Get("SoundWindow", "w", &w, GetSize().GetWidth()); - _IniFile.Get("SoundWindow", "h", &h, GetSize().GetHeight()); - SetSize(x, y, w, h); - - // Show console or not - bool Console; - _IniFile.Get("SoundWindow", "Console", &Console, m_options->IsChecked(3)); - m_options->Check(3, Console); - DoShowHideConsole(); - - // Show number base - _IniFile.Get("SoundWindow", "ShowBase", &bShowBase, !m_RadioBox[0]->GetSelection()); - m_RadioBox[0]->SetSelection(!bShowBase); - - _IniFile.Get("SoundWindow", "UpdateFrequency", &gUpdFreq, m_RadioBox[1]->GetSelection()); - m_RadioBox[1]->SetSelection(gUpdFreq); - DoChangeFrequency(); - - // Read and store mails on/off - _IniFile.Get("SoundWindow", "ScanMails", &ScanMails, m_gcwiiset->IsChecked(0)); - m_gcwiiset->Check(0, ScanMails); - _IniFile.Get("SoundWindow", "StoreMails", &StoreMails, m_gcwiiset->IsChecked(1)); - m_gcwiiset->Check(1, StoreMails); -} - -void CDebugger::CreateGUIControls() -{ -SetTitle(wxT("Sound Debugging")); - - // Basic settings - SetIcon(wxNullIcon); - SetSize(8, 8, 200, 100); // these will become the minimin sizes allowed by resizing - Center(); - - - // Declarations - wxBoxSizer * sMAIN, * sMain, *_sMail, * sBlock; - - wxButton* m_Upd; - wxButton* m_SelC; - wxButton* m_Presets; - - wxStaticBoxSizer* sLeft; - - int m_radioBoxNChoices[3]; - - - // Notebook ----------------------------------------------------- - m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize); - m_PageMain = new wxPanel(m_Notebook, ID_PAGEMAIN, wxDefaultPosition, wxDefaultSize); - m_Notebook->AddPage(m_PageMain, wxT("Main")); - m_PageMail = new wxPanel(m_Notebook, ID_PAGEMAIL, wxDefaultPosition, wxDefaultSize); - m_Notebook->AddPage(m_PageMail, wxT("Mail")); - m_PageBlock = new wxPanel(m_Notebook, ID_PAGEBLOCK, wxDefaultPosition, wxDefaultSize); - m_Notebook->AddPage(m_PageBlock, wxT("Blocks")); - - - - - // =================================================================== - // Blocks Page - - wxStaticBoxSizer * m_bl0Sizer = new wxStaticBoxSizer (wxVERTICAL, m_PageBlock, wxT("Block")); - m_bl0 = new wxTextCtrl(m_PageBlock, ID_BL0, _T(""), wxDefaultPosition, wxSize(250, 120), - wxTE_RICH | wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP | wxNO_BORDER); - m_bl0Sizer->Add(m_bl0, 1, wxEXPAND | wxALL, 0); - - wxStaticBoxSizer * m_bl1Sizer = new wxStaticBoxSizer (wxVERTICAL, m_PageBlock, wxT("Block 95")); - m_bl95 = new wxTextCtrl(m_PageBlock, ID_BL95, _T(""), wxDefaultPosition, wxSize(300, 120), - wxTE_RICH | wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP | wxNO_BORDER); - m_bl1Sizer->Add(m_bl95, 1, wxEXPAND | wxALL, 0); - - wxStaticBoxSizer * m_bl2Sizer = new wxStaticBoxSizer (wxVERTICAL, m_PageBlock, wxT("Block 94")); - m_bl94 = new wxTextCtrl(m_PageBlock, ID_BL94, _T(""), wxDefaultPosition, wxSize(300, 120), - wxTE_RICH | wxTE_MULTILINE | wxTE_DONTWRAP | wxNO_BORDER ); - m_bl2Sizer->Add(m_bl94, 1, wxEXPAND | wxALL, 0); - - - - - - // =================================================================== - // Mail Page - - wxStaticBoxSizer * m_m1Sizer = new wxStaticBoxSizer (wxVERTICAL, m_PageMail, wxT("Entire mail")); - m_log = new wxTextCtrl(m_PageMail, ID_LOG, _T(""), wxDefaultPosition, wxSize(175, 120), - wxTE_RICH | wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP | wxNO_BORDER); - m_m1Sizer->Add(m_log, 1, wxEXPAND | wxALL, 0); - - wxStaticBoxSizer * m_m2Sizer = new wxStaticBoxSizer (wxVERTICAL, m_PageMail, wxT("Logged mail")); - m_log1 = new wxTextCtrl(m_PageMail, ID_LOG1, _T(""), wxDefaultPosition, wxSize(300, 120), - wxTE_RICH | wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP | wxNO_BORDER ); - m_m2Sizer->Add(m_log1, 1, wxEXPAND | wxALL, 0); - - // Show different mails, make room for five mails, in usual circumstances it's two or three - wxString m_radioBoxChoices3[] = { wxT("0"), wxT("1"), wxT("2"), wxT("3"), wxT("4") }; - m_radioBoxNChoices[3] = sizeof( m_radioBoxChoices3 ) / sizeof( wxString ); - m_RadioBox[3] = new wxRadioBox( m_PageMail, IDC_RADIO3, wxT("Show mail"), - wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[3], m_radioBoxChoices3, 1, wxRA_SPECIFY_COLS); - m_RadioBox[3]->Enable(false); - - // Games checkboxes (m_PageMail) ----------------------------- - wxStaticBoxSizer * m_gameSizer1 = new wxStaticBoxSizer(wxVERTICAL, m_PageMail, wxT("GC")); - m_gc = new wxCheckListBox(m_PageMail, IDC_CHECKLIST2, wxDefaultPosition, wxDefaultSize, - 0, NULL, wxNO_BORDER | wxLB_SINGLE); - m_gameSizer1->Add(m_gc, 1, wxEXPAND | wxALL, 0); - - wxStaticBoxSizer * m_gameSizer2 = new wxStaticBoxSizer(wxVERTICAL, m_PageMail, wxT("Wii")); - m_wii = new wxCheckListBox(m_PageMail, IDC_CHECKLIST3, wxDefaultPosition, wxDefaultSize, - 0, NULL, wxNO_BORDER | wxLB_SINGLE); - m_gameSizer2->Add(m_wii, 1, wxEXPAND | wxALL, 0); - - // Settings - wxStaticBoxSizer * m_gameSizer3 = new wxStaticBoxSizer(wxVERTICAL, m_PageMail, wxT("Settings")); - m_gcwiiset = new wxCheckListBox(m_PageMail, IDC_CHECKLIST4, wxDefaultPosition, wxDefaultSize, - 0, NULL, wxNO_BORDER | wxLB_SINGLE); - m_gameSizer3->Add(m_gcwiiset, 0, 0, 0); - m_gcwiiset->Append(wxT("Scan mails")); - m_gcwiiset->Append(wxT("Store mails")); - - - - // =================================================================== - // Main Page - - // Options checkboxlist (m_PageMain) ----------------------------------- - wxStaticBoxSizer * m_checkSizer = new wxStaticBoxSizer (wxVERTICAL, m_PageMain, wxT("Options")); - m_options = new wxCheckListBox(m_PageMain, IDC_CHECKLIST5, wxDefaultPosition, wxDefaultSize, - 0, NULL, wxNO_BORDER); - - // checkboxes - m_options->Append(wxT("Save to file")); - m_options->Append(wxT("Only looping")); - m_options->Append(wxT("Show all")); - m_options->Append(wxT("Show console")); - - m_options->Check(0, gSaveFile); - m_options->Check(1, gOnlyLooping); - m_options->Check(2, gShowAll); - m_options->Check(3, gSaveFile); - - m_options->SetMinSize(wxSize(m_options->GetSize().GetWidth() - 40, - m_options->GetCount() * 15)); - - m_checkSizer->Add(m_options, 0, 0, 0); - // ------------------------ - - - // Options checkboxlist (m_PageMain) ----------------------------------- - wxStaticBoxSizer * m_showallSizer = new wxStaticBoxSizer (wxVERTICAL, m_PageMain, wxT("Show all")); - m_opt_showall = new wxCheckListBox(m_PageMain, IDC_CHECKLIST6, wxDefaultPosition, wxDefaultSize, - 0, NULL, wxNO_BORDER); - - // checkboxes - m_opt_showall->Append(wxT("Part 1")); - m_opt_showall->Append(wxT("Part 2")); - m_opt_showall->Append(wxT("Part 3")); - m_opt_showall->Append(wxT("Part 4")); - - m_opt_showall->SetMinSize(wxSize(m_opt_showall->GetSize().GetWidth() - 40, - m_opt_showall->GetCount() * 15)); - - m_showallSizer->Add(m_opt_showall, 0, 0, 0); - - - // Update frequency, numeric base, presets radio boxes -------------------- - wxString m_radioBoxChoices0[] = { wxT("Show base 10"), wxT("Show base 16") }; - m_radioBoxNChoices[0] = sizeof( m_radioBoxChoices0 ) / sizeof( wxString ); - m_RadioBox[0] = new wxRadioBox( m_PageMain, IDC_RADIO0, wxT("Show base"), - wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[0], m_radioBoxChoices0, 1, wxRA_SPECIFY_COLS); - - wxString m_radioBoxChoices1[] = { wxT("Never"), wxT("5 times/s"), wxT("15 times/s"), wxT("30 times/s") }; - m_radioBoxNChoices[1] = sizeof( m_radioBoxChoices1 ) / sizeof( wxString ); - m_RadioBox[1] = new wxRadioBox( m_PageMain, IDC_RADIO1, wxT("Update freq."), - wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[1], m_radioBoxChoices1, 1, wxRA_SPECIFY_COLS); - - wxString m_radioBoxChoices2[] = { wxT("Preset 1"), wxT("Updates"), wxT("Looping"), wxT("Mixer") }; - m_radioBoxNChoices[2] = sizeof( m_radioBoxChoices2 ) / sizeof( wxString ); - m_RadioBox[2] = new wxRadioBox( m_PageMain, IDC_RADIO2, wxT("Presets"), - wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[2], m_radioBoxChoices2, 1, wxRA_SPECIFY_COLS); - // ------------------------ - - - // -------------------------------------------------------------------- - // Settings checkboxes (m_PageMain) - // ------------------------- - wxStaticBoxSizer * m_checkSizer2 = new wxStaticBoxSizer(wxVERTICAL, m_PageMain, wxT("Settings")); - m_settings = new wxCheckListBox(m_PageMain, IDC_CHECKLIST1, wxDefaultPosition, wxDefaultSize, - 0, NULL, wxNO_BORDER); - - m_settings->Append(wxT("SSBM fix")); - m_settings->Append(wxT("SSBM remedy 1")); - m_settings->Append(wxT("SSBM remedy 2")); - m_settings->Append(wxT("Sequenced")); - m_settings->Append(wxT("Volume delta")); - m_settings->Append(wxT("Reset all")); - - m_settings->Check(0, gSSBM); - m_settings->Check(1, gSSBMremedy1); - m_settings->Check(2, gSSBMremedy2); - m_settings->Check(3, gSequenced); - m_settings->Check(4, gVolume); - m_settings->Check(5, gReset); - - // because the wxCheckListBox is a little underdeveloped we have to help it with this - // to bad there's no windows xp styles for the checkboxes - m_settings->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); - m_settings->SetMinSize(wxSize(m_settings->GetSize().GetWidth() - 40, - m_settings->GetCount() * 15)); -#ifdef _WIN32 - //for (int i = 0; i < m_settings->GetCount(); ++i) - // m_settings->GetItem(i)->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); -#endif - m_checkSizer2->Add(m_settings, 0, 0, 0); - // ------------------------ - - - // -------------------------------------------------------------------- - // Buttons - // ------------------------ - m_Upd = new wxButton(m_PageMain, ID_UPD, wxT("Update"), - wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_SelC = new wxButton(m_PageMain, ID_SELC, wxT("Select Columns"), - wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_SelC->Enable(false); - m_Presets = new wxButton(m_PageMain, ID_PRESETS, wxT("Presets"), - wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_Presets->Enable(false); - // -------------------------------------------------------------------- - - - // -------------------------------------------------------------------- - // Left buttons and checkboxes (MAIN - // ------------------------ - wxBoxSizer* sButtons; - sButtons = new wxBoxSizer(wxVERTICAL); - - sButtons->AddSpacer(5); // to set a minimum margin - - sButtons->Add(m_Upd, 0, 0, 5); - sButtons->Add(m_SelC, 0, 0, 5); - sButtons->Add(m_Presets, 0, 0, 5); - - sButtons->AddStretchSpacer(1); - sButtons->Add(m_checkSizer, 0, 0, 5); - sButtons->AddStretchSpacer(1); - sButtons->Add(m_showallSizer, 0, 0, 5); - sButtons->AddStretchSpacer(1); - sButtons->Add(m_RadioBox[0], 0, 0, 5); - - sButtons->AddSpacer(5); - // ------------------------ - - - // -------------------------------------------------------------------- - // Right buttons and checkboxes (MAIN) - // ------------------------ - wxBoxSizer* sButtons2; - sButtons2 = new wxBoxSizer(wxVERTICAL); - - sButtons2->AddStretchSpacer(1); - sButtons2->Add(m_RadioBox[1], 0, 0, 5); // Update freq. - sButtons2->AddStretchSpacer(1); - sButtons2->Add(m_RadioBox[2], 0, 0, 5); - sButtons2->AddStretchSpacer(1); - sButtons2->Add(m_checkSizer2, 0, 0, 5); - sButtons2->AddStretchSpacer(1); - // ------------------------ - - - // -------------------------------------------------------------------- - // Parameter tables view (MAIN) - sLeft = new wxStaticBoxSizer(wxVERTICAL, m_PageMain, wxT("Current Status")); - - // The big window that holds the parameter tables - m_GPRListView = new CPBView(m_PageMain, ID_GPR, wxDefaultPosition, GetSize(), - wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT | wxLC_SINGLE_SEL | wxLC_SORT_ASCENDING); - - sLeft->Add(m_GPRListView, 1, wxEXPAND|wxALL, 5); - - sMain = new wxBoxSizer(wxHORIZONTAL); - sMain->Add(sLeft, 1, wxEXPAND | wxALL, 5); // margin = 5 - sMain->Add(sButtons, 0, wxALL, 0); - sMain->Add(sButtons2, 0, wxALL, 5); // margin = 5 - // -------------------------------------------------------------------- - - - // -------------------------------------------------------------------- - // Add all stuff to the mail container (MAIL) - // ----------------------------- - // For the buttons on the right - wxBoxSizer * sMailRight = new wxBoxSizer(wxVERTICAL); - //wxStaticBoxSizer * sMailRight = new wxStaticBoxSizer(wxVERTICAL, m_PageMail, wxT("Current")); - - _sMail = new wxBoxSizer(wxHORIZONTAL); - _sMail->Add(m_m1Sizer, 0, wxEXPAND | (wxUP | wxDOWN), 5); // margin = 5 - _sMail->Add(m_m2Sizer, 1, wxEXPAND | (wxUP | wxDOWN | wxLEFT), 5); // margin = 5 - _sMail->Add(sMailRight, 0, wxEXPAND | wxALL, 0); // margin = 0 - - sMailRight->Add(m_RadioBox[3], 0, wxALL, 5); // margin = 5 - sMailRight->Add(m_gameSizer1, 1, wxEXPAND | wxALL, 5); // margin = 5 - sMailRight->Add(m_gameSizer2, 1, wxEXPAND | wxALL, 5); // margin = 5 - sMailRight->Add(m_gameSizer3, 0, wxALL, 5); // margin = 5 - // -------------------------------------------------------------------- - - - // -------------------------------------------------------------------- - // The blocks view container (BLOCKS) - // ----------------------------- - // For the buttons on the right - //wxBoxSizer * sMailRight = new wxBoxSizer(wxVERTICAL); - //wxStaticBoxSizer * sMailRight = new wxStaticBoxSizer(wxVERTICAL, m_PageMail, wxT("Current")); - - sBlock = new wxBoxSizer(wxHORIZONTAL); - sBlock->Add(m_bl0Sizer, 0, wxEXPAND | (wxUP | wxDOWN), 5); // margin = 5 - sBlock->Add(m_bl1Sizer, 1, wxEXPAND | (wxUP | wxDOWN | wxLEFT), 5); // margin = 5 - sBlock->Add(m_bl2Sizer, 1, wxEXPAND | (wxUP | wxDOWN | wxRIGHT), 5); // margin = 5 - //sBlock->Add(sMailRight, 0, wxEXPAND | wxALL, 0); // margin = 0 - - /*sMailRight->Add(m_RadioBox[3], 0, wxALL, 5); // margin = 5 - sMailRight->Add(m_gameSizer1, 1, wxEXPAND | wxALL, 5); // margin = 5 - sMailRight->Add(m_gameSizer2, 1, wxEXPAND | wxALL, 5); // margin = 5 - sMailRight->Add(m_gameSizer3, 0, wxALL, 5); // margin = 5*/ - // -------------------------------------------------------------------- - - - // -------------------------------------------------------------------- - // Main containers - // ----------------------------- - sMAIN = new wxBoxSizer(wxVERTICAL); - sMAIN->Add(m_Notebook, 1, wxEXPAND | wxALL, 5); - //sMAIN->SetSizeHints(this); - - m_PageMain->SetSizer(sMain); - m_PageMail->SetSizer(_sMail); - m_PageBlock->SetSizer(sBlock); - //sMain->Layout(); - - this->SetSizer(sMAIN); - //this->Layout(); - - NotifyUpdate(); - // -------------------------------------------------------------------- -} - -// ======================================================================== -// System functions -// -------------- -void CDebugger::OnClose(wxCloseEvent& /*event*/) -{ - // save the window position when we hide the window to - IniFile file; - file.Load(DEBUGGER_CONFIG_FILE); - this->Save(file); - file.Save(DEBUGGER_CONFIG_FILE); - - EndModal(0); - CloseConsole(); // Take the console window with it -} - -void CDebugger::DoHide() -{ - Hide(); - CloseConsole(); // The console goes with the wx window -} - -void CDebugger::DoShow() -{ - Show(); - DoShowHideConsole(); // The console goes with the wx window -} - -void CDebugger::OnUpdate(wxCommandEvent& /*event*/) -{ - this->NotifyUpdate(); -} -// =============== - - -// ======================================================================================= -// Settings -// -------------- -void CDebugger::OnSettingsCheck(wxCommandEvent& event) -{ - gSSBM = m_settings->IsChecked(0); - gSSBMremedy1 = m_settings->IsChecked(1); - gSSBMremedy2 = m_settings->IsChecked(2); - gSequenced = m_settings->IsChecked(3); - gVolume = m_settings->IsChecked(4); - gReset = m_settings->IsChecked(5); - -} -// ======================================================================================= - - -// ======================================================================================= -// Change preset -// -------------- -void CDebugger::ChangePreset(wxCommandEvent& event) -{ - DoChangePreset(); -} - -void CDebugger::DoChangePreset() -{ - if(m_RadioBox[2]->GetSelection() == 0) - gPreset = 0; - else if(m_RadioBox[2]->GetSelection() == 1) - gPreset = 1; - else if(m_RadioBox[2]->GetSelection() == 2) - gPreset = 2; - else if(m_RadioBox[2]->GetSelection() == 3) - gPreset = 3; -} -// ============== - - -// ======================================================================================= -// Show base -// -------------- -void CDebugger::ShowBase(wxCommandEvent& event) -{ - if(m_RadioBox[0]->GetSelection() == 0) - bShowBase = true; - else if(m_RadioBox[0]->GetSelection() == 1) - bShowBase = false; -} -// ============== - - -// ======================================================================================= -// Change update frequency -// -------------- -void CDebugger::ChangeFrequency(wxCommandEvent& event) -{ - DoChangeFrequency(); -} - -void CDebugger::DoChangeFrequency() -{ - if(m_RadioBox[1]->GetSelection() == 0) - gUpdFreq = 0; - else if(m_RadioBox[1]->GetSelection() == 1) - gUpdFreq = 5; - else if(m_RadioBox[1]->GetSelection() == 2) - gUpdFreq = 15; - else if(m_RadioBox[1]->GetSelection() == 3) - gUpdFreq = 30; -} -// ============== - - -// ======================================================================================= -// Options -// -------------- -void CDebugger::OnOptions(wxCommandEvent& event) -{ - gSaveFile = m_options->IsChecked(0); - gOnlyLooping = m_options->IsChecked(1); - gShowAll = m_options->IsChecked(2); - gSaveFile = m_options->IsChecked(3); - - if(event.GetInt() == 3) DoShowHideConsole(); -} - -void CDebugger::OnShowAll(wxCommandEvent& event) -{ - /// Only allow one selection at a time - for (u32 i = 0; i < m_opt_showall->GetCount(); ++i) - if(i != (u32)event.GetInt()) m_opt_showall->Check(i, false); - - if(m_opt_showall->IsChecked(0)) giShowAll = 0; - else if(m_opt_showall->IsChecked(1)) giShowAll = 1; - else if(m_opt_showall->IsChecked(2)) giShowAll = 2; - else if(m_opt_showall->IsChecked(3)) giShowAll = 3; - else giShowAll = -1; -} - -// -------------- - - -// ======================================================================================= -// Show or hide console window -// -------------- -void CDebugger::ShowHideConsole(wxCommandEvent& event) -{ - DoShowHideConsole(); -} - -void CDebugger::DoShowHideConsole() -{ - if(m_options->IsChecked(3)) - OpenConsole(); - else - CloseConsole(); -} -// ============== - - -void CDebugger::NotifyUpdate() -{ - if (m_GPRListView != NULL) - { - m_GPRListView->Update(); - } -} - +////////////////////////////////////////////////////////////////////////////////////////// +// +// Licensetype: GNU General Public License (GPL) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. +// +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ +// +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +// +////////////////////////////////////////////////////////////////////////////////////////// + +// includes +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +#include "Debugger.h" +#include "PBView.h" +#include "IniFile.h" +#include "FileUtil.h" +#include "StringUtil.h" +#include "FileSearch.h" +#include "../Logging/Console.h" // open and close console + + +// externals that are needed even in Release builds +bool gSSBM = true; +bool gSSBMremedy1 = true; +bool gSSBMremedy2 = true; +bool gSequenced = true; +bool gVolume = true; +bool gReset = false; + + +// ======================================================================================= +// Declare events +BEGIN_EVENT_TABLE(CDebugger,wxDialog) + EVT_CLOSE(CDebugger::OnClose) // on close event + + EVT_BUTTON(ID_UPD,CDebugger::OnUpdate) // buttons + + // left cotrols + EVT_CHECKLISTBOX(IDC_CHECKLIST5, CDebugger::OnOptions) // options + EVT_CHECKLISTBOX(IDC_CHECKLIST6, CDebugger::OnShowAll) + EVT_RADIOBOX(IDC_RADIO0,CDebugger::ShowBase) // update frequency + + // right cotrols + EVT_RADIOBOX(IDC_RADIO0,CDebugger::ShowBase) + EVT_RADIOBOX(IDC_RADIO1,CDebugger::ChangeFrequency) // update frequency + EVT_RADIOBOX(IDC_RADIO2,CDebugger::ChangePreset) // presets + EVT_CHECKLISTBOX(IDC_CHECKLIST1, CDebugger::OnSettingsCheck) // settings + + EVT_NOTEBOOK_PAGE_CHANGED(ID_NOTEBOOK, CDebugger::UpdateMail) // mails + EVT_RADIOBOX(IDC_RADIO3,CDebugger::ChangeMail) + EVT_CHECKLISTBOX(IDC_CHECKLIST2, CDebugger::OnGameChange) // gc + EVT_CHECKLISTBOX(IDC_CHECKLIST3, CDebugger::OnGameChange) // wii + EVT_CHECKLISTBOX(IDC_CHECKLIST4, CDebugger::MailSettings) // settings + + //EVT_RIGHT_DOWN(CDebugger::ScrollBlocks) + //EVT_LEFT_DOWN(CDebugger::ScrollBlocks) + //EVT_MOUSE_EVENTS(CDebugger::ScrollBlocks) + //EVT_MOTION(CDebugger::ScrollBlocks) + + //EVT_SCROLL(CDebugger::ScrollBlocks) + //EVT_SCROLLWIN(CDebugger::ScrollBlocks) +END_EVENT_TABLE() +// ======================================================================================= + + +CDebugger::CDebugger(wxWindow *parent, wxWindowID id, const wxString &title, + const wxPoint &position, const wxSize& size, long style) + : wxDialog(parent, id, title, position, size, style) + , m_GPRListView(NULL) + //, gUpdFreq(5) // loaded from file + , giShowAll(-1) + , gPreset(0) + + + , upd95(false) // block view settings + , upd94(false) + , upd93(false) + , upd92(false) +{ + CreateGUIControls(); + + // load ini... + IniFile file; + file.Load(DEBUGGER_CONFIG_FILE); + this->Load(file); + + // append block names + PBn.resize(266/2); + PBn[10] = "mixer"; + PBn[34] = "initial_time_delay"; + PBn[41] = "updates"; + PBn[46] = "dpop"; + PBn[58] = "vol_env"; + PBn[60] = "audio_addr"; + PBn[68] = "adpcm"; + PBn[88] = "src"; + PBn[95] = "adpcm_loop_info"; + PBn[98] = "lpf"; + PBn[102] = "hpf"; + PBn[106] = "pad"; + + PBp.resize(266/2); + PBp[10] = "volume_left, unknown"; + + PBp[58] = "cur_volume, cur_volume_delta"; // PBVolumeEnvelope + + + PBp[60] = "looping, sample_format"; // PBAudioAddr + PBp[62] = "loop_addr_hi, loop_addr_lo"; + PBp[64] = "end_addr_hi, end_addr_lo"; + PBp[66] = "cur_addr_hi, cur_addr_lo"; + + PBp[68] = "coef[0], coef[1]"; // PBADPCMInfo + + PBp[94] = "cur_addr_frac, last_samples[0]"; + + PBp[94] = "last_samples[3], pred_scale"; + PBp[96] = "yn1, yn2"; + + //wxEVT_RIGHT_DOWN, wxEVT_MOUSEWHEEL, wxEVT_LEFT_UP, + //m_bl95, m_PageBlock, sBlock + + m_bl95->Connect(wxID_ANY, wxEVT_SCROLLWIN_THUMBTRACK, + wxScrollWinEventHandler(CDebugger::ScrollBlocksCursor), (wxObject*)NULL, this); + m_bl95->Connect(wxID_ANY, wxEVT_SCROLLWIN_THUMBRELEASE, + wxScrollWinEventHandler(CDebugger::ScrollBlocksCursor), (wxObject*)NULL, this); + m_bl95->Connect(wxID_ANY, wxEVT_MOTION, + wxMouseEventHandler(CDebugger::ScrollBlocksMouse), (wxObject*)NULL, this); + m_bl95->Connect(wxID_ANY, wxEVT_MOUSEWHEEL, + wxMouseEventHandler(CDebugger::ScrollBlocksMouse), (wxObject*)NULL, this); +} + +CDebugger::~CDebugger() +{ + // empty + IniFile file; + file.Load(DEBUGGER_CONFIG_FILE); + this->Save(file); + file.Save(DEBUGGER_CONFIG_FILE); +} + +void CDebugger::Save(IniFile& _IniFile) const +{ + // TODO2: get the screen resolution and make limits from that + if(GetPosition().x < 1000 && GetPosition().y < 1000 + && GetSize().GetWidth() < 1000 && GetSize().GetHeight() < 1000 + ) + { + _IniFile.Set("SoundWindow", "x", GetPosition().x); + _IniFile.Set("SoundWindow", "y", GetPosition().y); + _IniFile.Set("SoundWindow", "w", GetSize().GetWidth()); + _IniFile.Set("SoundWindow", "h", GetSize().GetHeight()); + } + _IniFile.Set("SoundWindow", "Console", m_options->IsChecked(3)); // save settings + _IniFile.Set("SoundWindow", "UpdateFrequency", m_RadioBox[1]->GetSelection()); + _IniFile.Set("SoundWindow", "ScanMails", m_gcwiiset->IsChecked(0)); + _IniFile.Set("SoundWindow", "StoreMails", m_gcwiiset->IsChecked(1)); + _IniFile.Set("SoundWindow", "ShowBase", m_RadioBox[0]->GetSelection() ? false : true); +} + + +void CDebugger::Load(IniFile& _IniFile) +{ + int x,y,w,h; + _IniFile.Get("SoundWindow", "x", &x, GetPosition().x); + _IniFile.Get("SoundWindow", "y", &y, GetPosition().y); + _IniFile.Get("SoundWindow", "w", &w, GetSize().GetWidth()); + _IniFile.Get("SoundWindow", "h", &h, GetSize().GetHeight()); + SetSize(x, y, w, h); + + // Show console or not + bool Console; + _IniFile.Get("SoundWindow", "Console", &Console, m_options->IsChecked(3)); + m_options->Check(3, Console); + DoShowHideConsole(); + + // Show number base + _IniFile.Get("SoundWindow", "ShowBase", &bShowBase, !m_RadioBox[0]->GetSelection()); + m_RadioBox[0]->SetSelection(!bShowBase); + + _IniFile.Get("SoundWindow", "UpdateFrequency", &gUpdFreq, m_RadioBox[1]->GetSelection()); + m_RadioBox[1]->SetSelection(gUpdFreq); + DoChangeFrequency(); + + // Read and store mails on/off + _IniFile.Get("SoundWindow", "ScanMails", &ScanMails, m_gcwiiset->IsChecked(0)); + m_gcwiiset->Check(0, ScanMails); + _IniFile.Get("SoundWindow", "StoreMails", &StoreMails, m_gcwiiset->IsChecked(1)); + m_gcwiiset->Check(1, StoreMails); +} + +void CDebugger::CreateGUIControls() +{ +SetTitle(wxT("Sound Debugging")); + + // Basic settings + SetIcon(wxNullIcon); + SetSize(8, 8, 200, 100); // these will become the minimin sizes allowed by resizing + Center(); + + + // Declarations + wxBoxSizer * sMAIN, * sMain, *_sMail, * sBlock; + + wxButton* m_Upd; + wxButton* m_SelC; + wxButton* m_Presets; + + wxStaticBoxSizer* sLeft; + + int m_radioBoxNChoices[3]; + + + // Notebook ----------------------------------------------------- + m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize); + m_PageMain = new wxPanel(m_Notebook, ID_PAGEMAIN, wxDefaultPosition, wxDefaultSize); + m_Notebook->AddPage(m_PageMain, wxT("Main")); + m_PageMail = new wxPanel(m_Notebook, ID_PAGEMAIL, wxDefaultPosition, wxDefaultSize); + m_Notebook->AddPage(m_PageMail, wxT("Mail")); + m_PageBlock = new wxPanel(m_Notebook, ID_PAGEBLOCK, wxDefaultPosition, wxDefaultSize); + m_Notebook->AddPage(m_PageBlock, wxT("Blocks")); + + + + + // =================================================================== + // Blocks Page + + wxStaticBoxSizer * m_bl0Sizer = new wxStaticBoxSizer (wxVERTICAL, m_PageBlock, wxT("Block")); + m_bl0 = new wxTextCtrl(m_PageBlock, ID_BL0, _T(""), wxDefaultPosition, wxSize(250, 120), + wxTE_RICH | wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP | wxNO_BORDER); + m_bl0Sizer->Add(m_bl0, 1, wxEXPAND | wxALL, 0); + + wxStaticBoxSizer * m_bl1Sizer = new wxStaticBoxSizer (wxVERTICAL, m_PageBlock, wxT("Block 95")); + m_bl95 = new wxTextCtrl(m_PageBlock, ID_BL95, _T(""), wxDefaultPosition, wxSize(300, 120), + wxTE_RICH | wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP | wxNO_BORDER); + m_bl1Sizer->Add(m_bl95, 1, wxEXPAND | wxALL, 0); + + wxStaticBoxSizer * m_bl2Sizer = new wxStaticBoxSizer (wxVERTICAL, m_PageBlock, wxT("Block 94")); + m_bl94 = new wxTextCtrl(m_PageBlock, ID_BL94, _T(""), wxDefaultPosition, wxSize(300, 120), + wxTE_RICH | wxTE_MULTILINE | wxTE_DONTWRAP | wxNO_BORDER ); + m_bl2Sizer->Add(m_bl94, 1, wxEXPAND | wxALL, 0); + + + + + + // =================================================================== + // Mail Page + + wxStaticBoxSizer * m_m1Sizer = new wxStaticBoxSizer (wxVERTICAL, m_PageMail, wxT("Entire mail")); + m_log = new wxTextCtrl(m_PageMail, ID_LOG, _T(""), wxDefaultPosition, wxSize(175, 120), + wxTE_RICH | wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP | wxNO_BORDER); + m_m1Sizer->Add(m_log, 1, wxEXPAND | wxALL, 0); + + wxStaticBoxSizer * m_m2Sizer = new wxStaticBoxSizer (wxVERTICAL, m_PageMail, wxT("Logged mail")); + m_log1 = new wxTextCtrl(m_PageMail, ID_LOG1, _T(""), wxDefaultPosition, wxSize(300, 120), + wxTE_RICH | wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP | wxNO_BORDER ); + m_m2Sizer->Add(m_log1, 1, wxEXPAND | wxALL, 0); + + // Show different mails, make room for five mails, in usual circumstances it's two or three + wxString m_radioBoxChoices3[] = { wxT("0"), wxT("1"), wxT("2"), wxT("3"), wxT("4") }; + m_radioBoxNChoices[3] = sizeof( m_radioBoxChoices3 ) / sizeof( wxString ); + m_RadioBox[3] = new wxRadioBox( m_PageMail, IDC_RADIO3, wxT("Show mail"), + wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[3], m_radioBoxChoices3, 1, wxRA_SPECIFY_COLS); + m_RadioBox[3]->Enable(false); + + // Games checkboxes (m_PageMail) ----------------------------- + wxStaticBoxSizer * m_gameSizer1 = new wxStaticBoxSizer(wxVERTICAL, m_PageMail, wxT("GC")); + m_gc = new wxCheckListBox(m_PageMail, IDC_CHECKLIST2, wxDefaultPosition, wxDefaultSize, + 0, NULL, wxNO_BORDER | wxLB_SINGLE); + m_gameSizer1->Add(m_gc, 1, wxEXPAND | wxALL, 0); + + wxStaticBoxSizer * m_gameSizer2 = new wxStaticBoxSizer(wxVERTICAL, m_PageMail, wxT("Wii")); + m_wii = new wxCheckListBox(m_PageMail, IDC_CHECKLIST3, wxDefaultPosition, wxDefaultSize, + 0, NULL, wxNO_BORDER | wxLB_SINGLE); + m_gameSizer2->Add(m_wii, 1, wxEXPAND | wxALL, 0); + + // Settings + wxStaticBoxSizer * m_gameSizer3 = new wxStaticBoxSizer(wxVERTICAL, m_PageMail, wxT("Settings")); + m_gcwiiset = new wxCheckListBox(m_PageMail, IDC_CHECKLIST4, wxDefaultPosition, wxDefaultSize, + 0, NULL, wxNO_BORDER | wxLB_SINGLE); + m_gameSizer3->Add(m_gcwiiset, 0, 0, 0); + m_gcwiiset->Append(wxT("Scan mails")); + m_gcwiiset->Append(wxT("Store mails")); + + + + // =================================================================== + // Main Page + + // Options checkboxlist (m_PageMain) ----------------------------------- + wxStaticBoxSizer * m_checkSizer = new wxStaticBoxSizer (wxVERTICAL, m_PageMain, wxT("Options")); + m_options = new wxCheckListBox(m_PageMain, IDC_CHECKLIST5, wxDefaultPosition, wxDefaultSize, + 0, NULL, wxNO_BORDER); + + // checkboxes + m_options->Append(wxT("Save to file")); + m_options->Append(wxT("Only looping")); + m_options->Append(wxT("Show all")); + m_options->Append(wxT("Show console")); + + m_options->Check(0, gSaveFile); + m_options->Check(1, gOnlyLooping); + m_options->Check(2, gShowAll); + m_options->Check(3, gSaveFile); + + m_options->SetMinSize(wxSize(m_options->GetSize().GetWidth() - 40, + m_options->GetCount() * 15)); + + m_checkSizer->Add(m_options, 0, 0, 0); + // ------------------------ + + + // Options checkboxlist (m_PageMain) ----------------------------------- + wxStaticBoxSizer * m_showallSizer = new wxStaticBoxSizer (wxVERTICAL, m_PageMain, wxT("Show all")); + m_opt_showall = new wxCheckListBox(m_PageMain, IDC_CHECKLIST6, wxDefaultPosition, wxDefaultSize, + 0, NULL, wxNO_BORDER); + + // checkboxes + m_opt_showall->Append(wxT("Part 1")); + m_opt_showall->Append(wxT("Part 2")); + m_opt_showall->Append(wxT("Part 3")); + m_opt_showall->Append(wxT("Part 4")); + + m_opt_showall->SetMinSize(wxSize(m_opt_showall->GetSize().GetWidth() - 40, + m_opt_showall->GetCount() * 15)); + + m_showallSizer->Add(m_opt_showall, 0, 0, 0); + + + // Update frequency, numeric base, presets radio boxes -------------------- + wxString m_radioBoxChoices0[] = { wxT("Show base 10"), wxT("Show base 16") }; + m_radioBoxNChoices[0] = sizeof( m_radioBoxChoices0 ) / sizeof( wxString ); + m_RadioBox[0] = new wxRadioBox( m_PageMain, IDC_RADIO0, wxT("Show base"), + wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[0], m_radioBoxChoices0, 1, wxRA_SPECIFY_COLS); + + wxString m_radioBoxChoices1[] = { wxT("Never"), wxT("5 times/s"), wxT("15 times/s"), wxT("30 times/s") }; + m_radioBoxNChoices[1] = sizeof( m_radioBoxChoices1 ) / sizeof( wxString ); + m_RadioBox[1] = new wxRadioBox( m_PageMain, IDC_RADIO1, wxT("Update freq."), + wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[1], m_radioBoxChoices1, 1, wxRA_SPECIFY_COLS); + + wxString m_radioBoxChoices2[] = { wxT("Preset 1"), wxT("Updates"), wxT("Looping"), wxT("Mixer") }; + m_radioBoxNChoices[2] = sizeof( m_radioBoxChoices2 ) / sizeof( wxString ); + m_RadioBox[2] = new wxRadioBox( m_PageMain, IDC_RADIO2, wxT("Presets"), + wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[2], m_radioBoxChoices2, 1, wxRA_SPECIFY_COLS); + // ------------------------ + + + // -------------------------------------------------------------------- + // Settings checkboxes (m_PageMain) + // ------------------------- + wxStaticBoxSizer * m_checkSizer2 = new wxStaticBoxSizer(wxVERTICAL, m_PageMain, wxT("Settings")); + m_settings = new wxCheckListBox(m_PageMain, IDC_CHECKLIST1, wxDefaultPosition, wxDefaultSize, + 0, NULL, wxNO_BORDER); + + m_settings->Append(wxT("SSBM fix")); + m_settings->Append(wxT("SSBM remedy 1")); + m_settings->Append(wxT("SSBM remedy 2")); + m_settings->Append(wxT("Sequenced")); + m_settings->Append(wxT("Volume delta")); + m_settings->Append(wxT("Reset all")); + + m_settings->Check(0, gSSBM); + m_settings->Check(1, gSSBMremedy1); + m_settings->Check(2, gSSBMremedy2); + m_settings->Check(3, gSequenced); + m_settings->Check(4, gVolume); + m_settings->Check(5, gReset); + + // because the wxCheckListBox is a little underdeveloped we have to help it with this + // to bad there's no windows xp styles for the checkboxes + m_settings->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); + m_settings->SetMinSize(wxSize(m_settings->GetSize().GetWidth() - 40, + m_settings->GetCount() * 15)); +#ifdef _WIN32 + //for (int i = 0; i < m_settings->GetCount(); ++i) + // m_settings->GetItem(i)->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); +#endif + m_checkSizer2->Add(m_settings, 0, 0, 0); + // ------------------------ + + + // -------------------------------------------------------------------- + // Buttons + // ------------------------ + m_Upd = new wxButton(m_PageMain, ID_UPD, wxT("Update"), + wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_SelC = new wxButton(m_PageMain, ID_SELC, wxT("Select Columns"), + wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_SelC->Enable(false); + m_Presets = new wxButton(m_PageMain, ID_PRESETS, wxT("Presets"), + wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_Presets->Enable(false); + // -------------------------------------------------------------------- + + + // -------------------------------------------------------------------- + // Left buttons and checkboxes (MAIN + // ------------------------ + wxBoxSizer* sButtons; + sButtons = new wxBoxSizer(wxVERTICAL); + + sButtons->AddSpacer(5); // to set a minimum margin + + sButtons->Add(m_Upd, 0, 0, 5); + sButtons->Add(m_SelC, 0, 0, 5); + sButtons->Add(m_Presets, 0, 0, 5); + + sButtons->AddStretchSpacer(1); + sButtons->Add(m_checkSizer, 0, 0, 5); + sButtons->AddStretchSpacer(1); + sButtons->Add(m_showallSizer, 0, 0, 5); + sButtons->AddStretchSpacer(1); + sButtons->Add(m_RadioBox[0], 0, 0, 5); + + sButtons->AddSpacer(5); + // ------------------------ + + + // -------------------------------------------------------------------- + // Right buttons and checkboxes (MAIN) + // ------------------------ + wxBoxSizer* sButtons2; + sButtons2 = new wxBoxSizer(wxVERTICAL); + + sButtons2->AddStretchSpacer(1); + sButtons2->Add(m_RadioBox[1], 0, 0, 5); // Update freq. + sButtons2->AddStretchSpacer(1); + sButtons2->Add(m_RadioBox[2], 0, 0, 5); + sButtons2->AddStretchSpacer(1); + sButtons2->Add(m_checkSizer2, 0, 0, 5); + sButtons2->AddStretchSpacer(1); + // ------------------------ + + + // -------------------------------------------------------------------- + // Parameter tables view (MAIN) + sLeft = new wxStaticBoxSizer(wxVERTICAL, m_PageMain, wxT("Current Status")); + + // The big window that holds the parameter tables + m_GPRListView = new CPBView(m_PageMain, ID_GPR, wxDefaultPosition, GetSize(), + wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT | wxLC_SINGLE_SEL | wxLC_SORT_ASCENDING); + + sLeft->Add(m_GPRListView, 1, wxEXPAND|wxALL, 5); + + sMain = new wxBoxSizer(wxHORIZONTAL); + sMain->Add(sLeft, 1, wxEXPAND | wxALL, 5); // margin = 5 + sMain->Add(sButtons, 0, wxALL, 0); + sMain->Add(sButtons2, 0, wxALL, 5); // margin = 5 + // -------------------------------------------------------------------- + + + // -------------------------------------------------------------------- + // Add all stuff to the mail container (MAIL) + // ----------------------------- + // For the buttons on the right + wxBoxSizer * sMailRight = new wxBoxSizer(wxVERTICAL); + //wxStaticBoxSizer * sMailRight = new wxStaticBoxSizer(wxVERTICAL, m_PageMail, wxT("Current")); + + _sMail = new wxBoxSizer(wxHORIZONTAL); + _sMail->Add(m_m1Sizer, 0, wxEXPAND | (wxUP | wxDOWN), 5); // margin = 5 + _sMail->Add(m_m2Sizer, 1, wxEXPAND | (wxUP | wxDOWN | wxLEFT), 5); // margin = 5 + _sMail->Add(sMailRight, 0, wxEXPAND | wxALL, 0); // margin = 0 + + sMailRight->Add(m_RadioBox[3], 0, wxALL, 5); // margin = 5 + sMailRight->Add(m_gameSizer1, 1, wxEXPAND | wxALL, 5); // margin = 5 + sMailRight->Add(m_gameSizer2, 1, wxEXPAND | wxALL, 5); // margin = 5 + sMailRight->Add(m_gameSizer3, 0, wxALL, 5); // margin = 5 + // -------------------------------------------------------------------- + + + // -------------------------------------------------------------------- + // The blocks view container (BLOCKS) + // ----------------------------- + // For the buttons on the right + //wxBoxSizer * sMailRight = new wxBoxSizer(wxVERTICAL); + //wxStaticBoxSizer * sMailRight = new wxStaticBoxSizer(wxVERTICAL, m_PageMail, wxT("Current")); + + sBlock = new wxBoxSizer(wxHORIZONTAL); + sBlock->Add(m_bl0Sizer, 0, wxEXPAND | (wxUP | wxDOWN), 5); // margin = 5 + sBlock->Add(m_bl1Sizer, 1, wxEXPAND | (wxUP | wxDOWN | wxLEFT), 5); // margin = 5 + sBlock->Add(m_bl2Sizer, 1, wxEXPAND | (wxUP | wxDOWN | wxRIGHT), 5); // margin = 5 + //sBlock->Add(sMailRight, 0, wxEXPAND | wxALL, 0); // margin = 0 + + /*sMailRight->Add(m_RadioBox[3], 0, wxALL, 5); // margin = 5 + sMailRight->Add(m_gameSizer1, 1, wxEXPAND | wxALL, 5); // margin = 5 + sMailRight->Add(m_gameSizer2, 1, wxEXPAND | wxALL, 5); // margin = 5 + sMailRight->Add(m_gameSizer3, 0, wxALL, 5); // margin = 5*/ + // -------------------------------------------------------------------- + + + // -------------------------------------------------------------------- + // Main containers + // ----------------------------- + sMAIN = new wxBoxSizer(wxVERTICAL); + sMAIN->Add(m_Notebook, 1, wxEXPAND | wxALL, 5); + //sMAIN->SetSizeHints(this); + + m_PageMain->SetSizer(sMain); + m_PageMail->SetSizer(_sMail); + m_PageBlock->SetSizer(sBlock); + //sMain->Layout(); + + this->SetSizer(sMAIN); + //this->Layout(); + + NotifyUpdate(); + // -------------------------------------------------------------------- +} + +// ======================================================================== +// System functions +// -------------- +void CDebugger::OnClose(wxCloseEvent& /*event*/) +{ + // save the window position when we hide the window to + IniFile file; + file.Load(DEBUGGER_CONFIG_FILE); + this->Save(file); + file.Save(DEBUGGER_CONFIG_FILE); + + EndModal(0); + CloseConsole(); // Take the console window with it +} + +void CDebugger::DoHide() +{ + Hide(); + CloseConsole(); // The console goes with the wx window +} + +void CDebugger::DoShow() +{ + Show(); + DoShowHideConsole(); // The console goes with the wx window +} + +void CDebugger::OnUpdate(wxCommandEvent& /*event*/) +{ + this->NotifyUpdate(); +} +// =============== + + +// ======================================================================================= +// Settings +// -------------- +void CDebugger::OnSettingsCheck(wxCommandEvent& event) +{ + gSSBM = m_settings->IsChecked(0); + gSSBMremedy1 = m_settings->IsChecked(1); + gSSBMremedy2 = m_settings->IsChecked(2); + gSequenced = m_settings->IsChecked(3); + gVolume = m_settings->IsChecked(4); + gReset = m_settings->IsChecked(5); + +} +// ======================================================================================= + + +// ======================================================================================= +// Change preset +// -------------- +void CDebugger::ChangePreset(wxCommandEvent& event) +{ + DoChangePreset(); +} + +void CDebugger::DoChangePreset() +{ + if(m_RadioBox[2]->GetSelection() == 0) + gPreset = 0; + else if(m_RadioBox[2]->GetSelection() == 1) + gPreset = 1; + else if(m_RadioBox[2]->GetSelection() == 2) + gPreset = 2; + else if(m_RadioBox[2]->GetSelection() == 3) + gPreset = 3; +} +// ============== + + +// ======================================================================================= +// Show base +// -------------- +void CDebugger::ShowBase(wxCommandEvent& event) +{ + if(m_RadioBox[0]->GetSelection() == 0) + bShowBase = true; + else if(m_RadioBox[0]->GetSelection() == 1) + bShowBase = false; +} +// ============== + + +// ======================================================================================= +// Change update frequency +// -------------- +void CDebugger::ChangeFrequency(wxCommandEvent& event) +{ + DoChangeFrequency(); +} + +void CDebugger::DoChangeFrequency() +{ + if(m_RadioBox[1]->GetSelection() == 0) + gUpdFreq = 0; + else if(m_RadioBox[1]->GetSelection() == 1) + gUpdFreq = 5; + else if(m_RadioBox[1]->GetSelection() == 2) + gUpdFreq = 15; + else if(m_RadioBox[1]->GetSelection() == 3) + gUpdFreq = 30; +} +// ============== + + +// ======================================================================================= +// Options +// -------------- +void CDebugger::OnOptions(wxCommandEvent& event) +{ + gSaveFile = m_options->IsChecked(0); + gOnlyLooping = m_options->IsChecked(1); + gShowAll = m_options->IsChecked(2); + gSaveFile = m_options->IsChecked(3); + + if(event.GetInt() == 3) DoShowHideConsole(); +} + +void CDebugger::OnShowAll(wxCommandEvent& event) +{ + /// Only allow one selection at a time + for (u32 i = 0; i < m_opt_showall->GetCount(); ++i) + if(i != (u32)event.GetInt()) m_opt_showall->Check(i, false); + + if(m_opt_showall->IsChecked(0)) giShowAll = 0; + else if(m_opt_showall->IsChecked(1)) giShowAll = 1; + else if(m_opt_showall->IsChecked(2)) giShowAll = 2; + else if(m_opt_showall->IsChecked(3)) giShowAll = 3; + else giShowAll = -1; +} + +// -------------- + + +// ======================================================================================= +// Show or hide console window +// -------------- +void CDebugger::ShowHideConsole(wxCommandEvent& event) +{ + DoShowHideConsole(); +} + +void CDebugger::DoShowHideConsole() +{ + if(m_options->IsChecked(3)) + OpenConsole(); + else + CloseConsole(); +} +// ============== + + +void CDebugger::NotifyUpdate() +{ + if (m_GPRListView != NULL) + { + m_GPRListView->Update(); + } +} + diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/Debugger/Mails.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/Debugger/Mails.cpp index fa06a9f7dd..0e34eab079 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/Debugger/Mails.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/Debugger/Mails.cpp @@ -1,288 +1,288 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// -// Licensetype: GNU General Public License (GPL) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. -// -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ -// -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ -// -////////////////////////////////////////////////////////////////////////////////////////// - -// includes -#include -#include -#include - -#ifndef _WIN32 -#include -#endif - -#include "Debugger.h" -#include "PBView.h" -#include "IniFile.h" -#include "FileUtil.h" -#include "StringUtil.h" -#include "FileSearch.h" -#include "../Logging/Console.h" // open and close console - -extern std::vector sMailLog, sMailTime; -extern CDebugger* m_frame; - -// ======================================================================================= -// Update mail window -// -------------- -void CDebugger::DoUpdateMail() -{ - //wprintf("i %i %i\n", sFullMail.size(), sMailLog.size()); - - if(sFullMail.size() > 0 && sMailLog.size() > 0) - { - m_log->SetValue(wxString::FromAscii(sFullMail.at(m_RadioBox[3]->GetSelection()).c_str())); - m_log->SetDefaultStyle(wxTextAttr(*wxBLUE)); // doesn't work because of the current wx - - m_log1->SetValue(wxString::FromAscii(sMailLog.at(m_RadioBox[3]->GetSelection()).c_str())); - m_log1->AppendText(wxT("\n\n")); - } -} - - -void CDebugger::UpdateMail(wxNotebookEvent& event) -{ - DoUpdateMail(); - /* This may be called before m_frame is fully created through the - EVT_NOTEBOOK_PAGE_CHANGED, in that case it will crash because this - is accessing members of it */ - if(StoreMails && m_frame) ReadDir(); -} - -// Change mail from radio button change -void CDebugger::ChangeMail(wxCommandEvent& event) -{ - //wprintf("abc"); - DoUpdateMail(); - //if(StoreMails) ReadDir(); -} -// ============== - - - -// ======================================================================================= -// Read out mails from dir -// -------------- -void CDebugger::ReadDir() -{ - CFileSearch::XStringVector Directories; - //Directories.push_back("Logs/Mail"); - Directories.push_back(FULL_MAIL_LOGS_DIR); - - CFileSearch::XStringVector Extensions; - Extensions.push_back("*.log"); - - CFileSearch FileSearch(Extensions, Directories); - const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames(); - - //m_gc->Show(false); - //m_gc->Append(wxT("SSBM ffffix")); - //m_gc->Show(true); - - // Clear in case we already did this earlier - all_all_files.clear(); - - if (rFilenames.size() > 0 && m_gc && m_wii) - { - for (u32 i = 0; i < rFilenames.size(); i++) - { - std::string FileName; - SplitPath(rFilenames[i], NULL, &FileName, NULL); // place the filename in FileName - - //std::string FileName = StripSpaces(*FileName); - std::vector pieces; - SplitString(FileName, "_sep", pieces); // split string - - // Save all filenames heres - if(pieces[2] == "0") all_all_files.push_back(pieces[0]); - - // Cut to size - std::string cut; - if(pieces[0].length() > 18) - cut = pieces[0].substr(0, 18) + "..."; - else - cut = pieces[0]; - - //wprintf("%s %s %s\n", pieces[0].c_str(), pieces[1].c_str(), - // pieces[2].c_str(), pieces[3].c_str()); - - if (NoDuplicate(pieces[0]) && pieces.size() >= 3) - { - all_files.push_back(pieces[0]); - if (pieces[3] == "GC") - { - gc_files.push_back(pieces[0]); - m_gc->Append(wxString::FromAscii(cut.c_str())); - } - else - { - wii_files.push_back(pieces[0]); - m_wii->Append(wxString::FromAscii(cut.c_str())); - } - } - } - } -} - - - -// ======================================================================================= -// Check for duplicates and count files from all_all_files -// -------------- -bool CDebugger::NoDuplicate(std::string FileName) -{ - for (u32 i = 0; i < all_files.size(); i++) - { - if(all_files.at(i) == FileName) - return false; - } - return true; -} - -// Count the number of files for each game -u32 CDebugger::CountFiles(std::string FileName) -{ - int match = 0; - - for (u32 i = 0; i < all_all_files.size(); i++) - { - //wprintf("CountFiles %i %s\n", i, all_all_files[i].c_str()); - if(all_all_files[i] == FileName) - match++; - } - //wprintf("We found %i files for this game\n", match); - return match; -} -// ============== - - -// ======================================================================================= -// Read file from harddrive -// -------------- -std::string CDebugger::Readfile_(std::string FileName) -{ - char c; // declare a char variable - FILE *file; // declare a FILE pointer - std::string sz = ""; - - if(File::Exists(FileName.c_str())) - file = fopen(FileName.c_str(), "r"); // open a text file for reading - else - return ""; - - if(file == NULL) - { - // file could not be opened - } - else - { - while(1) // looping through file - { - c = fgetc(file); - - if(c != EOF) - sz += c; // print the file one character at a time - else - break; // break when EOF is reached - } - - fclose(file); - } - return sz; -} - -// Read file -void CDebugger::Readfile(std::string FileName, bool GC) -{ - u32 n = CountFiles(FileName); // count how many mails we have - u32 curr_n = 0; - std::ifstream file; - for (u32 i = 0; i < m_RadioBox[3]->GetCount(); i++) - { - if(m_RadioBox[3]->IsItemEnabled(i)) curr_n++; - m_RadioBox[3]->Enable(i, false); // disable all - } - //wprintf("Disabled all: n %i\n", n); - - - for (u32 i = 0; i < n; i++) - { - m_RadioBox[3]->Enable(i, true); // then anble the right ones - //wprintf("m_RadioBox[3] enabled: %i\n", i); - - std::string sz = ""; - std::ostringstream ci; - ci << i; - std::string f0 = FULL_MAIL_LOGS_DIR + FileName + "_sep" + ci.str() + "_sep" + "0_sep" + (GC ? "GC" : "Wii") + "_sep.log"; - std::string f1 = FULL_MAIL_LOGS_DIR + FileName + "_sep" + ci.str() + "_sep" + "1_sep" + (GC ? "GC" : "Wii") + "_sep.log"; - - //wprintf("ifstream %s %s\n", f0.c_str(), f1.c_str()); - - if(sFullMail.size() <= i) sFullMail.resize(sFullMail.size() + 1); - if(sMailLog.size() <= i) sMailLog.resize(sMailLog.size() + 1); - - if(Readfile_(f0).length() > 0) sFullMail.at(i) = Readfile_(f0); - else sFullMail.at(i) = ""; - if(Readfile_(f1).length() > 0) sMailLog.at(i) = Readfile_(f1); - else sMailLog.at(i) = ""; - } - if(n < curr_n) m_RadioBox[3]->Select(n - 1); - //wprintf("Select: %i | n %i curr_n %i\n", n - 1, n, curr_n); - DoUpdateMail(); -} -// ============== - - -// ======================================================================================= -// Read the file to the text window -// --------------- -void CDebugger::OnGameChange(wxCommandEvent& event) -{ - if(event.GetId() == 2006) - { - // Only allow one selected game at a time - for (u32 i = 0; i < m_gc->GetCount(); ++i) - if(i != (u32)event.GetInt()) m_gc->Check(i, false); - for (u32 i = 0; i < m_wii->GetCount(); ++i) - m_wii->Check(i, false); - Readfile(gc_files[event.GetInt()], true); - } - else - { - for (u32 i = 0; i < m_gc->GetCount(); ++i) - m_gc->Check(i, false); - for (u32 i = 0; i < m_wii->GetCount(); ++i) - if(i != (u32)event.GetInt()) m_wii->Check(i, false); - Readfile(wii_files[event.GetInt()], false); - } -} - -// Settings -void CDebugger::MailSettings(wxCommandEvent& event) -{ - //for (int i = 0; i < all_all_files.size(); ++i) - //wprintf("s: %s \n", all_all_files.at(i).c_str()); - - ScanMails = m_gcwiiset->IsChecked(0); - StoreMails = m_gcwiiset->IsChecked(1); -} - - - +////////////////////////////////////////////////////////////////////////////////////////// +// +// Licensetype: GNU General Public License (GPL) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. +// +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ +// +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +// +////////////////////////////////////////////////////////////////////////////////////////// + +// includes +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +#include "Debugger.h" +#include "PBView.h" +#include "IniFile.h" +#include "FileUtil.h" +#include "StringUtil.h" +#include "FileSearch.h" +#include "../Logging/Console.h" // open and close console + +extern std::vector sMailLog, sMailTime; +extern CDebugger* m_frame; + +// ======================================================================================= +// Update mail window +// -------------- +void CDebugger::DoUpdateMail() +{ + //wprintf("i %i %i\n", sFullMail.size(), sMailLog.size()); + + if(sFullMail.size() > 0 && sMailLog.size() > 0) + { + m_log->SetValue(wxString::FromAscii(sFullMail.at(m_RadioBox[3]->GetSelection()).c_str())); + m_log->SetDefaultStyle(wxTextAttr(*wxBLUE)); // doesn't work because of the current wx + + m_log1->SetValue(wxString::FromAscii(sMailLog.at(m_RadioBox[3]->GetSelection()).c_str())); + m_log1->AppendText(wxT("\n\n")); + } +} + + +void CDebugger::UpdateMail(wxNotebookEvent& event) +{ + DoUpdateMail(); + /* This may be called before m_frame is fully created through the + EVT_NOTEBOOK_PAGE_CHANGED, in that case it will crash because this + is accessing members of it */ + if(StoreMails && m_frame) ReadDir(); +} + +// Change mail from radio button change +void CDebugger::ChangeMail(wxCommandEvent& event) +{ + //wprintf("abc"); + DoUpdateMail(); + //if(StoreMails) ReadDir(); +} +// ============== + + + +// ======================================================================================= +// Read out mails from dir +// -------------- +void CDebugger::ReadDir() +{ + CFileSearch::XStringVector Directories; + //Directories.push_back("Logs/Mail"); + Directories.push_back(FULL_MAIL_LOGS_DIR); + + CFileSearch::XStringVector Extensions; + Extensions.push_back("*.log"); + + CFileSearch FileSearch(Extensions, Directories); + const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames(); + + //m_gc->Show(false); + //m_gc->Append(wxT("SSBM ffffix")); + //m_gc->Show(true); + + // Clear in case we already did this earlier + all_all_files.clear(); + + if (rFilenames.size() > 0 && m_gc && m_wii) + { + for (u32 i = 0; i < rFilenames.size(); i++) + { + std::string FileName; + SplitPath(rFilenames[i], NULL, &FileName, NULL); // place the filename in FileName + + //std::string FileName = StripSpaces(*FileName); + std::vector pieces; + SplitString(FileName, "_sep", pieces); // split string + + // Save all filenames heres + if(pieces[2] == "0") all_all_files.push_back(pieces[0]); + + // Cut to size + std::string cut; + if(pieces[0].length() > 18) + cut = pieces[0].substr(0, 18) + "..."; + else + cut = pieces[0]; + + //wprintf("%s %s %s\n", pieces[0].c_str(), pieces[1].c_str(), + // pieces[2].c_str(), pieces[3].c_str()); + + if (NoDuplicate(pieces[0]) && pieces.size() >= 3) + { + all_files.push_back(pieces[0]); + if (pieces[3] == "GC") + { + gc_files.push_back(pieces[0]); + m_gc->Append(wxString::FromAscii(cut.c_str())); + } + else + { + wii_files.push_back(pieces[0]); + m_wii->Append(wxString::FromAscii(cut.c_str())); + } + } + } + } +} + + + +// ======================================================================================= +// Check for duplicates and count files from all_all_files +// -------------- +bool CDebugger::NoDuplicate(std::string FileName) +{ + for (u32 i = 0; i < all_files.size(); i++) + { + if(all_files.at(i) == FileName) + return false; + } + return true; +} + +// Count the number of files for each game +u32 CDebugger::CountFiles(std::string FileName) +{ + int match = 0; + + for (u32 i = 0; i < all_all_files.size(); i++) + { + //wprintf("CountFiles %i %s\n", i, all_all_files[i].c_str()); + if(all_all_files[i] == FileName) + match++; + } + //wprintf("We found %i files for this game\n", match); + return match; +} +// ============== + + +// ======================================================================================= +// Read file from harddrive +// -------------- +std::string CDebugger::Readfile_(std::string FileName) +{ + char c; // declare a char variable + FILE *file; // declare a FILE pointer + std::string sz = ""; + + if(File::Exists(FileName.c_str())) + file = fopen(FileName.c_str(), "r"); // open a text file for reading + else + return ""; + + if(file == NULL) + { + // file could not be opened + } + else + { + while(1) // looping through file + { + c = fgetc(file); + + if(c != EOF) + sz += c; // print the file one character at a time + else + break; // break when EOF is reached + } + + fclose(file); + } + return sz; +} + +// Read file +void CDebugger::Readfile(std::string FileName, bool GC) +{ + u32 n = CountFiles(FileName); // count how many mails we have + u32 curr_n = 0; + std::ifstream file; + for (u32 i = 0; i < m_RadioBox[3]->GetCount(); i++) + { + if(m_RadioBox[3]->IsItemEnabled(i)) curr_n++; + m_RadioBox[3]->Enable(i, false); // disable all + } + //wprintf("Disabled all: n %i\n", n); + + + for (u32 i = 0; i < n; i++) + { + m_RadioBox[3]->Enable(i, true); // then anble the right ones + //wprintf("m_RadioBox[3] enabled: %i\n", i); + + std::string sz = ""; + std::ostringstream ci; + ci << i; + std::string f0 = FULL_MAIL_LOGS_DIR + FileName + "_sep" + ci.str() + "_sep" + "0_sep" + (GC ? "GC" : "Wii") + "_sep.log"; + std::string f1 = FULL_MAIL_LOGS_DIR + FileName + "_sep" + ci.str() + "_sep" + "1_sep" + (GC ? "GC" : "Wii") + "_sep.log"; + + //wprintf("ifstream %s %s\n", f0.c_str(), f1.c_str()); + + if(sFullMail.size() <= i) sFullMail.resize(sFullMail.size() + 1); + if(sMailLog.size() <= i) sMailLog.resize(sMailLog.size() + 1); + + if(Readfile_(f0).length() > 0) sFullMail.at(i) = Readfile_(f0); + else sFullMail.at(i) = ""; + if(Readfile_(f1).length() > 0) sMailLog.at(i) = Readfile_(f1); + else sMailLog.at(i) = ""; + } + if(n < curr_n) m_RadioBox[3]->Select(n - 1); + //wprintf("Select: %i | n %i curr_n %i\n", n - 1, n, curr_n); + DoUpdateMail(); +} +// ============== + + +// ======================================================================================= +// Read the file to the text window +// --------------- +void CDebugger::OnGameChange(wxCommandEvent& event) +{ + if(event.GetId() == 2006) + { + // Only allow one selected game at a time + for (u32 i = 0; i < m_gc->GetCount(); ++i) + if(i != (u32)event.GetInt()) m_gc->Check(i, false); + for (u32 i = 0; i < m_wii->GetCount(); ++i) + m_wii->Check(i, false); + Readfile(gc_files[event.GetInt()], true); + } + else + { + for (u32 i = 0; i < m_gc->GetCount(); ++i) + m_gc->Check(i, false); + for (u32 i = 0; i < m_wii->GetCount(); ++i) + if(i != (u32)event.GetInt()) m_wii->Check(i, false); + Readfile(wii_files[event.GetInt()], false); + } +} + +// Settings +void CDebugger::MailSettings(wxCommandEvent& event) +{ + //for (int i = 0; i < all_all_files.size(); ++i) + //wprintf("s: %s \n", all_all_files.at(i).c_str()); + + ScanMails = m_gcwiiset->IsChecked(0); + StoreMails = m_gcwiiset->IsChecked(1); +} + + + diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/Debugger/PBView.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/Debugger/PBView.cpp index d8146720b9..f0a52c9e84 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/Debugger/PBView.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/Debugger/PBView.cpp @@ -1,168 +1,168 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -#include "PBView.h" - -#include -#include -#include -#include - - - - -// --------------------------------------------------------------------------------------- -// external declarations -extern const char* GetGRPName(unsigned int index); - -// No buttons or events so far -BEGIN_EVENT_TABLE(CPBView, wxListCtrl) - -END_EVENT_TABLE() -// --------------------------------------------------------------------------------------- - - - -CPBView::CPBView(wxWindow* parent, const wxWindowID id, const wxPoint& pos, const wxSize& size, long style) - : wxListCtrl(parent, id, pos, size, style) -{ - InsertColumn(1, wxT("upd4"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(1, wxT("upd3"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(1, wxT("upd2"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(1, wxT("upd1"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(1, wxT("upd0"), wxLIST_FORMAT_LEFT, 90); - - InsertColumn(1, wxT("r_lo"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(1, wxT("r_hi"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(1, wxT("ratio"), wxLIST_FORMAT_LEFT, 90); - - InsertColumn(1, wxT("frac"), wxLIST_FORMAT_LEFT, 90); - - InsertColumn(1, wxT("coef"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(1, wxT("src_t"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(1, wxT("form"), wxLIST_FORMAT_LEFT, 90); - - InsertColumn(1, wxT("isstr"), wxLIST_FORMAT_LEFT, 90); - - InsertColumn(1, wxT("yn2"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(1, wxT("yn1"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(1, wxT("pred_s"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(1, wxT("isloop"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(1, wxT("volr"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(1, wxT("voll"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(1, wxT("loopto"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(1, wxT("end"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(0, wxT("pos"), wxLIST_FORMAT_LEFT, 90); - InsertColumn(0, wxT("run"), wxLIST_FORMAT_RIGHT, 50); - InsertColumn(0, wxT("Block"), wxLIST_FORMAT_CENTER, 40); - - SetFont(wxFont(8, wxSWISS, wxNORMAL, wxNORMAL, false, wxT("Segoe UI"))); - - for (int i = 0; i < 64; i++) - { - - // Print values from 0 to 63 - char buffer [33]; - sprintf(buffer, "%02i", i); - int Item = InsertItem(0, wxString::FromAscii(buffer)); - - - wxListItem item; - item.SetId(Item); - item.SetBackgroundColour(0xFFFFFF); - item.SetData(i); - SetItem(item); - } - - // This is a wx call that leads to MSWDrawSubItem - Refresh(); -} - - -void -CPBView::Update() -{ - - Refresh(); - -} - - -bool -CPBView::MSWDrawSubItem(wxPaintDC& rPainDC, int item, int subitem) -{ - bool Result = false; - - // don't change 0, it has the block values - if(subitem > 0) - { - #ifdef __WXMSW__ // what's this? should I use that? - const wxChar* bgColor = _T("#ffffff"); - wxBrush bgBrush(bgColor); - wxPen bgPen(bgColor); - - wxRect SubItemRect; - this->GetSubItemRect(item, subitem, SubItemRect); - rPainDC.SetBrush(bgBrush); - rPainDC.SetPen(bgPen); - rPainDC.DrawRectangle(SubItemRect); - #endif - // A somewhat primitive attempt to show the playing history for a certain block. - - wxString text; - if(subitem == 1) - { - char cbuff [33]; - - sprintf(cbuff, "%08i", m_CachedRegs[subitem][item]); - std::string c = cbuff; - int n[8]; - - for (int j = 0; j < 8; j++) - { - - n[j] = atoi( c.substr(j, 1).c_str()); - // 149 = dot, 160 = space - if (n[j] == 1){ - n[j] = 149;} else {n[j] = 160;} - } - // pretty neat huh? - text.Printf(wxT("%c%c%c%c%c%c%c%c"), n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); - - } - else - { - text.Printf(wxT("0x%08x"), m_CachedRegs[subitem][item]); - } - #ifdef __WXMSW__ - rPainDC.DrawText(text, SubItemRect.GetLeft() + 10, SubItemRect.GetTop() + 4); - #else - // May not show up pretty in !Win32 - rPainDC.DrawText(text, 10, 4); - #endif - - return(true); - } - else - { - // what does this mean? - return(Result); - } -} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#include "PBView.h" + +#include +#include +#include +#include + + + + +// --------------------------------------------------------------------------------------- +// external declarations +extern const char* GetGRPName(unsigned int index); + +// No buttons or events so far +BEGIN_EVENT_TABLE(CPBView, wxListCtrl) + +END_EVENT_TABLE() +// --------------------------------------------------------------------------------------- + + + +CPBView::CPBView(wxWindow* parent, const wxWindowID id, const wxPoint& pos, const wxSize& size, long style) + : wxListCtrl(parent, id, pos, size, style) +{ + InsertColumn(1, wxT("upd4"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(1, wxT("upd3"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(1, wxT("upd2"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(1, wxT("upd1"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(1, wxT("upd0"), wxLIST_FORMAT_LEFT, 90); + + InsertColumn(1, wxT("r_lo"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(1, wxT("r_hi"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(1, wxT("ratio"), wxLIST_FORMAT_LEFT, 90); + + InsertColumn(1, wxT("frac"), wxLIST_FORMAT_LEFT, 90); + + InsertColumn(1, wxT("coef"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(1, wxT("src_t"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(1, wxT("form"), wxLIST_FORMAT_LEFT, 90); + + InsertColumn(1, wxT("isstr"), wxLIST_FORMAT_LEFT, 90); + + InsertColumn(1, wxT("yn2"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(1, wxT("yn1"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(1, wxT("pred_s"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(1, wxT("isloop"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(1, wxT("volr"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(1, wxT("voll"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(1, wxT("loopto"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(1, wxT("end"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(0, wxT("pos"), wxLIST_FORMAT_LEFT, 90); + InsertColumn(0, wxT("run"), wxLIST_FORMAT_RIGHT, 50); + InsertColumn(0, wxT("Block"), wxLIST_FORMAT_CENTER, 40); + + SetFont(wxFont(8, wxSWISS, wxNORMAL, wxNORMAL, false, wxT("Segoe UI"))); + + for (int i = 0; i < 64; i++) + { + + // Print values from 0 to 63 + char buffer [33]; + sprintf(buffer, "%02i", i); + int Item = InsertItem(0, wxString::FromAscii(buffer)); + + + wxListItem item; + item.SetId(Item); + item.SetBackgroundColour(0xFFFFFF); + item.SetData(i); + SetItem(item); + } + + // This is a wx call that leads to MSWDrawSubItem + Refresh(); +} + + +void +CPBView::Update() +{ + + Refresh(); + +} + + +bool +CPBView::MSWDrawSubItem(wxPaintDC& rPainDC, int item, int subitem) +{ + bool Result = false; + + // don't change 0, it has the block values + if(subitem > 0) + { + #ifdef __WXMSW__ // what's this? should I use that? + const wxChar* bgColor = _T("#ffffff"); + wxBrush bgBrush(bgColor); + wxPen bgPen(bgColor); + + wxRect SubItemRect; + this->GetSubItemRect(item, subitem, SubItemRect); + rPainDC.SetBrush(bgBrush); + rPainDC.SetPen(bgPen); + rPainDC.DrawRectangle(SubItemRect); + #endif + // A somewhat primitive attempt to show the playing history for a certain block. + + wxString text; + if(subitem == 1) + { + char cbuff [33]; + + sprintf(cbuff, "%08i", m_CachedRegs[subitem][item]); + std::string c = cbuff; + int n[8]; + + for (int j = 0; j < 8; j++) + { + + n[j] = atoi( c.substr(j, 1).c_str()); + // 149 = dot, 160 = space + if (n[j] == 1){ + n[j] = 149;} else {n[j] = 160;} + } + // pretty neat huh? + text.Printf(wxT("%c%c%c%c%c%c%c%c"), n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); + + } + else + { + text.Printf(wxT("0x%08x"), m_CachedRegs[subitem][item]); + } + #ifdef __WXMSW__ + rPainDC.DrawText(text, SubItemRect.GetLeft() + 10, SubItemRect.GetTop() + 4); + #else + // May not show up pretty in !Win32 + rPainDC.DrawText(text, 10, 4); + #endif + + return(true); + } + else + { + // what does this mean? + return(Result); + } +} + + diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/Globals.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/Globals.cpp index 685e12f79e..8e19c9fffb 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/Globals.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/Globals.cpp @@ -1,85 +1,85 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include -#include - -#include "Globals.h" -#include "Common.h" - -void __Log(int, const char *fmt, ...) -{ - DebugLog(fmt); -} - -void __Log_(int v, const char *fmt, ...) -{ - char Msg[512]; - va_list ap; - - va_start(ap, fmt); - vsprintf(Msg, fmt, ap); - va_end(ap); - - g_dspInitialize.pLog(Msg, v); -} - -void DebugLog(const char* _fmt, ...) -{ -#if defined(_DEBUG) || defined(DEBUGFAST) -//if(strncmp (_fmt, "AX", 2)) // match = 0, in that case this is ignored -{ - char Msg[512]; - va_list ap; - - va_start(ap, _fmt); - vsprintf(Msg, _fmt, ap); - va_end(ap); - - g_dspInitialize.pLog(Msg, 0); -} -#endif -} - -extern u8* g_pMemory; - -// TODO: Wii support? Most likely audio data still must be in the old 24MB TRAM. -#define RAM_MASK 0x1FFFFFF - -u8 Memory_Read_U8(u32 _uAddress) -{ - _uAddress &= RAM_MASK; - return g_pMemory[_uAddress]; -} - -u16 Memory_Read_U16(u32 _uAddress) -{ - _uAddress &= RAM_MASK; - return Common::swap16(*(u16*)&g_pMemory[_uAddress]); -} - -u32 Memory_Read_U32(u32 _uAddress) -{ - _uAddress &= RAM_MASK; - return Common::swap32(*(u32*)&g_pMemory[_uAddress]); -} - -float Memory_Read_Float(u32 _uAddress) -{ - u32 uTemp = Memory_Read_U32(_uAddress); - return *(float*)&uTemp; -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include +#include + +#include "Globals.h" +#include "Common.h" + +void __Log(int, const char *fmt, ...) +{ + DebugLog(fmt); +} + +void __Log_(int v, const char *fmt, ...) +{ + char Msg[512]; + va_list ap; + + va_start(ap, fmt); + vsprintf(Msg, fmt, ap); + va_end(ap); + + g_dspInitialize.pLog(Msg, v); +} + +void DebugLog(const char* _fmt, ...) +{ +#if defined(_DEBUG) || defined(DEBUGFAST) +//if(strncmp (_fmt, "AX", 2)) // match = 0, in that case this is ignored +{ + char Msg[512]; + va_list ap; + + va_start(ap, _fmt); + vsprintf(Msg, _fmt, ap); + va_end(ap); + + g_dspInitialize.pLog(Msg, 0); +} +#endif +} + +extern u8* g_pMemory; + +// TODO: Wii support? Most likely audio data still must be in the old 24MB TRAM. +#define RAM_MASK 0x1FFFFFF + +u8 Memory_Read_U8(u32 _uAddress) +{ + _uAddress &= RAM_MASK; + return g_pMemory[_uAddress]; +} + +u16 Memory_Read_U16(u32 _uAddress) +{ + _uAddress &= RAM_MASK; + return Common::swap16(*(u16*)&g_pMemory[_uAddress]); +} + +u32 Memory_Read_U32(u32 _uAddress) +{ + _uAddress &= RAM_MASK; + return Common::swap32(*(u32*)&g_pMemory[_uAddress]); +} + +float Memory_Read_Float(u32 _uAddress) +{ + u32 uTemp = Memory_Read_U32(_uAddress); + return *(float*)&uTemp; +} diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/Logging/Console.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/Logging/Console.cpp index b4656c4524..71c8e61a28 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/Logging/Console.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/Logging/Console.cpp @@ -1,226 +1,226 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -// -------------------- -// Includes -#include -#include -#ifdef _WIN32 -#include -#endif -#include "../Debugger/Debugger.h" - -extern CDebugger* m_frame; - -// -------------------- -// On and off -bool g_consoleEnable = true; -//int gSaveFile = 0; -#define DEBUG_HLE - - -// -------------------- -// Settings -int nFiles = 4; - - -// -------------------- -// Create handles - -#ifdef DEBUG_HLE - FILE* __fStdOut[4]; // you have to update this manually, we can't place a nFiles in there -#endif -#ifdef _WIN32 - HANDLE __hStdOut = NULL; -#endif - - -// ======================================================================================= -/* Start console window - width and height is the size of console window, if you specify -fname, the output will also be written to this file. TODO: Close the file pointer when the app -is closed */ -// ------------- -void startConsoleWin(int width, int height, char* fname) -{ -#if defined(DEBUG_HLE) && defined(_WIN32) - - AllocConsole(); - - SetConsoleTitle(fname); - __hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); - - COORD co = {width,height}; - SetConsoleScreenBufferSize(__hStdOut, co); - - SMALL_RECT coo = {0,0,(width - 1),70}; // top, left, right, bottom - SetConsoleWindowInfo(__hStdOut, TRUE, &coo); - - // --------------------------------------------------------------------------------------- - // Write to a file - if(fname) - { - for(int i = 0; i < nFiles; i++) - { - // Edit the log file name - std::string FileEnding = ".log"; - std::string FileName = fname; - char buffer[33]; itoa(i, buffer, 10); // convert number to string - std::string FullFilename = (FileName + buffer + FileEnding); - __fStdOut[i] = fopen(FullFilename.c_str(), "w"); - } - } - // --------------- - -#endif -} - - -// --------------------------------------------------------------------------------------- -// File printf function -int aprintf(int a, char *fmt, ...) -{ -#if defined(DEBUG_HLE) && defined(_WIN32) - - if(m_frame->gSaveFile) - { - char s[5000]; // WARNING: mind this value - va_list argptr; - int cnt; - - va_start(argptr, fmt); - cnt = vsnprintf(s, 5000, fmt, argptr); // remember to update this value to - va_end(argptr); - - // --------------------------------------------------------------------------------------- - if(__fStdOut[a]) // TODO: make this work, we have to set all default values to NULL - //to make it work - fprintf(__fStdOut[a], s); - // ------------- - - return(cnt); - } - else - { - return 0; - } -#else - return 0; -#endif -} - - - -// --------------------------------------------------------------------------------------- -// Printf to screen function -int wprintf(const char *fmt, ...) -{ -#if defined(DEBUG_HLE) && defined(_WIN32) - char s[1024*20]; // Warning, mind this value - va_list argptr; - int cnt; - - va_start(argptr, fmt); - cnt = vsnprintf(s, 1024*20, fmt, argptr); - va_end(argptr); - - DWORD cCharsWritten; - - // --------------------------------------------------------------------------------------- - if(__hStdOut) - { - WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL); - } - // ------------- - - return(cnt); -#else - return 0; -#endif -} - - -// --------------------------------------------------------------------------------------- -// Clear console screen -void ClearScreen() -{ -#if defined(DEBUG_HLE) && defined(_WIN32) - if(g_consoleEnable) - { - COORD coordScreen = { 0, 0 }; - DWORD cCharsWritten; - CONSOLE_SCREEN_BUFFER_INFO csbi; - DWORD dwConSize; - - HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - - GetConsoleScreenBufferInfo(hConsole, &csbi); - dwConSize = csbi.dwSize.X * csbi.dwSize.Y; - FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, - coordScreen, &cCharsWritten); - GetConsoleScreenBufferInfo(hConsole, &csbi); - FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, - coordScreen, &cCharsWritten); - SetConsoleCursorPosition(hConsole, coordScreen); - } -#endif -} - - -// --------------------------------------------------------------------------------------- -// Get window handle of console window to be able to resize it -#if defined(DEBUG_HLE) && defined(_WIN32) -HWND GetConsoleHwnd(void) -{ - - #define MY_BUFSIZE 1024 // Buffer size for console window titles. - HWND hwndFound; // This is what is returned to the caller. - char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated - // WindowTitle. - char pszOldWindowTitle[MY_BUFSIZE]; // Contains original - // WindowTitle. - - // Fetch current window title. - - GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE); - - // Format a "unique" NewWindowTitle. - - wsprintf(pszNewWindowTitle,"%d/%d", - GetTickCount(), - GetCurrentProcessId()); - - // Change current window title. - - SetConsoleTitle(pszNewWindowTitle); - - // Ensure window title has been updated. - - Sleep(40); - - // Look for NewWindowTitle. - - hwndFound = FindWindow(NULL, pszNewWindowTitle); - - // Restore original window title. - - SetConsoleTitle(pszOldWindowTitle); - - return(hwndFound); - -} -#endif // win32 +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +// -------------------- +// Includes +#include +#include +#ifdef _WIN32 +#include +#endif +#include "../Debugger/Debugger.h" + +extern CDebugger* m_frame; + +// -------------------- +// On and off +bool g_consoleEnable = true; +//int gSaveFile = 0; +#define DEBUG_HLE + + +// -------------------- +// Settings +int nFiles = 4; + + +// -------------------- +// Create handles + +#ifdef DEBUG_HLE + FILE* __fStdOut[4]; // you have to update this manually, we can't place a nFiles in there +#endif +#ifdef _WIN32 + HANDLE __hStdOut = NULL; +#endif + + +// ======================================================================================= +/* Start console window - width and height is the size of console window, if you specify +fname, the output will also be written to this file. TODO: Close the file pointer when the app +is closed */ +// ------------- +void startConsoleWin(int width, int height, char* fname) +{ +#if defined(DEBUG_HLE) && defined(_WIN32) + + AllocConsole(); + + SetConsoleTitle(fname); + __hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + + COORD co = {width,height}; + SetConsoleScreenBufferSize(__hStdOut, co); + + SMALL_RECT coo = {0,0,(width - 1),70}; // top, left, right, bottom + SetConsoleWindowInfo(__hStdOut, TRUE, &coo); + + // --------------------------------------------------------------------------------------- + // Write to a file + if(fname) + { + for(int i = 0; i < nFiles; i++) + { + // Edit the log file name + std::string FileEnding = ".log"; + std::string FileName = fname; + char buffer[33]; itoa(i, buffer, 10); // convert number to string + std::string FullFilename = (FileName + buffer + FileEnding); + __fStdOut[i] = fopen(FullFilename.c_str(), "w"); + } + } + // --------------- + +#endif +} + + +// --------------------------------------------------------------------------------------- +// File printf function +int aprintf(int a, char *fmt, ...) +{ +#if defined(DEBUG_HLE) && defined(_WIN32) + + if(m_frame->gSaveFile) + { + char s[5000]; // WARNING: mind this value + va_list argptr; + int cnt; + + va_start(argptr, fmt); + cnt = vsnprintf(s, 5000, fmt, argptr); // remember to update this value to + va_end(argptr); + + // --------------------------------------------------------------------------------------- + if(__fStdOut[a]) // TODO: make this work, we have to set all default values to NULL + //to make it work + fprintf(__fStdOut[a], s); + // ------------- + + return(cnt); + } + else + { + return 0; + } +#else + return 0; +#endif +} + + + +// --------------------------------------------------------------------------------------- +// Printf to screen function +int wprintf(const char *fmt, ...) +{ +#if defined(DEBUG_HLE) && defined(_WIN32) + char s[1024*20]; // Warning, mind this value + va_list argptr; + int cnt; + + va_start(argptr, fmt); + cnt = vsnprintf(s, 1024*20, fmt, argptr); + va_end(argptr); + + DWORD cCharsWritten; + + // --------------------------------------------------------------------------------------- + if(__hStdOut) + { + WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL); + } + // ------------- + + return(cnt); +#else + return 0; +#endif +} + + +// --------------------------------------------------------------------------------------- +// Clear console screen +void ClearScreen() +{ +#if defined(DEBUG_HLE) && defined(_WIN32) + if(g_consoleEnable) + { + COORD coordScreen = { 0, 0 }; + DWORD cCharsWritten; + CONSOLE_SCREEN_BUFFER_INFO csbi; + DWORD dwConSize; + + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + + GetConsoleScreenBufferInfo(hConsole, &csbi); + dwConSize = csbi.dwSize.X * csbi.dwSize.Y; + FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, + coordScreen, &cCharsWritten); + GetConsoleScreenBufferInfo(hConsole, &csbi); + FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, + coordScreen, &cCharsWritten); + SetConsoleCursorPosition(hConsole, coordScreen); + } +#endif +} + + +// --------------------------------------------------------------------------------------- +// Get window handle of console window to be able to resize it +#if defined(DEBUG_HLE) && defined(_WIN32) +HWND GetConsoleHwnd(void) +{ + + #define MY_BUFSIZE 1024 // Buffer size for console window titles. + HWND hwndFound; // This is what is returned to the caller. + char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated + // WindowTitle. + char pszOldWindowTitle[MY_BUFSIZE]; // Contains original + // WindowTitle. + + // Fetch current window title. + + GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE); + + // Format a "unique" NewWindowTitle. + + wsprintf(pszNewWindowTitle,"%d/%d", + GetTickCount(), + GetCurrentProcessId()); + + // Change current window title. + + SetConsoleTitle(pszNewWindowTitle); + + // Ensure window title has been updated. + + Sleep(40); + + // Look for NewWindowTitle. + + hwndFound = FindWindow(NULL, pszNewWindowTitle); + + // Restore original window title. + + SetConsoleTitle(pszOldWindowTitle); + + return(hwndFound); + +} +#endif // win32 diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/Logging/Logging.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/Logging/Logging.cpp index e255b21e23..d05511da38 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/Logging/Logging.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/Logging/Logging.cpp @@ -1,951 +1,951 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// -// Licensetype: GNU General Public License (GPL) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. -// -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ -// -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ -// -////////////////////////////////////////////////////////////////////////////////////////// - - - -// Includes - -#include -#include -#include // so that we can test std::string == abc -#include // for the pow() function -#ifdef _WIN32 - #include -#endif - -#include "StringUtil.h" - -#include "../Debugger/Debugger.h" -#include "../Debugger/PBView.h" -#include "Console.h" // open and close console, clear console window - -#include "../Globals.h" -#include "../UCodes/UCodes.h" -#include "../UCodes/UCode_AXStructs.h" -#include "../UCodes/UCode_AX.h" -#include "../UCodes/UCode_AXWii.h" -#include "../UCodes/UCode_AX_Voice.h" - -// Externals - -extern bool gSSBM; -extern bool gSSBMremedy1; -extern bool gSSBMremedy2; -extern bool gSequenced; -extern bool gVolume; -extern bool gReset; -extern int nFiles; -float ratioFactor; // a global to get the ratio factor from MixAdd -extern CDebugger* m_frame; -//int PBSize = 128; - -// Parameter blocks - - std::vector mem(NUMBER_OF_PBS); // mem1 or mem2 - std::vector gloopPos(NUMBER_OF_PBS); - std::vector gsampleEnd(NUMBER_OF_PBS); - std::vector gsamplePos(NUMBER_OF_PBS); - -// main - std::vector running(NUMBER_OF_PBS, 0); - std::vector gsrc_type(NUMBER_OF_PBS); - std::vector gis_stream(NUMBER_OF_PBS); - -// PBSampleRateConverter src - std::vector gratio(NUMBER_OF_PBS); - std::vector gratiohi(NUMBER_OF_PBS); - std::vector gratiolo(NUMBER_OF_PBS); - std::vector gfrac(NUMBER_OF_PBS); - std::vector gcoef(NUMBER_OF_PBS); - -// PBSampleRateConverter mixer - std::vector gvolume_left(NUMBER_OF_PBS); - std::vector gmix_unknown(NUMBER_OF_PBS); - std::vector gvolume_right(NUMBER_OF_PBS); - std::vector gmix_unknown2(NUMBER_OF_PBS); - std::vector gmixer_control(NUMBER_OF_PBS); - std::vector gmixer_control_wii(NUMBER_OF_PBS); - - std::vector gmixer_vol1(NUMBER_OF_PBS); - std::vector gmixer_vol2(NUMBER_OF_PBS); - std::vector gmixer_vol3(NUMBER_OF_PBS); - std::vector gmixer_vol4(NUMBER_OF_PBS); - std::vector gmixer_vol5(NUMBER_OF_PBS); - std::vector gmixer_vol6(NUMBER_OF_PBS); - std::vector gmixer_vol7(NUMBER_OF_PBS); - - std::vector gmixer_d1(NUMBER_OF_PBS); - std::vector gmixer_d2(NUMBER_OF_PBS); - std::vector gmixer_d3(NUMBER_OF_PBS); - std::vector gmixer_d4(NUMBER_OF_PBS); - std::vector gmixer_d5(NUMBER_OF_PBS); - std::vector gmixer_d6(NUMBER_OF_PBS); - std::vector gmixer_d7(NUMBER_OF_PBS); - -// PBVolumeEnvelope vol_env - std::vector gcur_volume(NUMBER_OF_PBS); - std::vector gcur_volume_delta(NUMBER_OF_PBS); - -// PBAudioAddr audio_addr (incl looping) - std::vector gaudioFormat(NUMBER_OF_PBS); - std::vector glooping(NUMBER_OF_PBS); - std::vector gloop1(NUMBER_OF_PBS); - std::vector gloop2(NUMBER_OF_PBS); - std::vector gloop3(NUMBER_OF_PBS); - -// PBADPCMInfo adpcm - std::vector gadloop1(NUMBER_OF_PBS); - std::vector gadloop2(NUMBER_OF_PBS); - std::vector gadloop3(NUMBER_OF_PBS); - -// updates - std::vector gupdates1(NUMBER_OF_PBS); - std::vector gupdates2(NUMBER_OF_PBS); - std::vector gupdates3(NUMBER_OF_PBS); - std::vector gupdates4(NUMBER_OF_PBS); - std::vector gupdates5(NUMBER_OF_PBS); - std::vector gupdates_addr(NUMBER_OF_PBS); - std::vector gupdates_data(NUMBER_OF_PBS); - std::vector gupdates_data1(NUMBER_OF_PBS); - std::vector gupdates_data2(NUMBER_OF_PBS); - std::vector gupdates_data3(NUMBER_OF_PBS); - std::vector gupdates_data4(NUMBER_OF_PBS); - -// Counters - -int count1 = 0; -int count2 = 0; -int iupd = 0; -bool iupdonce = false; -std::vector viupd(15); // the length of the update frequency bar -int vectorLengthGUI = 8; // length of playback history bar for the GUI version -int vectorLength = 15; // for console version -int vectorLength2 = 100; // for console version, how long to show - -// More stuff - -// should we worry about the additonal memory these lists require? bool will allocate -// very little memory -std::vector< std::vector > vector1(NUMBER_OF_PBS, std::vector(vectorLength, false)); -std::vector< std::vector > vector2(NUMBER_OF_PBS, std::vector(vectorLength2, false)); -std::vector numberRunning(NUMBER_OF_PBS); - - -// Classes - -extern CDebugger* m_frame; - - - -// ======================================================================================= -// Write title -// -------------- -std::string writeTitle(int a, bool Wii) -{ - std::string b; - if(a == 0) - { - if(m_frame->bShowBase) // show base 10 - { - b = " adpcm adpcm_loop\n"; - b = b + " Nr m pos / end lpos | voll volr | isl iss | pre yn1 yn2 pre yn1 yn2 | frac ratio[hi lo]\n"; - } - else - { - b = " adpcm adpcm_loop\n"; - b = b + " Nr pos / end lpos | voll volr | isl iss | pre yn1 yn2 pre yn1 yn2 | frac rati[hi lo ]\n"; - } - } - else if(a == 1) - { - if(m_frame->bShowBase) // show base 10 - { - b = " Nr pos / end lpos | voll volr | src form coef | 1 2 3 4 5 addr value\n"; - } - else - { - b = " Nr pos / end lpos | voll volr | src form coef | 1 2 3 4 5 addr value\n"; - } - } - else if(a == 2) - { - if(m_frame->bShowBase) // show base 10 - { - b = " Nr pos / end lpos | voll volr | isl iss | e-l e-s\n"; - } - else - { - b = " Nr pos / end lpos | voll volr | isl iss | e-l e-s\n"; - } - } - else if(a == 3) - { - if(m_frame->bShowBase) // show base 10 - { - if(Wii) - b = " Nr voll volr dl dr curv delt mixc r | v1 v2 v3 v4 v5 v6 v7 | d1 d2 d3 d4 d5 d6 d7\n"; - else - b = " Nr voll volr dl dr curv delt mixc r | v1 v2 v3 v4 v5 v6 v7 | d1 d2 d3 d4 d5 d6 d7\n"; - } - else - { - if(Wii) - b = " Nr voll volr dl dr curv delt mixc r | v1 v2 v3 v4 v5 v6 v7 | d1 d2 d3 d4 d5 d6 d7\n"; - else - b = " Nr voll volr dl dr curv delt mixc r | v1 v2 v3 v4 v5 v6 v7 | d1 d2 d3 d4 d5 d6 d7\n"; - } - } - return b; -} -// ======================================================================================= - - - -// ======================================================================================= -// Write main message (presets) -// -------------- -std::string writeMessage(int a, int i, bool Wii) -{ - char buf [1000] = ""; - std::string sbuf; - // ======================================================================================= - // PRESETS - // --------------------------------------------------------------------------------------- - /* - PRESET 0 - " Nr m pos / end lpos | voll volr | isl iss | pre yn1 yn2 pre yn1 yn2 | frac ratio[hi lo]\n"; - "---------------|00 1 12,341,234/134,123,412 12341234 | 00,000 00,000 | 0 0 | 000 00000 00000 000 00000 00000 | 00000 00000[0 00000] - - " Nr pos / end lpos | voll volr | isl iss | pre yn1 yn2 pre yn1 yn2 | frac rati[hi lo ]\n"; - "---------------|00 12,341,234/134,123,412 12341234 | 00,000 00,000 | 0 0 | 000 0000 0000 000 0000 0000 | 0000 0000[0 00000] - - PRESET 1 (updates) - " Nr pos / end lpos | voll volr | src form coef | 1 2 3 4 5 addr value\n"; - "---------------|00 12,341,234/12,341,234 12341234 | 00,000 00,000 | 0 0 0 | 0 0 0 0 0 80808080 80808080 - - PRESET 2 - " Nr pos / end lpos | voll volr | isl iss | e-l e-s\n"; - "---------------|00 12,341,234/12341234 12,341,234 | 00000 00000 | 0 0 | 00,000,000 00,000,000 - */ - if(a == 0) - { - if(m_frame->bShowBase) // base 10 (decimal) - { - if(Wii) // Wii - { - sprintf(buf,"%c%02i %i %10s/%10s %10s | %6s %6s | %i %i | %03i %05i %05i %03i %05i %05i | %05i %05i[%i %05i]", - 223, i, mem[i], ThS(gsamplePos[i],true).c_str(), ThS(gsampleEnd[i],true).c_str(), ThS(gloopPos[i],true).c_str(), - ThS(gvolume_left[i]).c_str(), ThS(gvolume_right[i]).c_str(), - glooping[i], gis_stream[i], - gadloop1[i], gadloop2[i], gadloop3[i], gloop1[i], gloop2[i], gloop3[i], - gfrac[i], gratio[i], gratiohi[i], gratiolo[i] - ); - } - else // GC - { - sprintf(buf,"%c%02i %10s/%10s %10s | %6s %6s | %i %i | %03i %05i %05i %03i %05i %05i | %05i %05i[%i %05i]", - 223, i, ThS(gsamplePos[i],true).c_str(), ThS(gsampleEnd[i],true).c_str(), ThS(gloopPos[i],true).c_str(), - ThS(gvolume_left[i]).c_str(), ThS(gvolume_right[i]).c_str(), - glooping[i], gis_stream[i], - gadloop1[i], gadloop2[i], gadloop3[i], gloop1[i], gloop2[i], gloop3[i], - gfrac[i], gratio[i], gratiohi[i], gratiolo[i] - ); - } - } - else - { - sprintf(buf,"%c%02i %08x/%08x %08x | %04x %04x | %i %i | %02x %04x %04x %02x %04x %04x | %04x %04x[%i %04x]", - 223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i], - gvolume_left[i], gvolume_right[i], - glooping[i], gis_stream[i], - gadloop1[i], gadloop2[i], gadloop3[i], gloop1[i], gloop2[i], gloop3[i], - gfrac[i], gratio[i], gratiohi[i], gratiolo[i] - ); - } - } - else if(a == 1) - { - if(m_frame->bShowBase) // base 10 (decimal) - { - sprintf(buf,"%c%02i %10s/%10s %10s | %6s %6s | %u %u %u | %u %u %u %u %u %08x %08x %08x %08x %08x %08x", - 223, i, ThS(gsamplePos[i]).c_str(), ThS(gsampleEnd[i]).c_str(), ThS(gloopPos[i]).c_str(), - ThS(gvolume_left[i]).c_str(), ThS(gvolume_right[i]).c_str(), - gsrc_type[i], gaudioFormat[i], gcoef[i], - gupdates1[i], gupdates2[i], gupdates3[i], gupdates4[i], gupdates5[i], gupdates_addr[i], - gupdates_data[i], gupdates_data1[i], gupdates_data2[i], gupdates_data3[i], gupdates_data4[i] - ); - } - else // base 16 (hexadecimal) - { - if(Wii) // Wii - { - sprintf(buf,"%c%02i %08x/%08x %08x | %04x %04x | %u %u %u | %u %u %u %08x %08x %08x %08x %08x %08x", - 223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i], - gvolume_left[i], gvolume_right[i], - gsrc_type[i], gaudioFormat[i], gcoef[i], - gupdates1[i], gupdates2[i], gupdates3[i], gupdates_addr[i], - gupdates_data[i], gupdates_data1[i], gupdates_data2[i], gupdates_data3[i], gupdates_data4[i] - ); - } - else // GC - { - sprintf(buf,"%c%02i %08x/%08x %08x | %04x %04x | %u %u %u | %u %u %u %u %u %08x %08x %08x %08x %08x %08x", - 223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i], - gvolume_left[i], gvolume_right[i], - gsrc_type[i], gaudioFormat[i], gcoef[i], - gupdates1[i], gupdates2[i], gupdates3[i], gupdates4[i], gupdates5[i], gupdates_addr[i], - gupdates_data[i], gupdates_data1[i], gupdates_data2[i], gupdates_data3[i], gupdates_data4[i] - ); - } - } - } - else if(a == 2) - { - if(m_frame->bShowBase) - { - sprintf(buf,"%c%02i %10s/%10s %10s | %05i %05i | %i %i | %10s %10s", - 223, i, ThS(gsamplePos[i]).c_str(), ThS(gsampleEnd[i]).c_str(), ThS(gloopPos[i]).c_str(), - gvolume_left[i], gvolume_right[i], - glooping[i], gis_stream[i], - ThS(gsampleEnd[i] - gloopPos[i], false).c_str(), ThS(gsampleEnd[i] - gsamplePos[i], false).c_str() - ); - } - else - { - sprintf(buf,"%c%02i %08x/%08x %08x | %04x %04x | %i %i | %08x %08x", - 223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i], - gvolume_left[i], gvolume_right[i], - glooping[i], gis_stream[i], - gsampleEnd[i] - gloopPos[i], gsampleEnd[i] - gsamplePos[i] - ); - } - } - /* - PRESET 3 - " Nr voll volr dl dr curv delt mixc r | v1 v2 v3 v4 v5 v6 v7 | d1 d2 d3 d4 d5 d6 d7\n"; - "---------------|00 00000 00000 00000 00000 00000 00000 00000 0 | 00000 00000 00000 00000 00000 00000 00000 | 00000 00000 00000 00000 00000 00000 00000 - */ - else if(a == 3) - { - if(m_frame->bShowBase) - { - if(Wii) // Wii - { - sprintf(buf,"%c%02i %05i %05i %05i %05i %05i %05i %05i %i | %05i %05i %05i %05i %05i %05i %05i | %05i %05i %05i %05i %05i %05i %05i", - 223, i, - gvolume_left[i], gvolume_right[i], gmix_unknown[i], gmix_unknown2[i], gcur_volume[i], gcur_volume_delta[i], - gmixer_control_wii[i], (gmixer_control_wii[i] & MIXCONTROL_RAMPING), - gmixer_vol1[i], gmixer_vol2[i], gmixer_vol3[i], gmixer_vol4[i], gmixer_vol5[i], - gmixer_vol6[i], gmixer_vol7[i], - gmixer_d1[i], gmixer_d2[i], gmixer_d3[i], gmixer_d4[i], gmixer_d5[i], - gmixer_d6[i], gmixer_d7[i] - ); - } - else // GC - { - sprintf(buf,"%c%02i %05i %05i %05i %05i %05i %05i %08i %i | %05i %05i %05i %05i %05i %05i %05i | %05i %05i %05i %05i %05i %05i %05i", - 223, i, - gvolume_left[i], gvolume_right[i], gmix_unknown[i], gmix_unknown2[i], gcur_volume[i], gcur_volume_delta[i], - gmixer_control[i], (gmixer_control[i] & MIXCONTROL_RAMPING), - gmixer_vol1[i], gmixer_vol2[i], gmixer_vol3[i], gmixer_vol4[i], gmixer_vol5[i], - gmixer_vol6[i], gmixer_vol7[i], - gmixer_d1[i], gmixer_d2[i], gmixer_d3[i], gmixer_d4[i], gmixer_d5[i], - gmixer_d6[i], gmixer_d7[i] - ); - } - } - else - { - if(Wii) - { - sprintf(buf,"%c%02i %04x %04x %04x %04x %04x %04x %08x %i | %04x %04x %04x %04x %04x %04x %04x | %04x %04x %04x %04x %04x %04x %04x", - 223, i, - gvolume_left[i], gvolume_right[i], gmix_unknown[i], gmix_unknown2[i], gcur_volume[i], gcur_volume_delta[i], - gmixer_control_wii[i], (gmixer_control_wii[i] & MIXCONTROL_RAMPING), - gmixer_vol1[i], gmixer_vol2[i], gmixer_vol3[i], gmixer_vol4[i], gmixer_vol5[i], - gmixer_vol6[i], gmixer_vol7[i], - gmixer_d1[i], gmixer_d2[i], gmixer_d3[i], gmixer_d4[i], gmixer_d5[i], - gmixer_d6[i], gmixer_d7[i] - ); - } - else - { - sprintf(buf,"%c%02i %04x %04x %04x %04x %04x %04x %04x %i | %04x %04x %04x %04x %04x %04x %04x | %04x %04x %04x %04x %04x %04x %04x", - 223, i, - gvolume_left[i], gvolume_right[i], gmix_unknown[i], gmix_unknown2[i], gcur_volume[i], gcur_volume_delta[i], - gmixer_control[i], (gmixer_control[i] & MIXCONTROL_RAMPING), - gmixer_vol1[i], gmixer_vol2[i], gmixer_vol3[i], gmixer_vol4[i], gmixer_vol5[i], - gmixer_vol6[i], gmixer_vol7[i], - gmixer_d1[i], gmixer_d2[i], gmixer_d3[i], gmixer_d4[i], gmixer_d5[i], - gmixer_d6[i], gmixer_d7[i] - ); - } - } - } - sbuf = buf; - return sbuf; -} - - -// ================ - - -// ======================================================================================= -// Collect parameters from Wii or GC -// -------------- -/* -std::string ShowAllPB(int a, int i) -{ - if(a == 0) - { - - } - else if(a == 1) - { - - - } - else if(a == 1) - { - - } - else if(a == 1) - -} -*/ -// ================ - - -// ======================================================================================= -// Collect parameters from Wii or GC -// -------------- - -//inline void MixAddVoice(ParamBlockType &pb -//void CollectPB(bool Wii, int i, AXParamBlockWii * PBw, ParamBlockType &pb) -template void CollectPB(bool Wii, int i, ParamBlockType &PBs) -//void CollectPB(bool Wii, int i, AXParamBlockWii * PBw, AXParamBlock * PBs) -{ - // AXPB base - gsrc_type[i] = PBs[i].src_type; - gcoef[i] = PBs[i].coef_select; - if(Wii) gmixer_control_wii[i] = PBs[i].mixer_control; - else gmixer_control[i] = PBs[i].mixer_control; - - //running[i] = PBs[i].running; - gis_stream[i] = PBs[i].is_stream; - - // mixer (some differences) - gvolume_left[i] = PBs[i].mixer.volume_left; - gvolume_right[i] = PBs[i].mixer.volume_right; - - gmix_unknown[i] = PBs[i].mixer.unknown; - gmix_unknown2[i] = PBs[i].mixer.unknown2; - - gcur_volume[i] = PBs[i].vol_env.cur_volume; - gcur_volume_delta[i] = PBs[i].vol_env.cur_volume_delta; - - gmixer_vol1[i] = PBs[i].mixer.unknown3[0]; - gmixer_vol2[i] = PBs[i].mixer.unknown3[2]; - gmixer_vol3[i] = PBs[i].mixer.unknown3[4]; - gmixer_vol4[i] = PBs[i].mixer.unknown3[6]; - gmixer_vol5[i] = PBs[i].mixer.unknown3[0]; - gmixer_vol6[i] = PBs[i].mixer.unknown3[2]; - gmixer_vol7[i] = PBs[i].mixer.unknown3[4]; - - gmixer_d1[i] = PBs[i].mixer.unknown4[1]; - gmixer_d2[i] = PBs[i].mixer.unknown4[3]; - gmixer_d3[i] = PBs[i].mixer.unknown4[5]; - gmixer_d4[i] = PBs[i].mixer.unknown4[7]; - gmixer_d5[i] = PBs[i].mixer.unknown4[1]; - gmixer_d6[i] = PBs[i].mixer.unknown4[3]; - gmixer_d7[i] = PBs[i].mixer.unknown4[5]; - - // PBAudioAddr audio_addr - glooping[i] = PBs[i].audio_addr.looping; - gaudioFormat[i] = PBs[i].audio_addr.sample_format; - gloopPos[i] = (PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo; - gsampleEnd[i] = (PBs[i].audio_addr.end_addr_hi << 16) | PBs[i].audio_addr.end_addr_lo; - gsamplePos[i] = (PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo; - - if(gloopPos[i] > 0x20000000) gloopPos[i] -= 0x20000000; - if(gsampleEnd[i] > 0x20000000) gsampleEnd[i] -= 0x20000000; - if(gsamplePos[i] > 0x20000000) { gsamplePos[i] -= 0x20000000; - mem[i] = 2;} else { mem[i] = 1; } - - // PBADPCMLoopInfo adpcm_loop_info (same in GC and Wii) - gadloop1[i] = PBs[i].adpcm.pred_scale; - gadloop2[i] = PBs[i].adpcm.yn1; - gadloop3[i] = PBs[i].adpcm.yn2; - - gloop1[i] = PBs[i].adpcm_loop_info.pred_scale; - gloop2[i] = PBs[i].adpcm_loop_info.yn1; - gloop3[i] = PBs[i].adpcm_loop_info.yn2; - - // updates (differences) - gupdates1[i] = PBs[i].updates.num_updates[0]; - gupdates2[i] = PBs[i].updates.num_updates[1]; - gupdates3[i] = PBs[i].updates.num_updates[2]; - gupdates4[i] = PBs[i].updates.num_updates[3]; - gupdates5[i] = PBs[i].updates.num_updates[4]; - - gupdates_addr[i] = (PBs[i].updates.data_hi << 16) | PBs[i].updates.data_lo; - if(gupdates_addr[i] > 0x80000000 && gupdates_addr[i] < 0x93ffffff) - { - gupdates_data[i] = Memory_Read_U32(gupdates_addr[i]); - gupdates_data1[i] = Memory_Read_U32(gupdates_addr[i] + 4); - gupdates_data2[i] = Memory_Read_U32(gupdates_addr[i] + 8); - gupdates_data3[i] = Memory_Read_U32(gupdates_addr[i] + 12); - gupdates_data3[i] = Memory_Read_U32(gupdates_addr[i] + 16); - } - - // PBSampleRateConverter src - - gratio[i] = (u32)(((PBs[i].src.ratio_hi << 16) + PBs[i].src.ratio_lo) * ratioFactor); - gratiohi[i] = PBs[i].src.ratio_hi; - gratiolo[i] = PBs[i].src.ratio_lo; - gfrac[i] = PBs[i].src.cur_addr_frac; -} -// =============== - - - -// ======================================================================================= -// Prepare the condition that makes us show a certain block -// -------------- -template -bool PrepareConditions(bool Wii, int i, ParamBlockType &PBs) -{ - bool Conditions; - - if (m_frame->gOnlyLooping) // show only looping blocks - { - Conditions = PBs[i].audio_addr.looping ? true : false; - } - else if (m_frame->gShowAll) // show all blocks - { - Conditions = true; - } - else if (m_frame->giShowAll > -1) // show all blocks - { - if (m_frame->giShowAll == 0) - Conditions = (i < 31); - else if(m_frame->giShowAll == 1) - Conditions = (i > 30 && i < 61); - else if(m_frame->giShowAll == 2) - Conditions = (i > 60 && i < 91); - else if(m_frame->giShowAll == 3) - Conditions = (i > 90 && i < 121); - } - else // show only the ones that have recently been running - { - Conditions = (numberRunning.at(i) > 0 || PBs[i].audio_addr.looping); - } - - return Conditions; -} -// =============== - - - -template -void Logging_(short* _pBuffer, int _iSize, int a, bool Wii, ParamBlockType &PBs, - int numberOfPBs, u32 m_addressPBs) -//void Logging__(short* _pBuffer, int _iSize, int a, bool Wii) -{ - bool Conditions; // Select blocks to show - - // ======================================================================================= - // Update parameter values - // -------------- - // We could chose to update these only if a block is currently running. Later I'll add options - // to see both the current and the latest active value. - int irun = 0; - for (int i = 0; i < numberOfPBs; i++) - { - // -------------------------------------------------------------------- - // Write a line for the text log if nothing is playing - // -------------- - if (PBs[i].running) - { - irun++; - } - - if (i == numberOfPBs - 1 && irun == 0) - { - for (int j = 0; j < nFiles; j++) - { - std::string sfbuff; - sfbuff = "-----\n"; - aprintf(j, (char *)sfbuff.c_str()); - } - } - // -------------- - - - // -------------------------------------- - // Now go through only a subset of the blocks depending on Conditions - // ------------------ - /* Prepare conditions. We may for example get Conditions = true for blocks - that currently have numberRunning.at(i) > 0 */ - Conditions = PrepareConditions(Wii, i, PBs); - if (Conditions) - { - // Collect parameters - CollectPB(Wii, i, PBs); - - // --------------------------------------------------------------------------------------- - // Write to file - // -------------- - for (int ii = 0; ii < nFiles; ii++) - { - std::string sfbuff; - if(a == 0) sfbuff = "***"; // note if it's before or after an update (*** = before) - else sfbuff = " "; - - // write running - char cbuf[10]; - sprintf(cbuf, "%i", PBs[i].running); - sfbuff = sfbuff + cbuf; - - sfbuff = sfbuff + writeMessage(ii, i, Wii); - - // write _iSize - strcpy(cbuf, ""); sprintf(cbuf, "%i", _iSize); - sfbuff = sfbuff + " | _iSize: " + cbuf + "\n"; - - aprintf(ii, (char *)sfbuff.c_str()); - } - // -------------- - } - } - // ============== - - - // ======================================================================================= - // Control how often the screen is updated, and then update the screen - // -------------- - if(a == 0) count1++; // a == 0 when Logging is called before the blocks are updated - if (m_frame->gUpdFreq > 0 && count1 > (200/m_frame->gUpdFreq)) - { - - // ======================================================================================= - /* Save the displayed running history for each block. Vector1 is a vector1[NUMBER_OF_PBS] - [100] vector. */ - // -------------- - /* - Move all items back like this: - 1 to 0 - 2 1 - 3 ... - 5 to 4 - */ - for (int i = 0; i < numberOfPBs; i++) - { - for (int j = 1; j < vectorLength; j++) - { - vector1.at(i).at(j-1) = vector1.at(i).at(j); - } - // save the latest value - vector1.at(i).at(vectorLength-1) = PBs[i].running ? true : false; - } - // ============== - - - // ======================================================================================= - /* Have a separate set for which ones to show. Currently show blocks that have been - running at least once the last 100 updates. - // -------------- - - Move all items back like this: - 1 to 0 - 2 1 - 3 ... - */ - for (int i = 0; i < numberOfPBs; i++) - { - for (int j = 1; j < vectorLength2; j++) - { - vector2.at(i).at(j-1) = vector2.at(i).at(j); - } - // save the latest value - vector2.at(i).at(vectorLength2-1) = PBs[i].running ? true : false; - } - // ============== - - - // ======================================================================================= - // Count how many we have running now in a certain block - // -------------- - int jj = 0; - for (int i = 0; i < numberOfPBs; i++) - { - jj = 0; - for (int j = 0; j < vectorLength2-1; j++) // the hundred last updates - { - if (vector2.at(i).at(j)) // if it was on then - { - jj++; - } - numberRunning.at(i) = jj; - } - } - // ============== - - - // ======================================================================================= - // Write header - // -------------- - char buffer [1000] = ""; - std::string sbuff; - sbuff = writeTitle(m_frame->gPreset, Wii); - // ============== - - - // ======================================================================================= - // Now go through all blocks - // -------------- - for (int i = 0; i < numberOfPBs; i++) - { - - - // -------------------------------------- - // Now go through only a subset of the blocks depending on Conditions - // ------------------ - // Prepare conditions - Conditions = PrepareConditions(Wii, i, PBs); - if (Conditions) - { - // -------------------------------------- - // Save playback history text string for the console and GUI debugger - // ------------------ - if(m_frame) - { - std::string guipr; // gui progress - - for (int j = 0; j < vectorLengthGUI; j++) - { - if(vector1.at(i).at(j) == false) - { - guipr = guipr + "0"; - } - else - { - guipr = guipr + "1"; - } - } - - u32 run = atoi( guipr.c_str()); - m_frame->m_GPRListView->m_CachedRegs[1][i] = run; - guipr.clear(); - } - - // and for the console debugger - for (int j = 0; j < vectorLength; j++) - { - if(vector1.at(i).at(j) == false) - { - sbuff = sbuff + " "; - } - else - { - sprintf(buffer, "%c", 177); - sbuff = sbuff + buffer; strcpy(buffer, ""); - } - } - // --------- - - - // Hopefully this is false if we don't have a debugging window and so it doesn't cause a crash - if(m_frame) - { - m_frame->m_GPRListView->m_CachedRegs[2][i] = gsamplePos[i]; - m_frame->m_GPRListView->m_CachedRegs[3][i] = gsampleEnd[i]; - m_frame->m_GPRListView->m_CachedRegs[4][i] = gloopPos[i]; - - m_frame->m_GPRListView->m_CachedRegs[5][i] = gvolume_left[i]; - m_frame->m_GPRListView->m_CachedRegs[6][i] = gvolume_right[i]; - - m_frame->m_GPRListView->m_CachedRegs[7][i] = glooping[i]; - m_frame->m_GPRListView->m_CachedRegs[8][i] = gloop1[i]; - m_frame->m_GPRListView->m_CachedRegs[9][i] = gloop2[i]; - m_frame->m_GPRListView->m_CachedRegs[10][i] = gloop3[i]; - - m_frame->m_GPRListView->m_CachedRegs[11][i] = gis_stream[i]; - - m_frame->m_GPRListView->m_CachedRegs[12][i] = gaudioFormat[i]; - m_frame->m_GPRListView->m_CachedRegs[13][i] = gsrc_type[i]; - m_frame->m_GPRListView->m_CachedRegs[14][i] = gcoef[i]; - - m_frame->m_GPRListView->m_CachedRegs[15][i] = gfrac[i]; - - m_frame->m_GPRListView->m_CachedRegs[16][i] = gratio[i]; - m_frame->m_GPRListView->m_CachedRegs[17][i] = gratiohi[i]; - m_frame->m_GPRListView->m_CachedRegs[18][i] = gratiolo[i]; - - m_frame->m_GPRListView->m_CachedRegs[19][i] = gupdates1[i]; - m_frame->m_GPRListView->m_CachedRegs[20][i] = gupdates2[i]; - m_frame->m_GPRListView->m_CachedRegs[21][i] = gupdates3[i]; - m_frame->m_GPRListView->m_CachedRegs[22][i] = gupdates4[i]; - m_frame->m_GPRListView->m_CachedRegs[23][i] = gupdates5[i]; - } - - // add new line - sbuff = sbuff + writeMessage(m_frame->gPreset, i, Wii); strcpy(buffer, ""); - sbuff = sbuff + "\n"; - - } // end of if(Conditions) - // ============== - - } // end of for (int i = 0; i < numberOfPBs; i++) - - - // ======================================================================================= - // Write global values - // --------------- - int nOfBlocks; - int span = m_frame->gLastBlock - m_addressPBs; - if(Wii) - nOfBlocks = (m_frame->gLastBlock-m_addressPBs) / 256; - else - nOfBlocks = (m_frame->gLastBlock-m_addressPBs) / 192; - sprintf(buffer, "\nThe parameter blocks span from %08x to %08x (%s bytes) impl. %i blocks | numberOfPBs %i | _iSize %i\n", - m_addressPBs, m_frame->gLastBlock, ThS(span).c_str(), nOfBlocks, numberOfPBs, _iSize); - sbuff = sbuff + buffer; strcpy(buffer, ""); - // =============== - - - // ======================================================================================= - // Write settings - // --------------- - sprintf(buffer, "\nSettings: SSBM fix %i | SSBM rem1 %i | SSBM rem2 %i\nSequenced %i | Volume %i | Reset %i | Only looping %i | Save file %i\n", - gSSBM, gSSBMremedy1, gSSBMremedy2, gSequenced, - gVolume, gReset, m_frame->gOnlyLooping, m_frame->gSaveFile); - sbuff = sbuff + buffer; strcpy(buffer, ""); - // =============== - - - // ======================================================================================= - // Show update frequency - // --------------- - sbuff = sbuff + "\n"; - if(!iupdonce) - { - viupd.at(0) = 1; - viupd.at(1) = 1; - viupd.at(2) = 1; - iupdonce = true; - } - - for (u32 i = 0; i < viupd.size(); i++) // 0, 1,..., 9 - { - if (i < viupd.size()-1) - { - viupd.at(viupd.size()-i-1) = viupd.at(viupd.size()-i-2); // move all forward - } - else - { - viupd.at(0) = viupd.at(viupd.size()-1); - } - - // Correction - if (viupd.at(viupd.size()-3) == 1 && viupd.at(viupd.size()-2) == 1 && viupd.at(viupd.size()-1) == 1) - { - viupd.at(0) = 0; - } - if(viupd.at(0) == 0 && viupd.at(1) == 1 && viupd.at(2) == 1 && viupd.at(3) == 0) - { - viupd.at(0) = 1; - } - } - - for (u32 i = 0; i < viupd.size(); i++) - { - if(viupd.at(i) == 0) - sbuff = sbuff + " "; - else - sbuff = sbuff + "."; - } - // ================ - - - // ======================================================================================= - // Print - // ---------------- - ClearScreen(); - wprintf("%s", sbuff.c_str()); - sbuff.clear(); strcpy(buffer, ""); - // ================ - - - // New values are written so update - DISABLED - It flickered a lot, even worse than a - // console window. So for now only the console windows is updated. - /* - if(m_frame) - { - m_frame->NotifyUpdate(); - } - */ - - count2=0; - count1=0; - - } // end of if (j>20) - -} // end of function - - -// I placed this in CUCode_AX so it can share member values with that class -void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a, bool Wii) -{ - /* Doing all this may have a noticable CPU effect, so we can disable it completely - this way. But remember that "Save to file" will not write anything then either. */ - if (m_frame->gUpdFreq > 0) - { - int version; // AX version - int numberOfPBs; - - // Declare structures - AXParamBlock PBs[NUMBER_OF_PBS]; - AXParamBlockWii PBw[NUMBER_OF_PBS]; - AXParamBlockWii_ PBw_[NUMBER_OF_PBS]; - if(_CRC == 0xfa450138) version = 0; else version = 1; - - // Read out structs and number of PBs that have data - if(Wii) - { - if(version == 0) - { - numberOfPBs = ReadOutPBsWii(m_addressPBs, PBw, NUMBER_OF_PBS); - Logging_(_pBuffer, _iSize, a, Wii, PBw, numberOfPBs, m_addressPBs); - } - else - { - numberOfPBs = ReadOutPBsWii(m_addressPBs, PBw_, NUMBER_OF_PBS); - Logging_(_pBuffer, _iSize, a, Wii, PBw_, numberOfPBs, m_addressPBs); - } - } - else - { - numberOfPBs = ReadOutPBs(m_addressPBs, PBs, NUMBER_OF_PBS); - Logging_(_pBuffer, _iSize, a, Wii, PBs, numberOfPBs, m_addressPBs); - } - } -} +////////////////////////////////////////////////////////////////////////////////////////// +// +// Licensetype: GNU General Public License (GPL) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. +// +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ +// +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +// +////////////////////////////////////////////////////////////////////////////////////////// + + + +// Includes + +#include +#include +#include // so that we can test std::string == abc +#include // for the pow() function +#ifdef _WIN32 + #include +#endif + +#include "StringUtil.h" + +#include "../Debugger/Debugger.h" +#include "../Debugger/PBView.h" +#include "Console.h" // open and close console, clear console window + +#include "../Globals.h" +#include "../UCodes/UCodes.h" +#include "../UCodes/UCode_AXStructs.h" +#include "../UCodes/UCode_AX.h" +#include "../UCodes/UCode_AXWii.h" +#include "../UCodes/UCode_AX_Voice.h" + +// Externals + +extern bool gSSBM; +extern bool gSSBMremedy1; +extern bool gSSBMremedy2; +extern bool gSequenced; +extern bool gVolume; +extern bool gReset; +extern int nFiles; +float ratioFactor; // a global to get the ratio factor from MixAdd +extern CDebugger* m_frame; +//int PBSize = 128; + +// Parameter blocks + + std::vector mem(NUMBER_OF_PBS); // mem1 or mem2 + std::vector gloopPos(NUMBER_OF_PBS); + std::vector gsampleEnd(NUMBER_OF_PBS); + std::vector gsamplePos(NUMBER_OF_PBS); + +// main + std::vector running(NUMBER_OF_PBS, 0); + std::vector gsrc_type(NUMBER_OF_PBS); + std::vector gis_stream(NUMBER_OF_PBS); + +// PBSampleRateConverter src + std::vector gratio(NUMBER_OF_PBS); + std::vector gratiohi(NUMBER_OF_PBS); + std::vector gratiolo(NUMBER_OF_PBS); + std::vector gfrac(NUMBER_OF_PBS); + std::vector gcoef(NUMBER_OF_PBS); + +// PBSampleRateConverter mixer + std::vector gvolume_left(NUMBER_OF_PBS); + std::vector gmix_unknown(NUMBER_OF_PBS); + std::vector gvolume_right(NUMBER_OF_PBS); + std::vector gmix_unknown2(NUMBER_OF_PBS); + std::vector gmixer_control(NUMBER_OF_PBS); + std::vector gmixer_control_wii(NUMBER_OF_PBS); + + std::vector gmixer_vol1(NUMBER_OF_PBS); + std::vector gmixer_vol2(NUMBER_OF_PBS); + std::vector gmixer_vol3(NUMBER_OF_PBS); + std::vector gmixer_vol4(NUMBER_OF_PBS); + std::vector gmixer_vol5(NUMBER_OF_PBS); + std::vector gmixer_vol6(NUMBER_OF_PBS); + std::vector gmixer_vol7(NUMBER_OF_PBS); + + std::vector gmixer_d1(NUMBER_OF_PBS); + std::vector gmixer_d2(NUMBER_OF_PBS); + std::vector gmixer_d3(NUMBER_OF_PBS); + std::vector gmixer_d4(NUMBER_OF_PBS); + std::vector gmixer_d5(NUMBER_OF_PBS); + std::vector gmixer_d6(NUMBER_OF_PBS); + std::vector gmixer_d7(NUMBER_OF_PBS); + +// PBVolumeEnvelope vol_env + std::vector gcur_volume(NUMBER_OF_PBS); + std::vector gcur_volume_delta(NUMBER_OF_PBS); + +// PBAudioAddr audio_addr (incl looping) + std::vector gaudioFormat(NUMBER_OF_PBS); + std::vector glooping(NUMBER_OF_PBS); + std::vector gloop1(NUMBER_OF_PBS); + std::vector gloop2(NUMBER_OF_PBS); + std::vector gloop3(NUMBER_OF_PBS); + +// PBADPCMInfo adpcm + std::vector gadloop1(NUMBER_OF_PBS); + std::vector gadloop2(NUMBER_OF_PBS); + std::vector gadloop3(NUMBER_OF_PBS); + +// updates + std::vector gupdates1(NUMBER_OF_PBS); + std::vector gupdates2(NUMBER_OF_PBS); + std::vector gupdates3(NUMBER_OF_PBS); + std::vector gupdates4(NUMBER_OF_PBS); + std::vector gupdates5(NUMBER_OF_PBS); + std::vector gupdates_addr(NUMBER_OF_PBS); + std::vector gupdates_data(NUMBER_OF_PBS); + std::vector gupdates_data1(NUMBER_OF_PBS); + std::vector gupdates_data2(NUMBER_OF_PBS); + std::vector gupdates_data3(NUMBER_OF_PBS); + std::vector gupdates_data4(NUMBER_OF_PBS); + +// Counters + +int count1 = 0; +int count2 = 0; +int iupd = 0; +bool iupdonce = false; +std::vector viupd(15); // the length of the update frequency bar +int vectorLengthGUI = 8; // length of playback history bar for the GUI version +int vectorLength = 15; // for console version +int vectorLength2 = 100; // for console version, how long to show + +// More stuff + +// should we worry about the additonal memory these lists require? bool will allocate +// very little memory +std::vector< std::vector > vector1(NUMBER_OF_PBS, std::vector(vectorLength, false)); +std::vector< std::vector > vector2(NUMBER_OF_PBS, std::vector(vectorLength2, false)); +std::vector numberRunning(NUMBER_OF_PBS); + + +// Classes + +extern CDebugger* m_frame; + + + +// ======================================================================================= +// Write title +// -------------- +std::string writeTitle(int a, bool Wii) +{ + std::string b; + if(a == 0) + { + if(m_frame->bShowBase) // show base 10 + { + b = " adpcm adpcm_loop\n"; + b = b + " Nr m pos / end lpos | voll volr | isl iss | pre yn1 yn2 pre yn1 yn2 | frac ratio[hi lo]\n"; + } + else + { + b = " adpcm adpcm_loop\n"; + b = b + " Nr pos / end lpos | voll volr | isl iss | pre yn1 yn2 pre yn1 yn2 | frac rati[hi lo ]\n"; + } + } + else if(a == 1) + { + if(m_frame->bShowBase) // show base 10 + { + b = " Nr pos / end lpos | voll volr | src form coef | 1 2 3 4 5 addr value\n"; + } + else + { + b = " Nr pos / end lpos | voll volr | src form coef | 1 2 3 4 5 addr value\n"; + } + } + else if(a == 2) + { + if(m_frame->bShowBase) // show base 10 + { + b = " Nr pos / end lpos | voll volr | isl iss | e-l e-s\n"; + } + else + { + b = " Nr pos / end lpos | voll volr | isl iss | e-l e-s\n"; + } + } + else if(a == 3) + { + if(m_frame->bShowBase) // show base 10 + { + if(Wii) + b = " Nr voll volr dl dr curv delt mixc r | v1 v2 v3 v4 v5 v6 v7 | d1 d2 d3 d4 d5 d6 d7\n"; + else + b = " Nr voll volr dl dr curv delt mixc r | v1 v2 v3 v4 v5 v6 v7 | d1 d2 d3 d4 d5 d6 d7\n"; + } + else + { + if(Wii) + b = " Nr voll volr dl dr curv delt mixc r | v1 v2 v3 v4 v5 v6 v7 | d1 d2 d3 d4 d5 d6 d7\n"; + else + b = " Nr voll volr dl dr curv delt mixc r | v1 v2 v3 v4 v5 v6 v7 | d1 d2 d3 d4 d5 d6 d7\n"; + } + } + return b; +} +// ======================================================================================= + + + +// ======================================================================================= +// Write main message (presets) +// -------------- +std::string writeMessage(int a, int i, bool Wii) +{ + char buf [1000] = ""; + std::string sbuf; + // ======================================================================================= + // PRESETS + // --------------------------------------------------------------------------------------- + /* + PRESET 0 + " Nr m pos / end lpos | voll volr | isl iss | pre yn1 yn2 pre yn1 yn2 | frac ratio[hi lo]\n"; + "---------------|00 1 12,341,234/134,123,412 12341234 | 00,000 00,000 | 0 0 | 000 00000 00000 000 00000 00000 | 00000 00000[0 00000] + + " Nr pos / end lpos | voll volr | isl iss | pre yn1 yn2 pre yn1 yn2 | frac rati[hi lo ]\n"; + "---------------|00 12,341,234/134,123,412 12341234 | 00,000 00,000 | 0 0 | 000 0000 0000 000 0000 0000 | 0000 0000[0 00000] + + PRESET 1 (updates) + " Nr pos / end lpos | voll volr | src form coef | 1 2 3 4 5 addr value\n"; + "---------------|00 12,341,234/12,341,234 12341234 | 00,000 00,000 | 0 0 0 | 0 0 0 0 0 80808080 80808080 + + PRESET 2 + " Nr pos / end lpos | voll volr | isl iss | e-l e-s\n"; + "---------------|00 12,341,234/12341234 12,341,234 | 00000 00000 | 0 0 | 00,000,000 00,000,000 + */ + if(a == 0) + { + if(m_frame->bShowBase) // base 10 (decimal) + { + if(Wii) // Wii + { + sprintf(buf,"%c%02i %i %10s/%10s %10s | %6s %6s | %i %i | %03i %05i %05i %03i %05i %05i | %05i %05i[%i %05i]", + 223, i, mem[i], ThS(gsamplePos[i],true).c_str(), ThS(gsampleEnd[i],true).c_str(), ThS(gloopPos[i],true).c_str(), + ThS(gvolume_left[i]).c_str(), ThS(gvolume_right[i]).c_str(), + glooping[i], gis_stream[i], + gadloop1[i], gadloop2[i], gadloop3[i], gloop1[i], gloop2[i], gloop3[i], + gfrac[i], gratio[i], gratiohi[i], gratiolo[i] + ); + } + else // GC + { + sprintf(buf,"%c%02i %10s/%10s %10s | %6s %6s | %i %i | %03i %05i %05i %03i %05i %05i | %05i %05i[%i %05i]", + 223, i, ThS(gsamplePos[i],true).c_str(), ThS(gsampleEnd[i],true).c_str(), ThS(gloopPos[i],true).c_str(), + ThS(gvolume_left[i]).c_str(), ThS(gvolume_right[i]).c_str(), + glooping[i], gis_stream[i], + gadloop1[i], gadloop2[i], gadloop3[i], gloop1[i], gloop2[i], gloop3[i], + gfrac[i], gratio[i], gratiohi[i], gratiolo[i] + ); + } + } + else + { + sprintf(buf,"%c%02i %08x/%08x %08x | %04x %04x | %i %i | %02x %04x %04x %02x %04x %04x | %04x %04x[%i %04x]", + 223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i], + gvolume_left[i], gvolume_right[i], + glooping[i], gis_stream[i], + gadloop1[i], gadloop2[i], gadloop3[i], gloop1[i], gloop2[i], gloop3[i], + gfrac[i], gratio[i], gratiohi[i], gratiolo[i] + ); + } + } + else if(a == 1) + { + if(m_frame->bShowBase) // base 10 (decimal) + { + sprintf(buf,"%c%02i %10s/%10s %10s | %6s %6s | %u %u %u | %u %u %u %u %u %08x %08x %08x %08x %08x %08x", + 223, i, ThS(gsamplePos[i]).c_str(), ThS(gsampleEnd[i]).c_str(), ThS(gloopPos[i]).c_str(), + ThS(gvolume_left[i]).c_str(), ThS(gvolume_right[i]).c_str(), + gsrc_type[i], gaudioFormat[i], gcoef[i], + gupdates1[i], gupdates2[i], gupdates3[i], gupdates4[i], gupdates5[i], gupdates_addr[i], + gupdates_data[i], gupdates_data1[i], gupdates_data2[i], gupdates_data3[i], gupdates_data4[i] + ); + } + else // base 16 (hexadecimal) + { + if(Wii) // Wii + { + sprintf(buf,"%c%02i %08x/%08x %08x | %04x %04x | %u %u %u | %u %u %u %08x %08x %08x %08x %08x %08x", + 223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i], + gvolume_left[i], gvolume_right[i], + gsrc_type[i], gaudioFormat[i], gcoef[i], + gupdates1[i], gupdates2[i], gupdates3[i], gupdates_addr[i], + gupdates_data[i], gupdates_data1[i], gupdates_data2[i], gupdates_data3[i], gupdates_data4[i] + ); + } + else // GC + { + sprintf(buf,"%c%02i %08x/%08x %08x | %04x %04x | %u %u %u | %u %u %u %u %u %08x %08x %08x %08x %08x %08x", + 223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i], + gvolume_left[i], gvolume_right[i], + gsrc_type[i], gaudioFormat[i], gcoef[i], + gupdates1[i], gupdates2[i], gupdates3[i], gupdates4[i], gupdates5[i], gupdates_addr[i], + gupdates_data[i], gupdates_data1[i], gupdates_data2[i], gupdates_data3[i], gupdates_data4[i] + ); + } + } + } + else if(a == 2) + { + if(m_frame->bShowBase) + { + sprintf(buf,"%c%02i %10s/%10s %10s | %05i %05i | %i %i | %10s %10s", + 223, i, ThS(gsamplePos[i]).c_str(), ThS(gsampleEnd[i]).c_str(), ThS(gloopPos[i]).c_str(), + gvolume_left[i], gvolume_right[i], + glooping[i], gis_stream[i], + ThS(gsampleEnd[i] - gloopPos[i], false).c_str(), ThS(gsampleEnd[i] - gsamplePos[i], false).c_str() + ); + } + else + { + sprintf(buf,"%c%02i %08x/%08x %08x | %04x %04x | %i %i | %08x %08x", + 223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i], + gvolume_left[i], gvolume_right[i], + glooping[i], gis_stream[i], + gsampleEnd[i] - gloopPos[i], gsampleEnd[i] - gsamplePos[i] + ); + } + } + /* + PRESET 3 + " Nr voll volr dl dr curv delt mixc r | v1 v2 v3 v4 v5 v6 v7 | d1 d2 d3 d4 d5 d6 d7\n"; + "---------------|00 00000 00000 00000 00000 00000 00000 00000 0 | 00000 00000 00000 00000 00000 00000 00000 | 00000 00000 00000 00000 00000 00000 00000 + */ + else if(a == 3) + { + if(m_frame->bShowBase) + { + if(Wii) // Wii + { + sprintf(buf,"%c%02i %05i %05i %05i %05i %05i %05i %05i %i | %05i %05i %05i %05i %05i %05i %05i | %05i %05i %05i %05i %05i %05i %05i", + 223, i, + gvolume_left[i], gvolume_right[i], gmix_unknown[i], gmix_unknown2[i], gcur_volume[i], gcur_volume_delta[i], + gmixer_control_wii[i], (gmixer_control_wii[i] & MIXCONTROL_RAMPING), + gmixer_vol1[i], gmixer_vol2[i], gmixer_vol3[i], gmixer_vol4[i], gmixer_vol5[i], + gmixer_vol6[i], gmixer_vol7[i], + gmixer_d1[i], gmixer_d2[i], gmixer_d3[i], gmixer_d4[i], gmixer_d5[i], + gmixer_d6[i], gmixer_d7[i] + ); + } + else // GC + { + sprintf(buf,"%c%02i %05i %05i %05i %05i %05i %05i %08i %i | %05i %05i %05i %05i %05i %05i %05i | %05i %05i %05i %05i %05i %05i %05i", + 223, i, + gvolume_left[i], gvolume_right[i], gmix_unknown[i], gmix_unknown2[i], gcur_volume[i], gcur_volume_delta[i], + gmixer_control[i], (gmixer_control[i] & MIXCONTROL_RAMPING), + gmixer_vol1[i], gmixer_vol2[i], gmixer_vol3[i], gmixer_vol4[i], gmixer_vol5[i], + gmixer_vol6[i], gmixer_vol7[i], + gmixer_d1[i], gmixer_d2[i], gmixer_d3[i], gmixer_d4[i], gmixer_d5[i], + gmixer_d6[i], gmixer_d7[i] + ); + } + } + else + { + if(Wii) + { + sprintf(buf,"%c%02i %04x %04x %04x %04x %04x %04x %08x %i | %04x %04x %04x %04x %04x %04x %04x | %04x %04x %04x %04x %04x %04x %04x", + 223, i, + gvolume_left[i], gvolume_right[i], gmix_unknown[i], gmix_unknown2[i], gcur_volume[i], gcur_volume_delta[i], + gmixer_control_wii[i], (gmixer_control_wii[i] & MIXCONTROL_RAMPING), + gmixer_vol1[i], gmixer_vol2[i], gmixer_vol3[i], gmixer_vol4[i], gmixer_vol5[i], + gmixer_vol6[i], gmixer_vol7[i], + gmixer_d1[i], gmixer_d2[i], gmixer_d3[i], gmixer_d4[i], gmixer_d5[i], + gmixer_d6[i], gmixer_d7[i] + ); + } + else + { + sprintf(buf,"%c%02i %04x %04x %04x %04x %04x %04x %04x %i | %04x %04x %04x %04x %04x %04x %04x | %04x %04x %04x %04x %04x %04x %04x", + 223, i, + gvolume_left[i], gvolume_right[i], gmix_unknown[i], gmix_unknown2[i], gcur_volume[i], gcur_volume_delta[i], + gmixer_control[i], (gmixer_control[i] & MIXCONTROL_RAMPING), + gmixer_vol1[i], gmixer_vol2[i], gmixer_vol3[i], gmixer_vol4[i], gmixer_vol5[i], + gmixer_vol6[i], gmixer_vol7[i], + gmixer_d1[i], gmixer_d2[i], gmixer_d3[i], gmixer_d4[i], gmixer_d5[i], + gmixer_d6[i], gmixer_d7[i] + ); + } + } + } + sbuf = buf; + return sbuf; +} + + +// ================ + + +// ======================================================================================= +// Collect parameters from Wii or GC +// -------------- +/* +std::string ShowAllPB(int a, int i) +{ + if(a == 0) + { + + } + else if(a == 1) + { + + + } + else if(a == 1) + { + + } + else if(a == 1) + +} +*/ +// ================ + + +// ======================================================================================= +// Collect parameters from Wii or GC +// -------------- + +//inline void MixAddVoice(ParamBlockType &pb +//void CollectPB(bool Wii, int i, AXParamBlockWii * PBw, ParamBlockType &pb) +template void CollectPB(bool Wii, int i, ParamBlockType &PBs) +//void CollectPB(bool Wii, int i, AXParamBlockWii * PBw, AXParamBlock * PBs) +{ + // AXPB base + gsrc_type[i] = PBs[i].src_type; + gcoef[i] = PBs[i].coef_select; + if(Wii) gmixer_control_wii[i] = PBs[i].mixer_control; + else gmixer_control[i] = PBs[i].mixer_control; + + //running[i] = PBs[i].running; + gis_stream[i] = PBs[i].is_stream; + + // mixer (some differences) + gvolume_left[i] = PBs[i].mixer.volume_left; + gvolume_right[i] = PBs[i].mixer.volume_right; + + gmix_unknown[i] = PBs[i].mixer.unknown; + gmix_unknown2[i] = PBs[i].mixer.unknown2; + + gcur_volume[i] = PBs[i].vol_env.cur_volume; + gcur_volume_delta[i] = PBs[i].vol_env.cur_volume_delta; + + gmixer_vol1[i] = PBs[i].mixer.unknown3[0]; + gmixer_vol2[i] = PBs[i].mixer.unknown3[2]; + gmixer_vol3[i] = PBs[i].mixer.unknown3[4]; + gmixer_vol4[i] = PBs[i].mixer.unknown3[6]; + gmixer_vol5[i] = PBs[i].mixer.unknown3[0]; + gmixer_vol6[i] = PBs[i].mixer.unknown3[2]; + gmixer_vol7[i] = PBs[i].mixer.unknown3[4]; + + gmixer_d1[i] = PBs[i].mixer.unknown4[1]; + gmixer_d2[i] = PBs[i].mixer.unknown4[3]; + gmixer_d3[i] = PBs[i].mixer.unknown4[5]; + gmixer_d4[i] = PBs[i].mixer.unknown4[7]; + gmixer_d5[i] = PBs[i].mixer.unknown4[1]; + gmixer_d6[i] = PBs[i].mixer.unknown4[3]; + gmixer_d7[i] = PBs[i].mixer.unknown4[5]; + + // PBAudioAddr audio_addr + glooping[i] = PBs[i].audio_addr.looping; + gaudioFormat[i] = PBs[i].audio_addr.sample_format; + gloopPos[i] = (PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo; + gsampleEnd[i] = (PBs[i].audio_addr.end_addr_hi << 16) | PBs[i].audio_addr.end_addr_lo; + gsamplePos[i] = (PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo; + + if(gloopPos[i] > 0x20000000) gloopPos[i] -= 0x20000000; + if(gsampleEnd[i] > 0x20000000) gsampleEnd[i] -= 0x20000000; + if(gsamplePos[i] > 0x20000000) { gsamplePos[i] -= 0x20000000; + mem[i] = 2;} else { mem[i] = 1; } + + // PBADPCMLoopInfo adpcm_loop_info (same in GC and Wii) + gadloop1[i] = PBs[i].adpcm.pred_scale; + gadloop2[i] = PBs[i].adpcm.yn1; + gadloop3[i] = PBs[i].adpcm.yn2; + + gloop1[i] = PBs[i].adpcm_loop_info.pred_scale; + gloop2[i] = PBs[i].adpcm_loop_info.yn1; + gloop3[i] = PBs[i].adpcm_loop_info.yn2; + + // updates (differences) + gupdates1[i] = PBs[i].updates.num_updates[0]; + gupdates2[i] = PBs[i].updates.num_updates[1]; + gupdates3[i] = PBs[i].updates.num_updates[2]; + gupdates4[i] = PBs[i].updates.num_updates[3]; + gupdates5[i] = PBs[i].updates.num_updates[4]; + + gupdates_addr[i] = (PBs[i].updates.data_hi << 16) | PBs[i].updates.data_lo; + if(gupdates_addr[i] > 0x80000000 && gupdates_addr[i] < 0x93ffffff) + { + gupdates_data[i] = Memory_Read_U32(gupdates_addr[i]); + gupdates_data1[i] = Memory_Read_U32(gupdates_addr[i] + 4); + gupdates_data2[i] = Memory_Read_U32(gupdates_addr[i] + 8); + gupdates_data3[i] = Memory_Read_U32(gupdates_addr[i] + 12); + gupdates_data3[i] = Memory_Read_U32(gupdates_addr[i] + 16); + } + + // PBSampleRateConverter src + + gratio[i] = (u32)(((PBs[i].src.ratio_hi << 16) + PBs[i].src.ratio_lo) * ratioFactor); + gratiohi[i] = PBs[i].src.ratio_hi; + gratiolo[i] = PBs[i].src.ratio_lo; + gfrac[i] = PBs[i].src.cur_addr_frac; +} +// =============== + + + +// ======================================================================================= +// Prepare the condition that makes us show a certain block +// -------------- +template +bool PrepareConditions(bool Wii, int i, ParamBlockType &PBs) +{ + bool Conditions; + + if (m_frame->gOnlyLooping) // show only looping blocks + { + Conditions = PBs[i].audio_addr.looping ? true : false; + } + else if (m_frame->gShowAll) // show all blocks + { + Conditions = true; + } + else if (m_frame->giShowAll > -1) // show all blocks + { + if (m_frame->giShowAll == 0) + Conditions = (i < 31); + else if(m_frame->giShowAll == 1) + Conditions = (i > 30 && i < 61); + else if(m_frame->giShowAll == 2) + Conditions = (i > 60 && i < 91); + else if(m_frame->giShowAll == 3) + Conditions = (i > 90 && i < 121); + } + else // show only the ones that have recently been running + { + Conditions = (numberRunning.at(i) > 0 || PBs[i].audio_addr.looping); + } + + return Conditions; +} +// =============== + + + +template +void Logging_(short* _pBuffer, int _iSize, int a, bool Wii, ParamBlockType &PBs, + int numberOfPBs, u32 m_addressPBs) +//void Logging__(short* _pBuffer, int _iSize, int a, bool Wii) +{ + bool Conditions; // Select blocks to show + + // ======================================================================================= + // Update parameter values + // -------------- + // We could chose to update these only if a block is currently running. Later I'll add options + // to see both the current and the latest active value. + int irun = 0; + for (int i = 0; i < numberOfPBs; i++) + { + // -------------------------------------------------------------------- + // Write a line for the text log if nothing is playing + // -------------- + if (PBs[i].running) + { + irun++; + } + + if (i == numberOfPBs - 1 && irun == 0) + { + for (int j = 0; j < nFiles; j++) + { + std::string sfbuff; + sfbuff = "-----\n"; + aprintf(j, (char *)sfbuff.c_str()); + } + } + // -------------- + + + // -------------------------------------- + // Now go through only a subset of the blocks depending on Conditions + // ------------------ + /* Prepare conditions. We may for example get Conditions = true for blocks + that currently have numberRunning.at(i) > 0 */ + Conditions = PrepareConditions(Wii, i, PBs); + if (Conditions) + { + // Collect parameters + CollectPB(Wii, i, PBs); + + // --------------------------------------------------------------------------------------- + // Write to file + // -------------- + for (int ii = 0; ii < nFiles; ii++) + { + std::string sfbuff; + if(a == 0) sfbuff = "***"; // note if it's before or after an update (*** = before) + else sfbuff = " "; + + // write running + char cbuf[10]; + sprintf(cbuf, "%i", PBs[i].running); + sfbuff = sfbuff + cbuf; + + sfbuff = sfbuff + writeMessage(ii, i, Wii); + + // write _iSize + strcpy(cbuf, ""); sprintf(cbuf, "%i", _iSize); + sfbuff = sfbuff + " | _iSize: " + cbuf + "\n"; + + aprintf(ii, (char *)sfbuff.c_str()); + } + // -------------- + } + } + // ============== + + + // ======================================================================================= + // Control how often the screen is updated, and then update the screen + // -------------- + if(a == 0) count1++; // a == 0 when Logging is called before the blocks are updated + if (m_frame->gUpdFreq > 0 && count1 > (200/m_frame->gUpdFreq)) + { + + // ======================================================================================= + /* Save the displayed running history for each block. Vector1 is a vector1[NUMBER_OF_PBS] + [100] vector. */ + // -------------- + /* + Move all items back like this: + 1 to 0 + 2 1 + 3 ... + 5 to 4 + */ + for (int i = 0; i < numberOfPBs; i++) + { + for (int j = 1; j < vectorLength; j++) + { + vector1.at(i).at(j-1) = vector1.at(i).at(j); + } + // save the latest value + vector1.at(i).at(vectorLength-1) = PBs[i].running ? true : false; + } + // ============== + + + // ======================================================================================= + /* Have a separate set for which ones to show. Currently show blocks that have been + running at least once the last 100 updates. + // -------------- + + Move all items back like this: + 1 to 0 + 2 1 + 3 ... + */ + for (int i = 0; i < numberOfPBs; i++) + { + for (int j = 1; j < vectorLength2; j++) + { + vector2.at(i).at(j-1) = vector2.at(i).at(j); + } + // save the latest value + vector2.at(i).at(vectorLength2-1) = PBs[i].running ? true : false; + } + // ============== + + + // ======================================================================================= + // Count how many we have running now in a certain block + // -------------- + int jj = 0; + for (int i = 0; i < numberOfPBs; i++) + { + jj = 0; + for (int j = 0; j < vectorLength2-1; j++) // the hundred last updates + { + if (vector2.at(i).at(j)) // if it was on then + { + jj++; + } + numberRunning.at(i) = jj; + } + } + // ============== + + + // ======================================================================================= + // Write header + // -------------- + char buffer [1000] = ""; + std::string sbuff; + sbuff = writeTitle(m_frame->gPreset, Wii); + // ============== + + + // ======================================================================================= + // Now go through all blocks + // -------------- + for (int i = 0; i < numberOfPBs; i++) + { + + + // -------------------------------------- + // Now go through only a subset of the blocks depending on Conditions + // ------------------ + // Prepare conditions + Conditions = PrepareConditions(Wii, i, PBs); + if (Conditions) + { + // -------------------------------------- + // Save playback history text string for the console and GUI debugger + // ------------------ + if(m_frame) + { + std::string guipr; // gui progress + + for (int j = 0; j < vectorLengthGUI; j++) + { + if(vector1.at(i).at(j) == false) + { + guipr = guipr + "0"; + } + else + { + guipr = guipr + "1"; + } + } + + u32 run = atoi( guipr.c_str()); + m_frame->m_GPRListView->m_CachedRegs[1][i] = run; + guipr.clear(); + } + + // and for the console debugger + for (int j = 0; j < vectorLength; j++) + { + if(vector1.at(i).at(j) == false) + { + sbuff = sbuff + " "; + } + else + { + sprintf(buffer, "%c", 177); + sbuff = sbuff + buffer; strcpy(buffer, ""); + } + } + // --------- + + + // Hopefully this is false if we don't have a debugging window and so it doesn't cause a crash + if(m_frame) + { + m_frame->m_GPRListView->m_CachedRegs[2][i] = gsamplePos[i]; + m_frame->m_GPRListView->m_CachedRegs[3][i] = gsampleEnd[i]; + m_frame->m_GPRListView->m_CachedRegs[4][i] = gloopPos[i]; + + m_frame->m_GPRListView->m_CachedRegs[5][i] = gvolume_left[i]; + m_frame->m_GPRListView->m_CachedRegs[6][i] = gvolume_right[i]; + + m_frame->m_GPRListView->m_CachedRegs[7][i] = glooping[i]; + m_frame->m_GPRListView->m_CachedRegs[8][i] = gloop1[i]; + m_frame->m_GPRListView->m_CachedRegs[9][i] = gloop2[i]; + m_frame->m_GPRListView->m_CachedRegs[10][i] = gloop3[i]; + + m_frame->m_GPRListView->m_CachedRegs[11][i] = gis_stream[i]; + + m_frame->m_GPRListView->m_CachedRegs[12][i] = gaudioFormat[i]; + m_frame->m_GPRListView->m_CachedRegs[13][i] = gsrc_type[i]; + m_frame->m_GPRListView->m_CachedRegs[14][i] = gcoef[i]; + + m_frame->m_GPRListView->m_CachedRegs[15][i] = gfrac[i]; + + m_frame->m_GPRListView->m_CachedRegs[16][i] = gratio[i]; + m_frame->m_GPRListView->m_CachedRegs[17][i] = gratiohi[i]; + m_frame->m_GPRListView->m_CachedRegs[18][i] = gratiolo[i]; + + m_frame->m_GPRListView->m_CachedRegs[19][i] = gupdates1[i]; + m_frame->m_GPRListView->m_CachedRegs[20][i] = gupdates2[i]; + m_frame->m_GPRListView->m_CachedRegs[21][i] = gupdates3[i]; + m_frame->m_GPRListView->m_CachedRegs[22][i] = gupdates4[i]; + m_frame->m_GPRListView->m_CachedRegs[23][i] = gupdates5[i]; + } + + // add new line + sbuff = sbuff + writeMessage(m_frame->gPreset, i, Wii); strcpy(buffer, ""); + sbuff = sbuff + "\n"; + + } // end of if(Conditions) + // ============== + + } // end of for (int i = 0; i < numberOfPBs; i++) + + + // ======================================================================================= + // Write global values + // --------------- + int nOfBlocks; + int span = m_frame->gLastBlock - m_addressPBs; + if(Wii) + nOfBlocks = (m_frame->gLastBlock-m_addressPBs) / 256; + else + nOfBlocks = (m_frame->gLastBlock-m_addressPBs) / 192; + sprintf(buffer, "\nThe parameter blocks span from %08x to %08x (%s bytes) impl. %i blocks | numberOfPBs %i | _iSize %i\n", + m_addressPBs, m_frame->gLastBlock, ThS(span).c_str(), nOfBlocks, numberOfPBs, _iSize); + sbuff = sbuff + buffer; strcpy(buffer, ""); + // =============== + + + // ======================================================================================= + // Write settings + // --------------- + sprintf(buffer, "\nSettings: SSBM fix %i | SSBM rem1 %i | SSBM rem2 %i\nSequenced %i | Volume %i | Reset %i | Only looping %i | Save file %i\n", + gSSBM, gSSBMremedy1, gSSBMremedy2, gSequenced, + gVolume, gReset, m_frame->gOnlyLooping, m_frame->gSaveFile); + sbuff = sbuff + buffer; strcpy(buffer, ""); + // =============== + + + // ======================================================================================= + // Show update frequency + // --------------- + sbuff = sbuff + "\n"; + if(!iupdonce) + { + viupd.at(0) = 1; + viupd.at(1) = 1; + viupd.at(2) = 1; + iupdonce = true; + } + + for (u32 i = 0; i < viupd.size(); i++) // 0, 1,..., 9 + { + if (i < viupd.size()-1) + { + viupd.at(viupd.size()-i-1) = viupd.at(viupd.size()-i-2); // move all forward + } + else + { + viupd.at(0) = viupd.at(viupd.size()-1); + } + + // Correction + if (viupd.at(viupd.size()-3) == 1 && viupd.at(viupd.size()-2) == 1 && viupd.at(viupd.size()-1) == 1) + { + viupd.at(0) = 0; + } + if(viupd.at(0) == 0 && viupd.at(1) == 1 && viupd.at(2) == 1 && viupd.at(3) == 0) + { + viupd.at(0) = 1; + } + } + + for (u32 i = 0; i < viupd.size(); i++) + { + if(viupd.at(i) == 0) + sbuff = sbuff + " "; + else + sbuff = sbuff + "."; + } + // ================ + + + // ======================================================================================= + // Print + // ---------------- + ClearScreen(); + wprintf("%s", sbuff.c_str()); + sbuff.clear(); strcpy(buffer, ""); + // ================ + + + // New values are written so update - DISABLED - It flickered a lot, even worse than a + // console window. So for now only the console windows is updated. + /* + if(m_frame) + { + m_frame->NotifyUpdate(); + } + */ + + count2=0; + count1=0; + + } // end of if (j>20) + +} // end of function + + +// I placed this in CUCode_AX so it can share member values with that class +void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a, bool Wii) +{ + /* Doing all this may have a noticable CPU effect, so we can disable it completely + this way. But remember that "Save to file" will not write anything then either. */ + if (m_frame->gUpdFreq > 0) + { + int version; // AX version + int numberOfPBs; + + // Declare structures + AXParamBlock PBs[NUMBER_OF_PBS]; + AXParamBlockWii PBw[NUMBER_OF_PBS]; + AXParamBlockWii_ PBw_[NUMBER_OF_PBS]; + if(_CRC == 0xfa450138) version = 0; else version = 1; + + // Read out structs and number of PBs that have data + if(Wii) + { + if(version == 0) + { + numberOfPBs = ReadOutPBsWii(m_addressPBs, PBw, NUMBER_OF_PBS); + Logging_(_pBuffer, _iSize, a, Wii, PBw, numberOfPBs, m_addressPBs); + } + else + { + numberOfPBs = ReadOutPBsWii(m_addressPBs, PBw_, NUMBER_OF_PBS); + Logging_(_pBuffer, _iSize, a, Wii, PBw_, numberOfPBs, m_addressPBs); + } + } + else + { + numberOfPBs = ReadOutPBs(m_addressPBs, PBs, NUMBER_OF_PBS); + Logging_(_pBuffer, _iSize, a, Wii, PBs, numberOfPBs, m_addressPBs); + } + } +} diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.cpp index 2119351e14..dd7b806599 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.cpp @@ -1,96 +1,96 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "MailHandler.h" - -CMailHandler::CMailHandler() -{ - -} - -CMailHandler::~CMailHandler() -{ - Clear(); -} - -void CMailHandler::PushMail(u32 _Mail) -{ - m_Mails.push(_Mail); - - Update(); -} - -u16 CMailHandler::ReadDSPMailboxHigh() -{ - // check if we have a mail for the core - if (!m_Mails.empty()) - { - u16 result = (m_Mails.front() >> 16) & 0xFFFF; - Update(); - return result; - } - - return 0x00; -} - -u16 CMailHandler::ReadDSPMailboxLow() -{ - // check if we have a mail for the core - if (!m_Mails.empty()) - { - u16 result = m_Mails.front() & 0xFFFF; - m_Mails.pop(); - - Update(); - - return(result); - } - - return 0x00; -} - -void CMailHandler::Clear() -{ - while (!m_Mails.empty()) - m_Mails.pop(); -} - -bool CMailHandler::IsEmpty() -{ - return m_Mails.empty(); -} - -void CMailHandler::Halt(bool _Halt) -{ - if (_Halt) - { - Clear(); - m_Mails.push(0x80544348); - } - - Update(); -} - -void CMailHandler::Update() -{ - if (!IsEmpty()) - { - // g_dspInitialize.pGenerateDSPInterrupt(); - } -} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "MailHandler.h" + +CMailHandler::CMailHandler() +{ + +} + +CMailHandler::~CMailHandler() +{ + Clear(); +} + +void CMailHandler::PushMail(u32 _Mail) +{ + m_Mails.push(_Mail); + + Update(); +} + +u16 CMailHandler::ReadDSPMailboxHigh() +{ + // check if we have a mail for the core + if (!m_Mails.empty()) + { + u16 result = (m_Mails.front() >> 16) & 0xFFFF; + Update(); + return result; + } + + return 0x00; +} + +u16 CMailHandler::ReadDSPMailboxLow() +{ + // check if we have a mail for the core + if (!m_Mails.empty()) + { + u16 result = m_Mails.front() & 0xFFFF; + m_Mails.pop(); + + Update(); + + return(result); + } + + return 0x00; +} + +void CMailHandler::Clear() +{ + while (!m_Mails.empty()) + m_Mails.pop(); +} + +bool CMailHandler::IsEmpty() +{ + return m_Mails.empty(); +} + +void CMailHandler::Halt(bool _Halt) +{ + if (_Halt) + { + Clear(); + m_Mails.push(0x80544348); + } + + Update(); +} + +void CMailHandler::Update() +{ + if (!IsEmpty()) + { + // g_dspInitialize.pGenerateDSPInterrupt(); + } +} + + diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/PCHW/DSoundStream.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/PCHW/DSoundStream.cpp index 1541d20cd0..65ed031ad4 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/PCHW/DSoundStream.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/PCHW/DSoundStream.cpp @@ -1,248 +1,248 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "stdafx.h" - -#include -#include - -#include "DSoundStream.h" - -namespace DSound -{ - -#define BUFSIZE 32768 -#define MAXWAIT 70 //ms - -CRITICAL_SECTION soundCriticalSection; -HANDLE soundSyncEvent; -HANDLE hThread; - -StreamCallback callback; - -IDirectSound8* ds; -IDirectSoundBuffer* dsBuffer; - -int bufferSize; //i bytes -int totalRenderedBytes; -int sampleRate; - -// playback position -int currentPos; -int lastPos; -short realtimeBuffer[1024 * 1024]; - -// We set this to shut down the sound thread. -// 0=keep playing, 1=stop playing NOW. -volatile int threadData; - - -inline int FIX128(int x) -{ - return(x & (~127)); -} - -int DSound_GetSampleRate() -{ - return(sampleRate); -} - -bool CreateBuffer() -{ - PCMWAVEFORMAT pcmwf; - DSBUFFERDESC dsbdesc; - - memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT)); - memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); - - pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM; - pcmwf.wf.nChannels = 2; - pcmwf.wf.nSamplesPerSec = sampleRate; - pcmwf.wf.nBlockAlign = 4; - pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign; - pcmwf.wBitsPerSample = 16; - - //buffer description - dsbdesc.dwSize = sizeof(DSBUFFERDESC); - dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS; //VIKTIGT //DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; - dsbdesc.dwBufferBytes = bufferSize = BUFSIZE; - dsbdesc.lpwfxFormat = (WAVEFORMATEX*)&pcmwf; - - if (SUCCEEDED(ds->CreateSoundBuffer(&dsbdesc, &dsBuffer, NULL))) - { - dsBuffer->SetCurrentPosition(0); - return(true); - } - else - { - // Failed. - dsBuffer = NULL; - return(false); - } -} - -bool WriteDataToBuffer(DWORD dwOffset, // Our own write cursor. - char* soundData, // Start of our data. - DWORD dwSoundBytes) // Size of block to copy. -{ - void* ptr1, * ptr2; - DWORD numBytes1, numBytes2; - // Obtain memory address of write block. This will be in two parts if the block wraps around. - HRESULT hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0); - - // If the buffer was lost, restore and retry lock. - if (DSERR_BUFFERLOST == hr) - { - dsBuffer->Restore(); - hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0); - } - - if (SUCCEEDED(hr)) - { - memcpy(ptr1, soundData, numBytes1); - - if (ptr2 != 0) - { - memcpy(ptr2, soundData + numBytes1, numBytes2); - } - - // Release the data back to DirectSound. - dsBuffer->Unlock(ptr1, numBytes1, ptr2, numBytes2); - return(true); - } - - return(false); -} - -inline int ModBufferSize(int x) -{ - return((x + bufferSize) % bufferSize); -} - -// The audio thread. -DWORD WINAPI soundThread(void*) -{ - currentPos = 0; - lastPos = 0; - - // Prefill buffer? - //writeDataToBuffer(0,realtimeBuffer,bufferSize); - // dsBuffer->Lock(0, bufferSize, (void **)&p1, &num1, (void **)&p2, &num2, 0); - dsBuffer->Play(0, 0, DSBPLAY_LOOPING); - - while (!threadData) - { - // No blocking inside the csection - EnterCriticalSection(&soundCriticalSection); - dsBuffer->GetCurrentPosition((DWORD*)¤tPos, 0); - int numBytesToRender = FIX128(ModBufferSize(currentPos - lastPos)); - - if (numBytesToRender >= 256) - { - if (numBytesToRender > sizeof(realtimeBuffer)) - MessageBox(0,"soundThread: too big render call",0,0); - (*callback)(realtimeBuffer, numBytesToRender >> 2, 16, sampleRate, 2); - - WriteDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender); - currentPos = ModBufferSize(lastPos + numBytesToRender); - totalRenderedBytes += numBytesToRender; - - lastPos = currentPos; - } - - LeaveCriticalSection(&soundCriticalSection); - WaitForSingleObject(soundSyncEvent, MAXWAIT); - } - - dsBuffer->Stop(); - return(0); //hurra! -} - -bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback) -{ - callback = _callback; - threadData = 0; - sampleRate = _sampleRate; - - //no security attributes, automatic resetting, init state nonset, untitled - soundSyncEvent = CreateEvent(0, false, false, 0); - - //vi initierar den........... - InitializeCriticalSection(&soundCriticalSection); - - //vi vill ha access till DSOUND sċ... - if (FAILED(DirectSoundCreate8(0, &ds, 0))) - return false; - - ds->SetCooperativeLevel(window, DSSCL_NORMAL); - - if (!CreateBuffer()) - { - return false; - } - - DWORD num1; - short* p1; - dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0); - memset(p1, 0, num1); - dsBuffer->Unlock(p1, num1, 0, 0); - totalRenderedBytes = -bufferSize; - DWORD h; - hThread = CreateThread(0, 0, soundThread, 0, 0, &h); - SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL); - return true; -} - -void DSound_UpdateSound() -{ - SetEvent(soundSyncEvent); -} - -void DSound_StopSound() -{ - EnterCriticalSection(&soundCriticalSection); - threadData = 1; - // kick the thread if it's waiting - SetEvent(soundSyncEvent); - LeaveCriticalSection(&soundCriticalSection); - WaitForSingleObject(hThread, INFINITE); - CloseHandle(hThread); - - dsBuffer->Release(); - ds->Release(); - - CloseHandle(soundSyncEvent); - soundSyncEvent = INVALID_HANDLE_VALUE; - hThread = INVALID_HANDLE_VALUE; -} - -int DSound_GetCurSample() -{ - EnterCriticalSection(&soundCriticalSection); - int playCursor; - dsBuffer->GetCurrentPosition((DWORD*)&playCursor, 0); - playCursor = ModBufferSize(playCursor - lastPos) + totalRenderedBytes; - LeaveCriticalSection(&soundCriticalSection); - return(playCursor); -} - -float DSound_GetTimer() -{ - return((float)DSound_GetCurSample() * (1.0f / (4.0f * sampleRate))); -} - -} // namespace +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" + +#include +#include + +#include "DSoundStream.h" + +namespace DSound +{ + +#define BUFSIZE 32768 +#define MAXWAIT 70 //ms + +CRITICAL_SECTION soundCriticalSection; +HANDLE soundSyncEvent; +HANDLE hThread; + +StreamCallback callback; + +IDirectSound8* ds; +IDirectSoundBuffer* dsBuffer; + +int bufferSize; //i bytes +int totalRenderedBytes; +int sampleRate; + +// playback position +int currentPos; +int lastPos; +short realtimeBuffer[1024 * 1024]; + +// We set this to shut down the sound thread. +// 0=keep playing, 1=stop playing NOW. +volatile int threadData; + + +inline int FIX128(int x) +{ + return(x & (~127)); +} + +int DSound_GetSampleRate() +{ + return(sampleRate); +} + +bool CreateBuffer() +{ + PCMWAVEFORMAT pcmwf; + DSBUFFERDESC dsbdesc; + + memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT)); + memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); + + pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM; + pcmwf.wf.nChannels = 2; + pcmwf.wf.nSamplesPerSec = sampleRate; + pcmwf.wf.nBlockAlign = 4; + pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign; + pcmwf.wBitsPerSample = 16; + + //buffer description + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS; //VIKTIGT //DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; + dsbdesc.dwBufferBytes = bufferSize = BUFSIZE; + dsbdesc.lpwfxFormat = (WAVEFORMATEX*)&pcmwf; + + if (SUCCEEDED(ds->CreateSoundBuffer(&dsbdesc, &dsBuffer, NULL))) + { + dsBuffer->SetCurrentPosition(0); + return(true); + } + else + { + // Failed. + dsBuffer = NULL; + return(false); + } +} + +bool WriteDataToBuffer(DWORD dwOffset, // Our own write cursor. + char* soundData, // Start of our data. + DWORD dwSoundBytes) // Size of block to copy. +{ + void* ptr1, * ptr2; + DWORD numBytes1, numBytes2; + // Obtain memory address of write block. This will be in two parts if the block wraps around. + HRESULT hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0); + + // If the buffer was lost, restore and retry lock. + if (DSERR_BUFFERLOST == hr) + { + dsBuffer->Restore(); + hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0); + } + + if (SUCCEEDED(hr)) + { + memcpy(ptr1, soundData, numBytes1); + + if (ptr2 != 0) + { + memcpy(ptr2, soundData + numBytes1, numBytes2); + } + + // Release the data back to DirectSound. + dsBuffer->Unlock(ptr1, numBytes1, ptr2, numBytes2); + return(true); + } + + return(false); +} + +inline int ModBufferSize(int x) +{ + return((x + bufferSize) % bufferSize); +} + +// The audio thread. +DWORD WINAPI soundThread(void*) +{ + currentPos = 0; + lastPos = 0; + + // Prefill buffer? + //writeDataToBuffer(0,realtimeBuffer,bufferSize); + // dsBuffer->Lock(0, bufferSize, (void **)&p1, &num1, (void **)&p2, &num2, 0); + dsBuffer->Play(0, 0, DSBPLAY_LOOPING); + + while (!threadData) + { + // No blocking inside the csection + EnterCriticalSection(&soundCriticalSection); + dsBuffer->GetCurrentPosition((DWORD*)¤tPos, 0); + int numBytesToRender = FIX128(ModBufferSize(currentPos - lastPos)); + + if (numBytesToRender >= 256) + { + if (numBytesToRender > sizeof(realtimeBuffer)) + MessageBox(0,"soundThread: too big render call",0,0); + (*callback)(realtimeBuffer, numBytesToRender >> 2, 16, sampleRate, 2); + + WriteDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender); + currentPos = ModBufferSize(lastPos + numBytesToRender); + totalRenderedBytes += numBytesToRender; + + lastPos = currentPos; + } + + LeaveCriticalSection(&soundCriticalSection); + WaitForSingleObject(soundSyncEvent, MAXWAIT); + } + + dsBuffer->Stop(); + return(0); //hurra! +} + +bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback) +{ + callback = _callback; + threadData = 0; + sampleRate = _sampleRate; + + //no security attributes, automatic resetting, init state nonset, untitled + soundSyncEvent = CreateEvent(0, false, false, 0); + + //vi initierar den........... + InitializeCriticalSection(&soundCriticalSection); + + //vi vill ha access till DSOUND sċ... + if (FAILED(DirectSoundCreate8(0, &ds, 0))) + return false; + + ds->SetCooperativeLevel(window, DSSCL_NORMAL); + + if (!CreateBuffer()) + { + return false; + } + + DWORD num1; + short* p1; + dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0); + memset(p1, 0, num1); + dsBuffer->Unlock(p1, num1, 0, 0); + totalRenderedBytes = -bufferSize; + DWORD h; + hThread = CreateThread(0, 0, soundThread, 0, 0, &h); + SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL); + return true; +} + +void DSound_UpdateSound() +{ + SetEvent(soundSyncEvent); +} + +void DSound_StopSound() +{ + EnterCriticalSection(&soundCriticalSection); + threadData = 1; + // kick the thread if it's waiting + SetEvent(soundSyncEvent); + LeaveCriticalSection(&soundCriticalSection); + WaitForSingleObject(hThread, INFINITE); + CloseHandle(hThread); + + dsBuffer->Release(); + ds->Release(); + + CloseHandle(soundSyncEvent); + soundSyncEvent = INVALID_HANDLE_VALUE; + hThread = INVALID_HANDLE_VALUE; +} + +int DSound_GetCurSample() +{ + EnterCriticalSection(&soundCriticalSection); + int playCursor; + dsBuffer->GetCurrentPosition((DWORD*)&playCursor, 0); + playCursor = ModBufferSize(playCursor - lastPos) + totalRenderedBytes; + LeaveCriticalSection(&soundCriticalSection); + return(playCursor); +} + +float DSound_GetTimer() +{ + return((float)DSound_GetCurSample() * (1.0f / (4.0f * sampleRate))); +} + +} // namespace diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/PCHW/Mixer.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/PCHW/Mixer.cpp index 7e9505933f..4d36a3166a 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/PCHW/Mixer.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/PCHW/Mixer.cpp @@ -1,183 +1,183 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -// This queue solution is temporary. I'll implement something more efficient later. - -#include -#include "../Config.h" -#include "../Globals.h" -#include "../DSPHandler.h" -#include "../Logging/Console.h" -#include "Thread.h" -#include "Mixer.h" -#include "FixedSizeQueue.h" - -#ifdef _WIN32 -#include "../PCHW/DSoundStream.h" -#endif - -namespace { -Common::CriticalSection push_sync; - -// On real hardware, this fifo is much, much smaller. But timing is also tighter than under Windows, so... -const int queue_minlength = 1024 * 4; -const int queue_maxlength = 1024 * 28; - -FixedSizeQueue sample_queue; - -} // namespace - -volatile bool mixer_HLEready = false; -volatile int queue_size = 0; - -void Mixer(short *buffer, int numSamples, int bits, int rate, int channels) -{ - // silence - memset(buffer, 0, numSamples * 2 * sizeof(short)); - - // first get the DTK Music - if (g_Config.m_EnableDTKMusic) - { - g_dspInitialize.pGetAudioStreaming(buffer, numSamples); - } - - //if this was called directly from the HLE, and not by timeout - if (g_Config.m_EnableHLEAudio && mixer_HLEready) - { - IUCode* pUCode = CDSPHandler::GetInstance().GetUCode(); - if (pUCode != NULL) - pUCode->MixAdd(buffer, numSamples); - } - - push_sync.Enter(); - int count = 0; - while (queue_size > queue_minlength && count < numSamples * 2) { - int x = buffer[count]; - x += sample_queue.front(); - if (x > 32767) x = 32767; - if (x < -32767) x = -32767; - buffer[count++] = x; - sample_queue.pop(); - x = buffer[count]; - x += sample_queue.front(); - if (x > 32767) x = 32767; - if (x < -32767) x = -32767; - buffer[count++] = x; - sample_queue.pop(); - queue_size-=2; - } - push_sync.Leave(); -} - -void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) { -// static FILE *f; -// if (!f) -// f = fopen("d:\\hello.raw", "wb"); -// fwrite(buffer, num_stereo_samples * 4, 1, f); - if (queue_size == 0) - { - queue_size = queue_minlength; - for (int i = 0; i < queue_minlength; i++) - sample_queue.push((s16)0); - } - - static int PV1l=0,PV2l=0,PV3l=0,PV4l=0; - static int PV1r=0,PV2r=0,PV3r=0,PV4r=0; - static int acc=0; - -#ifdef _WIN32 - if (! (GetAsyncKeyState(VK_TAB)) && g_Config.m_EnableThrottle) { - - /* This is only needed for non-AX sound, currently directly streamed and - DTK sound. For AX we call DSound_UpdateSound in AXTask() for example. */ - while (queue_size > queue_maxlength / 2) { - DSound::DSound_UpdateSound(); - Sleep(0); - } - } else { - return; - } -#else - while (queue_size > queue_maxlength) { - sleep(0); - } -#endif - //convert into config option? - const int mode = 2; - - push_sync.Enter(); - while (num_stereo_samples) - { - acc += sample_rate; - while (num_stereo_samples && (acc >= 48000)) - { - PV4l=PV3l; - PV3l=PV2l; - PV2l=PV1l; - PV1l=*(buffer++); //32bit processing - PV4r=PV3r; - PV3r=PV2r; - PV2r=PV1r; - PV1r=*(buffer++); //32bit processing - num_stereo_samples--; - acc-=48000; - } - - // defaults to nearest - s32 DataL = PV1l; - s32 DataR = PV1r; - - if (mode == 1) //linear - { - DataL = PV1l + ((PV2l - PV1l)*acc)/48000; - DataR = PV1r + ((PV2r - PV1r)*acc)/48000; - } - else if (mode == 2) //cubic - { - s32 a0l = PV1l - PV2l - PV4l + PV3l; - s32 a0r = PV1r - PV2r - PV4r + PV3r; - s32 a1l = PV4l - PV3l - a0l; - s32 a1r = PV4r - PV3r - a0r; - s32 a2l = PV1l - PV4l; - s32 a2r = PV1r - PV4r; - s32 a3l = PV2l; - s32 a3r = PV2r; - - s32 t0l = ((a0l )*acc)/48000; - s32 t0r = ((a0r )*acc)/48000; - s32 t1l = ((t0l+a1l)*acc)/48000; - s32 t1r = ((t0r+a1r)*acc)/48000; - s32 t2l = ((t1l+a2l)*acc)/48000; - s32 t2r = ((t1r+a2r)*acc)/48000; - s32 t3l = ((t2l+a3l)); - s32 t3r = ((t2r+a3r)); - - DataL = t3l; - DataR = t3r; - } - - int l = DataL, r = DataR; - if (l < -32767) l = -32767; - if (r < -32767) r = -32767; - if (l > 32767) l = 32767; - if (r > 32767) r = 32767; - sample_queue.push(l); - sample_queue.push(r); - queue_size += 2; - } - push_sync.Leave(); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +// This queue solution is temporary. I'll implement something more efficient later. + +#include +#include "../Config.h" +#include "../Globals.h" +#include "../DSPHandler.h" +#include "../Logging/Console.h" +#include "Thread.h" +#include "Mixer.h" +#include "FixedSizeQueue.h" + +#ifdef _WIN32 +#include "../PCHW/DSoundStream.h" +#endif + +namespace { +Common::CriticalSection push_sync; + +// On real hardware, this fifo is much, much smaller. But timing is also tighter than under Windows, so... +const int queue_minlength = 1024 * 4; +const int queue_maxlength = 1024 * 28; + +FixedSizeQueue sample_queue; + +} // namespace + +volatile bool mixer_HLEready = false; +volatile int queue_size = 0; + +void Mixer(short *buffer, int numSamples, int bits, int rate, int channels) +{ + // silence + memset(buffer, 0, numSamples * 2 * sizeof(short)); + + // first get the DTK Music + if (g_Config.m_EnableDTKMusic) + { + g_dspInitialize.pGetAudioStreaming(buffer, numSamples); + } + + //if this was called directly from the HLE, and not by timeout + if (g_Config.m_EnableHLEAudio && mixer_HLEready) + { + IUCode* pUCode = CDSPHandler::GetInstance().GetUCode(); + if (pUCode != NULL) + pUCode->MixAdd(buffer, numSamples); + } + + push_sync.Enter(); + int count = 0; + while (queue_size > queue_minlength && count < numSamples * 2) { + int x = buffer[count]; + x += sample_queue.front(); + if (x > 32767) x = 32767; + if (x < -32767) x = -32767; + buffer[count++] = x; + sample_queue.pop(); + x = buffer[count]; + x += sample_queue.front(); + if (x > 32767) x = 32767; + if (x < -32767) x = -32767; + buffer[count++] = x; + sample_queue.pop(); + queue_size-=2; + } + push_sync.Leave(); +} + +void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) { +// static FILE *f; +// if (!f) +// f = fopen("d:\\hello.raw", "wb"); +// fwrite(buffer, num_stereo_samples * 4, 1, f); + if (queue_size == 0) + { + queue_size = queue_minlength; + for (int i = 0; i < queue_minlength; i++) + sample_queue.push((s16)0); + } + + static int PV1l=0,PV2l=0,PV3l=0,PV4l=0; + static int PV1r=0,PV2r=0,PV3r=0,PV4r=0; + static int acc=0; + +#ifdef _WIN32 + if (! (GetAsyncKeyState(VK_TAB)) && g_Config.m_EnableThrottle) { + + /* This is only needed for non-AX sound, currently directly streamed and + DTK sound. For AX we call DSound_UpdateSound in AXTask() for example. */ + while (queue_size > queue_maxlength / 2) { + DSound::DSound_UpdateSound(); + Sleep(0); + } + } else { + return; + } +#else + while (queue_size > queue_maxlength) { + sleep(0); + } +#endif + //convert into config option? + const int mode = 2; + + push_sync.Enter(); + while (num_stereo_samples) + { + acc += sample_rate; + while (num_stereo_samples && (acc >= 48000)) + { + PV4l=PV3l; + PV3l=PV2l; + PV2l=PV1l; + PV1l=*(buffer++); //32bit processing + PV4r=PV3r; + PV3r=PV2r; + PV2r=PV1r; + PV1r=*(buffer++); //32bit processing + num_stereo_samples--; + acc-=48000; + } + + // defaults to nearest + s32 DataL = PV1l; + s32 DataR = PV1r; + + if (mode == 1) //linear + { + DataL = PV1l + ((PV2l - PV1l)*acc)/48000; + DataR = PV1r + ((PV2r - PV1r)*acc)/48000; + } + else if (mode == 2) //cubic + { + s32 a0l = PV1l - PV2l - PV4l + PV3l; + s32 a0r = PV1r - PV2r - PV4r + PV3r; + s32 a1l = PV4l - PV3l - a0l; + s32 a1r = PV4r - PV3r - a0r; + s32 a2l = PV1l - PV4l; + s32 a2r = PV1r - PV4r; + s32 a3l = PV2l; + s32 a3r = PV2r; + + s32 t0l = ((a0l )*acc)/48000; + s32 t0r = ((a0r )*acc)/48000; + s32 t1l = ((t0l+a1l)*acc)/48000; + s32 t1r = ((t0r+a1r)*acc)/48000; + s32 t2l = ((t1l+a2l)*acc)/48000; + s32 t2r = ((t1r+a2r)*acc)/48000; + s32 t3l = ((t2l+a3l)); + s32 t3r = ((t2r+a3r)); + + DataL = t3l; + DataR = t3r; + } + + int l = DataL, r = DataR; + if (l < -32767) l = -32767; + if (r < -32767) r = -32767; + if (l > 32767) l = 32767; + if (r > 32767) r = 32767; + sample_queue.push(l); + sample_queue.push(r); + queue_size += 2; + } + push_sync.Leave(); +} diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX.cpp index b102927ec1..f19c2fc25e 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX.cpp @@ -1,629 +1,629 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "FileUtil.h" // for IsDirectory -#include "StringUtil.h" // for StringFromFormat -#include "../Debugger/Debugger.h" -#include "../Logging/Console.h" // for aprintf -#include - -#ifdef _WIN32 -#include "../PCHW/DSoundStream.h" -#endif -#include "../PCHW/Mixer.h" -#include "../MailHandler.h" - -#include "UCodes.h" -#include "UCode_AXStructs.h" -#include "UCode_AX.h" -#include "UCode_AX_Voice.h" - - -// ------------------------------------------------------------------ -// Externals -// ----------- -extern bool gSSBM; -extern bool gSSBMremedy1; -extern bool gSSBMremedy2; -extern bool gSequenced; -extern bool gVolume; -extern bool gReset; -extern std::string gpName; -extern CDebugger* m_frame; -std::vector sMailLog, sMailTime; -// ----------- - - -CUCode_AX::CUCode_AX(CMailHandler& _rMailHandler) - : IUCode(_rMailHandler) - , m_addressPBs(0xFFFFFFFF) -{ - // we got loaded - m_rMailHandler.PushMail(0xDCD10000); - m_rMailHandler.PushMail(0x80000000); // handshake ??? only (crc == 0xe2136399) needs it ... - - templbuffer = new int[1024 * 1024]; - temprbuffer = new int[1024 * 1024]; -} - -CUCode_AX::~CUCode_AX() -{ - m_rMailHandler.Clear(); - delete [] templbuffer; - delete [] temprbuffer; -} - - -// ============================================ -// Save file to harddrive -// ---------------- -void CUCode_AX::SaveLogFile(std::string f, int resizeTo, bool type, bool Wii) -{ - if(gpName.length() > 0) // thios is currently off in the Release build - { - std::ostringstream ci; - std::ostringstream cType; - - ci << (resizeTo - 1); // write ci - cType << type; // write cType - - std::string FileName = FULL_MAIL_LOGS_DIR + gpName; - FileName += "_sep"; FileName += ci.str(); FileName += "_sep"; FileName += cType.str(); - FileName += Wii ? "_sepWii_sep" : "_sepGC_sep"; FileName += ".log"; - - FILE* fhandle = fopen(FileName.c_str(), "w"); - fprintf(fhandle, f.c_str()); - fflush(fhandle); fhandle = NULL; - } -} - - -// ============================================ -// Save the logged AX mail -// ---------------- -void CUCode_AX::SaveLog_(bool Wii, const char* _fmt, va_list ap) -{ -if(m_frame->ScanMails) -{ - char Msg[512]; - vsprintf(Msg, _fmt, ap); - - //wxMessageBox( wxString::Format("SaveLog_ again: %s\n", Msg) ); - - if(strcmp(Msg, "Begin") == 0) - { - TmpMailLog = ""; - } - else if(strcmp(Msg, "End") == 0) - { - if(saveNext && saveNext < 100) // limit because saveNext is not initialized - { - //wprintf("End"); - - // Save the timestamps and comment - std::ostringstream ci; - ci << (saveNext - 1); - TmpMailLog += "\n\n"; - TmpMailLog += "-----------------------------------------------------------------------\n"; - TmpMailLog += "Current mail: " + gpName + " mail " + ci.str() + "\n"; - if(Wii) - TmpMailLog += "Current CRC: " + StringFromFormat("0x%08x \n\n", _CRC); - - for (u32 i = 0; i < sMailTime.size(); i++) - { - char tmpbuf[128]; sprintf(tmpbuf, "Mail %i received: %s\n", i, sMailTime.at(i).c_str()); - TmpMailLog += tmpbuf; - } - TmpMailLog += "-----------------------------------------------------------------------"; - - sMailLog.push_back(TmpMailLog); - // Save file to disc - if(m_frame->StoreMails) - { - SaveLogFile(TmpMailLog, saveNext, 1, Wii); - } - - m_frame->DoUpdateMail(); // update the view - saveNext = 0; - } - } - else - { - TmpMailLog += Msg; - TmpMailLog += "\n"; - LOG_(1, Msg); // also write it to the log - } -} -} -// ---------------- - - -// ============================================ -// Save the whole AX mail -// ---------------- -void CUCode_AX::SaveMail(bool Wii, u32 _uMail) -{ -if(m_frame->ScanMails) -{ - int i = 0; - std::string sTemp; - std::string sTempEnd; - std::string * sAct = &sTemp; - bool doOnce = true; // for the while loop, to avoid getting stuck - - // Go through the mail - while (i < 250) - { - // Make a new row for each AX-Command - u16 axcomm = Memory_Read_U16(_uMail + i); - if(axcomm < 15 && axcomm != 0) // we can at most write 8 messages per log - { - *sAct += "\n"; - } - - char szTemp2[128] = ""; - sprintf(szTemp2, "%08x : 0x%04x\n", _uMail + i, axcomm); - *sAct += szTemp2; - - // set i to 160 so that we show some things after the end to - if ((axcomm == AXLIST_END || axcomm == 0x000e) && doOnce) - { - i = 160; - sAct = &sTempEnd; - doOnce = false; - } - - i += 2; - } - - // Compare this mail to old mails - u32 addnew = 0; - for (u32 j = 0; j < m_frame->sMail.size(); j++) - { - if(m_frame->sMail.at(j).length() != sTemp.length()) - { - //wxMessageBox( wxString::Format("%s \n\n%s", m_frame->sMail.at(i).c_str(), - // sTemp.c_str()) ); - addnew++; - } - } - - - // In case the mail didn't match any saved mail, save it - if(addnew == m_frame->sMail.size()) - { - //wprintf("%i | %i\n", addnew, m_frame->sMail.size()); - u32 resizeTo = m_frame->sMail.size() + 1; - - // ------------------------------------ - // get timestamp - wxDateTime datetime = wxDateTime::UNow(); - char Msg[128]; - sprintf(Msg, "%04i-%02i-%02i %02i:%02i:%02i:%03i", - datetime.GetYear(), datetime.GetMonth() + 1, datetime.GetDay(), - datetime.GetHour(), datetime.GetMinute(), datetime.GetSecond(), datetime.GetMillisecond()); - sMailTime.push_back(Msg); - // ------------------------------------ - - m_frame->sMail.push_back(sTemp); // save the main comparison mail - std::string lMail = sTemp + "------------------\n" + sTempEnd; - m_frame->sFullMail.push_back(lMail); - - // enable the radio button and update view - if(resizeTo <= m_frame->m_RadioBox[3]->GetCount()) - { - m_frame->m_RadioBox[3]->Enable(resizeTo - 1, true); - m_frame->m_RadioBox[3]->Select(resizeTo - 1); - } - - addnew = 0; - saveNext = resizeTo; // save the log to - - // ------------------------------------ - // Save as file - if(m_frame->StoreMails) - { - //wprintf("m_frame->sMail.size(): %i | resizeTo:%i\n", m_frame->sMail.size(), resizeTo); - SaveLogFile(lMail, resizeTo, 0, Wii); - } - - } - sTemp = ""; - sTempEnd = ""; -} -} -// ---------------- - - -int ReadOutPBs(u32 pbs_address, AXParamBlock* _pPBs, int _num) -{ - int count = 0; - u32 blockAddr = pbs_address; - - // reading and 'halfword' swap - for (int i = 0; i < _num; i++) - { - const short *pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr); - if (pSrc != NULL) - { - short *pDest = (short *)&_pPBs[i]; - for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++) - { - pDest[p] = Common::swap16(pSrc[p]); - - #if defined(_DEBUG) || defined(DEBUGFAST) - if(m_frame) m_frame->gLastBlock = blockAddr + p*2 + 2; // save last block location - #endif - } - blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo; - count++; - - // Detect the last mail by checking when next_pb = 0 - u32 next_pb = (Common::swap16(pSrc[0]) << 16) | Common::swap16(pSrc[1]); - if(next_pb == 0) break; - } - else - break; - } - - // return the number of read PBs - return count; -} - -void WriteBackPBs(u32 pbs_address, AXParamBlock* _pPBs, int _num) -{ - u32 blockAddr = pbs_address; - - // write back and 'halfword'swap - for (int i = 0; i < _num; i++) - { - short* pSrc = (short*)&_pPBs[i]; - short* pDest = (short*)g_dspInitialize.pGetMemoryPointer(blockAddr); - for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++) - { - pDest[p] = Common::swap16(pSrc[p]); - } - - // next block - blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo; - } -} - -void CUCode_AX::MixAdd(short* _pBuffer, int _iSize) -{ - AXParamBlock PBs[NUMBER_OF_PBS]; - - // read out pbs - int numberOfPBs = ReadOutPBs(m_addressPBs, PBs, NUMBER_OF_PBS); - - if (_iSize > 1024 * 1024) - _iSize = 1024 * 1024; - - memset(templbuffer, 0, _iSize * sizeof(int)); - memset(temprbuffer, 0, _iSize * sizeof(int)); - - // write logging data to debugger - if (m_frame) - { - CUCode_AX::Logging(_pBuffer, _iSize, 0, false); - } - - // --------------------------------------------------------------------------------------- - /* Make the updates we are told to do. When there are multiple updates for a block they - are placed in memory directly following updaddr. They are mostly for initial time - delays, sometimes for the FIR filter or channel volumes. We do all of them at once here. - If we get both an on and an off update we chose on. Perhaps that makes the RE1 music - work better. */ - // ------------ - for (int i = 0; i < numberOfPBs; i++) - { - u16 *pDest = (u16 *)&PBs[i]; - u16 upd0 = pDest[34]; u16 upd1 = pDest[35]; u16 upd2 = pDest[36]; // num_updates - u16 upd3 = pDest[37]; u16 upd4 = pDest[38]; - u16 upd_hi = pDest[39]; // update addr - u16 upd_lo = pDest[40]; - int numupd = upd0 + upd1 + upd2 + upd3 + upd4; - if(numupd > 64) numupd = 64; // prevent crazy values - const u32 updaddr = (u32)(upd_hi << 16) | upd_lo; - int on = false, off = false; - for (int j = 0; j < numupd; j++) - { - const u16 updpar = Memory_Read_U16(updaddr + j); - const u16 upddata = Memory_Read_U16(updaddr + j + 2); - // some safety checks, I hope it's enough - if(updaddr > 0x80000000 && updaddr < 0x817fffff - && updpar < 63 && updpar > 3 && upddata >= 0 // updpar > 3 because we don't want to change - // 0-3, those are important - //&& (upd0 || upd1 || upd2 || upd3 || upd4) // We should use these in some way to I think - // but I don't know how or when - && gSequenced) // on and off option - { - pDest[updpar] = upddata; - } - if (updpar == 7 && upddata == 1) on++; - if (updpar == 7 && upddata == 1) off++; - } - // hack: if we get both an on and an off select on rather than off - if (on > 0 && off > 0) pDest[7] = 1; - } - - //aprintf(1, "%08x %04x %04x\n", updaddr, updpar, upddata); - // ------------ - - for (int i = 0; i < numberOfPBs; i++) - { - AXParamBlock& pb = PBs[i]; - MixAddVoice(pb, templbuffer, temprbuffer, _iSize, false); - } - - // write back out pbs - WriteBackPBs(m_addressPBs, PBs, numberOfPBs); - - for (int i = 0; i < _iSize; i++) - { - // Clamp into 16-bit. Maybe we should add a volume compressor here. - int left = templbuffer[i] + _pBuffer[0]; - int right = temprbuffer[i] + _pBuffer[1]; - if (left < -32767) left = -32767; - if (left > 32767) left = 32767; - if (right < -32767) right = -32767; - if (right > 32767) right = 32767; - *_pBuffer++ = left; - *_pBuffer++ = right; - } - - // write logging data to debugger again after the update - if (m_frame) - { - CUCode_AX::Logging(_pBuffer, _iSize, 1, false); - } -} - - -// ------------------------------------------------------------------------------ -// Handle incoming mail -// ----------- -void CUCode_AX::HandleMail(u32 _uMail) -{ - if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST) - { - // a new List - DebugLog(" >>>> u32 MAIL : General Mail (%08x)", _uMail); - } - else - { - DebugLog(" >>>> u32 MAIL : AXTask Mail (%08x)", _uMail); - AXTask(_uMail); - - } -} - - -// ------------------------------------------------------------------------------ -// Update with DSP Interrupt -// ----------- -void CUCode_AX::Update() -{ - // check if we have to sent something - if (!m_rMailHandler.IsEmpty()) - { - g_dspInitialize.pGenerateDSPInterrupt(); - } -} -// ----------- - - -// Shortcut to avoid having to write SaveLog(false, ...) every time -void CUCode_AX::SaveLog(const char* _fmt, ...) -{ - va_list ap; va_start(ap, _fmt); if(m_frame) SaveLog_(false, _fmt, ap); va_end(ap); -} - - -// ============================================ -// AX seems to bootup one task only and waits for resume-callbacks -// everytime the DSP has "spare time" it sends a resume-mail to the CPU -// and the __DSPHandler calls a AX-Callback which generates a new AXFrame -bool CUCode_AX::AXTask(u32& _uMail) -{ - u32 uAddress = _uMail; - SaveLog("Begin"); - SaveLog("====================================================================="); - SaveLog("%08x : AXTask - AXCommandList-Addr:", uAddress); - - u32 Addr__AXStudio; - u32 Addr__AXOutSBuffer; - u32 Addr__AXOutSBuffer_1; - u32 Addr__AXOutSBuffer_2; - u32 Addr__A; - u32 Addr__12; - u32 Addr__4_1; - u32 Addr__4_2; - // u32 Addr__4_3; - // u32 Addr__4_4; - u32 Addr__5_1; - u32 Addr__5_2; - u32 Addr__6; - u32 Addr__9; - - bool bExecuteList = true; - - if(m_frame) SaveMail(false, _uMail); // Save mail for debugging - - while (bExecuteList) - { - static int last_valid_command = 0; - u16 iCommand = Memory_Read_U16(uAddress); - uAddress += 2; - switch (iCommand) - { - case AXLIST_STUDIOADDR: //00 - Addr__AXStudio = Memory_Read_U32(uAddress); - uAddress += 4; - SaveLog("%08x : AXLIST studio address: %08x", uAddress, Addr__AXStudio); - break; - - case 0x001: // 2byte x 10 - { - u32 address = Memory_Read_U32(uAddress); - uAddress += 4; - u16 param1 = Memory_Read_U16(uAddress); - uAddress += 2; - u16 param2 = Memory_Read_U16(uAddress); - uAddress += 2; - u16 param3 = Memory_Read_U16(uAddress); - uAddress += 2; - SaveLog("%08x : AXLIST 1: %08x, %04x, %04x, %04x", uAddress, address, param1, param2, param3); - } - break; - - // - // Somewhere we should be getting a bitmask of AX_SYNC values - // that tells us what has been updated - // Dunno if important - // - case AXLIST_PBADDR: //02 - { - m_addressPBs = Memory_Read_U32(uAddress); - uAddress += 4; - - mixer_HLEready = true; - SaveLog("%08x : AXLIST PB address: %08x", uAddress, m_addressPBs); -#ifdef _WIN32 - SaveLog("Update the SoundThread to be in sync"); - DSound::DSound_UpdateSound(); //do it in this thread to avoid sync problems -#endif - } - break; - - case 0x0003: - SaveLog("%08x : AXLIST command 0x0003 ????"); - break; - - case 0x0004: // AUX? - Addr__4_1 = Memory_Read_U32(uAddress); - uAddress += 4; - Addr__4_2 = Memory_Read_U32(uAddress); - uAddress += 4; - SaveLog("%08x : AXLIST 4_1 4_2 addresses: %08x %08x", uAddress, Addr__4_1, Addr__4_2); - break; - - case 0x0005: - Addr__5_1 = Memory_Read_U32(uAddress); - uAddress += 4; - Addr__5_2 = Memory_Read_U32(uAddress); - uAddress += 4; - SaveLog("%08x : AXLIST 5_1 5_2 addresses: %08x %08x", uAddress, Addr__5_1, Addr__5_2); - break; - - case 0x0006: - Addr__6 = Memory_Read_U32(uAddress); - uAddress += 4; - SaveLog("%08x : AXLIST 6 address: %08x", uAddress, Addr__6); - break; - - case AXLIST_SBUFFER: - Addr__AXOutSBuffer = Memory_Read_U32(uAddress); - uAddress += 4; - SaveLog("%08x : AXLIST OutSBuffer address: %08x", uAddress, Addr__AXOutSBuffer); - break; - - case 0x0009: - Addr__9 = Memory_Read_U32(uAddress); - uAddress += 4; - SaveLog("%08x : AXLIST 6 address: %08x", Addr__9); - break; - - case AXLIST_COMPRESSORTABLE: // 0xa - Addr__A = Memory_Read_U32(uAddress); - uAddress += 4; - SaveLog("%08x : AXLIST CompressorTable address: %08x", uAddress, Addr__A); - break; - - case 0x000e: - Addr__AXOutSBuffer_1 = Memory_Read_U32(uAddress); - uAddress += 4; - - // Addr__AXOutSBuffer_2 is the address in RAM that we are supposed to mix to. - // Although we don't, currently. - Addr__AXOutSBuffer_2 = Memory_Read_U32(uAddress); - uAddress += 4; - SaveLog("%08x : AXLIST sbuf2 addresses: %08x %08x", uAddress, Addr__AXOutSBuffer_1, Addr__AXOutSBuffer_2); - break; - - case AXLIST_END: - bExecuteList = false; - SaveLog("%08x : AXLIST end", uAddress); - break; - - case 0x0010: //Super Monkey Ball 2 - SaveLog("%08x : AXLIST 0x0010", uAddress); - //should probably read/skip stuff here - uAddress += 8; - break; - - case 0x0011: - uAddress += 4; - break; - - case 0x0012: - Addr__12 = Memory_Read_U16(uAddress); - uAddress += 2; - break; - - case 0x0013: - uAddress += 6 * 4; // 6 Addresses. - break; - - default: - { - static bool bFirst = true; - if (bFirst == true) - { - char szTemp[2048]; - sprintf(szTemp, "Unknown AX-Command 0x%x (address: 0x%08x). Last valid: %02x\n", - iCommand, uAddress - 2, last_valid_command); - int num = -32; - while (num < 64+32) - { - char szTemp2[128] = ""; - sprintf(szTemp2, "%s0x%04x\n", num == 0 ? ">>" : " ", Memory_Read_U16(uAddress + num)); - strcat(szTemp, szTemp2); - num += 2; - } - - // Wii AX will always show this - PanicAlert(szTemp); - // bFirst = false; - } - - // unknown command so stop the execution of this TaskList - bExecuteList = false; - } - break; - } - if (bExecuteList) - last_valid_command = iCommand; - } - SaveLog("AXTask - done, send resume"); - SaveLog("====================================================================="); - SaveLog("End"); - - // i hope resume is okay AX - m_rMailHandler.PushMail(0xDCD10001); - return true; -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "FileUtil.h" // for IsDirectory +#include "StringUtil.h" // for StringFromFormat +#include "../Debugger/Debugger.h" +#include "../Logging/Console.h" // for aprintf +#include + +#ifdef _WIN32 +#include "../PCHW/DSoundStream.h" +#endif +#include "../PCHW/Mixer.h" +#include "../MailHandler.h" + +#include "UCodes.h" +#include "UCode_AXStructs.h" +#include "UCode_AX.h" +#include "UCode_AX_Voice.h" + + +// ------------------------------------------------------------------ +// Externals +// ----------- +extern bool gSSBM; +extern bool gSSBMremedy1; +extern bool gSSBMremedy2; +extern bool gSequenced; +extern bool gVolume; +extern bool gReset; +extern std::string gpName; +extern CDebugger* m_frame; +std::vector sMailLog, sMailTime; +// ----------- + + +CUCode_AX::CUCode_AX(CMailHandler& _rMailHandler) + : IUCode(_rMailHandler) + , m_addressPBs(0xFFFFFFFF) +{ + // we got loaded + m_rMailHandler.PushMail(0xDCD10000); + m_rMailHandler.PushMail(0x80000000); // handshake ??? only (crc == 0xe2136399) needs it ... + + templbuffer = new int[1024 * 1024]; + temprbuffer = new int[1024 * 1024]; +} + +CUCode_AX::~CUCode_AX() +{ + m_rMailHandler.Clear(); + delete [] templbuffer; + delete [] temprbuffer; +} + + +// ============================================ +// Save file to harddrive +// ---------------- +void CUCode_AX::SaveLogFile(std::string f, int resizeTo, bool type, bool Wii) +{ + if(gpName.length() > 0) // thios is currently off in the Release build + { + std::ostringstream ci; + std::ostringstream cType; + + ci << (resizeTo - 1); // write ci + cType << type; // write cType + + std::string FileName = FULL_MAIL_LOGS_DIR + gpName; + FileName += "_sep"; FileName += ci.str(); FileName += "_sep"; FileName += cType.str(); + FileName += Wii ? "_sepWii_sep" : "_sepGC_sep"; FileName += ".log"; + + FILE* fhandle = fopen(FileName.c_str(), "w"); + fprintf(fhandle, f.c_str()); + fflush(fhandle); fhandle = NULL; + } +} + + +// ============================================ +// Save the logged AX mail +// ---------------- +void CUCode_AX::SaveLog_(bool Wii, const char* _fmt, va_list ap) +{ +if(m_frame->ScanMails) +{ + char Msg[512]; + vsprintf(Msg, _fmt, ap); + + //wxMessageBox( wxString::Format("SaveLog_ again: %s\n", Msg) ); + + if(strcmp(Msg, "Begin") == 0) + { + TmpMailLog = ""; + } + else if(strcmp(Msg, "End") == 0) + { + if(saveNext && saveNext < 100) // limit because saveNext is not initialized + { + //wprintf("End"); + + // Save the timestamps and comment + std::ostringstream ci; + ci << (saveNext - 1); + TmpMailLog += "\n\n"; + TmpMailLog += "-----------------------------------------------------------------------\n"; + TmpMailLog += "Current mail: " + gpName + " mail " + ci.str() + "\n"; + if(Wii) + TmpMailLog += "Current CRC: " + StringFromFormat("0x%08x \n\n", _CRC); + + for (u32 i = 0; i < sMailTime.size(); i++) + { + char tmpbuf[128]; sprintf(tmpbuf, "Mail %i received: %s\n", i, sMailTime.at(i).c_str()); + TmpMailLog += tmpbuf; + } + TmpMailLog += "-----------------------------------------------------------------------"; + + sMailLog.push_back(TmpMailLog); + // Save file to disc + if(m_frame->StoreMails) + { + SaveLogFile(TmpMailLog, saveNext, 1, Wii); + } + + m_frame->DoUpdateMail(); // update the view + saveNext = 0; + } + } + else + { + TmpMailLog += Msg; + TmpMailLog += "\n"; + LOG_(1, Msg); // also write it to the log + } +} +} +// ---------------- + + +// ============================================ +// Save the whole AX mail +// ---------------- +void CUCode_AX::SaveMail(bool Wii, u32 _uMail) +{ +if(m_frame->ScanMails) +{ + int i = 0; + std::string sTemp; + std::string sTempEnd; + std::string * sAct = &sTemp; + bool doOnce = true; // for the while loop, to avoid getting stuck + + // Go through the mail + while (i < 250) + { + // Make a new row for each AX-Command + u16 axcomm = Memory_Read_U16(_uMail + i); + if(axcomm < 15 && axcomm != 0) // we can at most write 8 messages per log + { + *sAct += "\n"; + } + + char szTemp2[128] = ""; + sprintf(szTemp2, "%08x : 0x%04x\n", _uMail + i, axcomm); + *sAct += szTemp2; + + // set i to 160 so that we show some things after the end to + if ((axcomm == AXLIST_END || axcomm == 0x000e) && doOnce) + { + i = 160; + sAct = &sTempEnd; + doOnce = false; + } + + i += 2; + } + + // Compare this mail to old mails + u32 addnew = 0; + for (u32 j = 0; j < m_frame->sMail.size(); j++) + { + if(m_frame->sMail.at(j).length() != sTemp.length()) + { + //wxMessageBox( wxString::Format("%s \n\n%s", m_frame->sMail.at(i).c_str(), + // sTemp.c_str()) ); + addnew++; + } + } + + + // In case the mail didn't match any saved mail, save it + if(addnew == m_frame->sMail.size()) + { + //wprintf("%i | %i\n", addnew, m_frame->sMail.size()); + u32 resizeTo = m_frame->sMail.size() + 1; + + // ------------------------------------ + // get timestamp + wxDateTime datetime = wxDateTime::UNow(); + char Msg[128]; + sprintf(Msg, "%04i-%02i-%02i %02i:%02i:%02i:%03i", + datetime.GetYear(), datetime.GetMonth() + 1, datetime.GetDay(), + datetime.GetHour(), datetime.GetMinute(), datetime.GetSecond(), datetime.GetMillisecond()); + sMailTime.push_back(Msg); + // ------------------------------------ + + m_frame->sMail.push_back(sTemp); // save the main comparison mail + std::string lMail = sTemp + "------------------\n" + sTempEnd; + m_frame->sFullMail.push_back(lMail); + + // enable the radio button and update view + if(resizeTo <= m_frame->m_RadioBox[3]->GetCount()) + { + m_frame->m_RadioBox[3]->Enable(resizeTo - 1, true); + m_frame->m_RadioBox[3]->Select(resizeTo - 1); + } + + addnew = 0; + saveNext = resizeTo; // save the log to + + // ------------------------------------ + // Save as file + if(m_frame->StoreMails) + { + //wprintf("m_frame->sMail.size(): %i | resizeTo:%i\n", m_frame->sMail.size(), resizeTo); + SaveLogFile(lMail, resizeTo, 0, Wii); + } + + } + sTemp = ""; + sTempEnd = ""; +} +} +// ---------------- + + +int ReadOutPBs(u32 pbs_address, AXParamBlock* _pPBs, int _num) +{ + int count = 0; + u32 blockAddr = pbs_address; + + // reading and 'halfword' swap + for (int i = 0; i < _num; i++) + { + const short *pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr); + if (pSrc != NULL) + { + short *pDest = (short *)&_pPBs[i]; + for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++) + { + pDest[p] = Common::swap16(pSrc[p]); + + #if defined(_DEBUG) || defined(DEBUGFAST) + if(m_frame) m_frame->gLastBlock = blockAddr + p*2 + 2; // save last block location + #endif + } + blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo; + count++; + + // Detect the last mail by checking when next_pb = 0 + u32 next_pb = (Common::swap16(pSrc[0]) << 16) | Common::swap16(pSrc[1]); + if(next_pb == 0) break; + } + else + break; + } + + // return the number of read PBs + return count; +} + +void WriteBackPBs(u32 pbs_address, AXParamBlock* _pPBs, int _num) +{ + u32 blockAddr = pbs_address; + + // write back and 'halfword'swap + for (int i = 0; i < _num; i++) + { + short* pSrc = (short*)&_pPBs[i]; + short* pDest = (short*)g_dspInitialize.pGetMemoryPointer(blockAddr); + for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++) + { + pDest[p] = Common::swap16(pSrc[p]); + } + + // next block + blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo; + } +} + +void CUCode_AX::MixAdd(short* _pBuffer, int _iSize) +{ + AXParamBlock PBs[NUMBER_OF_PBS]; + + // read out pbs + int numberOfPBs = ReadOutPBs(m_addressPBs, PBs, NUMBER_OF_PBS); + + if (_iSize > 1024 * 1024) + _iSize = 1024 * 1024; + + memset(templbuffer, 0, _iSize * sizeof(int)); + memset(temprbuffer, 0, _iSize * sizeof(int)); + + // write logging data to debugger + if (m_frame) + { + CUCode_AX::Logging(_pBuffer, _iSize, 0, false); + } + + // --------------------------------------------------------------------------------------- + /* Make the updates we are told to do. When there are multiple updates for a block they + are placed in memory directly following updaddr. They are mostly for initial time + delays, sometimes for the FIR filter or channel volumes. We do all of them at once here. + If we get both an on and an off update we chose on. Perhaps that makes the RE1 music + work better. */ + // ------------ + for (int i = 0; i < numberOfPBs; i++) + { + u16 *pDest = (u16 *)&PBs[i]; + u16 upd0 = pDest[34]; u16 upd1 = pDest[35]; u16 upd2 = pDest[36]; // num_updates + u16 upd3 = pDest[37]; u16 upd4 = pDest[38]; + u16 upd_hi = pDest[39]; // update addr + u16 upd_lo = pDest[40]; + int numupd = upd0 + upd1 + upd2 + upd3 + upd4; + if(numupd > 64) numupd = 64; // prevent crazy values + const u32 updaddr = (u32)(upd_hi << 16) | upd_lo; + int on = false, off = false; + for (int j = 0; j < numupd; j++) + { + const u16 updpar = Memory_Read_U16(updaddr + j); + const u16 upddata = Memory_Read_U16(updaddr + j + 2); + // some safety checks, I hope it's enough + if(updaddr > 0x80000000 && updaddr < 0x817fffff + && updpar < 63 && updpar > 3 && upddata >= 0 // updpar > 3 because we don't want to change + // 0-3, those are important + //&& (upd0 || upd1 || upd2 || upd3 || upd4) // We should use these in some way to I think + // but I don't know how or when + && gSequenced) // on and off option + { + pDest[updpar] = upddata; + } + if (updpar == 7 && upddata == 1) on++; + if (updpar == 7 && upddata == 1) off++; + } + // hack: if we get both an on and an off select on rather than off + if (on > 0 && off > 0) pDest[7] = 1; + } + + //aprintf(1, "%08x %04x %04x\n", updaddr, updpar, upddata); + // ------------ + + for (int i = 0; i < numberOfPBs; i++) + { + AXParamBlock& pb = PBs[i]; + MixAddVoice(pb, templbuffer, temprbuffer, _iSize, false); + } + + // write back out pbs + WriteBackPBs(m_addressPBs, PBs, numberOfPBs); + + for (int i = 0; i < _iSize; i++) + { + // Clamp into 16-bit. Maybe we should add a volume compressor here. + int left = templbuffer[i] + _pBuffer[0]; + int right = temprbuffer[i] + _pBuffer[1]; + if (left < -32767) left = -32767; + if (left > 32767) left = 32767; + if (right < -32767) right = -32767; + if (right > 32767) right = 32767; + *_pBuffer++ = left; + *_pBuffer++ = right; + } + + // write logging data to debugger again after the update + if (m_frame) + { + CUCode_AX::Logging(_pBuffer, _iSize, 1, false); + } +} + + +// ------------------------------------------------------------------------------ +// Handle incoming mail +// ----------- +void CUCode_AX::HandleMail(u32 _uMail) +{ + if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST) + { + // a new List + DebugLog(" >>>> u32 MAIL : General Mail (%08x)", _uMail); + } + else + { + DebugLog(" >>>> u32 MAIL : AXTask Mail (%08x)", _uMail); + AXTask(_uMail); + + } +} + + +// ------------------------------------------------------------------------------ +// Update with DSP Interrupt +// ----------- +void CUCode_AX::Update() +{ + // check if we have to sent something + if (!m_rMailHandler.IsEmpty()) + { + g_dspInitialize.pGenerateDSPInterrupt(); + } +} +// ----------- + + +// Shortcut to avoid having to write SaveLog(false, ...) every time +void CUCode_AX::SaveLog(const char* _fmt, ...) +{ + va_list ap; va_start(ap, _fmt); if(m_frame) SaveLog_(false, _fmt, ap); va_end(ap); +} + + +// ============================================ +// AX seems to bootup one task only and waits for resume-callbacks +// everytime the DSP has "spare time" it sends a resume-mail to the CPU +// and the __DSPHandler calls a AX-Callback which generates a new AXFrame +bool CUCode_AX::AXTask(u32& _uMail) +{ + u32 uAddress = _uMail; + SaveLog("Begin"); + SaveLog("====================================================================="); + SaveLog("%08x : AXTask - AXCommandList-Addr:", uAddress); + + u32 Addr__AXStudio; + u32 Addr__AXOutSBuffer; + u32 Addr__AXOutSBuffer_1; + u32 Addr__AXOutSBuffer_2; + u32 Addr__A; + u32 Addr__12; + u32 Addr__4_1; + u32 Addr__4_2; + // u32 Addr__4_3; + // u32 Addr__4_4; + u32 Addr__5_1; + u32 Addr__5_2; + u32 Addr__6; + u32 Addr__9; + + bool bExecuteList = true; + + if(m_frame) SaveMail(false, _uMail); // Save mail for debugging + + while (bExecuteList) + { + static int last_valid_command = 0; + u16 iCommand = Memory_Read_U16(uAddress); + uAddress += 2; + switch (iCommand) + { + case AXLIST_STUDIOADDR: //00 + Addr__AXStudio = Memory_Read_U32(uAddress); + uAddress += 4; + SaveLog("%08x : AXLIST studio address: %08x", uAddress, Addr__AXStudio); + break; + + case 0x001: // 2byte x 10 + { + u32 address = Memory_Read_U32(uAddress); + uAddress += 4; + u16 param1 = Memory_Read_U16(uAddress); + uAddress += 2; + u16 param2 = Memory_Read_U16(uAddress); + uAddress += 2; + u16 param3 = Memory_Read_U16(uAddress); + uAddress += 2; + SaveLog("%08x : AXLIST 1: %08x, %04x, %04x, %04x", uAddress, address, param1, param2, param3); + } + break; + + // + // Somewhere we should be getting a bitmask of AX_SYNC values + // that tells us what has been updated + // Dunno if important + // + case AXLIST_PBADDR: //02 + { + m_addressPBs = Memory_Read_U32(uAddress); + uAddress += 4; + + mixer_HLEready = true; + SaveLog("%08x : AXLIST PB address: %08x", uAddress, m_addressPBs); +#ifdef _WIN32 + SaveLog("Update the SoundThread to be in sync"); + DSound::DSound_UpdateSound(); //do it in this thread to avoid sync problems +#endif + } + break; + + case 0x0003: + SaveLog("%08x : AXLIST command 0x0003 ????"); + break; + + case 0x0004: // AUX? + Addr__4_1 = Memory_Read_U32(uAddress); + uAddress += 4; + Addr__4_2 = Memory_Read_U32(uAddress); + uAddress += 4; + SaveLog("%08x : AXLIST 4_1 4_2 addresses: %08x %08x", uAddress, Addr__4_1, Addr__4_2); + break; + + case 0x0005: + Addr__5_1 = Memory_Read_U32(uAddress); + uAddress += 4; + Addr__5_2 = Memory_Read_U32(uAddress); + uAddress += 4; + SaveLog("%08x : AXLIST 5_1 5_2 addresses: %08x %08x", uAddress, Addr__5_1, Addr__5_2); + break; + + case 0x0006: + Addr__6 = Memory_Read_U32(uAddress); + uAddress += 4; + SaveLog("%08x : AXLIST 6 address: %08x", uAddress, Addr__6); + break; + + case AXLIST_SBUFFER: + Addr__AXOutSBuffer = Memory_Read_U32(uAddress); + uAddress += 4; + SaveLog("%08x : AXLIST OutSBuffer address: %08x", uAddress, Addr__AXOutSBuffer); + break; + + case 0x0009: + Addr__9 = Memory_Read_U32(uAddress); + uAddress += 4; + SaveLog("%08x : AXLIST 6 address: %08x", Addr__9); + break; + + case AXLIST_COMPRESSORTABLE: // 0xa + Addr__A = Memory_Read_U32(uAddress); + uAddress += 4; + SaveLog("%08x : AXLIST CompressorTable address: %08x", uAddress, Addr__A); + break; + + case 0x000e: + Addr__AXOutSBuffer_1 = Memory_Read_U32(uAddress); + uAddress += 4; + + // Addr__AXOutSBuffer_2 is the address in RAM that we are supposed to mix to. + // Although we don't, currently. + Addr__AXOutSBuffer_2 = Memory_Read_U32(uAddress); + uAddress += 4; + SaveLog("%08x : AXLIST sbuf2 addresses: %08x %08x", uAddress, Addr__AXOutSBuffer_1, Addr__AXOutSBuffer_2); + break; + + case AXLIST_END: + bExecuteList = false; + SaveLog("%08x : AXLIST end", uAddress); + break; + + case 0x0010: //Super Monkey Ball 2 + SaveLog("%08x : AXLIST 0x0010", uAddress); + //should probably read/skip stuff here + uAddress += 8; + break; + + case 0x0011: + uAddress += 4; + break; + + case 0x0012: + Addr__12 = Memory_Read_U16(uAddress); + uAddress += 2; + break; + + case 0x0013: + uAddress += 6 * 4; // 6 Addresses. + break; + + default: + { + static bool bFirst = true; + if (bFirst == true) + { + char szTemp[2048]; + sprintf(szTemp, "Unknown AX-Command 0x%x (address: 0x%08x). Last valid: %02x\n", + iCommand, uAddress - 2, last_valid_command); + int num = -32; + while (num < 64+32) + { + char szTemp2[128] = ""; + sprintf(szTemp2, "%s0x%04x\n", num == 0 ? ">>" : " ", Memory_Read_U16(uAddress + num)); + strcat(szTemp, szTemp2); + num += 2; + } + + // Wii AX will always show this + PanicAlert(szTemp); + // bFirst = false; + } + + // unknown command so stop the execution of this TaskList + bExecuteList = false; + } + break; + } + if (bExecuteList) + last_valid_command = iCommand; + } + SaveLog("AXTask - done, send resume"); + SaveLog("====================================================================="); + SaveLog("End"); + + // i hope resume is okay AX + m_rMailHandler.PushMail(0xDCD10001); + return true; +} diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXWii.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXWii.cpp index 46745d2ff6..47debbe85a 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXWii.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXWii.cpp @@ -1,432 +1,432 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "StringUtil.h" - -#include "../Debugger/Debugger.h" -#include "../Logging/Console.h" // for aprintf - -#ifdef _WIN32 -#include "../PCHW/DSoundStream.h" -#endif -#include "../PCHW/Mixer.h" -#include "../MailHandler.h" - -#include "UCodes.h" -#include "UCode_AXStructs.h" -#include "UCode_AX.h" // for some functions in CUCode_AX -#include "UCode_AXWii.h" -#include "UCode_AX_Voice.h" - - -// ------------------------------------------------------------------ -// Declarations -// ----------- -extern bool gSequenced; -extern CDebugger * m_frame; -// ----------- - - -CUCode_AXWii::CUCode_AXWii(CMailHandler& _rMailHandler, u32 l_CRC) - : IUCode(_rMailHandler) - , m_addressPBs(0xFFFFFFFF) - , _CRC(l_CRC) -{ - // we got loaded - m_rMailHandler.PushMail(0xDCD10000); - m_rMailHandler.PushMail(0x80000000); // handshake ??? only (crc == 0xe2136399) needs it ... - - templbuffer = new int[1024 * 1024]; - temprbuffer = new int[1024 * 1024]; - - lCUCode_AX = new CUCode_AX(_rMailHandler); - lCUCode_AX->_CRC = l_CRC; -} - -CUCode_AXWii::~CUCode_AXWii() -{ - m_rMailHandler.Clear(); - delete [] templbuffer; - delete [] temprbuffer; -} - -void CUCode_AXWii::HandleMail(u32 _uMail) -{ - if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST) - { - // a new List - } - else - { - AXTask(_uMail); - } -} - - -void CUCode_AXWii::MixAdd(short* _pBuffer, int _iSize) -{ - if(_CRC == 0xfa450138) - { - AXParamBlockWii PBs[NUMBER_OF_PBS]; - MixAdd_( _pBuffer, _iSize, PBs); - } - else - { - AXParamBlockWii_ PBs[NUMBER_OF_PBS]; - MixAdd_(_pBuffer, _iSize, PBs); - } -} - - -template -void CUCode_AXWii::MixAdd_(short* _pBuffer, int _iSize, ParamBlockType &PBs) -{ - //AXParamBlockWii PBs[NUMBER_OF_PBS]; - - // read out pbs - int numberOfPBs = ReadOutPBsWii(m_addressPBs, PBs, NUMBER_OF_PBS); - - if (_iSize > 1024 * 1024) - _iSize = 1024 * 1024; - - // write zeroes to the beginning of templbuffer - memset(templbuffer, 0, _iSize * sizeof(int)); - memset(temprbuffer, 0, _iSize * sizeof(int)); - - // ------------------------------------------- - // write logging data to debugger - if (m_frame) - { - lCUCode_AX->Logging(_pBuffer, _iSize, 0, true); - - // ------------------------------------------- - // Write the first block values - int p = numberOfPBs - 1; - if(numberOfPBs > p) - { - if(PBs[p].running && !m_frame->upd95) - { - const u32 blockAddr = (u32)(PBs[p].this_pb_hi<< 16) | PBs[p].this_pb_lo; - const short *pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr); - for (u32 i = 0; i < sizeof(AXParamBlockWii) / 2; i+=2) - { - if(i == 10 || i == 34 || i == 41 || i == 46 || i == 46 || i == 58 || i == 60 - || i == 68 || i == 88 || i == 95) - {m_frame->str0 += "\n"; m_frame->str95 += "\n";} - - std::string line = StringFromFormat("%02i|%02i : %s : %s", - i/2, i, - m_frame->PBn[i].c_str(), m_frame->PBp[i].c_str() - ); - for (u32 j = 0; j < 50 - line.length(); ++j) - line += " "; - m_frame->str0 += line; - - m_frame->str0 += "\n"; - m_frame->str95 += StringFromFormat(" : %02i|%02i : %04x%04x\n", - i/2, i, - Common::swap16(pSrc[i]), Common::swap16(pSrc[i+1])); - } - m_frame->m_bl95->AppendText(wxString::FromAscii(m_frame->str95.c_str())); - m_frame->m_bl0->AppendText(wxString::FromAscii(m_frame->str0.c_str())); - m_frame->upd95 = true; - } - } - } - // ----------------- - - - // --------------------------------------------------------------------------------------- - /* Make the updates we are told to do. See comments to the GC version in UCode_AX.cpp */ - // ------------ - for (int i = 0; i < numberOfPBs; i++) - { - u16 *pDest = (u16 *)&PBs[i]; - u16 upd0 = pDest[41]; u16 upd1 = pDest[42]; u16 upd2 = pDest[43]; // num_updates - u16 upd_hi = pDest[44]; // update addr - u16 upd_lo = pDest[45]; - int numupd = upd0 + upd1 + upd2; - if(numupd > 64) numupd = 64; // prevent to high values - const u32 updaddr = (u32)(upd_hi << 16) | upd_lo; - int on = false, off = false; - for (int j = 0; j < numupd; j++) // make alll updates - { - const u16 updpar = Memory_Read_U16(updaddr); - const u16 upddata = Memory_Read_U16(updaddr + 2); - // some safety checks, I hope it's enough - if( ( (updaddr > 0x80000000 && updaddr < 0x817fffff) - || (updaddr > 0x90000000 && updaddr < 0x93ffffff) ) - && updpar < 127 && updpar > 3 && upddata >= 0 // updpar > 3 because we don't want to change - // 0-3, those are important - //&& (upd0 || upd1 || upd2) // We should use these in some way to I think - // but I don't know how or when - && gSequenced) // on and off option - { - //PanicAlert("Update %i: %i = %04x", i, updpar, upddata); - //DebugLog("Update: %i = %04x", updpar, upddata); - pDest[updpar] = upddata; - } - if (updpar == 7 && upddata == 1) on++; - if (updpar == 7 && upddata == 1) off++; - } - // hack: if we get both an on and an off select on rather than off - if (on > 0 && off > 0) pDest[7] = 1; - } - - //aprintf(1, "%08x %04x %04x\n", updaddr, updpar, upddata); - // ------------ - - - for (int i = 0; i < numberOfPBs; i++) - { - MixAddVoice(PBs[i], templbuffer, temprbuffer, _iSize, true); - } - - WriteBackPBsWii(m_addressPBs, PBs, numberOfPBs); - // We write the sound to _pBuffer - for (int i = 0; i < _iSize; i++) - { - // Clamp into 16-bit. Maybe we should add a volume compressor here. - int left = templbuffer[i] + _pBuffer[0]; - int right = temprbuffer[i] + _pBuffer[1]; - if (left < -32767) left = -32767; - if (left > 32767) left = 32767; - if (right < -32767) right = -32767; - if (right > 32767) right = 32767; - *_pBuffer++ = left; - *_pBuffer++ = right; - } - - // write logging data to debugger again after the update - if (m_frame) - { - lCUCode_AX->Logging(_pBuffer, _iSize, 1, true); - } -} - - -void CUCode_AXWii::Update() -{ - // check if we have to sent something - if (!m_rMailHandler.IsEmpty()) - { - g_dspInitialize.pGenerateDSPInterrupt(); - } -} - - -// Shortcut -void CUCode_AXWii::SaveLog(const char* _fmt, ...) -{ - va_list ap; va_start(ap, _fmt); if(m_frame) lCUCode_AX->SaveLog_(true, _fmt, ap); va_end(ap); -} - - -// AX seems to bootup one task only and waits for resume-callbacks -// everytime the DSP has "spare time" it sends a resume-mail to the CPU -// and the __DSPHandler calls a AX-Callback which generates a new AXFrame -bool CUCode_AXWii::AXTask(u32& _uMail) -{ - u32 uAddress = _uMail; - SaveLog("Begin"); - SaveLog("====================================================================="); - SaveLog("%08x: AXTask - AXCommandList-Addr", uAddress); - - u32 Addr__AXStudio; - u32 Addr__AXOutSBuffer; - // u32 Addr__AXOutSBuffer_1; - // u32 Addr__AXOutSBuffer_2; - u32 Addr__A; - // u32 Addr__12; - u32 Addr__5_1; - u32 Addr__5_2; - u32 Addr__6; - // u32 Addr__9; - - bool bExecuteList = true; - - if(m_frame) lCUCode_AX->SaveMail(true, uAddress); // Save mail for debugging - - if (false) - { - // PanicAlert("%i", sizeof(AXParamBlockWii)); // 252 ?? - FILE *f = fopen("D:\\axdump.txt", "a"); - if (!f) - f = fopen("D:\\axdump.txt", "w"); - - u32 addr = uAddress; - for (int i = 0; i < 100; i++) { - fprintf(f, "%02x\n", Memory_Read_U16(addr + i * 2)); - } - fprintf(f, "===========------------------------------------------------=\n"); - fclose(f); - } - else - { - // PanicAlert("%i", sizeof(AXParamBlock)); // 192 - } - - while (bExecuteList) - { - static int last_valid_command = 0; - u16 iCommand = Memory_Read_U16(uAddress); - uAddress += 2; - switch (iCommand) - { - case 0x0000: //00 - Addr__AXStudio = Memory_Read_U32(uAddress); - uAddress += 4; - SaveLog("%08x : AXLIST studio address: %08x", uAddress, Addr__AXStudio); - break; - - case 0x0001: - { - u32 address = Memory_Read_U32(uAddress); - uAddress += 4; - SaveLog("%08x : AXLIST 1: %08x", uAddress, address); - } - break; - - case 0x0003: - { - u32 address = Memory_Read_U32(uAddress); - uAddress += 4; - SaveLog("%08x : AXLIST 3: %08x", uAddress, address); - } - break; - - case 0x0004: // PBs are here now - m_addressPBs = Memory_Read_U32(uAddress); - lCUCode_AX->m_addressPBs = m_addressPBs; // for the sake of logging - mixer_HLEready = true; - SaveLog("%08x : AXLIST PB address: %08x", uAddress, m_addressPBs); -#ifdef _WIN32 - //DebugLog("Update the SoundThread to be in sync"); - DSound::DSound_UpdateSound(); //do it in this thread to avoid sync problems -#endif - uAddress += 4; - break; - - case 0x0005: - if(Memory_Read_U16(uAddress) > 25) // this occured in Wii Sports - { - Addr__5_1 = Memory_Read_U32(uAddress); - uAddress += 4; - Addr__5_2 = Memory_Read_U32(uAddress); - uAddress += 4; - - uAddress += 2; - SaveLog("%08x : AXLIST 5_1 5_2 addresses: %08x %08x", uAddress, Addr__5_1, Addr__5_2); - } - else - { - uAddress += 2; - SaveLog("%08x : AXLIST Empty 0x0005", uAddress); - } - break; - - case 0x0006: - Addr__6 = Memory_Read_U32(uAddress); - uAddress += 10; - SaveLog("%08x : AXLIST 6 address: %08x", uAddress, Addr__6); - break; - -/**/ case 0x0007: // AXLIST_SBUFFER - Addr__AXOutSBuffer = Memory_Read_U32(uAddress); - uAddress += 10; - // uAddress += 12; - SaveLog("%08x : AXLIST OutSBuffer (0x0007) address: %08x", uAddress, Addr__AXOutSBuffer); - break; - -/* case 0x0009: - Addr__9 = Memory_Read_U32(uAddress); - uAddress += 4; - DebugLog("AXLIST 6 address: %08x", Addr__9); - break;*/ - - case 0x000a: // AXLIST_COMPRESSORTABLE - Addr__A = Memory_Read_U32(uAddress); - uAddress += 4; - //Addr__A = Memory_Read_U32(uAddress); - uAddress += 4; - SaveLog("%08x : AXLIST CompressorTable address: %08x", uAddress, Addr__A); - break; - - case 0x000b: - uAddress += 2; // one 0x8000 in rabbids - uAddress += 4 * 2; // then two RAM addressses - break; - - case 0x000c: - uAddress += 2; // one 0x8000 in rabbids - uAddress += 4 * 2; // then two RAM addressses - break; - - case 0x000d: - uAddress += 4 * 4; - break; - - case 0x000e: - // This is the end. - bExecuteList = false; - SaveLog("%08x : AXLIST end, wii stylee.", uAddress); - break; - - default: - { - static bool bFirst = true; - if (bFirst == true) - { - // A little more descreet way to say that there is a problem, that also let you - // take a look at the mail (and possible previous mails) in the debugger - SaveLog("%08x : Unknown AX-Command 0x%04x", uAddress, iCommand); - bExecuteList = false; - break; - - char szTemp[2048]; - sprintf(szTemp, "Unknown AX-Command 0x%04x (address: 0x%08x). Last valid: %02x\n", - iCommand, uAddress - 2, last_valid_command); - int num = -32; - while (num < 64+32) - { - char szTemp2[128] = ""; - sprintf(szTemp2, "%s0x%04x\n", num == 0 ? ">>" : " ", Memory_Read_U16(uAddress + num)); - strcat(szTemp, szTemp2); - num += 2; - } - - // Wii AX will always show this - PanicAlert(szTemp); - // bFirst = false; - } - - // unknown command so stop the execution of this TaskList - bExecuteList = false; - } - break; - } - if (bExecuteList) - last_valid_command = iCommand; - } - SaveLog("AXTask - done, send resume"); - SaveLog("====================================================================="); - SaveLog("End"); - - // i hope resume is okay AX - m_rMailHandler.PushMail(0xDCD10001); - return true; -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "StringUtil.h" + +#include "../Debugger/Debugger.h" +#include "../Logging/Console.h" // for aprintf + +#ifdef _WIN32 +#include "../PCHW/DSoundStream.h" +#endif +#include "../PCHW/Mixer.h" +#include "../MailHandler.h" + +#include "UCodes.h" +#include "UCode_AXStructs.h" +#include "UCode_AX.h" // for some functions in CUCode_AX +#include "UCode_AXWii.h" +#include "UCode_AX_Voice.h" + + +// ------------------------------------------------------------------ +// Declarations +// ----------- +extern bool gSequenced; +extern CDebugger * m_frame; +// ----------- + + +CUCode_AXWii::CUCode_AXWii(CMailHandler& _rMailHandler, u32 l_CRC) + : IUCode(_rMailHandler) + , m_addressPBs(0xFFFFFFFF) + , _CRC(l_CRC) +{ + // we got loaded + m_rMailHandler.PushMail(0xDCD10000); + m_rMailHandler.PushMail(0x80000000); // handshake ??? only (crc == 0xe2136399) needs it ... + + templbuffer = new int[1024 * 1024]; + temprbuffer = new int[1024 * 1024]; + + lCUCode_AX = new CUCode_AX(_rMailHandler); + lCUCode_AX->_CRC = l_CRC; +} + +CUCode_AXWii::~CUCode_AXWii() +{ + m_rMailHandler.Clear(); + delete [] templbuffer; + delete [] temprbuffer; +} + +void CUCode_AXWii::HandleMail(u32 _uMail) +{ + if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST) + { + // a new List + } + else + { + AXTask(_uMail); + } +} + + +void CUCode_AXWii::MixAdd(short* _pBuffer, int _iSize) +{ + if(_CRC == 0xfa450138) + { + AXParamBlockWii PBs[NUMBER_OF_PBS]; + MixAdd_( _pBuffer, _iSize, PBs); + } + else + { + AXParamBlockWii_ PBs[NUMBER_OF_PBS]; + MixAdd_(_pBuffer, _iSize, PBs); + } +} + + +template +void CUCode_AXWii::MixAdd_(short* _pBuffer, int _iSize, ParamBlockType &PBs) +{ + //AXParamBlockWii PBs[NUMBER_OF_PBS]; + + // read out pbs + int numberOfPBs = ReadOutPBsWii(m_addressPBs, PBs, NUMBER_OF_PBS); + + if (_iSize > 1024 * 1024) + _iSize = 1024 * 1024; + + // write zeroes to the beginning of templbuffer + memset(templbuffer, 0, _iSize * sizeof(int)); + memset(temprbuffer, 0, _iSize * sizeof(int)); + + // ------------------------------------------- + // write logging data to debugger + if (m_frame) + { + lCUCode_AX->Logging(_pBuffer, _iSize, 0, true); + + // ------------------------------------------- + // Write the first block values + int p = numberOfPBs - 1; + if(numberOfPBs > p) + { + if(PBs[p].running && !m_frame->upd95) + { + const u32 blockAddr = (u32)(PBs[p].this_pb_hi<< 16) | PBs[p].this_pb_lo; + const short *pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr); + for (u32 i = 0; i < sizeof(AXParamBlockWii) / 2; i+=2) + { + if(i == 10 || i == 34 || i == 41 || i == 46 || i == 46 || i == 58 || i == 60 + || i == 68 || i == 88 || i == 95) + {m_frame->str0 += "\n"; m_frame->str95 += "\n";} + + std::string line = StringFromFormat("%02i|%02i : %s : %s", + i/2, i, + m_frame->PBn[i].c_str(), m_frame->PBp[i].c_str() + ); + for (u32 j = 0; j < 50 - line.length(); ++j) + line += " "; + m_frame->str0 += line; + + m_frame->str0 += "\n"; + m_frame->str95 += StringFromFormat(" : %02i|%02i : %04x%04x\n", + i/2, i, + Common::swap16(pSrc[i]), Common::swap16(pSrc[i+1])); + } + m_frame->m_bl95->AppendText(wxString::FromAscii(m_frame->str95.c_str())); + m_frame->m_bl0->AppendText(wxString::FromAscii(m_frame->str0.c_str())); + m_frame->upd95 = true; + } + } + } + // ----------------- + + + // --------------------------------------------------------------------------------------- + /* Make the updates we are told to do. See comments to the GC version in UCode_AX.cpp */ + // ------------ + for (int i = 0; i < numberOfPBs; i++) + { + u16 *pDest = (u16 *)&PBs[i]; + u16 upd0 = pDest[41]; u16 upd1 = pDest[42]; u16 upd2 = pDest[43]; // num_updates + u16 upd_hi = pDest[44]; // update addr + u16 upd_lo = pDest[45]; + int numupd = upd0 + upd1 + upd2; + if(numupd > 64) numupd = 64; // prevent to high values + const u32 updaddr = (u32)(upd_hi << 16) | upd_lo; + int on = false, off = false; + for (int j = 0; j < numupd; j++) // make alll updates + { + const u16 updpar = Memory_Read_U16(updaddr); + const u16 upddata = Memory_Read_U16(updaddr + 2); + // some safety checks, I hope it's enough + if( ( (updaddr > 0x80000000 && updaddr < 0x817fffff) + || (updaddr > 0x90000000 && updaddr < 0x93ffffff) ) + && updpar < 127 && updpar > 3 && upddata >= 0 // updpar > 3 because we don't want to change + // 0-3, those are important + //&& (upd0 || upd1 || upd2) // We should use these in some way to I think + // but I don't know how or when + && gSequenced) // on and off option + { + //PanicAlert("Update %i: %i = %04x", i, updpar, upddata); + //DebugLog("Update: %i = %04x", updpar, upddata); + pDest[updpar] = upddata; + } + if (updpar == 7 && upddata == 1) on++; + if (updpar == 7 && upddata == 1) off++; + } + // hack: if we get both an on and an off select on rather than off + if (on > 0 && off > 0) pDest[7] = 1; + } + + //aprintf(1, "%08x %04x %04x\n", updaddr, updpar, upddata); + // ------------ + + + for (int i = 0; i < numberOfPBs; i++) + { + MixAddVoice(PBs[i], templbuffer, temprbuffer, _iSize, true); + } + + WriteBackPBsWii(m_addressPBs, PBs, numberOfPBs); + // We write the sound to _pBuffer + for (int i = 0; i < _iSize; i++) + { + // Clamp into 16-bit. Maybe we should add a volume compressor here. + int left = templbuffer[i] + _pBuffer[0]; + int right = temprbuffer[i] + _pBuffer[1]; + if (left < -32767) left = -32767; + if (left > 32767) left = 32767; + if (right < -32767) right = -32767; + if (right > 32767) right = 32767; + *_pBuffer++ = left; + *_pBuffer++ = right; + } + + // write logging data to debugger again after the update + if (m_frame) + { + lCUCode_AX->Logging(_pBuffer, _iSize, 1, true); + } +} + + +void CUCode_AXWii::Update() +{ + // check if we have to sent something + if (!m_rMailHandler.IsEmpty()) + { + g_dspInitialize.pGenerateDSPInterrupt(); + } +} + + +// Shortcut +void CUCode_AXWii::SaveLog(const char* _fmt, ...) +{ + va_list ap; va_start(ap, _fmt); if(m_frame) lCUCode_AX->SaveLog_(true, _fmt, ap); va_end(ap); +} + + +// AX seems to bootup one task only and waits for resume-callbacks +// everytime the DSP has "spare time" it sends a resume-mail to the CPU +// and the __DSPHandler calls a AX-Callback which generates a new AXFrame +bool CUCode_AXWii::AXTask(u32& _uMail) +{ + u32 uAddress = _uMail; + SaveLog("Begin"); + SaveLog("====================================================================="); + SaveLog("%08x: AXTask - AXCommandList-Addr", uAddress); + + u32 Addr__AXStudio; + u32 Addr__AXOutSBuffer; + // u32 Addr__AXOutSBuffer_1; + // u32 Addr__AXOutSBuffer_2; + u32 Addr__A; + // u32 Addr__12; + u32 Addr__5_1; + u32 Addr__5_2; + u32 Addr__6; + // u32 Addr__9; + + bool bExecuteList = true; + + if(m_frame) lCUCode_AX->SaveMail(true, uAddress); // Save mail for debugging + + if (false) + { + // PanicAlert("%i", sizeof(AXParamBlockWii)); // 252 ?? + FILE *f = fopen("D:\\axdump.txt", "a"); + if (!f) + f = fopen("D:\\axdump.txt", "w"); + + u32 addr = uAddress; + for (int i = 0; i < 100; i++) { + fprintf(f, "%02x\n", Memory_Read_U16(addr + i * 2)); + } + fprintf(f, "===========------------------------------------------------=\n"); + fclose(f); + } + else + { + // PanicAlert("%i", sizeof(AXParamBlock)); // 192 + } + + while (bExecuteList) + { + static int last_valid_command = 0; + u16 iCommand = Memory_Read_U16(uAddress); + uAddress += 2; + switch (iCommand) + { + case 0x0000: //00 + Addr__AXStudio = Memory_Read_U32(uAddress); + uAddress += 4; + SaveLog("%08x : AXLIST studio address: %08x", uAddress, Addr__AXStudio); + break; + + case 0x0001: + { + u32 address = Memory_Read_U32(uAddress); + uAddress += 4; + SaveLog("%08x : AXLIST 1: %08x", uAddress, address); + } + break; + + case 0x0003: + { + u32 address = Memory_Read_U32(uAddress); + uAddress += 4; + SaveLog("%08x : AXLIST 3: %08x", uAddress, address); + } + break; + + case 0x0004: // PBs are here now + m_addressPBs = Memory_Read_U32(uAddress); + lCUCode_AX->m_addressPBs = m_addressPBs; // for the sake of logging + mixer_HLEready = true; + SaveLog("%08x : AXLIST PB address: %08x", uAddress, m_addressPBs); +#ifdef _WIN32 + //DebugLog("Update the SoundThread to be in sync"); + DSound::DSound_UpdateSound(); //do it in this thread to avoid sync problems +#endif + uAddress += 4; + break; + + case 0x0005: + if(Memory_Read_U16(uAddress) > 25) // this occured in Wii Sports + { + Addr__5_1 = Memory_Read_U32(uAddress); + uAddress += 4; + Addr__5_2 = Memory_Read_U32(uAddress); + uAddress += 4; + + uAddress += 2; + SaveLog("%08x : AXLIST 5_1 5_2 addresses: %08x %08x", uAddress, Addr__5_1, Addr__5_2); + } + else + { + uAddress += 2; + SaveLog("%08x : AXLIST Empty 0x0005", uAddress); + } + break; + + case 0x0006: + Addr__6 = Memory_Read_U32(uAddress); + uAddress += 10; + SaveLog("%08x : AXLIST 6 address: %08x", uAddress, Addr__6); + break; + +/**/ case 0x0007: // AXLIST_SBUFFER + Addr__AXOutSBuffer = Memory_Read_U32(uAddress); + uAddress += 10; + // uAddress += 12; + SaveLog("%08x : AXLIST OutSBuffer (0x0007) address: %08x", uAddress, Addr__AXOutSBuffer); + break; + +/* case 0x0009: + Addr__9 = Memory_Read_U32(uAddress); + uAddress += 4; + DebugLog("AXLIST 6 address: %08x", Addr__9); + break;*/ + + case 0x000a: // AXLIST_COMPRESSORTABLE + Addr__A = Memory_Read_U32(uAddress); + uAddress += 4; + //Addr__A = Memory_Read_U32(uAddress); + uAddress += 4; + SaveLog("%08x : AXLIST CompressorTable address: %08x", uAddress, Addr__A); + break; + + case 0x000b: + uAddress += 2; // one 0x8000 in rabbids + uAddress += 4 * 2; // then two RAM addressses + break; + + case 0x000c: + uAddress += 2; // one 0x8000 in rabbids + uAddress += 4 * 2; // then two RAM addressses + break; + + case 0x000d: + uAddress += 4 * 4; + break; + + case 0x000e: + // This is the end. + bExecuteList = false; + SaveLog("%08x : AXLIST end, wii stylee.", uAddress); + break; + + default: + { + static bool bFirst = true; + if (bFirst == true) + { + // A little more descreet way to say that there is a problem, that also let you + // take a look at the mail (and possible previous mails) in the debugger + SaveLog("%08x : Unknown AX-Command 0x%04x", uAddress, iCommand); + bExecuteList = false; + break; + + char szTemp[2048]; + sprintf(szTemp, "Unknown AX-Command 0x%04x (address: 0x%08x). Last valid: %02x\n", + iCommand, uAddress - 2, last_valid_command); + int num = -32; + while (num < 64+32) + { + char szTemp2[128] = ""; + sprintf(szTemp2, "%s0x%04x\n", num == 0 ? ">>" : " ", Memory_Read_U16(uAddress + num)); + strcat(szTemp, szTemp2); + num += 2; + } + + // Wii AX will always show this + PanicAlert(szTemp); + // bFirst = false; + } + + // unknown command so stop the execution of this TaskList + bExecuteList = false; + } + break; + } + if (bExecuteList) + last_valid_command = iCommand; + } + SaveLog("AXTask - done, send resume"); + SaveLog("====================================================================="); + SaveLog("End"); + + // i hope resume is okay AX + m_rMailHandler.PushMail(0xDCD10001); + return true; +} diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_CARD.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_CARD.cpp index a0a6e53c48..3289304014 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_CARD.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_CARD.cpp @@ -1,62 +1,62 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "../Globals.h" -#include "../DSPHandler.h" -#include "UCodes.h" -#include "UCode_CARD.h" - - -CUCode_CARD::CUCode_CARD(CMailHandler& _rMailHandler) - : IUCode(_rMailHandler) -{ - DebugLog("CUCode_CARD - initialized"); - m_rMailHandler.PushMail(DSP_INIT); -} - - -CUCode_CARD::~CUCode_CARD() -{ - m_rMailHandler.Clear(); -} - - -void CUCode_CARD::Update() -{ - // check if we have to sent something - if (!m_rMailHandler.IsEmpty()) - { - g_dspInitialize.pGenerateDSPInterrupt(); - } -} - -void CUCode_CARD::HandleMail(u32 _uMail) -{ - if (_uMail == 0xFF000000) // unlock card - { - // m_Mails.push(0x00000001); // ACK (actualy anything != 0) - } - else - { - DebugLog("CUCode_CARD - unknown cmd: %x (size %i)", _uMail); - } - - m_rMailHandler.PushMail(DSP_DONE); - CDSPHandler::GetInstance().SetUCode(UCODE_ROM); -} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "../Globals.h" +#include "../DSPHandler.h" +#include "UCodes.h" +#include "UCode_CARD.h" + + +CUCode_CARD::CUCode_CARD(CMailHandler& _rMailHandler) + : IUCode(_rMailHandler) +{ + DebugLog("CUCode_CARD - initialized"); + m_rMailHandler.PushMail(DSP_INIT); +} + + +CUCode_CARD::~CUCode_CARD() +{ + m_rMailHandler.Clear(); +} + + +void CUCode_CARD::Update() +{ + // check if we have to sent something + if (!m_rMailHandler.IsEmpty()) + { + g_dspInitialize.pGenerateDSPInterrupt(); + } +} + +void CUCode_CARD::HandleMail(u32 _uMail) +{ + if (_uMail == 0xFF000000) // unlock card + { + // m_Mails.push(0x00000001); // ACK (actualy anything != 0) + } + else + { + DebugLog("CUCode_CARD - unknown cmd: %x (size %i)", _uMail); + } + + m_rMailHandler.PushMail(DSP_DONE); + CDSPHandler::GetInstance().SetUCode(UCODE_ROM); +} + + diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.cpp index 6a667c92ce..9cc863798a 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.cpp @@ -1,53 +1,53 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "../Globals.h" -#include "../DSPHandler.h" -#include "UCodes.h" -#include "UCode_InitAudioSystem.h" - -CUCode_InitAudioSystem::CUCode_InitAudioSystem(CMailHandler& _rMailHandler) - : IUCode(_rMailHandler) - , m_BootTask_numSteps(0) - , m_NextParameter(0) - , IsInitialized(false) -{ - DebugLog("CUCode_InitAudioSystem - initialized"); -} - - -CUCode_InitAudioSystem::~CUCode_InitAudioSystem() -{} - - -void CUCode_InitAudioSystem::Init() -{} - - -void CUCode_InitAudioSystem::Update() -{ - if (m_rMailHandler.IsEmpty()) - { - m_rMailHandler.PushMail(0x80544348); - // HALT - } -} - -void CUCode_InitAudioSystem::HandleMail(u32 _uMail) -{} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "../Globals.h" +#include "../DSPHandler.h" +#include "UCodes.h" +#include "UCode_InitAudioSystem.h" + +CUCode_InitAudioSystem::CUCode_InitAudioSystem(CMailHandler& _rMailHandler) + : IUCode(_rMailHandler) + , m_BootTask_numSteps(0) + , m_NextParameter(0) + , IsInitialized(false) +{ + DebugLog("CUCode_InitAudioSystem - initialized"); +} + + +CUCode_InitAudioSystem::~CUCode_InitAudioSystem() +{} + + +void CUCode_InitAudioSystem::Init() +{} + + +void CUCode_InitAudioSystem::Update() +{ + if (m_rMailHandler.IsEmpty()) + { + m_rMailHandler.PushMail(0x80544348); + // HALT + } +} + +void CUCode_InitAudioSystem::HandleMail(u32 _uMail) +{} + + diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Jac.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Jac.cpp index 2f3be39796..15b608ecce 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Jac.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Jac.cpp @@ -1,161 +1,161 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "../Globals.h" -#include "UCodes.h" -#include "UCode_Jac.h" -#include "../MailHandler.h" - -CUCode_Jac::CUCode_Jac(CMailHandler& _rMailHandler) - : IUCode(_rMailHandler) - , m_bListInProgress(false) -{ - DebugLog("CUCode_Jac: init"); - m_rMailHandler.PushMail(0xDCD10000); - m_rMailHandler.PushMail(0x80000000); -} - - -CUCode_Jac::~CUCode_Jac() -{ - m_rMailHandler.Clear(); -} - - -void CUCode_Jac::HandleMail(u32 _uMail) -{ - // this is prolly totally bullshit and should work like the zelda one... - // but i am to lazy to change it atm - - if (m_bListInProgress == false) - { - // get the command to find out how much steps it has - switch (_uMail & 0xFFFF) - { - // release halt - case 0x00: - // m_Mails.push(0x80000000); - g_dspInitialize.pGenerateDSPInterrupt(); - break; - - case 0x40: - m_step = 0; - ((u32*)m_Buffer)[m_step++] = _uMail; - m_bListInProgress = true; - m_numSteps = 5; - break; - - case 0x2000: - case 0x4000: - m_step = 0; - ((u32*)m_Buffer)[m_step++] = _uMail; - m_bListInProgress = true; - m_numSteps = 3; - break; - - default: - PanicAlert("UCode Jac"); - DebugLog("UCode Jac - unknown cmd: %x", _uMail & 0xFFFF); - break; - } - } - else - { - ((u32*)m_Buffer)[m_step] = _uMail; - m_step++; - - if (m_step == m_numSteps) - { - ExecuteList(); - m_bListInProgress = false; - } - } -} - - -void CUCode_Jac::Update() -{ - // check if we have to sent something -/* if (!g_MailHandler.empty()) - { - g_dspInitialize.pGenerateDSPInterrupt(); - }*/ -} - - -void CUCode_Jac::ExecuteList() -{ - // begin with the list - m_readOffset = 0; - - u16 cmd = Read16(); - u16 sync = Read16(); - - DebugLog("=============================================================================="); - DebugLog("UCode Jac - execute dlist (cmd: 0x%04x : sync: 0x%04x)", cmd, sync); - - switch (cmd) - { - // ============================================================================== - // DsetupTable - // ============================================================================== - case 0x40: - { - u32 tmp[4]; - tmp[0] = Read32(); - tmp[1] = Read32(); - tmp[2] = Read32(); - tmp[3] = Read32(); - - DebugLog("DsetupTable"); - DebugLog("???: 0x%08x", tmp[0]); - DebugLog("DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]); - DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]); - DebugLog("???: 0x%08x", tmp[3]); - } - break; - - // ============================================================================== - // UpdateDSPChannel - // ============================================================================== - case 0x2000: - case 0x4000: // animal crossing - { - u32 tmp[3]; - tmp[0] = Read32(); - tmp[1] = Read32(); - tmp[2] = Read32(); - - DebugLog("UpdateDSPChannel"); - DebugLog("audiomemory: 0x%08x", tmp[0]); - DebugLog("audiomemory: 0x%08x", tmp[1]); - DebugLog("DSPADPCM_FILTER (size: 0x40): 0x%08x", tmp[2]); - } - break; - - default: - PanicAlert("UCode Jac unknown cmd: %s (size %i)", cmd, m_numSteps); - DebugLog("Jac UCode - unknown cmd: %x (size %i)", cmd, m_numSteps); - break; - } - - // sync, we are rdy - m_rMailHandler.PushMail(DSP_SYNC); - m_rMailHandler.PushMail(0xF3550000 | sync); -} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "../Globals.h" +#include "UCodes.h" +#include "UCode_Jac.h" +#include "../MailHandler.h" + +CUCode_Jac::CUCode_Jac(CMailHandler& _rMailHandler) + : IUCode(_rMailHandler) + , m_bListInProgress(false) +{ + DebugLog("CUCode_Jac: init"); + m_rMailHandler.PushMail(0xDCD10000); + m_rMailHandler.PushMail(0x80000000); +} + + +CUCode_Jac::~CUCode_Jac() +{ + m_rMailHandler.Clear(); +} + + +void CUCode_Jac::HandleMail(u32 _uMail) +{ + // this is prolly totally bullshit and should work like the zelda one... + // but i am to lazy to change it atm + + if (m_bListInProgress == false) + { + // get the command to find out how much steps it has + switch (_uMail & 0xFFFF) + { + // release halt + case 0x00: + // m_Mails.push(0x80000000); + g_dspInitialize.pGenerateDSPInterrupt(); + break; + + case 0x40: + m_step = 0; + ((u32*)m_Buffer)[m_step++] = _uMail; + m_bListInProgress = true; + m_numSteps = 5; + break; + + case 0x2000: + case 0x4000: + m_step = 0; + ((u32*)m_Buffer)[m_step++] = _uMail; + m_bListInProgress = true; + m_numSteps = 3; + break; + + default: + PanicAlert("UCode Jac"); + DebugLog("UCode Jac - unknown cmd: %x", _uMail & 0xFFFF); + break; + } + } + else + { + ((u32*)m_Buffer)[m_step] = _uMail; + m_step++; + + if (m_step == m_numSteps) + { + ExecuteList(); + m_bListInProgress = false; + } + } +} + + +void CUCode_Jac::Update() +{ + // check if we have to sent something +/* if (!g_MailHandler.empty()) + { + g_dspInitialize.pGenerateDSPInterrupt(); + }*/ +} + + +void CUCode_Jac::ExecuteList() +{ + // begin with the list + m_readOffset = 0; + + u16 cmd = Read16(); + u16 sync = Read16(); + + DebugLog("=============================================================================="); + DebugLog("UCode Jac - execute dlist (cmd: 0x%04x : sync: 0x%04x)", cmd, sync); + + switch (cmd) + { + // ============================================================================== + // DsetupTable + // ============================================================================== + case 0x40: + { + u32 tmp[4]; + tmp[0] = Read32(); + tmp[1] = Read32(); + tmp[2] = Read32(); + tmp[3] = Read32(); + + DebugLog("DsetupTable"); + DebugLog("???: 0x%08x", tmp[0]); + DebugLog("DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]); + DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]); + DebugLog("???: 0x%08x", tmp[3]); + } + break; + + // ============================================================================== + // UpdateDSPChannel + // ============================================================================== + case 0x2000: + case 0x4000: // animal crossing + { + u32 tmp[3]; + tmp[0] = Read32(); + tmp[1] = Read32(); + tmp[2] = Read32(); + + DebugLog("UpdateDSPChannel"); + DebugLog("audiomemory: 0x%08x", tmp[0]); + DebugLog("audiomemory: 0x%08x", tmp[1]); + DebugLog("DSPADPCM_FILTER (size: 0x40): 0x%08x", tmp[2]); + } + break; + + default: + PanicAlert("UCode Jac unknown cmd: %s (size %i)", cmd, m_numSteps); + DebugLog("Jac UCode - unknown cmd: %x (size %i)", cmd, m_numSteps); + break; + } + + // sync, we are rdy + m_rMailHandler.PushMail(DSP_SYNC); + m_rMailHandler.PushMail(0xF3550000 | sync); +} + + diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.cpp index 7b7866eed4..36f58c3e78 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.cpp @@ -1,112 +1,112 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "../Globals.h" -#include "../DSPHandler.h" -#include "UCodes.h" -#include "UCode_ROM.h" - -CUCode_Rom::CUCode_Rom(CMailHandler& _rMailHandler) - : IUCode(_rMailHandler) - , m_BootTask_numSteps(0) - , m_NextParameter(0) -{ - DebugLog("UCode_Rom - initialized"); - m_rMailHandler.Clear(); - m_rMailHandler.PushMail(0x8071FEED); -} - -CUCode_Rom::~CUCode_Rom() -{} - -void CUCode_Rom::Update() -{} - -void CUCode_Rom::HandleMail(u32 _uMail) -{ - if (m_NextParameter == 0) - { - // wait for beginning of UCode - if ((_uMail & 0xFFFF0000) != 0x80F30000) - { - u32 Message = 0xFEEE0000 | (_uMail & 0xFFFF); - m_rMailHandler.PushMail(Message); - } - else - { - m_NextParameter = _uMail; - } - } - else - { - switch (m_NextParameter) - { - case 0x80F3A001: - m_CurrentUCode.m_RAMAddress = _uMail; - break; - - case 0x80F3A002: - m_CurrentUCode.m_Length = _uMail; - break; - - case 0x80F3C002: - m_CurrentUCode.m_IMEMAddress = _uMail; - break; - - case 0x80F3B002: - m_CurrentUCode.m_Unk = _uMail; - break; - - case 0x80F3D001: - { - m_CurrentUCode.m_StartPC = _uMail; - BootUCode(); - return; // FIXES THE OVERWRITE - } - break; - } - - // THE GODDAMN OVERWRITE WAS HERE. Without the return above, since BootUCode may delete "this", well ... - m_NextParameter = 0; - } -} - -void CUCode_Rom::BootUCode() -{ - // simple non-scientific crc invented by ector :P - // too annoying to change now, and probably good enough anyway - u32 crc = 0; - - for (u32 i = 0; i < m_CurrentUCode.m_Length; i++) - { - crc ^= Memory_Read_U8(m_CurrentUCode.m_RAMAddress + i); - //let's rol - crc = (crc << 3) | (crc >> 29); - } - - DebugLog("CurrentUCode SOURCE Addr: 0x%08x", m_CurrentUCode.m_RAMAddress); - DebugLog("CurrentUCode Length: 0x%08x", m_CurrentUCode.m_Length); - DebugLog("CurrentUCode DEST Addr: 0x%08x", m_CurrentUCode.m_IMEMAddress); - DebugLog("CurrentUCode ???: 0x%08x", m_CurrentUCode.m_Unk); - DebugLog("CurrentUCode init_vector: 0x%08x", m_CurrentUCode.m_StartPC); - DebugLog("CurrentUCode CRC: 0x%08x", crc); - DebugLog("BootTask - done"); - - CDSPHandler::GetInstance().SetUCode(crc); -} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "../Globals.h" +#include "../DSPHandler.h" +#include "UCodes.h" +#include "UCode_ROM.h" + +CUCode_Rom::CUCode_Rom(CMailHandler& _rMailHandler) + : IUCode(_rMailHandler) + , m_BootTask_numSteps(0) + , m_NextParameter(0) +{ + DebugLog("UCode_Rom - initialized"); + m_rMailHandler.Clear(); + m_rMailHandler.PushMail(0x8071FEED); +} + +CUCode_Rom::~CUCode_Rom() +{} + +void CUCode_Rom::Update() +{} + +void CUCode_Rom::HandleMail(u32 _uMail) +{ + if (m_NextParameter == 0) + { + // wait for beginning of UCode + if ((_uMail & 0xFFFF0000) != 0x80F30000) + { + u32 Message = 0xFEEE0000 | (_uMail & 0xFFFF); + m_rMailHandler.PushMail(Message); + } + else + { + m_NextParameter = _uMail; + } + } + else + { + switch (m_NextParameter) + { + case 0x80F3A001: + m_CurrentUCode.m_RAMAddress = _uMail; + break; + + case 0x80F3A002: + m_CurrentUCode.m_Length = _uMail; + break; + + case 0x80F3C002: + m_CurrentUCode.m_IMEMAddress = _uMail; + break; + + case 0x80F3B002: + m_CurrentUCode.m_Unk = _uMail; + break; + + case 0x80F3D001: + { + m_CurrentUCode.m_StartPC = _uMail; + BootUCode(); + return; // FIXES THE OVERWRITE + } + break; + } + + // THE GODDAMN OVERWRITE WAS HERE. Without the return above, since BootUCode may delete "this", well ... + m_NextParameter = 0; + } +} + +void CUCode_Rom::BootUCode() +{ + // simple non-scientific crc invented by ector :P + // too annoying to change now, and probably good enough anyway + u32 crc = 0; + + for (u32 i = 0; i < m_CurrentUCode.m_Length; i++) + { + crc ^= Memory_Read_U8(m_CurrentUCode.m_RAMAddress + i); + //let's rol + crc = (crc << 3) | (crc >> 29); + } + + DebugLog("CurrentUCode SOURCE Addr: 0x%08x", m_CurrentUCode.m_RAMAddress); + DebugLog("CurrentUCode Length: 0x%08x", m_CurrentUCode.m_Length); + DebugLog("CurrentUCode DEST Addr: 0x%08x", m_CurrentUCode.m_IMEMAddress); + DebugLog("CurrentUCode ???: 0x%08x", m_CurrentUCode.m_Unk); + DebugLog("CurrentUCode init_vector: 0x%08x", m_CurrentUCode.m_StartPC); + DebugLog("CurrentUCode CRC: 0x%08x", crc); + DebugLog("BootTask - done"); + + CDSPHandler::GetInstance().SetUCode(crc); +} + + diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp index 13d1160205..5fdad98214 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp @@ -1,181 +1,181 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -// Games that uses this UCode: -// Zelda: The Windwaker, Mario Sunshine, Mario Kart, Twilight Princess - -#include "../Globals.h" -#include "UCodes.h" -#include "UCode_Zelda.h" -#include "../MailHandler.h" - -#ifdef _WIN32 -#include "../PCHW/DSoundStream.h" -#endif -#include "../PCHW/Mixer.h" - - -CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler) - : IUCode(_rMailHandler) - , m_numSteps(0) - , m_bListInProgress(false) - , m_step(0) - , m_readOffset(0) -{ - DebugLog("UCode_Zelda - add boot mails for handshake"); - m_rMailHandler.PushMail(DSP_INIT); - m_rMailHandler.PushMail(0x80000000); // handshake - memset(m_Buffer, 0, sizeof(m_Buffer)); -} - - -CUCode_Zelda::~CUCode_Zelda() -{ - m_rMailHandler.Clear(); -} - - -void CUCode_Zelda::Update() -{ - // check if we have to sent something - if (!m_rMailHandler.IsEmpty()) - g_dspInitialize.pGenerateDSPInterrupt(); -} - - -void CUCode_Zelda::HandleMail(u32 _uMail) -{ - if (m_bListInProgress == false) - { - m_bListInProgress = true; - m_numSteps = _uMail; - m_step = 0; - } - else - { - if (m_step < 0 || m_step >= sizeof(m_Buffer)/4) - PanicAlert("m_step out of range"); - ((u32*)m_Buffer)[m_step] = _uMail; - m_step++; - - if (m_step == m_numSteps) - { - ExecuteList(); - m_bListInProgress = false; - } - } -} - -void CUCode_Zelda::MixAdd(short* buffer, int size) -{ - //TODO(XK): Zelda UCode MixAdd? -} - -void CUCode_Zelda::ExecuteList() -{ - // begin with the list - m_readOffset = 0; - - u32 Temp = Read32(); - u32 Command = (Temp >> 24) & 0x7f; - u32 Sync = Temp >> 16; - - DebugLog("=============================================================================="); - DebugLog("Zelda UCode - execute dlist (cmd: 0x%04x : sync: 0x%04x)", Command, Sync); - - switch (Command) - { - // DsetupTable ... zelda ww jumps to 0x0095 - case 0x01: - { - u32 tmp[4]; - tmp[0] = Read32(); - tmp[1] = Read32(); - tmp[2] = Read32(); - tmp[3] = Read32(); - - DebugLog("DsetupTable"); - DebugLog("???: 0x%08x", tmp[0]); - DebugLog("DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]); - DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]); - DebugLog("???: 0x%08x", tmp[3]); - } - break; - - // SyncFrame ... zelda ww jumps to 0x0243 - case 0x02: - { - u32 tmp[3]; - tmp[0] = Read32(); - tmp[1] = Read32(); - tmp[2] = Read32(); - - // We're ready to mix - mixer_HLEready = true; -#ifdef _WIN32 - DebugLog("Update the SoundThread to be in sync"); - DSound::DSound_UpdateSound(); //do it in this thread to avoid sync problems -#endif - - DebugLog("DsyncFrame"); - DebugLog("???: 0x%08x", tmp[0]); - DebugLog("???: 0x%08x", tmp[1]); - DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]); - } - break; - -/* - case 0x03: break; // dunno ... zelda ww jmps to 0x0073 - case 0x04: break; // dunno ... zelda ww jmps to 0x0580 - case 0x05: break; // dunno ... zelda ww jmps to 0x0592 - case 0x06: break; // dunno ... zelda ww jmps to 0x0469 - - case 0x07: break; // dunno ... zelda ww jmps to 0x044d - case 0x08: break; // Mixer ... zelda ww jmps to 0x0485 - case 0x09: break; // dunno ... zelda ww jmps to 0x044d - */ - - // DsetDolbyDelay ... zelda ww jumps to 0x00b2 - case 0x0d: - { - u32 tmp[2]; - tmp[0] = Read32(); - tmp[1] = Read32(); - - DebugLog("DSetDolbyDelay"); - DebugLog("DOLBY2_DELAY_BUF (size 0x960): 0x%08x", tmp[0]); - DebugLog("DSPRES_FILTER (size 0x500): 0x%08x", tmp[1]); - } - break; - - // Set VARAM - case 0x0e: -// MessageBox(NULL, "Zelda VARAM", "cmd", MB_OK); - break; - - // default ... zelda ww jumps to 0x0043 - default: - PanicAlert("Zelda UCode - unknown cmd: %x (size %i)", Command, m_numSteps); - break; - } - - // sync, we are rdy - m_rMailHandler.PushMail(DSP_SYNC); - m_rMailHandler.PushMail(0xF3550000 | Sync); -} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +// Games that uses this UCode: +// Zelda: The Windwaker, Mario Sunshine, Mario Kart, Twilight Princess + +#include "../Globals.h" +#include "UCodes.h" +#include "UCode_Zelda.h" +#include "../MailHandler.h" + +#ifdef _WIN32 +#include "../PCHW/DSoundStream.h" +#endif +#include "../PCHW/Mixer.h" + + +CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler) + : IUCode(_rMailHandler) + , m_numSteps(0) + , m_bListInProgress(false) + , m_step(0) + , m_readOffset(0) +{ + DebugLog("UCode_Zelda - add boot mails for handshake"); + m_rMailHandler.PushMail(DSP_INIT); + m_rMailHandler.PushMail(0x80000000); // handshake + memset(m_Buffer, 0, sizeof(m_Buffer)); +} + + +CUCode_Zelda::~CUCode_Zelda() +{ + m_rMailHandler.Clear(); +} + + +void CUCode_Zelda::Update() +{ + // check if we have to sent something + if (!m_rMailHandler.IsEmpty()) + g_dspInitialize.pGenerateDSPInterrupt(); +} + + +void CUCode_Zelda::HandleMail(u32 _uMail) +{ + if (m_bListInProgress == false) + { + m_bListInProgress = true; + m_numSteps = _uMail; + m_step = 0; + } + else + { + if (m_step < 0 || m_step >= sizeof(m_Buffer)/4) + PanicAlert("m_step out of range"); + ((u32*)m_Buffer)[m_step] = _uMail; + m_step++; + + if (m_step == m_numSteps) + { + ExecuteList(); + m_bListInProgress = false; + } + } +} + +void CUCode_Zelda::MixAdd(short* buffer, int size) +{ + //TODO(XK): Zelda UCode MixAdd? +} + +void CUCode_Zelda::ExecuteList() +{ + // begin with the list + m_readOffset = 0; + + u32 Temp = Read32(); + u32 Command = (Temp >> 24) & 0x7f; + u32 Sync = Temp >> 16; + + DebugLog("=============================================================================="); + DebugLog("Zelda UCode - execute dlist (cmd: 0x%04x : sync: 0x%04x)", Command, Sync); + + switch (Command) + { + // DsetupTable ... zelda ww jumps to 0x0095 + case 0x01: + { + u32 tmp[4]; + tmp[0] = Read32(); + tmp[1] = Read32(); + tmp[2] = Read32(); + tmp[3] = Read32(); + + DebugLog("DsetupTable"); + DebugLog("???: 0x%08x", tmp[0]); + DebugLog("DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]); + DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]); + DebugLog("???: 0x%08x", tmp[3]); + } + break; + + // SyncFrame ... zelda ww jumps to 0x0243 + case 0x02: + { + u32 tmp[3]; + tmp[0] = Read32(); + tmp[1] = Read32(); + tmp[2] = Read32(); + + // We're ready to mix + mixer_HLEready = true; +#ifdef _WIN32 + DebugLog("Update the SoundThread to be in sync"); + DSound::DSound_UpdateSound(); //do it in this thread to avoid sync problems +#endif + + DebugLog("DsyncFrame"); + DebugLog("???: 0x%08x", tmp[0]); + DebugLog("???: 0x%08x", tmp[1]); + DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]); + } + break; + +/* + case 0x03: break; // dunno ... zelda ww jmps to 0x0073 + case 0x04: break; // dunno ... zelda ww jmps to 0x0580 + case 0x05: break; // dunno ... zelda ww jmps to 0x0592 + case 0x06: break; // dunno ... zelda ww jmps to 0x0469 + + case 0x07: break; // dunno ... zelda ww jmps to 0x044d + case 0x08: break; // Mixer ... zelda ww jmps to 0x0485 + case 0x09: break; // dunno ... zelda ww jmps to 0x044d + */ + + // DsetDolbyDelay ... zelda ww jumps to 0x00b2 + case 0x0d: + { + u32 tmp[2]; + tmp[0] = Read32(); + tmp[1] = Read32(); + + DebugLog("DSetDolbyDelay"); + DebugLog("DOLBY2_DELAY_BUF (size 0x960): 0x%08x", tmp[0]); + DebugLog("DSPRES_FILTER (size 0x500): 0x%08x", tmp[1]); + } + break; + + // Set VARAM + case 0x0e: +// MessageBox(NULL, "Zelda VARAM", "cmd", MB_OK); + break; + + // default ... zelda ww jumps to 0x0043 + default: + PanicAlert("Zelda UCode - unknown cmd: %x (size %i)", Command, m_numSteps); + break; + } + + // sync, we are rdy + m_rMailHandler.PushMail(DSP_SYNC); + m_rMailHandler.PushMail(0xF3550000 | Sync); +} + + diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp index 48fa6c0986..2e7f1a2838 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp @@ -1,90 +1,90 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "../Globals.h" - -#include "UCodes.h" - -#include "UCode_AX.h" -#include "UCode_AXWii.h" -#include "UCode_Zelda.h" -#include "UCode_Jac.h" -#include "UCode_ROM.h" -#include "UCode_CARD.h" -#include "UCode_InitAudioSystem.h" - -IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler) -{ - switch (_CRC) - { - case UCODE_ROM: - return new CUCode_Rom(_rMailHandler); - - case UCODE_INIT_AUDIO_SYSTEM: - return new CUCode_InitAudioSystem(_rMailHandler); - - case 0x65d6cc6f: // CARD - return new CUCode_CARD(_rMailHandler); - - case 0x088e38a5: // IPL - JAP - case 0xd73338cf: // IPL - case 0x42f64ac4: // Luigi (after fix) - case 0x4be6a5cb: // AC, Pikmin (after fix) - printf("JAC ucode chosen"); - return new CUCode_Jac(_rMailHandler); - - case 0x3ad3b7ac: // Naruto3 - case 0x3daf59b9: // Alien Hominid - case 0x4e8a8b21: // spdemo, ctaxi, 18 wheeler, disney, monkeyball2,cubivore,puzzlecollection,wario, - // capcom vs snk, naruto2, lost kingdoms, star fox, mario party 4, mortal kombat, - // smugglers run warzone, smash brothers, sonic mega collection, ZooCube - // nddemo, starfox - case 0x07f88145: // bustamove, ikaruga, fzero, robotech battle cry, star soldier, soul calibur2, - // Zelda:OOT, Tony hawk, viewtiful joe - case 0xe2136399: // billy hatcher, dragonballz, mario party 5, TMNT, ava1080 - printf("AX ucode chosen, yay!"); - return new CUCode_AX(_rMailHandler); - - case 0x6CA33A6D: // DK Jungle Beat - case 0x86840740: // zelda - case 0x56d36052: // mario - case 0x2fcdf1ec: // mariokart, zelda 4 swords - printf("Zelda ucode chosen"); - return new CUCode_Zelda(_rMailHandler); - - // WII CRCs - case 0x6c3f6f94: // zelda - PAL - case 0xd643001f: // mario galaxy - PAL - printf("Zelda Wii ucode chosen"); - return new CUCode_Zelda(_rMailHandler); - - case 0x5ef56da3: // AX demo - case 0x347112ba: // raving rabbits - case 0xfa450138: // wii sports - PAL - case 0xadbc06bd: // Elebits - printf("Wii - AXWii chosen"); - return new CUCode_AXWii(_rMailHandler, _CRC); - - default: - PanicAlert("Unknown ucode (CRC = %08x) - forcing AX", _CRC); - return new CUCode_AX(_rMailHandler); - } - - return NULL; -} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "../Globals.h" + +#include "UCodes.h" + +#include "UCode_AX.h" +#include "UCode_AXWii.h" +#include "UCode_Zelda.h" +#include "UCode_Jac.h" +#include "UCode_ROM.h" +#include "UCode_CARD.h" +#include "UCode_InitAudioSystem.h" + +IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler) +{ + switch (_CRC) + { + case UCODE_ROM: + return new CUCode_Rom(_rMailHandler); + + case UCODE_INIT_AUDIO_SYSTEM: + return new CUCode_InitAudioSystem(_rMailHandler); + + case 0x65d6cc6f: // CARD + return new CUCode_CARD(_rMailHandler); + + case 0x088e38a5: // IPL - JAP + case 0xd73338cf: // IPL + case 0x42f64ac4: // Luigi (after fix) + case 0x4be6a5cb: // AC, Pikmin (after fix) + printf("JAC ucode chosen"); + return new CUCode_Jac(_rMailHandler); + + case 0x3ad3b7ac: // Naruto3 + case 0x3daf59b9: // Alien Hominid + case 0x4e8a8b21: // spdemo, ctaxi, 18 wheeler, disney, monkeyball2,cubivore,puzzlecollection,wario, + // capcom vs snk, naruto2, lost kingdoms, star fox, mario party 4, mortal kombat, + // smugglers run warzone, smash brothers, sonic mega collection, ZooCube + // nddemo, starfox + case 0x07f88145: // bustamove, ikaruga, fzero, robotech battle cry, star soldier, soul calibur2, + // Zelda:OOT, Tony hawk, viewtiful joe + case 0xe2136399: // billy hatcher, dragonballz, mario party 5, TMNT, ava1080 + printf("AX ucode chosen, yay!"); + return new CUCode_AX(_rMailHandler); + + case 0x6CA33A6D: // DK Jungle Beat + case 0x86840740: // zelda + case 0x56d36052: // mario + case 0x2fcdf1ec: // mariokart, zelda 4 swords + printf("Zelda ucode chosen"); + return new CUCode_Zelda(_rMailHandler); + + // WII CRCs + case 0x6c3f6f94: // zelda - PAL + case 0xd643001f: // mario galaxy - PAL + printf("Zelda Wii ucode chosen"); + return new CUCode_Zelda(_rMailHandler); + + case 0x5ef56da3: // AX demo + case 0x347112ba: // raving rabbits + case 0xfa450138: // wii sports - PAL + case 0xadbc06bd: // Elebits + printf("Wii - AXWii chosen"); + return new CUCode_AXWii(_rMailHandler, _CRC); + + default: + PanicAlert("Unknown ucode (CRC = %08x) - forcing AX", _CRC); + return new CUCode_AX(_rMailHandler); + } + + return NULL; +} + + diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp index c21cb32f94..8784d6e200 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp @@ -1,357 +1,357 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Debugger/Debugger.h" // for the CDebugger class -#include "ChunkFile.h" -#include "WaveFile.h" -#include "resource.h" - -#ifdef _WIN32 -#include "PCHW/DSoundStream.h" -#include "ConfigDlg.h" -#else -#include "PCHW/AOSoundStream.h" -#endif - -#include "PCHW/Mixer.h" - -#include "DSPHandler.h" -#include "Config.h" - -#include "Logging/Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd - -DSPInitialize g_dspInitialize; -u8* g_pMemory; -extern std::vector sMailLog, sMailTime; -std::string gpName; - -// Set this if you want to log audio. search for log_ai in this file to see the filename. -static bool log_ai = false; -static WaveFileWriter g_wave_writer; - -struct DSPState -{ - u32 CPUMailbox; - bool CPUMailbox_Written[2]; - - u32 DSPMailbox; - bool DSPMailbox_Read[2]; - - DSPState() - { - CPUMailbox = 0x00000000; - CPUMailbox_Written[0] = false; - CPUMailbox_Written[1] = false; - - DSPMailbox = 0x00000000; - DSPMailbox_Read[0] = true; - DSPMailbox_Read[1] = true; - } -}; - -DSPState g_dspState; -// ==================== - - -////////////////////////////////////////////////////////////////////////////////////////// -// wxWidgets - Some kind of stuff wx needs -// ŻŻŻŻŻŻŻŻŻ -class wxDLLApp : public wxApp -{ - bool OnInit() - { - return true; - } -}; - -IMPLEMENT_APP_NO_MAIN(wxDLLApp) -WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst); -/////////////////// - - -#ifdef _WIN32 -HINSTANCE g_hInstance = NULL; - -BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle - DWORD dwReason, // reason called - LPVOID lpvReserved) // reserved -{ - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - { - - // more stuff wx needs - wxSetInstance((HINSTANCE)hinstDLL); - int argc = 0; - char **argv = NULL; - wxEntryStart(argc, argv); - - // This is for ? - if ( !wxTheApp || !wxTheApp->CallOnInit() ) - return FALSE; - } - break; - - case DLL_PROCESS_DETACH: - wxEntryCleanup(); // use this or get a crash - break; - - default: - break; - } - - g_hInstance = hinstDLL; - return(TRUE); -} -#endif - - -// ======================================================================================= -// Open and close console -// ------------------- -void OpenConsole() -{ - #if defined (_WIN32) - startConsoleWin(155, 100, "Sound Debugging"); // give room for 100 rows - wprintf("OpenConsole > Console opened\n"); - MoveWindow(GetConsoleHwnd(), 0,400, 1280,550, true); // move window, TODO: make this - // adjustable from the debugging window - #endif -} - -void CloseConsole() -{ - #if defined (_WIN32) - FreeConsole(); - #endif -} -// =================== - - -// ======================================================================================= -// Create debugging window - We could use use wxWindow win; new CDebugger(win) like nJoy but I don't -// know why it would be better. - There's a lockup problem with ShowModal(), but Show() doesn't work -// because then DLL_PROCESS_DETACH is called immediately after DLL_PROCESS_ATTACH. -// ------------------- -CDebugger* m_frame; -void DllDebugger(HWND _hParent, bool Show) -{ - if(m_frame && Show) // if we have created it, let us show it again - { - m_frame->DoShow(); - } - else if(!m_frame && Show) - { - m_frame = new CDebugger(NULL); - m_frame->Show(); - } - else if(m_frame && !Show) - { - m_frame->DoHide(); - } -} -// =================== - - -void GetDllInfo(PLUGIN_INFO* _PluginInfo) -{ - _PluginInfo->Version = 0x0100; - _PluginInfo->Type = PLUGIN_TYPE_DSP; -#ifdef DEBUGFAST - sprintf(_PluginInfo->Name, "Dolphin DSP-HLE Plugin (DebugFast) "); -#else -#ifndef _DEBUG - sprintf(_PluginInfo->Name, "Dolphin DSP-HLE Plugin "); -#else - sprintf(_PluginInfo ->Name, "Dolphin DSP-HLE Plugin (Debug) "); -#endif -#endif -} - -void DllConfig(HWND _hParent) -{ -#ifdef _WIN32 - CConfigDlg configDlg; - configDlg.DoModal(_hParent); -#endif -} - -void DSP_Initialize(DSPInitialize _dspInitialize) -{ - g_Config.LoadDefaults(); - g_Config.Load(); - - g_dspInitialize = _dspInitialize; - - g_pMemory = g_dspInitialize.pGetMemoryPointer(0); - -#if defined(_DEBUG) || defined(DEBUGFAST) - gpName = g_dspInitialize.pName(); // save the game name globally - for (int i = 0; i < gpName.length(); ++i) // and fix it - { - wprintf("%c", gpName[i]); - std::cout << gpName[i]; - if (gpName[i] == ':') gpName[i] = ' '; - } - wprintf("\n"); -#endif - - CDSPHandler::CreateInstance(); - -#ifdef _WIN32 -#ifdef _DEBUG - int tmpflag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - tmpflag |= _CRTDBG_DELAY_FREE_MEM_DF; - _CrtSetDbgFlag(tmpflag); -#endif - if (log_ai) { - g_wave_writer.Start("D:\\ai_log.wav"); - g_wave_writer.SetSkipSilence(false); - } - - DSound::DSound_StartSound((HWND)g_dspInitialize.hWnd, 48000, Mixer); -#else - AOSound::AOSound_StartSound(48000, Mixer); -#endif -} - -void DSP_Shutdown() -{ - if (log_ai) - g_wave_writer.Stop(); - // delete the UCodes -#ifdef _WIN32 - DSound::DSound_StopSound(); -#else - AOSound::AOSound_StopSound(); -#endif - CDSPHandler::Destroy(); - - // Reset mails - if(m_frame) - { - sMailLog.clear(); - sMailTime.clear(); - m_frame->sMail.clear(); - m_frame->sMailEnd.clear(); - } -} - -void DSP_DoState(unsigned char **ptr, int mode) { - PointerWrap p(ptr, mode); -} - -unsigned short DSP_ReadMailboxHigh(bool _CPUMailbox) -{ - if (_CPUMailbox) - { - return (g_dspState.CPUMailbox >> 16) & 0xFFFF; - } - else - { - return CDSPHandler::GetInstance().AccessMailHandler().ReadDSPMailboxHigh(); - } -} - -unsigned short DSP_ReadMailboxLow(bool _CPUMailbox) -{ - if (_CPUMailbox) - { - return g_dspState.CPUMailbox & 0xFFFF; - } - else - { - return CDSPHandler::GetInstance().AccessMailHandler().ReadDSPMailboxLow(); - } -} - -void Update_DSP_WriteRegister() -{ - // check if the whole message is complete and if we can send it - if (g_dspState.CPUMailbox_Written[0] && g_dspState.CPUMailbox_Written[1]) - { - CDSPHandler::GetInstance().SendMailToDSP(g_dspState.CPUMailbox); - g_dspState.CPUMailbox_Written[0] = g_dspState.CPUMailbox_Written[1] = false; - g_dspState.CPUMailbox = 0; // Mail sent so clear it to show that it is progressed - } -} - -void DSP_WriteMailboxHigh(bool _CPUMailbox, unsigned short _Value) -{ - if (_CPUMailbox) - { - g_dspState.CPUMailbox = (g_dspState.CPUMailbox & 0xFFFF) | (_Value << 16); - g_dspState.CPUMailbox_Written[0] = true; - - Update_DSP_WriteRegister(); - } - else - { - PanicAlert("CPU can't write %08x to DSP mailbox", _Value); - } -} - -void DSP_WriteMailboxLow(bool _CPUMailbox, unsigned short _Value) -{ - if (_CPUMailbox) - { - g_dspState.CPUMailbox = (g_dspState.CPUMailbox & 0xFFFF0000) | _Value; - g_dspState.CPUMailbox_Written[1] = true; - - Update_DSP_WriteRegister(); - } - else - { - PanicAlert("CPU can't write %08x to DSP mailbox", _Value); - } -} - -unsigned short DSP_WriteControlRegister(unsigned short _Value) -{ - return CDSPHandler::GetInstance().WriteControlRegister(_Value); -} - -unsigned short DSP_ReadControlRegister() -{ - return CDSPHandler::GetInstance().ReadControlRegister(); -} - -void DSP_Update(int cycles) -{ - CDSPHandler::GetInstance().Update(); -} - -void DSP_SendAIBuffer(unsigned int address, int sample_rate) -{ - short samples[16] = {0}; // interleaved stereo - if (address) { - for (int i = 0; i < 16; i++) { - samples[i] = Memory_Read_U16(address + i * 2); - } - if (log_ai) - g_wave_writer.AddStereoSamples(samples, 8); - } - Mixer_PushSamples(samples, 32 / 4, sample_rate); - - static int counter = 0; - counter++; -#ifdef _WIN32 - if ((counter & 255) == 0) - DSound::DSound_UpdateSound(); -#endif -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Debugger/Debugger.h" // for the CDebugger class +#include "ChunkFile.h" +#include "WaveFile.h" +#include "resource.h" + +#ifdef _WIN32 +#include "PCHW/DSoundStream.h" +#include "ConfigDlg.h" +#else +#include "PCHW/AOSoundStream.h" +#endif + +#include "PCHW/Mixer.h" + +#include "DSPHandler.h" +#include "Config.h" + +#include "Logging/Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd + +DSPInitialize g_dspInitialize; +u8* g_pMemory; +extern std::vector sMailLog, sMailTime; +std::string gpName; + +// Set this if you want to log audio. search for log_ai in this file to see the filename. +static bool log_ai = false; +static WaveFileWriter g_wave_writer; + +struct DSPState +{ + u32 CPUMailbox; + bool CPUMailbox_Written[2]; + + u32 DSPMailbox; + bool DSPMailbox_Read[2]; + + DSPState() + { + CPUMailbox = 0x00000000; + CPUMailbox_Written[0] = false; + CPUMailbox_Written[1] = false; + + DSPMailbox = 0x00000000; + DSPMailbox_Read[0] = true; + DSPMailbox_Read[1] = true; + } +}; + +DSPState g_dspState; +// ==================== + + +////////////////////////////////////////////////////////////////////////////////////////// +// wxWidgets - Some kind of stuff wx needs +// ŻŻŻŻŻŻŻŻŻ +class wxDLLApp : public wxApp +{ + bool OnInit() + { + return true; + } +}; + +IMPLEMENT_APP_NO_MAIN(wxDLLApp) +WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst); +/////////////////// + + +#ifdef _WIN32 +HINSTANCE g_hInstance = NULL; + +BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle + DWORD dwReason, // reason called + LPVOID lpvReserved) // reserved +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + { + + // more stuff wx needs + wxSetInstance((HINSTANCE)hinstDLL); + int argc = 0; + char **argv = NULL; + wxEntryStart(argc, argv); + + // This is for ? + if ( !wxTheApp || !wxTheApp->CallOnInit() ) + return FALSE; + } + break; + + case DLL_PROCESS_DETACH: + wxEntryCleanup(); // use this or get a crash + break; + + default: + break; + } + + g_hInstance = hinstDLL; + return(TRUE); +} +#endif + + +// ======================================================================================= +// Open and close console +// ------------------- +void OpenConsole() +{ + #if defined (_WIN32) + startConsoleWin(155, 100, "Sound Debugging"); // give room for 100 rows + wprintf("OpenConsole > Console opened\n"); + MoveWindow(GetConsoleHwnd(), 0,400, 1280,550, true); // move window, TODO: make this + // adjustable from the debugging window + #endif +} + +void CloseConsole() +{ + #if defined (_WIN32) + FreeConsole(); + #endif +} +// =================== + + +// ======================================================================================= +// Create debugging window - We could use use wxWindow win; new CDebugger(win) like nJoy but I don't +// know why it would be better. - There's a lockup problem with ShowModal(), but Show() doesn't work +// because then DLL_PROCESS_DETACH is called immediately after DLL_PROCESS_ATTACH. +// ------------------- +CDebugger* m_frame; +void DllDebugger(HWND _hParent, bool Show) +{ + if(m_frame && Show) // if we have created it, let us show it again + { + m_frame->DoShow(); + } + else if(!m_frame && Show) + { + m_frame = new CDebugger(NULL); + m_frame->Show(); + } + else if(m_frame && !Show) + { + m_frame->DoHide(); + } +} +// =================== + + +void GetDllInfo(PLUGIN_INFO* _PluginInfo) +{ + _PluginInfo->Version = 0x0100; + _PluginInfo->Type = PLUGIN_TYPE_DSP; +#ifdef DEBUGFAST + sprintf(_PluginInfo->Name, "Dolphin DSP-HLE Plugin (DebugFast) "); +#else +#ifndef _DEBUG + sprintf(_PluginInfo->Name, "Dolphin DSP-HLE Plugin "); +#else + sprintf(_PluginInfo ->Name, "Dolphin DSP-HLE Plugin (Debug) "); +#endif +#endif +} + +void DllConfig(HWND _hParent) +{ +#ifdef _WIN32 + CConfigDlg configDlg; + configDlg.DoModal(_hParent); +#endif +} + +void DSP_Initialize(DSPInitialize _dspInitialize) +{ + g_Config.LoadDefaults(); + g_Config.Load(); + + g_dspInitialize = _dspInitialize; + + g_pMemory = g_dspInitialize.pGetMemoryPointer(0); + +#if defined(_DEBUG) || defined(DEBUGFAST) + gpName = g_dspInitialize.pName(); // save the game name globally + for (int i = 0; i < gpName.length(); ++i) // and fix it + { + wprintf("%c", gpName[i]); + std::cout << gpName[i]; + if (gpName[i] == ':') gpName[i] = ' '; + } + wprintf("\n"); +#endif + + CDSPHandler::CreateInstance(); + +#ifdef _WIN32 +#ifdef _DEBUG + int tmpflag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); + tmpflag |= _CRTDBG_DELAY_FREE_MEM_DF; + _CrtSetDbgFlag(tmpflag); +#endif + if (log_ai) { + g_wave_writer.Start("D:\\ai_log.wav"); + g_wave_writer.SetSkipSilence(false); + } + + DSound::DSound_StartSound((HWND)g_dspInitialize.hWnd, 48000, Mixer); +#else + AOSound::AOSound_StartSound(48000, Mixer); +#endif +} + +void DSP_Shutdown() +{ + if (log_ai) + g_wave_writer.Stop(); + // delete the UCodes +#ifdef _WIN32 + DSound::DSound_StopSound(); +#else + AOSound::AOSound_StopSound(); +#endif + CDSPHandler::Destroy(); + + // Reset mails + if(m_frame) + { + sMailLog.clear(); + sMailTime.clear(); + m_frame->sMail.clear(); + m_frame->sMailEnd.clear(); + } +} + +void DSP_DoState(unsigned char **ptr, int mode) { + PointerWrap p(ptr, mode); +} + +unsigned short DSP_ReadMailboxHigh(bool _CPUMailbox) +{ + if (_CPUMailbox) + { + return (g_dspState.CPUMailbox >> 16) & 0xFFFF; + } + else + { + return CDSPHandler::GetInstance().AccessMailHandler().ReadDSPMailboxHigh(); + } +} + +unsigned short DSP_ReadMailboxLow(bool _CPUMailbox) +{ + if (_CPUMailbox) + { + return g_dspState.CPUMailbox & 0xFFFF; + } + else + { + return CDSPHandler::GetInstance().AccessMailHandler().ReadDSPMailboxLow(); + } +} + +void Update_DSP_WriteRegister() +{ + // check if the whole message is complete and if we can send it + if (g_dspState.CPUMailbox_Written[0] && g_dspState.CPUMailbox_Written[1]) + { + CDSPHandler::GetInstance().SendMailToDSP(g_dspState.CPUMailbox); + g_dspState.CPUMailbox_Written[0] = g_dspState.CPUMailbox_Written[1] = false; + g_dspState.CPUMailbox = 0; // Mail sent so clear it to show that it is progressed + } +} + +void DSP_WriteMailboxHigh(bool _CPUMailbox, unsigned short _Value) +{ + if (_CPUMailbox) + { + g_dspState.CPUMailbox = (g_dspState.CPUMailbox & 0xFFFF) | (_Value << 16); + g_dspState.CPUMailbox_Written[0] = true; + + Update_DSP_WriteRegister(); + } + else + { + PanicAlert("CPU can't write %08x to DSP mailbox", _Value); + } +} + +void DSP_WriteMailboxLow(bool _CPUMailbox, unsigned short _Value) +{ + if (_CPUMailbox) + { + g_dspState.CPUMailbox = (g_dspState.CPUMailbox & 0xFFFF0000) | _Value; + g_dspState.CPUMailbox_Written[1] = true; + + Update_DSP_WriteRegister(); + } + else + { + PanicAlert("CPU can't write %08x to DSP mailbox", _Value); + } +} + +unsigned short DSP_WriteControlRegister(unsigned short _Value) +{ + return CDSPHandler::GetInstance().WriteControlRegister(_Value); +} + +unsigned short DSP_ReadControlRegister() +{ + return CDSPHandler::GetInstance().ReadControlRegister(); +} + +void DSP_Update(int cycles) +{ + CDSPHandler::GetInstance().Update(); +} + +void DSP_SendAIBuffer(unsigned int address, int sample_rate) +{ + short samples[16] = {0}; // interleaved stereo + if (address) { + for (int i = 0; i < 16; i++) { + samples[i] = Memory_Read_U16(address + i * 2); + } + if (log_ai) + g_wave_writer.AddStereoSamples(samples, 8); + } + Mixer_PushSamples(samples, 32 / 4, sample_rate); + + static int counter = 0; + counter++; +#ifdef _WIN32 + if ((counter & 255) == 0) + DSound::DSound_UpdateSound(); +#endif +} diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/stdafx.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/stdafx.cpp index 5d19def11f..9a2f6b5212 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/stdafx.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/stdafx.cpp @@ -1,19 +1,19 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "stdafx.h" - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" + diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSoundStream.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/DSoundStream.cpp index b59f330740..823003e17b 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/DSoundStream.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/DSoundStream.cpp @@ -1,280 +1,280 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "stdafx.h" - -#include -#include - -#include "DSoundStream.h" - -namespace DSound -{ -#define BUFSIZE 32768 -#define MAXWAIT 70 //ms - -//THE ROCK SOLID SYNCED DSOUND ENGINE :) - - -//vċran kritiska sektion och vċr syncevent-handle -CRITICAL_SECTION soundCriticalSection; -HANDLE soundSyncEvent; -HANDLE hThread; - -StreamCallback callback; - -//lite mojs -IDirectSound8* ds; -IDirectSoundBuffer* dsBuffer; - -//tja.. behövs -int bufferSize; //i bytes -int totalRenderedBytes; -int sampleRate; - -//med den här synkar vi stängning.. -//0=vi spelar oväsen, 1=stäng trċden NU! 2=japp,trċden är stängd sċ fortsätt -volatile int threadData; - - -//ser till sċ X kan delas med 32 -inline int FIX32(int x) -{ - return(x & (~127)); -} - - -int DSound_GetSampleRate() -{ - return(sampleRate); -} - - -//Dags att skapa vċr directsound buffert -bool createBuffer() -{ - PCMWAVEFORMAT pcmwf; - DSBUFFERDESC dsbdesc; - - //ljudformatet - memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT)); - memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); - - pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM; - pcmwf.wf.nChannels = 2; - pcmwf.wf.nSamplesPerSec = sampleRate; - pcmwf.wf.nBlockAlign = 4; - pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign; - pcmwf.wBitsPerSample = 16; - - //buffer description - dsbdesc.dwSize = sizeof(DSBUFFERDESC); - dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS; //VIKTIGT //DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; - dsbdesc.dwBufferBytes = bufferSize = BUFSIZE; //FIX32(pcmwf.wf.nAvgBytesPerSec); //ändra för att ställa in bufferstorlek - dsbdesc.lpwfxFormat = (WAVEFORMATEX*)&pcmwf; - // nu skapar vi bufferjäveln - - if (SUCCEEDED(ds->CreateSoundBuffer(&dsbdesc, &dsBuffer, NULL))) - { - dsBuffer->SetCurrentPosition(0); - return(true); - } - else - { - // Failed. - dsBuffer = NULL; - return(false); - } -} - - -bool writeDataToBuffer(DWORD dwOffset, // Our own write cursor. - char* soundData, // Start of our data. - DWORD dwSoundBytes) // Size of block to copy. -{ - void* ptr1, * ptr2; - DWORD numBytes1, numBytes2; - // Obtain memory address of write block. This will be in two parts if the block wraps around. - HRESULT hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0); - - // If the buffer was lost, restore and retry lock. - - if (DSERR_BUFFERLOST == hr) - { - dsBuffer->Restore(); - hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0); - } - - if (SUCCEEDED(hr)) - { - memcpy(ptr1, soundData, numBytes1); - - if (ptr2 != 0) - { - memcpy(ptr2, soundData + numBytes1, numBytes2); - } - - // Release the data back to DirectSound. - dsBuffer->Unlock(ptr1, numBytes1, ptr2, numBytes2); - return(true); - } /* - else - { - char temp[8]; - sprintf(temp,"%i\n",hr); - OutputDebugString(temp); - }*/ - - return(false); -} - - -inline int ModBufferSize(int x) -{ - return((x + bufferSize) % bufferSize); -} - - -int currentPos; -int lastPos; -short realtimeBuffer[1024 * 1024]; - - -DWORD WINAPI soundThread(void*) -{ - currentPos = 0; - lastPos = 0; - //writeDataToBuffer(0,realtimeBuffer,bufferSize); - // dsBuffer->Lock(0, bufferSize, (void **)&p1, &num1, (void **)&p2, &num2, 0); - - dsBuffer->Play(0, 0, DSBPLAY_LOOPING); - - while (!threadData) - { - EnterCriticalSection(&soundCriticalSection); - - dsBuffer->GetCurrentPosition((DWORD*)¤tPos, 0); - int numBytesToRender = FIX32(ModBufferSize(currentPos - lastPos)); - - //renderStuff(numBytesToRender/2); - //if (numBytesToRender>bufferSize/2) numBytesToRender=0; - - if (numBytesToRender >= 256) - { - (*callback)(realtimeBuffer, numBytesToRender >> 2, 16, 44100, 2); - - writeDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender); - - currentPos = ModBufferSize(lastPos + numBytesToRender); - totalRenderedBytes += numBytesToRender; - - lastPos = currentPos; - } - - LeaveCriticalSection(&soundCriticalSection); - WaitForSingleObject(soundSyncEvent, MAXWAIT); - } - - dsBuffer->Stop(); - - threadData = 2; - return(0); //hurra! -} - - -bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback) -{ - callback = _callback; - threadData = 0; - sampleRate = _sampleRate; - - //no security attributes, automatic resetting, init state nonset, untitled - soundSyncEvent = CreateEvent(0, false, false, 0); - - //vi initierar den........... - InitializeCriticalSection(&soundCriticalSection); - - //vi vill ha access till DSOUND sċ... - if (FAILED(DirectSoundCreate8(0, &ds, 0))) - { - return(false); - } - - //samarbetsvillig? nää :) - ds->SetCooperativeLevel(window, DSSCL_NORMAL); //DSSCL_PRIORITY? - - //sċ.. skapa buffern - if (!createBuffer()) - { - return(false); - } - - //rensa den.. ? - DWORD num1; - short* p1; - - dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0); - - memset(p1, 0, num1); - dsBuffer->Unlock(p1, num1, 0, 0); - totalRenderedBytes = -bufferSize; - DWORD h; - hThread = CreateThread(0, 0, soundThread, 0, 0, &h); - SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL); - return(true); -} - - -void DSound_UpdateSound() -{ - SetEvent(soundSyncEvent); -} - - -void DSound_StopSound() -{ - EnterCriticalSection(&soundCriticalSection); - threadData = 1; - //kick the thread if it's waiting - SetEvent(soundSyncEvent); - LeaveCriticalSection(&soundCriticalSection); - WaitForSingleObject(hThread, INFINITE); - CloseHandle(hThread); - - dsBuffer->Release(); - ds->Release(); - - CloseHandle(soundSyncEvent); -} - - -int DSound_GetCurSample() -{ - EnterCriticalSection(&soundCriticalSection); - int playCursor; - dsBuffer->GetCurrentPosition((DWORD*)&playCursor, 0); - playCursor = ModBufferSize(playCursor - lastPos) + totalRenderedBytes; - LeaveCriticalSection(&soundCriticalSection); - return(playCursor); -} - - -float DSound_GetTimer() -{ - return((float)DSound_GetCurSample() * (1.0f / (4.0f * 44100.0f))); -} -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" + +#include +#include + +#include "DSoundStream.h" + +namespace DSound +{ +#define BUFSIZE 32768 +#define MAXWAIT 70 //ms + +//THE ROCK SOLID SYNCED DSOUND ENGINE :) + + +//vċran kritiska sektion och vċr syncevent-handle +CRITICAL_SECTION soundCriticalSection; +HANDLE soundSyncEvent; +HANDLE hThread; + +StreamCallback callback; + +//lite mojs +IDirectSound8* ds; +IDirectSoundBuffer* dsBuffer; + +//tja.. behövs +int bufferSize; //i bytes +int totalRenderedBytes; +int sampleRate; + +//med den här synkar vi stängning.. +//0=vi spelar oväsen, 1=stäng trċden NU! 2=japp,trċden är stängd sċ fortsätt +volatile int threadData; + + +//ser till sċ X kan delas med 32 +inline int FIX32(int x) +{ + return(x & (~127)); +} + + +int DSound_GetSampleRate() +{ + return(sampleRate); +} + + +//Dags att skapa vċr directsound buffert +bool createBuffer() +{ + PCMWAVEFORMAT pcmwf; + DSBUFFERDESC dsbdesc; + + //ljudformatet + memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT)); + memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); + + pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM; + pcmwf.wf.nChannels = 2; + pcmwf.wf.nSamplesPerSec = sampleRate; + pcmwf.wf.nBlockAlign = 4; + pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign; + pcmwf.wBitsPerSample = 16; + + //buffer description + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS; //VIKTIGT //DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; + dsbdesc.dwBufferBytes = bufferSize = BUFSIZE; //FIX32(pcmwf.wf.nAvgBytesPerSec); //ändra för att ställa in bufferstorlek + dsbdesc.lpwfxFormat = (WAVEFORMATEX*)&pcmwf; + // nu skapar vi bufferjäveln + + if (SUCCEEDED(ds->CreateSoundBuffer(&dsbdesc, &dsBuffer, NULL))) + { + dsBuffer->SetCurrentPosition(0); + return(true); + } + else + { + // Failed. + dsBuffer = NULL; + return(false); + } +} + + +bool writeDataToBuffer(DWORD dwOffset, // Our own write cursor. + char* soundData, // Start of our data. + DWORD dwSoundBytes) // Size of block to copy. +{ + void* ptr1, * ptr2; + DWORD numBytes1, numBytes2; + // Obtain memory address of write block. This will be in two parts if the block wraps around. + HRESULT hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0); + + // If the buffer was lost, restore and retry lock. + + if (DSERR_BUFFERLOST == hr) + { + dsBuffer->Restore(); + hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0); + } + + if (SUCCEEDED(hr)) + { + memcpy(ptr1, soundData, numBytes1); + + if (ptr2 != 0) + { + memcpy(ptr2, soundData + numBytes1, numBytes2); + } + + // Release the data back to DirectSound. + dsBuffer->Unlock(ptr1, numBytes1, ptr2, numBytes2); + return(true); + } /* + else + { + char temp[8]; + sprintf(temp,"%i\n",hr); + OutputDebugString(temp); + }*/ + + return(false); +} + + +inline int ModBufferSize(int x) +{ + return((x + bufferSize) % bufferSize); +} + + +int currentPos; +int lastPos; +short realtimeBuffer[1024 * 1024]; + + +DWORD WINAPI soundThread(void*) +{ + currentPos = 0; + lastPos = 0; + //writeDataToBuffer(0,realtimeBuffer,bufferSize); + // dsBuffer->Lock(0, bufferSize, (void **)&p1, &num1, (void **)&p2, &num2, 0); + + dsBuffer->Play(0, 0, DSBPLAY_LOOPING); + + while (!threadData) + { + EnterCriticalSection(&soundCriticalSection); + + dsBuffer->GetCurrentPosition((DWORD*)¤tPos, 0); + int numBytesToRender = FIX32(ModBufferSize(currentPos - lastPos)); + + //renderStuff(numBytesToRender/2); + //if (numBytesToRender>bufferSize/2) numBytesToRender=0; + + if (numBytesToRender >= 256) + { + (*callback)(realtimeBuffer, numBytesToRender >> 2, 16, 44100, 2); + + writeDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender); + + currentPos = ModBufferSize(lastPos + numBytesToRender); + totalRenderedBytes += numBytesToRender; + + lastPos = currentPos; + } + + LeaveCriticalSection(&soundCriticalSection); + WaitForSingleObject(soundSyncEvent, MAXWAIT); + } + + dsBuffer->Stop(); + + threadData = 2; + return(0); //hurra! +} + + +bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback) +{ + callback = _callback; + threadData = 0; + sampleRate = _sampleRate; + + //no security attributes, automatic resetting, init state nonset, untitled + soundSyncEvent = CreateEvent(0, false, false, 0); + + //vi initierar den........... + InitializeCriticalSection(&soundCriticalSection); + + //vi vill ha access till DSOUND sċ... + if (FAILED(DirectSoundCreate8(0, &ds, 0))) + { + return(false); + } + + //samarbetsvillig? nää :) + ds->SetCooperativeLevel(window, DSSCL_NORMAL); //DSSCL_PRIORITY? + + //sċ.. skapa buffern + if (!createBuffer()) + { + return(false); + } + + //rensa den.. ? + DWORD num1; + short* p1; + + dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0); + + memset(p1, 0, num1); + dsBuffer->Unlock(p1, num1, 0, 0); + totalRenderedBytes = -bufferSize; + DWORD h; + hThread = CreateThread(0, 0, soundThread, 0, 0, &h); + SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL); + return(true); +} + + +void DSound_UpdateSound() +{ + SetEvent(soundSyncEvent); +} + + +void DSound_StopSound() +{ + EnterCriticalSection(&soundCriticalSection); + threadData = 1; + //kick the thread if it's waiting + SetEvent(soundSyncEvent); + LeaveCriticalSection(&soundCriticalSection); + WaitForSingleObject(hThread, INFINITE); + CloseHandle(hThread); + + dsBuffer->Release(); + ds->Release(); + + CloseHandle(soundSyncEvent); +} + + +int DSound_GetCurSample() +{ + EnterCriticalSection(&soundCriticalSection); + int playCursor; + dsBuffer->GetCurrentPosition((DWORD*)&playCursor, 0); + playCursor = ModBufferSize(playCursor - lastPos) + totalRenderedBytes; + LeaveCriticalSection(&soundCriticalSection); + return(playCursor); +} + + +float DSound_GetTimer() +{ + return((float)DSound_GetCurSample() * (1.0f / (4.0f * 44100.0f))); +} +} diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DisAsmDlg.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/DisAsmDlg.cpp index b34ca5b5e0..a72c7a08fa 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/DisAsmDlg.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/DisAsmDlg.cpp @@ -1,667 +1,667 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "stdafx.h" -#include "../res/resource.h" -#include "DisAsmDlg.h" - -#include "gdsp_memory.h" -#include "gdsp_interpreter.h" -#include "disassemble.h" -#include "RegSettings.h" - -CDisAsmDlg::CDisAsmDlg() - : m_CachedStepCounter(-1) - , m_CachedCR(-1) - , m_State(RUN) - , m_CachedUCodeCRC(-1) -{} - - -BOOL CDisAsmDlg::PreTranslateMessage(MSG* pMsg) -{ - return(IsDialogMessage(pMsg)); -} - - -BOOL CDisAsmDlg::OnIdle() -{ - return(FALSE); -} - - -LRESULT CDisAsmDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) -{ - CWindowSettings ws; - - if (ws.Load("Software\\Dolphin\\DSP", "DisAsm")) - { - ws.ApplyTo(CWindow(m_hWnd), SW_SHOW); - } - - m_DisAsmListViewCtrl.m_hWnd = GetDlgItem(IDC_DISASM_LIST); - - UIAddChildWindowContainer(m_hWnd); - - m_DisAsmListViewCtrl.AddColumn(_T("BP"), ColumnBP); - m_DisAsmListViewCtrl.AddColumn(_T("Function"), ColumnFunction); - m_DisAsmListViewCtrl.AddColumn(_T("Address"), ColumnAddress); - m_DisAsmListViewCtrl.AddColumn(_T("Mnenmomic"), ColumnMenmomic); - m_DisAsmListViewCtrl.AddColumn(_T("Opcode"), ColumnOpcode); - m_DisAsmListViewCtrl.AddColumn(_T("Ext"), ColumnExt); - m_DisAsmListViewCtrl.AddColumn(_T("Parameter"), ColumnParameter); - - m_DisAsmListViewCtrl.SetColumnWidth(ColumnBP, 25); - m_DisAsmListViewCtrl.SetColumnWidth(ColumnFunction, 160); - m_DisAsmListViewCtrl.SetColumnWidth(ColumnAddress, 55); - m_DisAsmListViewCtrl.SetColumnWidth(ColumnMenmomic, 55); - m_DisAsmListViewCtrl.SetColumnWidth(ColumnOpcode, 60); - m_DisAsmListViewCtrl.SetColumnWidth(ColumnExt, 40); - m_DisAsmListViewCtrl.SetColumnWidth(ColumnParameter, 500); - - m_DisAsmListViewCtrl.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); - - m_RegisterDlg.Create(m_hWnd); - - UpdateDialog(); - - DlgResize_Init(true, false, WS_THICKFRAME); - - return(TRUE); -} - - -LRESULT CDisAsmDlg::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) -{ - CWindowSettings ws; - ws.GetFrom(CWindow(m_hWnd)); - ws.Save("Software\\Dolphin\\DSP", "DisAsm"); - - return(0); -} - - -LRESULT CDisAsmDlg::OnStep(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) -{ - m_State = STEP; - - UpdateButtonTexts(); - return(0); -} - - -LRESULT CDisAsmDlg::OnGo(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) -{ - if ((m_State == RUN) || (m_State == RUN_START)) - { - m_State = PAUSE; - } - else - { - m_State = RUN_START; - } - - UpdateButtonTexts(); - return(0); -} - - -LRESULT CDisAsmDlg::OnShowRegisters(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) -{ - if (m_RegisterDlg.IsWindowVisible()) - { - m_RegisterDlg.ShowWindow(SW_HIDE); - } - else - { - m_RegisterDlg.ShowWindow(SW_SHOW); - } - - UpdateButtonTexts(); - return(0); -} - - -LRESULT CDisAsmDlg::OnDblClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) -{ - int Index = m_DisAsmListViewCtrl.GetSelectedIndex(); - - if (Index != -1) - { - uint16 SelectedPC = static_cast(m_DisAsmListViewCtrl.GetItemData(Index)); - ToggleBreakPoint(SelectedPC); - } - - RedrawDisAsmListView(); - return(0); -} - - -LRESULT CDisAsmDlg::OnRClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) -{ - int Index = m_DisAsmListViewCtrl.GetSelectedIndex(); - - if (Index != -1) - { - uint16 SelectedPC = static_cast(m_DisAsmListViewCtrl.GetItemData(Index)); - g_dsp.pc = SelectedPC; - } - - RedrawDisAsmListView(); - return(0); -} - - -void CDisAsmDlg::CloseDialog(int nVal) -{ - DestroyWindow(); - ::PostQuitMessage(nVal); -} - - -int CALLBACK CDisAsmDlg::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) -{ - return(lParam1 > lParam2); -} - - -void CDisAsmDlg::RebuildDisAsmListView() -{ - if (!m_DisAsmListViewCtrl.IsWindow()) - return; - - m_DisAsmListViewCtrl.ShowWindow(SW_HIDE); - m_DisAsmListViewCtrl.DeleteAllItems(); - - char Buffer[256]; - gd_globals_t gdg; - - if (g_dsp.pc & 0x8000) - { - gdg.binbuf = g_dsp.irom; - } - else - { - gdg.binbuf = g_dsp.iram; - } - - gdg.buffer = Buffer; - gdg.buffer_size = 256; - gdg.ext_separator = (char)0xff; - - gdg.show_pc = false; - gdg.show_hex = false; - gdg.print_tabs = true; - gdg.decode_names = true; - gdg.decode_registers = true; - - for (gdg.pc = 0; gdg.pc < DSP_IROM_SIZE;) - { - uint16 CurrentPC = gdg.pc; - - if (g_dsp.pc & 0x8000) - { - CurrentPC |= 0x8000; - } - - char Temp[256]; - sprintf_s(Temp, 256, "0x%04x", CurrentPC); - - char Temp2[256]; - sprintf_s(Temp2, 256, "0x%04x", dsp_imem_read(CurrentPC)); - - char* pOpcode = gd_dis_opcode(&gdg); - const char* pParameter = NULL; - const char* pExtension = NULL; - - size_t WholeString = strlen(pOpcode); - - for (size_t i = 0; i < WholeString; i++) - { - if (pOpcode[i] == (char)0xff) - { - pOpcode[i] = 0x00; - pExtension = &pOpcode[i + 1]; - } - - if (pOpcode[i] == 0x09) - { - pOpcode[i] = 0x00; - pParameter = &pOpcode[i + 1]; - } - } - - - const char* pFunctionName = NULL; - - if (m_SymbolMap.find(CurrentPC) != m_SymbolMap.end()) - { - pFunctionName = m_SymbolMap[CurrentPC].Name.c_str(); - } - - int Item = m_DisAsmListViewCtrl.AddItem(0, ColumnBP, _T(" ")); - m_DisAsmListViewCtrl.AddItem(Item, ColumnFunction, pFunctionName); - m_DisAsmListViewCtrl.AddItem(Item, ColumnAddress, Temp); - m_DisAsmListViewCtrl.AddItem(Item, ColumnMenmomic, Temp2); - m_DisAsmListViewCtrl.AddItem(Item, ColumnOpcode, pOpcode); - m_DisAsmListViewCtrl.AddItem(Item, ColumnExt, pExtension); - - if (!_stricmp(pOpcode, "CALL")) - { - uint32 FunctionAddress = -1; - sscanf(pParameter, "0x%04x", &FunctionAddress); - - if (m_SymbolMap.find(FunctionAddress) != m_SymbolMap.end()) - { - pParameter = m_SymbolMap[FunctionAddress].Name.c_str(); - } - } - - m_DisAsmListViewCtrl.AddItem(Item, ColumnParameter, pParameter); - - m_DisAsmListViewCtrl.SetItemData(Item, CurrentPC); - } - - m_DisAsmListViewCtrl.SortItems(CompareFunc, (LPARAM) this); - - m_DisAsmListViewCtrl.ShowWindow(SW_SHOW); -} - - -void CDisAsmDlg::UpdateDisAsmListView() -{ - if (g_dsp.dram == NULL) - { - return; - } - - // check if we have to rebuild the list view - if (m_DisAsmListViewCtrl.GetItemCount() == 0) - { - RebuildDisAsmListView(); - } - else - { - uint16 FirstPC = static_cast(m_DisAsmListViewCtrl.GetItemData(0)); - - if ((FirstPC & 0x8000) != (g_dsp.pc & 0x8000)) - { - RebuildDisAsmListView(); - } - } - - if (m_CachedStepCounter == g_dsp.step_counter) - { - return; - } - - // show PC - for (int i = 0; i < m_DisAsmListViewCtrl.GetItemCount(); i++) - { - if (m_DisAsmListViewCtrl.GetItemData(i) == g_dsp.pc) - { - m_DisAsmListViewCtrl.EnsureVisible(i - 5, FALSE); - m_DisAsmListViewCtrl.EnsureVisible(i + 14, FALSE); - break; - } - } - - m_CachedStepCounter = g_dsp.step_counter; - - RedrawDisAsmListView(); - - m_RegisterDlg.UpdateRegisterListView(); -} - - -void CDisAsmDlg::UpdateSymbolMap() -{ - if (g_dsp.dram == NULL) - { - return; - } - - if (m_CachedUCodeCRC != g_dsp.iram_crc) - { - // load symbol map (if there is one) - m_CachedUCodeCRC = g_dsp.iram_crc; - char FileName[MAX_PATH]; - sprintf(FileName, "maps\\DSP_%08x.map", m_CachedUCodeCRC); - LoadSymbolMap(FileName); - - // rebuild the disasm - RebuildDisAsmListView(); - } -} - - -void CDisAsmDlg::UpdateRegisterFlags() -{ - if (m_CachedCR == g_dsp.cr) - { - return; - } - - CButton ButtonAssertInt(GetDlgItem(IDC_ASSERT_INT)); - ButtonAssertInt.SetCheck(g_dsp.cr & 0x02 ? BST_CHECKED : BST_UNCHECKED); - - CButton ButtonReset(GetDlgItem(IDC_HALT)); - ButtonReset.SetCheck(g_dsp.cr & 0x04 ? BST_CHECKED : BST_UNCHECKED); - - CButton ButtonInit(GetDlgItem(IDC_INIT)); - ButtonInit.SetCheck(g_dsp.cr & 0x800 ? BST_CHECKED : BST_UNCHECKED); - - m_CachedCR = g_dsp.cr; -} - - -bool CDisAsmDlg::CanDoStep() -{ - UpdateSymbolMap(); // update the symbols all the time because there a script cmds like bps - - switch (m_State) - { - case RUN_START: - m_State = RUN; - return(true); - - case RUN: - - if (IsBreakPoint(g_dsp.pc)) - { - UpdateDialog(); - m_State = PAUSE; - return(false); - } - - return(true); - - case PAUSE: - UpdateDialog(); - return(false); - - case STEP: - UpdateDialog(); - m_State = PAUSE; - return(true); - } - - return(false); -} - - -void CDisAsmDlg::DebugBreak() -{ - m_State = PAUSE; -} - - -void CDisAsmDlg::UpdateButtonTexts() -{ - // go button - { - CButton Button(GetDlgItem(ID_GO)); - - switch (m_State) - { - case RUN_START: - case RUN: - Button.SetWindowText("Pause"); - break; - - case PAUSE: - case STEP: - Button.SetWindowText("Go"); - break; - } - } - - // show register - { - CButton Button(GetDlgItem(ID_SHOW_REGISTER)); - - if (m_RegisterDlg.IsWindowVisible()) - { - Button.SetWindowText("Hide Regs"); - } - else - { - Button.SetWindowText("Show Regs"); - } - } -} - - -bool CDisAsmDlg::IsBreakPoint(uint16 _Address) -{ - return(std::find(m_BreakPoints.begin(), m_BreakPoints.end(), _Address) != m_BreakPoints.end()); -} - - -void CDisAsmDlg::ToggleBreakPoint(uint16 _Address) -{ - if (IsBreakPoint(_Address)) - { - RemoveBreakPoint(_Address); - } - else - { - AddBreakPoint(_Address); - } -} - - -void CDisAsmDlg::RemoveBreakPoint(uint16 _Address) -{ - CBreakPointList::iterator itr = std::find(m_BreakPoints.begin(), m_BreakPoints.end(), _Address); - - if (itr != m_BreakPoints.end()) - { - m_BreakPoints.erase(itr); - } -} - - -void CDisAsmDlg::AddBreakPoint(uint16 _Address) -{ - CBreakPointList::iterator itr = std::find(m_BreakPoints.begin(), m_BreakPoints.end(), _Address); - - if (itr == m_BreakPoints.end()) - { - m_BreakPoints.push_back(_Address); - } -} - - -void CDisAsmDlg::ClearBreakPoints() -{ - m_BreakPoints.clear(); -} - - -LRESULT CDisAsmDlg::OnCustomDraw(int /*idCtrl*/, LPNMHDR pnmh, BOOL& _bHandled) -{ - int result = CDRF_DODEFAULT; - - NMLVCUSTOMDRAW* pLVCD = reinterpret_cast(pnmh); - - switch (pLVCD->nmcd.dwDrawStage) - { - case CDDS_PREPAINT: - result = CDRF_NOTIFYITEMDRAW; - break; - - case CDDS_ITEMPREPAINT: - result = CDRF_NOTIFYSUBITEMDRAW; - break; - - case (CDDS_ITEMPREPAINT | CDDS_SUBITEM): - { - pLVCD->nmcd.uItemState &= ~(CDIS_SELECTED | CDIS_FOCUS); - - uint16 CurrentAddress = static_cast(m_DisAsmListViewCtrl.GetItemData((int)pLVCD->nmcd.dwItemSpec)); - pLVCD->clrTextBk = FindColor(CurrentAddress); - - if (CurrentAddress == g_dsp.pc) - { - pLVCD->clrTextBk = RGB(96, 192, 128); - } - - switch (pLVCD->iSubItem) - { - case 0x00: - { - if (IsBreakPoint(CurrentAddress)) - { - pLVCD->clrTextBk = RGB(255, 64, 64); - } - } - break; - - default: - break; - } - } - } - - return(result); -} - - -void CDisAsmDlg::RedrawDisAsmListView() -{ - ::InvalidateRect(m_DisAsmListViewCtrl.m_hWnd, NULL, FALSE); -} - - -bool CDisAsmDlg::LoadSymbolMap(const char* _pFileName) -{ - m_SymbolMap.clear(); - - FILE* pFile = fopen(_pFileName, "r"); - - if (!pFile) - { - return(false); - } - - char Name[1024]; - uint32 AddressStart, AddressEnd; - - while (!feof(pFile)) - { - char line[512]; - fgets(line, 511, pFile); - - if (strlen(line) < 2) - { - continue; - } - - // check for comment - if (line[0] == '.') - { - continue; - } - - // clear all breakpoints - if (line[0] == 'C') - { - ClearBreakPoints(); - continue; - } - - // add breakpoint - if (line[0] == 'B') - { - sscanf(line, "B %04x", &AddressStart); - AddBreakPoint(static_cast(AddressStart)); - continue; - } - - // default add new symbol - sscanf(line, "%04x %04x %s", &AddressStart, &AddressEnd, Name); - - if (m_SymbolMap.find(AddressStart) == m_SymbolMap.end()) - { - m_SymbolMap.insert(std::pair(AddressStart, SSymbol(AddressStart, AddressEnd, Name))); - } - else - { - m_SymbolMap[AddressStart] = SSymbol(AddressStart, AddressEnd, Name); - } - } - - fclose(pFile); - - return(true); -} - - -DWORD CDisAsmDlg::FindColor(uint16 _Address) -{ - size_t Color = 0; - static int Colors[6] = {0xC0FFFF, 0xFFE0C0, 0xC0C0FF, 0xFFC0FF, 0xC0FFC0, 0xFFFFC0}; - - for (CSymbolMap::const_iterator itr = m_SymbolMap.begin(); itr != m_SymbolMap.end(); itr++) - { - const SSymbol& rSymbol = itr->second; - - if ((rSymbol.AddressStart <= _Address) && (_Address <= rSymbol.AddressEnd)) - { - return(Colors[Color % 6]); - } - - Color++; - } - - return(GetSysColor(COLOR_3DLIGHT)); -} - - -void CDisAsmDlg::UpdateDialog() -{ - UpdateSymbolMap(); - UpdateDisAsmListView(); -// UpdateButtonTexts(); - UpdateRegisterFlags(); -} - -LRESULT CDisAsmDlg::OnLvnItemchangedDisasmList(int /*idCtrl*/, LPNMHDR pNMHDR, BOOL& /*bHandled*/) -{ - LPNMLISTVIEW pNMLV = reinterpret_cast(pNMHDR); - // TODO: Add your control notification handler code here - - return 0; -} - - -// TODO: make the members adjust with the dialog -LRESULT CDisAsmDlg::OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) -{ - // we habe to make a group of the items I think - /* - CRect lpRect; - - - int wid = lpRect.right - lpRect.left - 100; - int hei = lpRect.bottom - lpRect.top - 20; - m_DisAsmListViewCtrl.ResizeClient(wid, hei, true); - */ - - return 0; -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" +#include "../res/resource.h" +#include "DisAsmDlg.h" + +#include "gdsp_memory.h" +#include "gdsp_interpreter.h" +#include "disassemble.h" +#include "RegSettings.h" + +CDisAsmDlg::CDisAsmDlg() + : m_CachedStepCounter(-1) + , m_CachedCR(-1) + , m_State(RUN) + , m_CachedUCodeCRC(-1) +{} + + +BOOL CDisAsmDlg::PreTranslateMessage(MSG* pMsg) +{ + return(IsDialogMessage(pMsg)); +} + + +BOOL CDisAsmDlg::OnIdle() +{ + return(FALSE); +} + + +LRESULT CDisAsmDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) +{ + CWindowSettings ws; + + if (ws.Load("Software\\Dolphin\\DSP", "DisAsm")) + { + ws.ApplyTo(CWindow(m_hWnd), SW_SHOW); + } + + m_DisAsmListViewCtrl.m_hWnd = GetDlgItem(IDC_DISASM_LIST); + + UIAddChildWindowContainer(m_hWnd); + + m_DisAsmListViewCtrl.AddColumn(_T("BP"), ColumnBP); + m_DisAsmListViewCtrl.AddColumn(_T("Function"), ColumnFunction); + m_DisAsmListViewCtrl.AddColumn(_T("Address"), ColumnAddress); + m_DisAsmListViewCtrl.AddColumn(_T("Mnenmomic"), ColumnMenmomic); + m_DisAsmListViewCtrl.AddColumn(_T("Opcode"), ColumnOpcode); + m_DisAsmListViewCtrl.AddColumn(_T("Ext"), ColumnExt); + m_DisAsmListViewCtrl.AddColumn(_T("Parameter"), ColumnParameter); + + m_DisAsmListViewCtrl.SetColumnWidth(ColumnBP, 25); + m_DisAsmListViewCtrl.SetColumnWidth(ColumnFunction, 160); + m_DisAsmListViewCtrl.SetColumnWidth(ColumnAddress, 55); + m_DisAsmListViewCtrl.SetColumnWidth(ColumnMenmomic, 55); + m_DisAsmListViewCtrl.SetColumnWidth(ColumnOpcode, 60); + m_DisAsmListViewCtrl.SetColumnWidth(ColumnExt, 40); + m_DisAsmListViewCtrl.SetColumnWidth(ColumnParameter, 500); + + m_DisAsmListViewCtrl.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); + + m_RegisterDlg.Create(m_hWnd); + + UpdateDialog(); + + DlgResize_Init(true, false, WS_THICKFRAME); + + return(TRUE); +} + + +LRESULT CDisAsmDlg::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) +{ + CWindowSettings ws; + ws.GetFrom(CWindow(m_hWnd)); + ws.Save("Software\\Dolphin\\DSP", "DisAsm"); + + return(0); +} + + +LRESULT CDisAsmDlg::OnStep(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) +{ + m_State = STEP; + + UpdateButtonTexts(); + return(0); +} + + +LRESULT CDisAsmDlg::OnGo(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) +{ + if ((m_State == RUN) || (m_State == RUN_START)) + { + m_State = PAUSE; + } + else + { + m_State = RUN_START; + } + + UpdateButtonTexts(); + return(0); +} + + +LRESULT CDisAsmDlg::OnShowRegisters(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) +{ + if (m_RegisterDlg.IsWindowVisible()) + { + m_RegisterDlg.ShowWindow(SW_HIDE); + } + else + { + m_RegisterDlg.ShowWindow(SW_SHOW); + } + + UpdateButtonTexts(); + return(0); +} + + +LRESULT CDisAsmDlg::OnDblClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) +{ + int Index = m_DisAsmListViewCtrl.GetSelectedIndex(); + + if (Index != -1) + { + uint16 SelectedPC = static_cast(m_DisAsmListViewCtrl.GetItemData(Index)); + ToggleBreakPoint(SelectedPC); + } + + RedrawDisAsmListView(); + return(0); +} + + +LRESULT CDisAsmDlg::OnRClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) +{ + int Index = m_DisAsmListViewCtrl.GetSelectedIndex(); + + if (Index != -1) + { + uint16 SelectedPC = static_cast(m_DisAsmListViewCtrl.GetItemData(Index)); + g_dsp.pc = SelectedPC; + } + + RedrawDisAsmListView(); + return(0); +} + + +void CDisAsmDlg::CloseDialog(int nVal) +{ + DestroyWindow(); + ::PostQuitMessage(nVal); +} + + +int CALLBACK CDisAsmDlg::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) +{ + return(lParam1 > lParam2); +} + + +void CDisAsmDlg::RebuildDisAsmListView() +{ + if (!m_DisAsmListViewCtrl.IsWindow()) + return; + + m_DisAsmListViewCtrl.ShowWindow(SW_HIDE); + m_DisAsmListViewCtrl.DeleteAllItems(); + + char Buffer[256]; + gd_globals_t gdg; + + if (g_dsp.pc & 0x8000) + { + gdg.binbuf = g_dsp.irom; + } + else + { + gdg.binbuf = g_dsp.iram; + } + + gdg.buffer = Buffer; + gdg.buffer_size = 256; + gdg.ext_separator = (char)0xff; + + gdg.show_pc = false; + gdg.show_hex = false; + gdg.print_tabs = true; + gdg.decode_names = true; + gdg.decode_registers = true; + + for (gdg.pc = 0; gdg.pc < DSP_IROM_SIZE;) + { + uint16 CurrentPC = gdg.pc; + + if (g_dsp.pc & 0x8000) + { + CurrentPC |= 0x8000; + } + + char Temp[256]; + sprintf_s(Temp, 256, "0x%04x", CurrentPC); + + char Temp2[256]; + sprintf_s(Temp2, 256, "0x%04x", dsp_imem_read(CurrentPC)); + + char* pOpcode = gd_dis_opcode(&gdg); + const char* pParameter = NULL; + const char* pExtension = NULL; + + size_t WholeString = strlen(pOpcode); + + for (size_t i = 0; i < WholeString; i++) + { + if (pOpcode[i] == (char)0xff) + { + pOpcode[i] = 0x00; + pExtension = &pOpcode[i + 1]; + } + + if (pOpcode[i] == 0x09) + { + pOpcode[i] = 0x00; + pParameter = &pOpcode[i + 1]; + } + } + + + const char* pFunctionName = NULL; + + if (m_SymbolMap.find(CurrentPC) != m_SymbolMap.end()) + { + pFunctionName = m_SymbolMap[CurrentPC].Name.c_str(); + } + + int Item = m_DisAsmListViewCtrl.AddItem(0, ColumnBP, _T(" ")); + m_DisAsmListViewCtrl.AddItem(Item, ColumnFunction, pFunctionName); + m_DisAsmListViewCtrl.AddItem(Item, ColumnAddress, Temp); + m_DisAsmListViewCtrl.AddItem(Item, ColumnMenmomic, Temp2); + m_DisAsmListViewCtrl.AddItem(Item, ColumnOpcode, pOpcode); + m_DisAsmListViewCtrl.AddItem(Item, ColumnExt, pExtension); + + if (!_stricmp(pOpcode, "CALL")) + { + uint32 FunctionAddress = -1; + sscanf(pParameter, "0x%04x", &FunctionAddress); + + if (m_SymbolMap.find(FunctionAddress) != m_SymbolMap.end()) + { + pParameter = m_SymbolMap[FunctionAddress].Name.c_str(); + } + } + + m_DisAsmListViewCtrl.AddItem(Item, ColumnParameter, pParameter); + + m_DisAsmListViewCtrl.SetItemData(Item, CurrentPC); + } + + m_DisAsmListViewCtrl.SortItems(CompareFunc, (LPARAM) this); + + m_DisAsmListViewCtrl.ShowWindow(SW_SHOW); +} + + +void CDisAsmDlg::UpdateDisAsmListView() +{ + if (g_dsp.dram == NULL) + { + return; + } + + // check if we have to rebuild the list view + if (m_DisAsmListViewCtrl.GetItemCount() == 0) + { + RebuildDisAsmListView(); + } + else + { + uint16 FirstPC = static_cast(m_DisAsmListViewCtrl.GetItemData(0)); + + if ((FirstPC & 0x8000) != (g_dsp.pc & 0x8000)) + { + RebuildDisAsmListView(); + } + } + + if (m_CachedStepCounter == g_dsp.step_counter) + { + return; + } + + // show PC + for (int i = 0; i < m_DisAsmListViewCtrl.GetItemCount(); i++) + { + if (m_DisAsmListViewCtrl.GetItemData(i) == g_dsp.pc) + { + m_DisAsmListViewCtrl.EnsureVisible(i - 5, FALSE); + m_DisAsmListViewCtrl.EnsureVisible(i + 14, FALSE); + break; + } + } + + m_CachedStepCounter = g_dsp.step_counter; + + RedrawDisAsmListView(); + + m_RegisterDlg.UpdateRegisterListView(); +} + + +void CDisAsmDlg::UpdateSymbolMap() +{ + if (g_dsp.dram == NULL) + { + return; + } + + if (m_CachedUCodeCRC != g_dsp.iram_crc) + { + // load symbol map (if there is one) + m_CachedUCodeCRC = g_dsp.iram_crc; + char FileName[MAX_PATH]; + sprintf(FileName, "maps\\DSP_%08x.map", m_CachedUCodeCRC); + LoadSymbolMap(FileName); + + // rebuild the disasm + RebuildDisAsmListView(); + } +} + + +void CDisAsmDlg::UpdateRegisterFlags() +{ + if (m_CachedCR == g_dsp.cr) + { + return; + } + + CButton ButtonAssertInt(GetDlgItem(IDC_ASSERT_INT)); + ButtonAssertInt.SetCheck(g_dsp.cr & 0x02 ? BST_CHECKED : BST_UNCHECKED); + + CButton ButtonReset(GetDlgItem(IDC_HALT)); + ButtonReset.SetCheck(g_dsp.cr & 0x04 ? BST_CHECKED : BST_UNCHECKED); + + CButton ButtonInit(GetDlgItem(IDC_INIT)); + ButtonInit.SetCheck(g_dsp.cr & 0x800 ? BST_CHECKED : BST_UNCHECKED); + + m_CachedCR = g_dsp.cr; +} + + +bool CDisAsmDlg::CanDoStep() +{ + UpdateSymbolMap(); // update the symbols all the time because there a script cmds like bps + + switch (m_State) + { + case RUN_START: + m_State = RUN; + return(true); + + case RUN: + + if (IsBreakPoint(g_dsp.pc)) + { + UpdateDialog(); + m_State = PAUSE; + return(false); + } + + return(true); + + case PAUSE: + UpdateDialog(); + return(false); + + case STEP: + UpdateDialog(); + m_State = PAUSE; + return(true); + } + + return(false); +} + + +void CDisAsmDlg::DebugBreak() +{ + m_State = PAUSE; +} + + +void CDisAsmDlg::UpdateButtonTexts() +{ + // go button + { + CButton Button(GetDlgItem(ID_GO)); + + switch (m_State) + { + case RUN_START: + case RUN: + Button.SetWindowText("Pause"); + break; + + case PAUSE: + case STEP: + Button.SetWindowText("Go"); + break; + } + } + + // show register + { + CButton Button(GetDlgItem(ID_SHOW_REGISTER)); + + if (m_RegisterDlg.IsWindowVisible()) + { + Button.SetWindowText("Hide Regs"); + } + else + { + Button.SetWindowText("Show Regs"); + } + } +} + + +bool CDisAsmDlg::IsBreakPoint(uint16 _Address) +{ + return(std::find(m_BreakPoints.begin(), m_BreakPoints.end(), _Address) != m_BreakPoints.end()); +} + + +void CDisAsmDlg::ToggleBreakPoint(uint16 _Address) +{ + if (IsBreakPoint(_Address)) + { + RemoveBreakPoint(_Address); + } + else + { + AddBreakPoint(_Address); + } +} + + +void CDisAsmDlg::RemoveBreakPoint(uint16 _Address) +{ + CBreakPointList::iterator itr = std::find(m_BreakPoints.begin(), m_BreakPoints.end(), _Address); + + if (itr != m_BreakPoints.end()) + { + m_BreakPoints.erase(itr); + } +} + + +void CDisAsmDlg::AddBreakPoint(uint16 _Address) +{ + CBreakPointList::iterator itr = std::find(m_BreakPoints.begin(), m_BreakPoints.end(), _Address); + + if (itr == m_BreakPoints.end()) + { + m_BreakPoints.push_back(_Address); + } +} + + +void CDisAsmDlg::ClearBreakPoints() +{ + m_BreakPoints.clear(); +} + + +LRESULT CDisAsmDlg::OnCustomDraw(int /*idCtrl*/, LPNMHDR pnmh, BOOL& _bHandled) +{ + int result = CDRF_DODEFAULT; + + NMLVCUSTOMDRAW* pLVCD = reinterpret_cast(pnmh); + + switch (pLVCD->nmcd.dwDrawStage) + { + case CDDS_PREPAINT: + result = CDRF_NOTIFYITEMDRAW; + break; + + case CDDS_ITEMPREPAINT: + result = CDRF_NOTIFYSUBITEMDRAW; + break; + + case (CDDS_ITEMPREPAINT | CDDS_SUBITEM): + { + pLVCD->nmcd.uItemState &= ~(CDIS_SELECTED | CDIS_FOCUS); + + uint16 CurrentAddress = static_cast(m_DisAsmListViewCtrl.GetItemData((int)pLVCD->nmcd.dwItemSpec)); + pLVCD->clrTextBk = FindColor(CurrentAddress); + + if (CurrentAddress == g_dsp.pc) + { + pLVCD->clrTextBk = RGB(96, 192, 128); + } + + switch (pLVCD->iSubItem) + { + case 0x00: + { + if (IsBreakPoint(CurrentAddress)) + { + pLVCD->clrTextBk = RGB(255, 64, 64); + } + } + break; + + default: + break; + } + } + } + + return(result); +} + + +void CDisAsmDlg::RedrawDisAsmListView() +{ + ::InvalidateRect(m_DisAsmListViewCtrl.m_hWnd, NULL, FALSE); +} + + +bool CDisAsmDlg::LoadSymbolMap(const char* _pFileName) +{ + m_SymbolMap.clear(); + + FILE* pFile = fopen(_pFileName, "r"); + + if (!pFile) + { + return(false); + } + + char Name[1024]; + uint32 AddressStart, AddressEnd; + + while (!feof(pFile)) + { + char line[512]; + fgets(line, 511, pFile); + + if (strlen(line) < 2) + { + continue; + } + + // check for comment + if (line[0] == '.') + { + continue; + } + + // clear all breakpoints + if (line[0] == 'C') + { + ClearBreakPoints(); + continue; + } + + // add breakpoint + if (line[0] == 'B') + { + sscanf(line, "B %04x", &AddressStart); + AddBreakPoint(static_cast(AddressStart)); + continue; + } + + // default add new symbol + sscanf(line, "%04x %04x %s", &AddressStart, &AddressEnd, Name); + + if (m_SymbolMap.find(AddressStart) == m_SymbolMap.end()) + { + m_SymbolMap.insert(std::pair(AddressStart, SSymbol(AddressStart, AddressEnd, Name))); + } + else + { + m_SymbolMap[AddressStart] = SSymbol(AddressStart, AddressEnd, Name); + } + } + + fclose(pFile); + + return(true); +} + + +DWORD CDisAsmDlg::FindColor(uint16 _Address) +{ + size_t Color = 0; + static int Colors[6] = {0xC0FFFF, 0xFFE0C0, 0xC0C0FF, 0xFFC0FF, 0xC0FFC0, 0xFFFFC0}; + + for (CSymbolMap::const_iterator itr = m_SymbolMap.begin(); itr != m_SymbolMap.end(); itr++) + { + const SSymbol& rSymbol = itr->second; + + if ((rSymbol.AddressStart <= _Address) && (_Address <= rSymbol.AddressEnd)) + { + return(Colors[Color % 6]); + } + + Color++; + } + + return(GetSysColor(COLOR_3DLIGHT)); +} + + +void CDisAsmDlg::UpdateDialog() +{ + UpdateSymbolMap(); + UpdateDisAsmListView(); +// UpdateButtonTexts(); + UpdateRegisterFlags(); +} + +LRESULT CDisAsmDlg::OnLvnItemchangedDisasmList(int /*idCtrl*/, LPNMHDR pNMHDR, BOOL& /*bHandled*/) +{ + LPNMLISTVIEW pNMLV = reinterpret_cast(pNMHDR); + // TODO: Add your control notification handler code here + + return 0; +} + + +// TODO: make the members adjust with the dialog +LRESULT CDisAsmDlg::OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) +{ + // we habe to make a group of the items I think + /* + CRect lpRect; + + + int wid = lpRect.right - lpRect.left - 100; + int hei = lpRect.bottom - lpRect.top - 20; + m_DisAsmListViewCtrl.ResizeClient(wid, hei, true); + */ + + return 0; +} diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/Globals.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/Globals.cpp index b45b2c41e7..be1fe31a54 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/Globals.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/Globals.cpp @@ -1,133 +1,133 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include // I hope this doesn't break anything -#include -#include - -#include "Common.h" // for Common::swap -#include "Globals.h" -#include "gdsp_interpreter.h" - - -// ======================================================================================= -// This is to verbose, it has to be turned on manually for now -// -------------- -void DebugLog(const char* _fmt, ...) -{ -#if defined(_DEBUG) || defined(DEBUGFAST) -char Msg[512]; - va_list ap; - - va_start( ap, _fmt ); - vsprintf( Msg, _fmt, ap ); - va_end( ap ); - - // Only show certain messages - std::string sMsg = Msg; - if(sMsg.find("Mail") != -1 || sMsg.find("AX") != -1) - // no match = -1 - { - OutputDebugString(Msg); - g_dspInitialize.pLog(Msg,0); - } - -#endif -} -// ============= - - -void ErrorLog(const char* _fmt, ...) -{ - char Msg[512]; - va_list ap; - - va_start(ap, _fmt); - vsprintf(Msg, _fmt, ap); - va_end(ap); - - g_dspInitialize.pLog(Msg,0); -#ifdef _WIN32 - ::MessageBox(NULL, Msg, "Error", MB_OK); -#endif - - DSP_DebugBreak(); // NOTICE: we also break the emulation if this happens -} - - -// ======================================================================================= -// For PB address detection -// -------------- -u32 RAM_MASK = 0x1FFFFFF; - - -u16 Memory_Read_U16(u32 _uAddress) -{ - _uAddress &= RAM_MASK; - return Common::swap16(*(u16*)&g_dsp.cpu_ram[_uAddress]); -} - -u32 Memory_Read_U32(u32 _uAddress) -{ - _uAddress &= RAM_MASK; - return Common::swap32(*(u32*)&g_dsp.cpu_ram[_uAddress]); -} - -#if PROFILE - -#define PROFILE_MAP_SIZE 0x10000 - -u64 g_profileMap[PROFILE_MAP_SIZE]; -bool g_profile = false; - -void ProfilerStart() -{ - g_profile = true; -} - -void ProfilerAddDelta(int _addr, int _delta) -{ - if (g_profile) - { - g_profileMap[_addr] += _delta; - } -} - -void ProfilerInit() -{ - memset(g_profileMap, 0, sizeof(g_profileMap)); -} - -void ProfilerDump(uint64 count) -{ - FILE* pFile = fopen("c:\\_\\DSP_Prof.txt", "wt"); - if (pFile != NULL) - { - fprintf(pFile, "Number of DSP steps: %llu\n\n", count); - for (int i=0; i 0) - { - fprintf(pFile, "0x%04X: %llu\n", i, g_profileMap[i]); - } - } - - fclose(pFile); - } -} - -#endif +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include // I hope this doesn't break anything +#include +#include + +#include "Common.h" // for Common::swap +#include "Globals.h" +#include "gdsp_interpreter.h" + + +// ======================================================================================= +// This is to verbose, it has to be turned on manually for now +// -------------- +void DebugLog(const char* _fmt, ...) +{ +#if defined(_DEBUG) || defined(DEBUGFAST) +char Msg[512]; + va_list ap; + + va_start( ap, _fmt ); + vsprintf( Msg, _fmt, ap ); + va_end( ap ); + + // Only show certain messages + std::string sMsg = Msg; + if(sMsg.find("Mail") != -1 || sMsg.find("AX") != -1) + // no match = -1 + { + OutputDebugString(Msg); + g_dspInitialize.pLog(Msg,0); + } + +#endif +} +// ============= + + +void ErrorLog(const char* _fmt, ...) +{ + char Msg[512]; + va_list ap; + + va_start(ap, _fmt); + vsprintf(Msg, _fmt, ap); + va_end(ap); + + g_dspInitialize.pLog(Msg,0); +#ifdef _WIN32 + ::MessageBox(NULL, Msg, "Error", MB_OK); +#endif + + DSP_DebugBreak(); // NOTICE: we also break the emulation if this happens +} + + +// ======================================================================================= +// For PB address detection +// -------------- +u32 RAM_MASK = 0x1FFFFFF; + + +u16 Memory_Read_U16(u32 _uAddress) +{ + _uAddress &= RAM_MASK; + return Common::swap16(*(u16*)&g_dsp.cpu_ram[_uAddress]); +} + +u32 Memory_Read_U32(u32 _uAddress) +{ + _uAddress &= RAM_MASK; + return Common::swap32(*(u32*)&g_dsp.cpu_ram[_uAddress]); +} + +#if PROFILE + +#define PROFILE_MAP_SIZE 0x10000 + +u64 g_profileMap[PROFILE_MAP_SIZE]; +bool g_profile = false; + +void ProfilerStart() +{ + g_profile = true; +} + +void ProfilerAddDelta(int _addr, int _delta) +{ + if (g_profile) + { + g_profileMap[_addr] += _delta; + } +} + +void ProfilerInit() +{ + memset(g_profileMap, 0, sizeof(g_profileMap)); +} + +void ProfilerDump(uint64 count) +{ + FILE* pFile = fopen("c:\\_\\DSP_Prof.txt", "wt"); + if (pFile != NULL) + { + fprintf(pFile, "Number of DSP steps: %llu\n\n", count); + for (int i=0; i 0) + { + fprintf(pFile, "0x%04X: %llu\n", i, g_profileMap[i]); + } + } + + fclose(pFile); + } +} + +#endif diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/HLE_Functions.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/HLE_Functions.cpp index c944691701..08f4a00d9a 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/HLE_Functions.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/HLE_Functions.cpp @@ -1,1490 +1,1490 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifdef _WIN32 -#include "stdafx.h" -#endif -#include "Globals.h" -#include "HLE_Helper.h" - - -uint16& R00 = g_dsp.r[0x00]; -uint16& R01 = g_dsp.r[0x01]; -uint16& R02 = g_dsp.r[0x02]; -uint16& R03 = g_dsp.r[0x03]; -uint16& R04 = g_dsp.r[0x04]; -uint16& R05 = g_dsp.r[0x05]; -uint16& R06 = g_dsp.r[0x06]; -uint16& R07 = g_dsp.r[0x07]; -uint16& R08 = g_dsp.r[0x08]; -uint16& R09 = g_dsp.r[0x09]; -uint16& R0A = g_dsp.r[0x0a]; -uint16& R0B = g_dsp.r[0x0b]; -uint16& R0C = g_dsp.r[0x0c]; -uint16& R0D = g_dsp.r[0x0d]; -uint16& R0E = g_dsp.r[0x0e]; -uint16& R0F = g_dsp.r[0x0f]; -uint16& R10 = g_dsp.r[0x10]; -uint16& R11 = g_dsp.r[0x11]; -uint16& R12 = g_dsp.r[0x12]; -uint16& R13 = g_dsp.r[0x13]; -uint16& R14 = g_dsp.r[0x14]; -uint16& R15 = g_dsp.r[0x15]; -uint16& R16 = g_dsp.r[0x16]; -uint16& R17 = g_dsp.r[0x17]; -uint16& R18 = g_dsp.r[0x18]; -uint16& R19 = g_dsp.r[0x19]; -uint16& R1A = g_dsp.r[0x1a]; -uint16& R1B = g_dsp.r[0x1b]; -uint16& R1C = g_dsp.r[0x1c]; -uint16& R1D = g_dsp.r[0x1d]; -uint16& R1E = g_dsp.r[0x1e]; -uint16& R1F = g_dsp.r[0x1f]; - - -uint16& ST0 = g_dsp.r[0x0c]; -uint16& ST1 = g_dsp.r[0x0d]; -uint16& ST2 = g_dsp.r[0x0e]; -uint16& ST3 = g_dsp.r[0x0f]; -uint16& ACH0 = g_dsp.r[0x10]; -uint16& ACH1 = g_dsp.r[0x11]; -uint16& CR = g_dsp.r[0x12]; -uint16& SR = g_dsp.r[0x13]; -uint16& PROD_l = g_dsp.r[0x14]; -uint16& PROD_m1 = g_dsp.r[0x15]; -uint16& PROD_h = g_dsp.r[0x16]; -uint16& PROD_m2 = g_dsp.r[0x17]; -uint16& AX0_l = g_dsp.r[0x18]; -uint16& AX1_l = g_dsp.r[0x19]; -uint16& AX0_h = g_dsp.r[0x1a]; -uint16& AX1_h = g_dsp.r[0x1b]; -uint16& AC0_l = g_dsp.r[0x1c]; -uint16& AC1_l = g_dsp.r[0x1d]; -uint16& AC0_m = g_dsp.r[0x1e]; -uint16& AC1_m = g_dsp.r[0x1f]; - -TAccumulator<0> ACC0; -TAccumulator<1> ACC1; -CProd PROD; - - -u16 HLE_ROM_80E7_81F8() -{ - sint8 MultiplyModifier = GetMultiplyModifier(); -// l_80E7: - AX0_h = ReadDMEM(R00); - R00++; - ACC0 = 0; - Update_SR_Register(ACC0); -// l_80E8: - AX1_l = ReadDMEM(R01); - R01++; - ACC1 = 0; - Update_SR_Register(ACC1); -// l_80E9: - AC0_m = ReadDMEM(R02); - R02++; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_80EA: - AC0_l = ReadDMEM(R02); - R02++; - ACC1 = 0; - Update_SR_Register(ACC1); -// l_80EB: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 <<= 16; - Update_SR_Register(ACC0); -// l_80EC: - AX0_h = ReadDMEM(R00); - R00++; -// l_80ED: - AC1_l = ReadDMEM(R02); - R02++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_80EE: - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_80EF: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_80F0: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_80F1: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_80F2: - AC0_l = ReadDMEM(R02); - R02++; -// l_80F3: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_80F4: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_80F5: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_80F6: - AC1_l = ReadDMEM(R02); - R02++; -// l_80F7: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_80F8: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_80F9: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_80FA: - AC0_l = ReadDMEM(R02); - R02++; -// l_80FB: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_80FC: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_80FD: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_80FE: - AC1_l = ReadDMEM(R02); - R02++; -// l_80FF: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_8100: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8101: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_8102: - AC0_l = ReadDMEM(R02); - R02++; -// l_8103: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_8104: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8105: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_8106: - AC1_l = ReadDMEM(R02); - R02++; -// l_8107: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_8108: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8109: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_810A: - AC0_l = ReadDMEM(R02); - R02++; -// l_810B: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_810C: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_810D: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_810E: - AC1_l = ReadDMEM(R02); - R02++; -// l_810F: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_8110: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8111: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_8112: - AC0_l = ReadDMEM(R02); - R02++; -// l_8113: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_8114: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8115: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_8116: - AC1_l = ReadDMEM(R02); - R02++; -// l_8117: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_8118: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8119: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_811A: - AC0_l = ReadDMEM(R02); - R02++; -// l_811B: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_811C: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_811D: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_811E: - AC1_l = ReadDMEM(R02); - R02++; -// l_811F: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_8120: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8121: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_8122: - AC0_l = ReadDMEM(R02); - R02++; -// l_8123: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_8124: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8125: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_8126: - AC1_l = ReadDMEM(R02); - R02++; -// l_8127: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_8128: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8129: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_812A: - AC0_l = ReadDMEM(R02); - R02++; -// l_812B: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_812C: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_812D: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_812E: - AC1_l = ReadDMEM(R02); - R02++; -// l_812F: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_8130: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8131: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_8132: - AC0_l = ReadDMEM(R02); - R02++; -// l_8133: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_8134: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8135: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_8136: - AC1_l = ReadDMEM(R02); - R02++; -// l_8137: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_8138: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8139: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_813A: - AC0_l = ReadDMEM(R02); - R02++; -// l_813B: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_813C: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_813D: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_813E: - AC1_l = ReadDMEM(R02); - R02++; -// l_813F: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_8140: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8141: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_8142: - AC0_l = ReadDMEM(R02); - R02++; -// l_8143: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_8144: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8145: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_8146: - AC1_l = ReadDMEM(R02); - R02++; -// l_8147: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_8148: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8149: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_814A: - AC0_l = ReadDMEM(R02); - R02++; -// l_814B: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_814C: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_814D: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_814E: - AC1_l = ReadDMEM(R02); - R02++; -// l_814F: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_8150: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8151: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_8152: - AC0_l = ReadDMEM(R02); - R02++; -// l_8153: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_8154: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8155: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_8156: - AC1_l = ReadDMEM(R02); - R02++; -// l_8157: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_8158: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8159: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_815A: - AC0_l = ReadDMEM(R02); - R02++; -// l_815B: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_815C: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_815D: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_815E: - AC1_l = ReadDMEM(R02); - R02++; -// l_815F: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_8160: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8161: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_8162: - AC0_l = ReadDMEM(R02); - R02++; -// l_8163: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_8164: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8165: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_8166: - AC1_l = ReadDMEM(R02); - R02++; -// l_8167: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_8168: - WriteDMEM(R03, AC0_l); - R03++; -// l_8169: - ACC0 = PROD; -// l_816A: - AX0_l = AC0_m; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_816B: - R01++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_816C: - WriteDMEM(R03, AC1_m); - R03++; -// l_816D: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 = 0; - Update_SR_Register(ACC0); -// l_816E: - R00 = R04; -// l_816F: - R02 = R05; -// l_8170: - R03 = R02; -// l_8171: - AX0_h = ReadDMEM(R00); - R00++; - ACC0 = 0; - Update_SR_Register(ACC0); -// l_8172: - AX1_l = ReadDMEM(R01); - R01++; - ACC1 = 0; - Update_SR_Register(ACC1); -// l_8173: - AC0_m = ReadDMEM(R02); - R02++; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8174: - AC0_l = ReadDMEM(R02); - R02++; - ACC1 = 0; - Update_SR_Register(ACC1); -// l_8175: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 <<= 16; - Update_SR_Register(ACC0); -// l_8176: - AX0_h = ReadDMEM(R00); - R00++; -// l_8177: - AC1_l = ReadDMEM(R02); - R02++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8178: - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_8179: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_817A: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_817B: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_817C: - AC0_l = ReadDMEM(R02); - R02++; -// l_817D: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_817E: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_817F: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_8180: - AC1_l = ReadDMEM(R02); - R02++; -// l_8181: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_8182: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8183: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_8184: - AC0_l = ReadDMEM(R02); - R02++; -// l_8185: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_8186: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8187: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_8188: - AC1_l = ReadDMEM(R02); - R02++; -// l_8189: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_818A: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_818B: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_818C: - AC0_l = ReadDMEM(R02); - R02++; -// l_818D: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_818E: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_818F: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_8190: - AC1_l = ReadDMEM(R02); - R02++; -// l_8191: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_8192: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8193: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_8194: - AC0_l = ReadDMEM(R02); - R02++; -// l_8195: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_8196: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_8197: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_8198: - AC1_l = ReadDMEM(R02); - R02++; -// l_8199: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_819A: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_819B: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_819C: - AC0_l = ReadDMEM(R02); - R02++; -// l_819D: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_819E: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_819F: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_81A0: - AC1_l = ReadDMEM(R02); - R02++; -// l_81A1: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_81A2: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81A3: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_81A4: - AC0_l = ReadDMEM(R02); - R02++; -// l_81A5: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_81A6: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81A7: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_81A8: - AC1_l = ReadDMEM(R02); - R02++; -// l_81A9: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_81AA: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81AB: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_81AC: - AC0_l = ReadDMEM(R02); - R02++; -// l_81AD: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_81AE: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81AF: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_81B0: - AC1_l = ReadDMEM(R02); - R02++; -// l_81B1: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_81B2: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81B3: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_81B4: - AC0_l = ReadDMEM(R02); - R02++; -// l_81B5: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_81B6: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81B7: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_81B8: - AC1_l = ReadDMEM(R02); - R02++; -// l_81B9: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_81BA: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81BB: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_81BC: - AC0_l = ReadDMEM(R02); - R02++; -// l_81BD: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_81BE: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81BF: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_81C0: - AC1_l = ReadDMEM(R02); - R02++; -// l_81C1: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_81C2: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81C3: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_81C4: - AC0_l = ReadDMEM(R02); - R02++; -// l_81C5: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_81C6: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81C7: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_81C8: - AC1_l = ReadDMEM(R02); - R02++; -// l_81C9: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_81CA: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81CB: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_81CC: - AC0_l = ReadDMEM(R02); - R02++; -// l_81CD: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_81CE: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81CF: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_81D0: - AC1_l = ReadDMEM(R02); - R02++; -// l_81D1: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_81D2: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81D3: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_81D4: - AC0_l = ReadDMEM(R02); - R02++; -// l_81D5: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_81D6: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81D7: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_81D8: - AC1_l = ReadDMEM(R02); - R02++; -// l_81D9: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_81DA: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81DB: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_81DC: - AC0_l = ReadDMEM(R02); - R02++; -// l_81DD: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_81DE: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81DF: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_81E0: - AC1_l = ReadDMEM(R02); - R02++; -// l_81E1: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_81E2: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81E3: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_81E4: - AC0_l = ReadDMEM(R02); - R02++; -// l_81E5: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_81E6: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81E7: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_81E8: - AC1_l = ReadDMEM(R02); - R02++; -// l_81E9: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_81EA: - WriteDMEM(R03, AC0_l); - R03++; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81EB: - AC0_m = ReadDMEM(R02); - R02++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_81EC: - AC0_l = ReadDMEM(R02); - R02++; -// l_81ED: - WriteDMEM(R03, AC1_m); - R03++; - ACC0 <<= 16; - Update_SR_Register(ACC0); - AX0_h = ReadDMEM(R00); - R00++; -// l_81EE: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81EF: - AC1_m = ReadDMEM(R02); - R02++; - ACC0 >>= 16; - Update_SR_Register(ACC0); -// l_81F0: - AC1_l = ReadDMEM(R02); - R02++; -// l_81F1: - WriteDMEM(R03, AC0_m); - R03++; - ACC1 <<= 16; - Update_SR_Register(ACC1); - AX0_h = ReadDMEM(R00); - R00++; -// l_81F2: - WriteDMEM(R03, AC0_l); - R03++; -// l_81F3: - ACC0 = PROD; -// l_81F4: - AX1_h = AC0_m; - ACC1 += PROD; - PROD = AX0_h * AX1_l * MultiplyModifier; - Update_SR_Register(PROD); -// l_81F5: - R01++; - ACC1 >>= 16; - Update_SR_Register(ACC1); -// l_81F6: - WriteDMEM(R03, AC1_m); - R03++; -// l_81F7: - WriteDMEM(R03, AC1_l); - R03++; - ACC0 = 0; - Update_SR_Register(ACC0); -// l_81F8: -//missing: dsp_opc_ret; - - return 0x81f8; -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifdef _WIN32 +#include "stdafx.h" +#endif +#include "Globals.h" +#include "HLE_Helper.h" + + +uint16& R00 = g_dsp.r[0x00]; +uint16& R01 = g_dsp.r[0x01]; +uint16& R02 = g_dsp.r[0x02]; +uint16& R03 = g_dsp.r[0x03]; +uint16& R04 = g_dsp.r[0x04]; +uint16& R05 = g_dsp.r[0x05]; +uint16& R06 = g_dsp.r[0x06]; +uint16& R07 = g_dsp.r[0x07]; +uint16& R08 = g_dsp.r[0x08]; +uint16& R09 = g_dsp.r[0x09]; +uint16& R0A = g_dsp.r[0x0a]; +uint16& R0B = g_dsp.r[0x0b]; +uint16& R0C = g_dsp.r[0x0c]; +uint16& R0D = g_dsp.r[0x0d]; +uint16& R0E = g_dsp.r[0x0e]; +uint16& R0F = g_dsp.r[0x0f]; +uint16& R10 = g_dsp.r[0x10]; +uint16& R11 = g_dsp.r[0x11]; +uint16& R12 = g_dsp.r[0x12]; +uint16& R13 = g_dsp.r[0x13]; +uint16& R14 = g_dsp.r[0x14]; +uint16& R15 = g_dsp.r[0x15]; +uint16& R16 = g_dsp.r[0x16]; +uint16& R17 = g_dsp.r[0x17]; +uint16& R18 = g_dsp.r[0x18]; +uint16& R19 = g_dsp.r[0x19]; +uint16& R1A = g_dsp.r[0x1a]; +uint16& R1B = g_dsp.r[0x1b]; +uint16& R1C = g_dsp.r[0x1c]; +uint16& R1D = g_dsp.r[0x1d]; +uint16& R1E = g_dsp.r[0x1e]; +uint16& R1F = g_dsp.r[0x1f]; + + +uint16& ST0 = g_dsp.r[0x0c]; +uint16& ST1 = g_dsp.r[0x0d]; +uint16& ST2 = g_dsp.r[0x0e]; +uint16& ST3 = g_dsp.r[0x0f]; +uint16& ACH0 = g_dsp.r[0x10]; +uint16& ACH1 = g_dsp.r[0x11]; +uint16& CR = g_dsp.r[0x12]; +uint16& SR = g_dsp.r[0x13]; +uint16& PROD_l = g_dsp.r[0x14]; +uint16& PROD_m1 = g_dsp.r[0x15]; +uint16& PROD_h = g_dsp.r[0x16]; +uint16& PROD_m2 = g_dsp.r[0x17]; +uint16& AX0_l = g_dsp.r[0x18]; +uint16& AX1_l = g_dsp.r[0x19]; +uint16& AX0_h = g_dsp.r[0x1a]; +uint16& AX1_h = g_dsp.r[0x1b]; +uint16& AC0_l = g_dsp.r[0x1c]; +uint16& AC1_l = g_dsp.r[0x1d]; +uint16& AC0_m = g_dsp.r[0x1e]; +uint16& AC1_m = g_dsp.r[0x1f]; + +TAccumulator<0> ACC0; +TAccumulator<1> ACC1; +CProd PROD; + + +u16 HLE_ROM_80E7_81F8() +{ + sint8 MultiplyModifier = GetMultiplyModifier(); +// l_80E7: + AX0_h = ReadDMEM(R00); + R00++; + ACC0 = 0; + Update_SR_Register(ACC0); +// l_80E8: + AX1_l = ReadDMEM(R01); + R01++; + ACC1 = 0; + Update_SR_Register(ACC1); +// l_80E9: + AC0_m = ReadDMEM(R02); + R02++; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_80EA: + AC0_l = ReadDMEM(R02); + R02++; + ACC1 = 0; + Update_SR_Register(ACC1); +// l_80EB: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 <<= 16; + Update_SR_Register(ACC0); +// l_80EC: + AX0_h = ReadDMEM(R00); + R00++; +// l_80ED: + AC1_l = ReadDMEM(R02); + R02++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_80EE: + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_80EF: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_80F0: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_80F1: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_80F2: + AC0_l = ReadDMEM(R02); + R02++; +// l_80F3: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_80F4: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_80F5: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_80F6: + AC1_l = ReadDMEM(R02); + R02++; +// l_80F7: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_80F8: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_80F9: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_80FA: + AC0_l = ReadDMEM(R02); + R02++; +// l_80FB: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_80FC: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_80FD: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_80FE: + AC1_l = ReadDMEM(R02); + R02++; +// l_80FF: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_8100: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8101: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_8102: + AC0_l = ReadDMEM(R02); + R02++; +// l_8103: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_8104: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8105: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_8106: + AC1_l = ReadDMEM(R02); + R02++; +// l_8107: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_8108: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8109: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_810A: + AC0_l = ReadDMEM(R02); + R02++; +// l_810B: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_810C: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_810D: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_810E: + AC1_l = ReadDMEM(R02); + R02++; +// l_810F: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_8110: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8111: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_8112: + AC0_l = ReadDMEM(R02); + R02++; +// l_8113: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_8114: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8115: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_8116: + AC1_l = ReadDMEM(R02); + R02++; +// l_8117: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_8118: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8119: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_811A: + AC0_l = ReadDMEM(R02); + R02++; +// l_811B: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_811C: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_811D: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_811E: + AC1_l = ReadDMEM(R02); + R02++; +// l_811F: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_8120: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8121: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_8122: + AC0_l = ReadDMEM(R02); + R02++; +// l_8123: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_8124: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8125: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_8126: + AC1_l = ReadDMEM(R02); + R02++; +// l_8127: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_8128: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8129: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_812A: + AC0_l = ReadDMEM(R02); + R02++; +// l_812B: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_812C: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_812D: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_812E: + AC1_l = ReadDMEM(R02); + R02++; +// l_812F: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_8130: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8131: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_8132: + AC0_l = ReadDMEM(R02); + R02++; +// l_8133: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_8134: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8135: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_8136: + AC1_l = ReadDMEM(R02); + R02++; +// l_8137: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_8138: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8139: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_813A: + AC0_l = ReadDMEM(R02); + R02++; +// l_813B: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_813C: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_813D: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_813E: + AC1_l = ReadDMEM(R02); + R02++; +// l_813F: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_8140: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8141: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_8142: + AC0_l = ReadDMEM(R02); + R02++; +// l_8143: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_8144: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8145: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_8146: + AC1_l = ReadDMEM(R02); + R02++; +// l_8147: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_8148: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8149: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_814A: + AC0_l = ReadDMEM(R02); + R02++; +// l_814B: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_814C: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_814D: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_814E: + AC1_l = ReadDMEM(R02); + R02++; +// l_814F: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_8150: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8151: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_8152: + AC0_l = ReadDMEM(R02); + R02++; +// l_8153: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_8154: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8155: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_8156: + AC1_l = ReadDMEM(R02); + R02++; +// l_8157: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_8158: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8159: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_815A: + AC0_l = ReadDMEM(R02); + R02++; +// l_815B: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_815C: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_815D: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_815E: + AC1_l = ReadDMEM(R02); + R02++; +// l_815F: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_8160: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8161: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_8162: + AC0_l = ReadDMEM(R02); + R02++; +// l_8163: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_8164: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8165: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_8166: + AC1_l = ReadDMEM(R02); + R02++; +// l_8167: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_8168: + WriteDMEM(R03, AC0_l); + R03++; +// l_8169: + ACC0 = PROD; +// l_816A: + AX0_l = AC0_m; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_816B: + R01++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_816C: + WriteDMEM(R03, AC1_m); + R03++; +// l_816D: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 = 0; + Update_SR_Register(ACC0); +// l_816E: + R00 = R04; +// l_816F: + R02 = R05; +// l_8170: + R03 = R02; +// l_8171: + AX0_h = ReadDMEM(R00); + R00++; + ACC0 = 0; + Update_SR_Register(ACC0); +// l_8172: + AX1_l = ReadDMEM(R01); + R01++; + ACC1 = 0; + Update_SR_Register(ACC1); +// l_8173: + AC0_m = ReadDMEM(R02); + R02++; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8174: + AC0_l = ReadDMEM(R02); + R02++; + ACC1 = 0; + Update_SR_Register(ACC1); +// l_8175: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 <<= 16; + Update_SR_Register(ACC0); +// l_8176: + AX0_h = ReadDMEM(R00); + R00++; +// l_8177: + AC1_l = ReadDMEM(R02); + R02++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8178: + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_8179: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_817A: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_817B: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_817C: + AC0_l = ReadDMEM(R02); + R02++; +// l_817D: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_817E: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_817F: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_8180: + AC1_l = ReadDMEM(R02); + R02++; +// l_8181: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_8182: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8183: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_8184: + AC0_l = ReadDMEM(R02); + R02++; +// l_8185: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_8186: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8187: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_8188: + AC1_l = ReadDMEM(R02); + R02++; +// l_8189: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_818A: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_818B: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_818C: + AC0_l = ReadDMEM(R02); + R02++; +// l_818D: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_818E: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_818F: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_8190: + AC1_l = ReadDMEM(R02); + R02++; +// l_8191: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_8192: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8193: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_8194: + AC0_l = ReadDMEM(R02); + R02++; +// l_8195: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_8196: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_8197: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_8198: + AC1_l = ReadDMEM(R02); + R02++; +// l_8199: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_819A: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_819B: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_819C: + AC0_l = ReadDMEM(R02); + R02++; +// l_819D: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_819E: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_819F: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_81A0: + AC1_l = ReadDMEM(R02); + R02++; +// l_81A1: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_81A2: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81A3: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_81A4: + AC0_l = ReadDMEM(R02); + R02++; +// l_81A5: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_81A6: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81A7: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_81A8: + AC1_l = ReadDMEM(R02); + R02++; +// l_81A9: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_81AA: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81AB: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_81AC: + AC0_l = ReadDMEM(R02); + R02++; +// l_81AD: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_81AE: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81AF: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_81B0: + AC1_l = ReadDMEM(R02); + R02++; +// l_81B1: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_81B2: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81B3: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_81B4: + AC0_l = ReadDMEM(R02); + R02++; +// l_81B5: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_81B6: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81B7: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_81B8: + AC1_l = ReadDMEM(R02); + R02++; +// l_81B9: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_81BA: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81BB: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_81BC: + AC0_l = ReadDMEM(R02); + R02++; +// l_81BD: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_81BE: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81BF: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_81C0: + AC1_l = ReadDMEM(R02); + R02++; +// l_81C1: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_81C2: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81C3: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_81C4: + AC0_l = ReadDMEM(R02); + R02++; +// l_81C5: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_81C6: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81C7: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_81C8: + AC1_l = ReadDMEM(R02); + R02++; +// l_81C9: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_81CA: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81CB: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_81CC: + AC0_l = ReadDMEM(R02); + R02++; +// l_81CD: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_81CE: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81CF: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_81D0: + AC1_l = ReadDMEM(R02); + R02++; +// l_81D1: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_81D2: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81D3: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_81D4: + AC0_l = ReadDMEM(R02); + R02++; +// l_81D5: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_81D6: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81D7: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_81D8: + AC1_l = ReadDMEM(R02); + R02++; +// l_81D9: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_81DA: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81DB: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_81DC: + AC0_l = ReadDMEM(R02); + R02++; +// l_81DD: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_81DE: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81DF: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_81E0: + AC1_l = ReadDMEM(R02); + R02++; +// l_81E1: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_81E2: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81E3: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_81E4: + AC0_l = ReadDMEM(R02); + R02++; +// l_81E5: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_81E6: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81E7: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_81E8: + AC1_l = ReadDMEM(R02); + R02++; +// l_81E9: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_81EA: + WriteDMEM(R03, AC0_l); + R03++; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81EB: + AC0_m = ReadDMEM(R02); + R02++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_81EC: + AC0_l = ReadDMEM(R02); + R02++; +// l_81ED: + WriteDMEM(R03, AC1_m); + R03++; + ACC0 <<= 16; + Update_SR_Register(ACC0); + AX0_h = ReadDMEM(R00); + R00++; +// l_81EE: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81EF: + AC1_m = ReadDMEM(R02); + R02++; + ACC0 >>= 16; + Update_SR_Register(ACC0); +// l_81F0: + AC1_l = ReadDMEM(R02); + R02++; +// l_81F1: + WriteDMEM(R03, AC0_m); + R03++; + ACC1 <<= 16; + Update_SR_Register(ACC1); + AX0_h = ReadDMEM(R00); + R00++; +// l_81F2: + WriteDMEM(R03, AC0_l); + R03++; +// l_81F3: + ACC0 = PROD; +// l_81F4: + AX1_h = AC0_m; + ACC1 += PROD; + PROD = AX0_h * AX1_l * MultiplyModifier; + Update_SR_Register(PROD); +// l_81F5: + R01++; + ACC1 >>= 16; + Update_SR_Register(ACC1); +// l_81F6: + WriteDMEM(R03, AC1_m); + R03++; +// l_81F7: + WriteDMEM(R03, AC1_l); + R03++; + ACC0 = 0; + Update_SR_Register(ACC0); +// l_81F8: +//missing: dsp_opc_ret; + + return 0x81f8; +} diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/HLE_Helper.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/HLE_Helper.cpp index 7be407b578..8d0c523554 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/HLE_Helper.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/HLE_Helper.cpp @@ -1,37 +1,37 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifdef _WIN32 -#include "stdafx.h" -#endif - -#include "Globals.h" -#include "gdsp_interpreter.h" -#include "gdsp_memory.h" -#include "gdsp_opcodes_helper.h" - - -bool WriteDMEM(uint16 addr, uint16 val) -{ - return dsp_dmem_write(addr, val); -} - -uint16 ReadDMEM(uint16 addr) -{ - return dsp_dmem_read(addr); -} - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifdef _WIN32 +#include "stdafx.h" +#endif + +#include "Globals.h" +#include "gdsp_interpreter.h" +#include "gdsp_memory.h" +#include "gdsp_opcodes_helper.h" + + +bool WriteDMEM(uint16 addr, uint16 val) +{ + return dsp_dmem_write(addr, val); +} + +uint16 ReadDMEM(uint16 addr) +{ + return dsp_dmem_read(addr); +} + diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/Logging/AXTask.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/Logging/AXTask.cpp index e058dc44cb..4a24adcd81 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/Logging/AXTask.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/Logging/AXTask.cpp @@ -1,100 +1,100 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -#include "../Globals.h" -#include "Common.h" - - -extern u32 m_addressPBs; - - -// ======================================================================================= -// Get the parameter block location - Example SSBM: We get the addr 8049cf00, first we -// always get 0 and go to AXLIST_STUDIOADDR, then we end up at AXLIST_PBADDR. -// -------------- -bool AXTask(u32& _uMail) -{ - u32 uAddress = _uMail; - DebugLog("AXTask - ================================================================"); - DebugLog("AXTask - AXCommandList-Addr: 0x%08x", uAddress); - - bool bExecuteList = true; - - while (bExecuteList) - { - // --------------------------------------------------------------------------------------- - // SSBM: We get the addr 8049cf00, first we always get 0 - u16 iCommand = Memory_Read_U16(uAddress); - uAddress += 2; - // --------------------------------------------------------------------------------------- - - switch (iCommand) - { - // --------------------------------------------------------------------------------------- - // ? - case 0: // AXLIST_STUDIOADDR: //00 - { - uAddress += 4; - DebugLog("AXLIST AXLIST_SBUFFER: %08x", uAddress); - } - break; - // --------------------------------------------------------------------------------------- - - - // --------------------------------------------------------------------------------------- - case 2: // AXLIST_PBADDR: // 02 - { - m_addressPBs = Memory_Read_U32(uAddress); - uAddress += 4; - DebugLog("AXLIST PB address: %08x", m_addressPBs); - bExecuteList = false; - } - break; - - // --------------------------------------------------------------------------------------- - case 7: // AXLIST_SBUFFER: // 7 - { - // Hopefully this is where in main ram to write. - uAddress += 4; - DebugLog("AXLIST AXLIST_SBUFFER: %08x", uAddress); - } - break; - - - - default: - { - // --------------------------------------------------------------------------------------- - // Stop the execution of this TaskList - DebugLog("AXLIST default: %08x", uAddress); - bExecuteList = false; - // --------------------------------------------------------------------------------------- - } - break; - } // end of switch - } - - DebugLog("AXTask - done, send resume"); - DebugLog("AXTask - ================================================================"); - - // now resume - return true; -} -// ======================================================================================= - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#include "../Globals.h" +#include "Common.h" + + +extern u32 m_addressPBs; + + +// ======================================================================================= +// Get the parameter block location - Example SSBM: We get the addr 8049cf00, first we +// always get 0 and go to AXLIST_STUDIOADDR, then we end up at AXLIST_PBADDR. +// -------------- +bool AXTask(u32& _uMail) +{ + u32 uAddress = _uMail; + DebugLog("AXTask - ================================================================"); + DebugLog("AXTask - AXCommandList-Addr: 0x%08x", uAddress); + + bool bExecuteList = true; + + while (bExecuteList) + { + // --------------------------------------------------------------------------------------- + // SSBM: We get the addr 8049cf00, first we always get 0 + u16 iCommand = Memory_Read_U16(uAddress); + uAddress += 2; + // --------------------------------------------------------------------------------------- + + switch (iCommand) + { + // --------------------------------------------------------------------------------------- + // ? + case 0: // AXLIST_STUDIOADDR: //00 + { + uAddress += 4; + DebugLog("AXLIST AXLIST_SBUFFER: %08x", uAddress); + } + break; + // --------------------------------------------------------------------------------------- + + + // --------------------------------------------------------------------------------------- + case 2: // AXLIST_PBADDR: // 02 + { + m_addressPBs = Memory_Read_U32(uAddress); + uAddress += 4; + DebugLog("AXLIST PB address: %08x", m_addressPBs); + bExecuteList = false; + } + break; + + // --------------------------------------------------------------------------------------- + case 7: // AXLIST_SBUFFER: // 7 + { + // Hopefully this is where in main ram to write. + uAddress += 4; + DebugLog("AXLIST AXLIST_SBUFFER: %08x", uAddress); + } + break; + + + + default: + { + // --------------------------------------------------------------------------------------- + // Stop the execution of this TaskList + DebugLog("AXLIST default: %08x", uAddress); + bExecuteList = false; + // --------------------------------------------------------------------------------------- + } + break; + } // end of switch + } + + DebugLog("AXTask - done, send resume"); + DebugLog("AXTask - ================================================================"); + + // now resume + return true; +} +// ======================================================================================= + + diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/Logging/Console.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/Logging/Console.cpp index ae4c9ea520..7c174733d4 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/Logging/Console.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/Logging/Console.cpp @@ -1,197 +1,197 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -#ifdef _WIN32 - - - -// ======================================================================================= -// Includes -// -------------- -#include -#include -#include - - -// --------------------------------------------------------------------------------------- -// Defines and settings -// -------------- -bool g_consoleEnable = true; -#define DEBUGG -//#define DEBUGG_FILEONLY -//#define DEBUGG_NOFILE -// --------------------------------------------------------------------------------------- - - -// --------------------------------------------------------------------------------------- -// Handles -// -------------- -#ifdef DEBUGG - FILE* __fStdOut = NULL; -#endif -#ifndef DEBUGG_FILEONLY - HANDLE __hStdOut = NULL; -#endif -// ============== - - -// ======================================================================================= -// Width and height is the size of console window, if you specify fname, -// the output will also be writton to this file. The file pointer is automatically closed -// when you close the app -// -------------- -void startConsoleWin(int width, int height, char* fname) -{ -#ifdef DEBUGG - -#ifndef DEBUGG_FILEONLY - AllocConsole(); - - SetConsoleTitle(fname); - __hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); - - COORD co = {width,height}; - SetConsoleScreenBufferSize(__hStdOut, co); - - SMALL_RECT coo = {0,0,(width - 1),70}; // top, left, right, bottom - SetConsoleWindowInfo(__hStdOut, TRUE, &coo); - -#endif -#ifndef DEBUGG_NOFILE - // --------------------------------------------------------------------------------------- - // Write to a file - if(fname) - { - // Edit the log file name - std::string FileEnding = ".log"; - std::string FileName = fname; - std::string FullFilename = (FileName + FileEnding); - __fStdOut = fopen(FullFilename.c_str(), "w"); - } - // ----------------- -#endif - -#endif -} - - -void ClearScreen(); -int wprintf(char *fmt, ...) -{ -#ifdef DEBUGG - char s[6000]; // WARNING: mind this value - va_list argptr; - int cnt; - - va_start(argptr, fmt); - cnt = vsnprintf(s, 3000, fmt, argptr); - va_end(argptr); - - DWORD cCharsWritten; - - // --------------------------------------------------------------------------------------- -#ifndef DEBUGG_FILEONLY - if(__hStdOut) - { - WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL); - } -#endif -#ifndef DEBUGG_NOFILE - // --------------------------------------------------------------------------------------- - - if(__fStdOut) - fprintf(__fStdOut, s); - // --------------------------------------------------------------------------------------- -#endif - - return(cnt); -#else - return 0; -#endif -} - - -// ======================================================================================= -// Clear screen -// -------------- -void ClearScreen() -{ - if(g_consoleEnable) - { - COORD coordScreen = { 0, 0 }; - DWORD cCharsWritten; - CONSOLE_SCREEN_BUFFER_INFO csbi; - DWORD dwConSize; - - HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - //HANDLE hConsole = __hStdOut; - - GetConsoleScreenBufferInfo(hConsole, &csbi); - dwConSize = csbi.dwSize.X * csbi.dwSize.Y; - FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, - coordScreen, &cCharsWritten); - GetConsoleScreenBufferInfo(hConsole, &csbi); - FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, - coordScreen, &cCharsWritten); - SetConsoleCursorPosition(hConsole, coordScreen); - } -} - - -// ======================================================================================= -// Get console HWND to be able to use MoveWindow() -// -------------- -HWND GetConsoleHwnd(void) -{ - #define MY_BUFSIZE 1024 // Buffer size for console window titles. - HWND hwndFound; // This is what is returned to the caller. - char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated - // WindowTitle. - char pszOldWindowTitle[MY_BUFSIZE]; // Contains original - // WindowTitle. - - // Fetch current window title. - - GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE); - - // Format a "unique" NewWindowTitle. - - wsprintf(pszNewWindowTitle,"%d/%d", - GetTickCount(), - GetCurrentProcessId()); - - // Change current window title. - - SetConsoleTitle(pszNewWindowTitle); - - // Ensure window title has been updated. - - Sleep(40); - - // Look for NewWindowTitle. - - hwndFound = FindWindow(NULL, pszNewWindowTitle); - - // Restore original window title. - - SetConsoleTitle(pszOldWindowTitle); - - return(hwndFound); -} - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#ifdef _WIN32 + + + +// ======================================================================================= +// Includes +// -------------- +#include +#include +#include + + +// --------------------------------------------------------------------------------------- +// Defines and settings +// -------------- +bool g_consoleEnable = true; +#define DEBUGG +//#define DEBUGG_FILEONLY +//#define DEBUGG_NOFILE +// --------------------------------------------------------------------------------------- + + +// --------------------------------------------------------------------------------------- +// Handles +// -------------- +#ifdef DEBUGG + FILE* __fStdOut = NULL; +#endif +#ifndef DEBUGG_FILEONLY + HANDLE __hStdOut = NULL; +#endif +// ============== + + +// ======================================================================================= +// Width and height is the size of console window, if you specify fname, +// the output will also be writton to this file. The file pointer is automatically closed +// when you close the app +// -------------- +void startConsoleWin(int width, int height, char* fname) +{ +#ifdef DEBUGG + +#ifndef DEBUGG_FILEONLY + AllocConsole(); + + SetConsoleTitle(fname); + __hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + + COORD co = {width,height}; + SetConsoleScreenBufferSize(__hStdOut, co); + + SMALL_RECT coo = {0,0,(width - 1),70}; // top, left, right, bottom + SetConsoleWindowInfo(__hStdOut, TRUE, &coo); + +#endif +#ifndef DEBUGG_NOFILE + // --------------------------------------------------------------------------------------- + // Write to a file + if(fname) + { + // Edit the log file name + std::string FileEnding = ".log"; + std::string FileName = fname; + std::string FullFilename = (FileName + FileEnding); + __fStdOut = fopen(FullFilename.c_str(), "w"); + } + // ----------------- +#endif + +#endif +} + + +void ClearScreen(); +int wprintf(char *fmt, ...) +{ +#ifdef DEBUGG + char s[6000]; // WARNING: mind this value + va_list argptr; + int cnt; + + va_start(argptr, fmt); + cnt = vsnprintf(s, 3000, fmt, argptr); + va_end(argptr); + + DWORD cCharsWritten; + + // --------------------------------------------------------------------------------------- +#ifndef DEBUGG_FILEONLY + if(__hStdOut) + { + WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL); + } +#endif +#ifndef DEBUGG_NOFILE + // --------------------------------------------------------------------------------------- + + if(__fStdOut) + fprintf(__fStdOut, s); + // --------------------------------------------------------------------------------------- +#endif + + return(cnt); +#else + return 0; +#endif +} + + +// ======================================================================================= +// Clear screen +// -------------- +void ClearScreen() +{ + if(g_consoleEnable) + { + COORD coordScreen = { 0, 0 }; + DWORD cCharsWritten; + CONSOLE_SCREEN_BUFFER_INFO csbi; + DWORD dwConSize; + + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + //HANDLE hConsole = __hStdOut; + + GetConsoleScreenBufferInfo(hConsole, &csbi); + dwConSize = csbi.dwSize.X * csbi.dwSize.Y; + FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, + coordScreen, &cCharsWritten); + GetConsoleScreenBufferInfo(hConsole, &csbi); + FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, + coordScreen, &cCharsWritten); + SetConsoleCursorPosition(hConsole, coordScreen); + } +} + + +// ======================================================================================= +// Get console HWND to be able to use MoveWindow() +// -------------- +HWND GetConsoleHwnd(void) +{ + #define MY_BUFSIZE 1024 // Buffer size for console window titles. + HWND hwndFound; // This is what is returned to the caller. + char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated + // WindowTitle. + char pszOldWindowTitle[MY_BUFSIZE]; // Contains original + // WindowTitle. + + // Fetch current window title. + + GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE); + + // Format a "unique" NewWindowTitle. + + wsprintf(pszNewWindowTitle,"%d/%d", + GetTickCount(), + GetCurrentProcessId()); + + // Change current window title. + + SetConsoleTitle(pszNewWindowTitle); + + // Ensure window title has been updated. + + Sleep(40); + + // Look for NewWindowTitle. + + hwndFound = FindWindow(NULL, pszNewWindowTitle); + + // Restore original window title. + + SetConsoleTitle(pszOldWindowTitle); + + return(hwndFound); +} + #endif \ No newline at end of file diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/Logging/Logging.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/Logging/Logging.cpp index 8af149dcee..f7ca3b1855 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/Logging/Logging.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/Logging/Logging.cpp @@ -1,380 +1,380 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -#ifdef _WIN32 - - -// ======================================================================================= -// Includes -// -------------- -#include -#include -#include // So that we can test if std::string == abc -#include - -#include "Common.h" - -#include "UCode_AXStructs.h" // they are only in a virtual dir called UCodes AX -#include "Console.h" // For wprintf, ClearScreen - -// --------------------------------------------------------------------------------------- -// Declarations -// -------------- -#define NUMBER_OF_PBS 64 // Todo: move this to a logging class - - - -// --------------------------------------------------------------------------------------- -// Externals -// -------------- -extern u32 m_addressPBs; -float ratioFactor; -int globaliSize; -short globalpBuffer; -u32 gLastBlock; -// -------------- - - -// --------------------------------------------------------------------------------------- -// Vectors and other stuff -// -------------- -std::vector gloopPos(64); -std::vector gsampleEnd(64); -std::vector gsamplePos(64); - std::vector gratio(64); - std::vector gratiohi(64); - std::vector gratiolo(64); - std::vector gfrac(64); - std::vector gcoef(64); - -// PBSampleRateConverter mixer - std::vector gvolume_left(64); - std::vector gvolume_right(64); - std::vector gmixer_control(64); - std::vector gcur_volume(64); - std::vector gcur_volume_delta(64); - - - std::vector gaudioFormat(64); - std::vector glooping(64); - std::vector gsrc_type(64); - std::vector gis_stream(64); - -// loop - std::vector gloop1(64); - std::vector gloop2(64); - std::vector gloop3(64); - std::vector gadloop1(64); - std::vector gadloop2(64); - std::vector gadloop3(64); - -// updates - std::vector gupdates1(64); - std::vector gupdates2(64); - std::vector gupdates3(64); - std::vector gupdates4(64); - std::vector gupdates5(64); - std::vector gupdates_addr(64); - -// other stuff -std::vector Jump(64); // this is 1 or 0 -std::vector musicLength(64); -std::vector< std::vector > vector1(64, std::vector(100,0)); -std::vector numberRunning(64); - -int j = 0; -int k = 0; -__int64 l = 0; -int iupd = 0; -bool iupdonce = false; -std::vector viupd(15); // the length of the update frequency bar -int vectorLength = 15; // the length of the playback history bar and how long -// old blocks are shown - -std::vector vector62(vectorLength); -std::vector vector63(vectorLength); - -int ReadOutPBs(AXParamBlock * _pPBs, int _num); -// =========== - - -// ======================================================================================= -// Main logging function -// -------------- -void Logging() -{ - // --------------------------------------------------------------------------------------- - - - // --------------------------------------------------------------------------------------- - // Control how often the screen is updated - j++; - l++; - if (j>1000000) // TODO: make the update frequency adjustable from the logging window - { - - AXParamBlock PBs[NUMBER_OF_PBS]; - int numberOfPBs = ReadOutPBs(PBs, NUMBER_OF_PBS); - - // ======================================================================================= - // Vector1 is a vector1[64][100] vector - /* - Move all items back like this - 1 to 2 - 2 3 - 3 ... - */ - // ---------------- - for (int i = 0; i < 64; i++) - { - for (int j = 1; j < vectorLength; j++) - { - vector1.at(i).at(j-1) = vector1.at(i).at(j); - } - } - // ================= - - // --------------------------------------------------------------------------------------- - // Enter the latest value - for (int i = 0; i < numberOfPBs; i++) - { - vector1.at(i).at(vectorLength-1) = PBs[i].running; - } - // ----------------- - - - // --------------------------------------------------------------------------------------- - // Count how many blocks we have running now - int jj = 0; - for (int i = 0; i < 64; i++) - { - for (int j = 0; j < vectorLength-1; j++) - { - if (vector1.at(i).at(j) == 1) - { - jj++; - } - numberRunning.at(i) = jj; - } - } - // -------------- - - - // --------------------------------------------------------------------------------------- - // Write the first row - char buffer [1000] = ""; - std::string sbuff; - //sbuff = sbuff + " Nr | | frac ratio | old new \n"; // 5 - sbuff = sbuff + " Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n"; - // -------------- - - - // --------------------------------------------------------------------------------------- - // Read out values for all blocks - for (int i = 0; i < numberOfPBs; i++) - { - if (numberRunning.at(i) > 0) - { - // ======================================================================================= - // Write the playback bar - // ------------- - for (int j = 0; j < vectorLength; j++) - { - if(vector1.at(i).at(j) == 0) - { - sbuff = sbuff + " "; - } - else - { - sprintf(buffer, "%c", 177); - sbuff = sbuff + buffer; strcpy(buffer, ""); - } - } - // ============== - - - // ================================================================================================ - int sampleJump; - int loopJump; - //if (PBs[i].running && PBs[i].adpcm_loop_info.yn1 && PBs[i].mixer.volume_left) - if (true) - { - // --------------------------------------------------------------------------------------- - // AXPB base - //int running = pb.running; - gcoef[i] = PBs[i].unknown1; - - sampleJump = ((PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo) - gsamplePos[i]; - loopJump = ((PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo) - gloopPos[i]; - - gloopPos[i] = (PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo; - gsampleEnd[i] = (PBs[i].audio_addr.end_addr_hi << 16) | PBs[i].audio_addr.end_addr_lo; - gsamplePos[i] = (PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo; - - // PBSampleRateConverter src - - gratio[i] = (u32)(((PBs[i].src.ratio_hi << 16) + PBs[i].src.ratio_lo) * ratioFactor); - gratiohi[i] = PBs[i].src.ratio_hi; - gratiolo[i] = PBs[i].src.ratio_lo; - gfrac[i] = PBs[i].src.cur_addr_frac; - - // adpcm_loop_info - gadloop1[i] = PBs[i].adpcm.pred_scale; - gadloop2[i] = PBs[i].adpcm.yn1; - gadloop3[i] = PBs[i].adpcm.yn2; - - gloop1[i] = PBs[i].adpcm_loop_info.pred_scale; - gloop2[i] = PBs[i].adpcm_loop_info.yn1; - gloop3[i] = PBs[i].adpcm_loop_info.yn2; - - // updates - gupdates1[i] = PBs[i].updates.num_updates[0]; - gupdates2[i] = PBs[i].updates.num_updates[1]; - gupdates3[i] = PBs[i].updates.num_updates[2]; - gupdates4[i] = PBs[i].updates.num_updates[3]; - gupdates5[i] = PBs[i].updates.num_updates[4]; - - gupdates_addr[i] = (PBs[i].updates.data_hi << 16) | PBs[i].updates.data_lo; - - gaudioFormat[i] = PBs[i].audio_addr.sample_format; - glooping[i] = PBs[i].audio_addr.looping; - gsrc_type[i] = PBs[i].src_type; - gis_stream[i] = PBs[i].is_stream; - - // mixer - gvolume_left[i] = PBs[i].mixer.volume_left; - gvolume_right[i] = PBs[i].mixer.volume_right; - - gmixer_control[i] = PBs[i].mixer_control; - gcur_volume[i] = PBs[i].vol_env.cur_volume; - gcur_volume_delta[i] = PBs[i].vol_env.cur_volume_delta; - - // other stuff - Jump[i] = (gfrac[i] >> 16); // This is 1 or 0 - musicLength[i] = gsampleEnd[i] - gloopPos[i]; - } - - // ================================================================================================ - - - - // ======================================================================================= - // PRESETS - // --------------------------------------------------------------------------------------- - /* - /" Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n"; - "---------------|00 12341234/12341234 12341234 | 00000 00000 00000 0000 00000 | 0[000 00000 00000] 0 | 00000 00000[0 00000] | - */ - sprintf(buffer,"%c%i %08i/%08i %08i | %05i %05i %05i %04i %05i | %i[%03i %05i %05i] %i | %05i %05i[%i %05i] | %i %i %i %i %i", - 223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i], - gvolume_left[i], gvolume_right[i], gcur_volume[i], gcur_volume_delta[i], gmixer_control[i], - glooping[i], gloop1[i], gloop2[i], gloop3[i], gis_stream[i], - gfrac[i], gratio[i], gratiohi[i], gratiolo[i], - gupdates1[i], gupdates2[i], gupdates3[i], gupdates4[i], gupdates5[i] - ); - // ======================================================================================= - - // write a new line - sbuff = sbuff + buffer; strcpy(buffer, ""); - sbuff = sbuff + "\n"; - - } // end of if (true) - - - } // end of big loop - for (int i = 0; i < numberOfPBs; i++) - - - // ======================================================================================= - // Write global values - sprintf(buffer, "\nParameter blocks span from %08x | to %08x | distance %i %i\n", m_addressPBs, gLastBlock, (gLastBlock-m_addressPBs), (gLastBlock-m_addressPBs) / 192); - sbuff = sbuff + buffer; strcpy(buffer, ""); - // ============== - - - // ======================================================================================= - // Show update frequency - // --------------- - sbuff = sbuff + "\n"; - if(!iupdonce) - { - /* - for (int i = 0; i < 10; i++) - { - viupd.at(i) == 0; - } - */ - viupd.at(0) = 1; - viupd.at(1) = 1; - viupd.at(2) = 1; - iupdonce = true; - } - - for (int i = 0; i < viupd.size(); i++) // 0, 1,..., 9 - { - if (i < viupd.size()-1) - { - viupd.at(viupd.size()-i-1) = viupd.at(viupd.size()-i-2); // move all forward - } - else - { - viupd.at(0) = viupd.at(viupd.size()-1); - } - - // Correction - if (viupd.at(viupd.size()-3) == 1 && viupd.at(viupd.size()-2) == 1 && viupd.at(viupd.size()-1) == 1) - { - viupd.at(0) = 0; - } - if(viupd.at(0) == 0 && viupd.at(1) == 1 && viupd.at(2) == 1 && viupd.at(3) == 0) - { - viupd.at(0) = 1; - } - } - - for (int i = 0; i < viupd.size(); i++) - { - if(viupd.at(i) == 0) - sbuff = sbuff + " "; - else - sbuff = sbuff + "."; - } - // ================ - - - // ======================================================================================= - // Print - // --------------- - ClearScreen(); - wprintf("%s", sbuff.c_str()); - sbuff.clear(); strcpy(buffer, ""); - // --------------- - k=0; - j=0; - // --------------- - } - - // --------------------------------------------------------------------------------------- - -} -// ======================================================================================= - - - - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#ifdef _WIN32 + + +// ======================================================================================= +// Includes +// -------------- +#include +#include +#include // So that we can test if std::string == abc +#include + +#include "Common.h" + +#include "UCode_AXStructs.h" // they are only in a virtual dir called UCodes AX +#include "Console.h" // For wprintf, ClearScreen + +// --------------------------------------------------------------------------------------- +// Declarations +// -------------- +#define NUMBER_OF_PBS 64 // Todo: move this to a logging class + + + +// --------------------------------------------------------------------------------------- +// Externals +// -------------- +extern u32 m_addressPBs; +float ratioFactor; +int globaliSize; +short globalpBuffer; +u32 gLastBlock; +// -------------- + + +// --------------------------------------------------------------------------------------- +// Vectors and other stuff +// -------------- +std::vector gloopPos(64); +std::vector gsampleEnd(64); +std::vector gsamplePos(64); + std::vector gratio(64); + std::vector gratiohi(64); + std::vector gratiolo(64); + std::vector gfrac(64); + std::vector gcoef(64); + +// PBSampleRateConverter mixer + std::vector gvolume_left(64); + std::vector gvolume_right(64); + std::vector gmixer_control(64); + std::vector gcur_volume(64); + std::vector gcur_volume_delta(64); + + + std::vector gaudioFormat(64); + std::vector glooping(64); + std::vector gsrc_type(64); + std::vector gis_stream(64); + +// loop + std::vector gloop1(64); + std::vector gloop2(64); + std::vector gloop3(64); + std::vector gadloop1(64); + std::vector gadloop2(64); + std::vector gadloop3(64); + +// updates + std::vector gupdates1(64); + std::vector gupdates2(64); + std::vector gupdates3(64); + std::vector gupdates4(64); + std::vector gupdates5(64); + std::vector gupdates_addr(64); + +// other stuff +std::vector Jump(64); // this is 1 or 0 +std::vector musicLength(64); +std::vector< std::vector > vector1(64, std::vector(100,0)); +std::vector numberRunning(64); + +int j = 0; +int k = 0; +__int64 l = 0; +int iupd = 0; +bool iupdonce = false; +std::vector viupd(15); // the length of the update frequency bar +int vectorLength = 15; // the length of the playback history bar and how long +// old blocks are shown + +std::vector vector62(vectorLength); +std::vector vector63(vectorLength); + +int ReadOutPBs(AXParamBlock * _pPBs, int _num); +// =========== + + +// ======================================================================================= +// Main logging function +// -------------- +void Logging() +{ + // --------------------------------------------------------------------------------------- + + + // --------------------------------------------------------------------------------------- + // Control how often the screen is updated + j++; + l++; + if (j>1000000) // TODO: make the update frequency adjustable from the logging window + { + + AXParamBlock PBs[NUMBER_OF_PBS]; + int numberOfPBs = ReadOutPBs(PBs, NUMBER_OF_PBS); + + // ======================================================================================= + // Vector1 is a vector1[64][100] vector + /* + Move all items back like this + 1 to 2 + 2 3 + 3 ... + */ + // ---------------- + for (int i = 0; i < 64; i++) + { + for (int j = 1; j < vectorLength; j++) + { + vector1.at(i).at(j-1) = vector1.at(i).at(j); + } + } + // ================= + + // --------------------------------------------------------------------------------------- + // Enter the latest value + for (int i = 0; i < numberOfPBs; i++) + { + vector1.at(i).at(vectorLength-1) = PBs[i].running; + } + // ----------------- + + + // --------------------------------------------------------------------------------------- + // Count how many blocks we have running now + int jj = 0; + for (int i = 0; i < 64; i++) + { + for (int j = 0; j < vectorLength-1; j++) + { + if (vector1.at(i).at(j) == 1) + { + jj++; + } + numberRunning.at(i) = jj; + } + } + // -------------- + + + // --------------------------------------------------------------------------------------- + // Write the first row + char buffer [1000] = ""; + std::string sbuff; + //sbuff = sbuff + " Nr | | frac ratio | old new \n"; // 5 + sbuff = sbuff + " Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n"; + // -------------- + + + // --------------------------------------------------------------------------------------- + // Read out values for all blocks + for (int i = 0; i < numberOfPBs; i++) + { + if (numberRunning.at(i) > 0) + { + // ======================================================================================= + // Write the playback bar + // ------------- + for (int j = 0; j < vectorLength; j++) + { + if(vector1.at(i).at(j) == 0) + { + sbuff = sbuff + " "; + } + else + { + sprintf(buffer, "%c", 177); + sbuff = sbuff + buffer; strcpy(buffer, ""); + } + } + // ============== + + + // ================================================================================================ + int sampleJump; + int loopJump; + //if (PBs[i].running && PBs[i].adpcm_loop_info.yn1 && PBs[i].mixer.volume_left) + if (true) + { + // --------------------------------------------------------------------------------------- + // AXPB base + //int running = pb.running; + gcoef[i] = PBs[i].unknown1; + + sampleJump = ((PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo) - gsamplePos[i]; + loopJump = ((PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo) - gloopPos[i]; + + gloopPos[i] = (PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo; + gsampleEnd[i] = (PBs[i].audio_addr.end_addr_hi << 16) | PBs[i].audio_addr.end_addr_lo; + gsamplePos[i] = (PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo; + + // PBSampleRateConverter src + + gratio[i] = (u32)(((PBs[i].src.ratio_hi << 16) + PBs[i].src.ratio_lo) * ratioFactor); + gratiohi[i] = PBs[i].src.ratio_hi; + gratiolo[i] = PBs[i].src.ratio_lo; + gfrac[i] = PBs[i].src.cur_addr_frac; + + // adpcm_loop_info + gadloop1[i] = PBs[i].adpcm.pred_scale; + gadloop2[i] = PBs[i].adpcm.yn1; + gadloop3[i] = PBs[i].adpcm.yn2; + + gloop1[i] = PBs[i].adpcm_loop_info.pred_scale; + gloop2[i] = PBs[i].adpcm_loop_info.yn1; + gloop3[i] = PBs[i].adpcm_loop_info.yn2; + + // updates + gupdates1[i] = PBs[i].updates.num_updates[0]; + gupdates2[i] = PBs[i].updates.num_updates[1]; + gupdates3[i] = PBs[i].updates.num_updates[2]; + gupdates4[i] = PBs[i].updates.num_updates[3]; + gupdates5[i] = PBs[i].updates.num_updates[4]; + + gupdates_addr[i] = (PBs[i].updates.data_hi << 16) | PBs[i].updates.data_lo; + + gaudioFormat[i] = PBs[i].audio_addr.sample_format; + glooping[i] = PBs[i].audio_addr.looping; + gsrc_type[i] = PBs[i].src_type; + gis_stream[i] = PBs[i].is_stream; + + // mixer + gvolume_left[i] = PBs[i].mixer.volume_left; + gvolume_right[i] = PBs[i].mixer.volume_right; + + gmixer_control[i] = PBs[i].mixer_control; + gcur_volume[i] = PBs[i].vol_env.cur_volume; + gcur_volume_delta[i] = PBs[i].vol_env.cur_volume_delta; + + // other stuff + Jump[i] = (gfrac[i] >> 16); // This is 1 or 0 + musicLength[i] = gsampleEnd[i] - gloopPos[i]; + } + + // ================================================================================================ + + + + // ======================================================================================= + // PRESETS + // --------------------------------------------------------------------------------------- + /* + /" Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n"; + "---------------|00 12341234/12341234 12341234 | 00000 00000 00000 0000 00000 | 0[000 00000 00000] 0 | 00000 00000[0 00000] | + */ + sprintf(buffer,"%c%i %08i/%08i %08i | %05i %05i %05i %04i %05i | %i[%03i %05i %05i] %i | %05i %05i[%i %05i] | %i %i %i %i %i", + 223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i], + gvolume_left[i], gvolume_right[i], gcur_volume[i], gcur_volume_delta[i], gmixer_control[i], + glooping[i], gloop1[i], gloop2[i], gloop3[i], gis_stream[i], + gfrac[i], gratio[i], gratiohi[i], gratiolo[i], + gupdates1[i], gupdates2[i], gupdates3[i], gupdates4[i], gupdates5[i] + ); + // ======================================================================================= + + // write a new line + sbuff = sbuff + buffer; strcpy(buffer, ""); + sbuff = sbuff + "\n"; + + } // end of if (true) + + + } // end of big loop - for (int i = 0; i < numberOfPBs; i++) + + + // ======================================================================================= + // Write global values + sprintf(buffer, "\nParameter blocks span from %08x | to %08x | distance %i %i\n", m_addressPBs, gLastBlock, (gLastBlock-m_addressPBs), (gLastBlock-m_addressPBs) / 192); + sbuff = sbuff + buffer; strcpy(buffer, ""); + // ============== + + + // ======================================================================================= + // Show update frequency + // --------------- + sbuff = sbuff + "\n"; + if(!iupdonce) + { + /* + for (int i = 0; i < 10; i++) + { + viupd.at(i) == 0; + } + */ + viupd.at(0) = 1; + viupd.at(1) = 1; + viupd.at(2) = 1; + iupdonce = true; + } + + for (int i = 0; i < viupd.size(); i++) // 0, 1,..., 9 + { + if (i < viupd.size()-1) + { + viupd.at(viupd.size()-i-1) = viupd.at(viupd.size()-i-2); // move all forward + } + else + { + viupd.at(0) = viupd.at(viupd.size()-1); + } + + // Correction + if (viupd.at(viupd.size()-3) == 1 && viupd.at(viupd.size()-2) == 1 && viupd.at(viupd.size()-1) == 1) + { + viupd.at(0) = 0; + } + if(viupd.at(0) == 0 && viupd.at(1) == 1 && viupd.at(2) == 1 && viupd.at(3) == 0) + { + viupd.at(0) = 1; + } + } + + for (int i = 0; i < viupd.size(); i++) + { + if(viupd.at(i) == 0) + sbuff = sbuff + " "; + else + sbuff = sbuff + "."; + } + // ================ + + + // ======================================================================================= + // Print + // --------------- + ClearScreen(); + wprintf("%s", sbuff.c_str()); + sbuff.clear(); strcpy(buffer, ""); + // --------------- + k=0; + j=0; + // --------------- + } + + // --------------------------------------------------------------------------------------- + +} +// ======================================================================================= + + + + + #endif \ No newline at end of file diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/Logging/ReadPBs.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/Logging/ReadPBs.cpp index 74ac5e0e6e..e3d6f947be 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/Logging/ReadPBs.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/Logging/ReadPBs.cpp @@ -1,115 +1,115 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - - - -// Turn on and off logging modes -// -------------- -//#define LOG1 // writes selected parameters only and with more readable formatting -//#define LOG2 // writes all parameters - -#include "Common.h" -#include "../Globals.h" -#include "CommonTypes.h" // Pluginspecs - -#include "UCode_AXStructs.h" // For the AXParamBlock structure -#include "Console.h" // For wprintf, ClearScreen - - -u32 m_addressPBs = 0; -extern u32 gLastBlock; - - - -#ifdef _WIN32 - -int m = 0; -int n = 0; -#ifdef LOG2 -bool logall = true; -#else -bool logall = false; -#endif -int ReadOutPBs(AXParamBlock * _pPBs, int _num) -{ - int count = 0; - u32 blockAddr = m_addressPBs; - u32 OldblockAddr = blockAddr; - u32 paraAddr = blockAddr; - - // reading and 'halfword' swap - n++; - if (n > 20 && logall) {ClearScreen();} - for (int i = 0; i < _num; i++) - { - // --------------------------------------------------------------------------------------- - // Check if there is something here. - const short * pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr); - // ------------- - - if (pSrc != NULL) // only read non-blank blocks - { - // --------------------------------------------------------------------------------------- - // Create a shortcut that let us update struct members - short * pDest = (short *) & _pPBs[i]; - - if (n > 20 && logall) {wprintf("%c%i:", 223, i);} // logging - - // -------------- - // Here we update the PB. We do it by going through all 192 / 2 = 96 u16 values - for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++) - { - paraAddr += 2; - - if(pSrc != NULL) - { - if (pSrc[p] != 0 && n > 20 && logall) - { - wprintf("%i %04x | ", p, Common::swap16(pSrc[p])); - } - } - - pDest[p] = Common::swap16(pSrc[p]); - - } - - if(n > 20 && logall) {wprintf("\n");} // logging - // -------------- - // Here we update the block address to the starting point of the next PB - blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo; - // -------------- - // save some values - count++; - gLastBlock = paraAddr; // blockAddr - // ============ - } - else - { - break; - } - - } // end of the big loop - if (n > 20) {n = 0;} // for logging - - - // return the number of readed PBs - return count; -} -// ======================================================================================= - -#endif +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + + + +// Turn on and off logging modes +// -------------- +//#define LOG1 // writes selected parameters only and with more readable formatting +//#define LOG2 // writes all parameters + +#include "Common.h" +#include "../Globals.h" +#include "CommonTypes.h" // Pluginspecs + +#include "UCode_AXStructs.h" // For the AXParamBlock structure +#include "Console.h" // For wprintf, ClearScreen + + +u32 m_addressPBs = 0; +extern u32 gLastBlock; + + + +#ifdef _WIN32 + +int m = 0; +int n = 0; +#ifdef LOG2 +bool logall = true; +#else +bool logall = false; +#endif +int ReadOutPBs(AXParamBlock * _pPBs, int _num) +{ + int count = 0; + u32 blockAddr = m_addressPBs; + u32 OldblockAddr = blockAddr; + u32 paraAddr = blockAddr; + + // reading and 'halfword' swap + n++; + if (n > 20 && logall) {ClearScreen();} + for (int i = 0; i < _num; i++) + { + // --------------------------------------------------------------------------------------- + // Check if there is something here. + const short * pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr); + // ------------- + + if (pSrc != NULL) // only read non-blank blocks + { + // --------------------------------------------------------------------------------------- + // Create a shortcut that let us update struct members + short * pDest = (short *) & _pPBs[i]; + + if (n > 20 && logall) {wprintf("%c%i:", 223, i);} // logging + + // -------------- + // Here we update the PB. We do it by going through all 192 / 2 = 96 u16 values + for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++) + { + paraAddr += 2; + + if(pSrc != NULL) + { + if (pSrc[p] != 0 && n > 20 && logall) + { + wprintf("%i %04x | ", p, Common::swap16(pSrc[p])); + } + } + + pDest[p] = Common::swap16(pSrc[p]); + + } + + if(n > 20 && logall) {wprintf("\n");} // logging + // -------------- + // Here we update the block address to the starting point of the next PB + blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo; + // -------------- + // save some values + count++; + gLastBlock = paraAddr; // blockAddr + // ============ + } + else + { + break; + } + + } // end of the big loop + if (n > 20) {n = 0;} // for logging + + + // return the number of readed PBs + return count; +} +// ======================================================================================= + +#endif diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/Mixer.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/Mixer.cpp index 2c0b8fedad..363571e752 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/Mixer.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/Mixer.cpp @@ -1,164 +1,164 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -// This queue solution is temporary. I'll implement something more efficient later. - -#include - -#include "Thread.h" -#include "Mixer.h" -#include "FixedSizeQueue.h" - -#ifdef _WIN32 -#include "DSoundStream.h" -#else -#include -#endif - -namespace { -Common::CriticalSection push_sync; - -// On real hardware, this fifo is much, much smaller. But timing is also tighter than under Windows, so... -const int queue_minlength = 1024 * 4; -const int queue_maxlength = 1024 * 28; - -FixedSizeQueue sample_queue; - -} // namespace - -volatile bool mixer_HLEready = false; -volatile int queue_size = 0; - -void Mixer(short *buffer, int numSamples, int bits, int rate, int channels) -{ - // silence - memset(buffer, 0, numSamples * 2 * sizeof(short)); - - push_sync.Enter(); - int count = 0; - while (queue_size > queue_minlength && count < numSamples * 2) { - int x = buffer[count]; - x += sample_queue.front(); - if (x > 32767) x = 32767; - if (x < -32767) x = -32767; - buffer[count++] = x; - sample_queue.pop(); - x = buffer[count]; - x += sample_queue.front(); - if (x > 32767) x = 32767; - if (x < -32767) x = -32767; - buffer[count++] = x; - sample_queue.pop(); - queue_size-=2; - } - push_sync.Leave(); -} - -void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) { -// static FILE *f; -// if (!f) -// f = fopen("d:\\hello.raw", "wb"); -// fwrite(buffer, num_stereo_samples * 4, 1, f); - if (queue_size == 0) - { - queue_size = queue_minlength; - for (int i = 0; i < queue_minlength; i++) - sample_queue.push((s16)0); - } - - static int PV1l=0,PV2l=0,PV3l=0,PV4l=0; - static int PV1r=0,PV2r=0,PV3r=0,PV4r=0; - static int acc=0; - -#ifdef _WIN32 - if (!GetAsyncKeyState(VK_TAB)) { - while (queue_size > queue_maxlength / 2) { - DSound::DSound_UpdateSound(); - Sleep(0); - } - } else { - return; - } -#else - while (queue_size > queue_maxlength) { - sleep(0); - } -#endif - //convert into config option? - const int mode = 2; - - push_sync.Enter(); - while (num_stereo_samples) - { - acc += sample_rate; - while (num_stereo_samples && (acc >= 48000)) - { - PV4l=PV3l; - PV3l=PV2l; - PV2l=PV1l; - PV1l=*(buffer++); //32bit processing - PV4r=PV3r; - PV3r=PV2r; - PV2r=PV1r; - PV1r=*(buffer++); //32bit processing - num_stereo_samples--; - acc-=48000; - } - - // defaults to nearest - s32 DataL = PV1l; - s32 DataR = PV1r; - - if (mode == 1) //linear - { - DataL = PV1l + ((PV2l - PV1l)*acc)/48000; - DataR = PV1r + ((PV2r - PV1r)*acc)/48000; - } - else if (mode == 2) //cubic - { - s32 a0l = PV1l - PV2l - PV4l + PV3l; - s32 a0r = PV1r - PV2r - PV4r + PV3r; - s32 a1l = PV4l - PV3l - a0l; - s32 a1r = PV4r - PV3r - a0r; - s32 a2l = PV1l - PV4l; - s32 a2r = PV1r - PV4r; - s32 a3l = PV2l; - s32 a3r = PV2r; - - s32 t0l = ((a0l )*acc)/48000; - s32 t0r = ((a0r )*acc)/48000; - s32 t1l = ((t0l+a1l)*acc)/48000; - s32 t1r = ((t0r+a1r)*acc)/48000; - s32 t2l = ((t1l+a2l)*acc)/48000; - s32 t2r = ((t1r+a2r)*acc)/48000; - s32 t3l = ((t2l+a3l)); - s32 t3r = ((t2r+a3r)); - - DataL = t3l; - DataR = t3r; - } - - int l = DataL, r = DataR; - if (l < -32767) l = -32767; - if (r < -32767) r = -32767; - if (l > 32767) l = 32767; - if (r > 32767) r = 32767; - sample_queue.push(l); - sample_queue.push(r); - } - push_sync.Leave(); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +// This queue solution is temporary. I'll implement something more efficient later. + +#include + +#include "Thread.h" +#include "Mixer.h" +#include "FixedSizeQueue.h" + +#ifdef _WIN32 +#include "DSoundStream.h" +#else +#include +#endif + +namespace { +Common::CriticalSection push_sync; + +// On real hardware, this fifo is much, much smaller. But timing is also tighter than under Windows, so... +const int queue_minlength = 1024 * 4; +const int queue_maxlength = 1024 * 28; + +FixedSizeQueue sample_queue; + +} // namespace + +volatile bool mixer_HLEready = false; +volatile int queue_size = 0; + +void Mixer(short *buffer, int numSamples, int bits, int rate, int channels) +{ + // silence + memset(buffer, 0, numSamples * 2 * sizeof(short)); + + push_sync.Enter(); + int count = 0; + while (queue_size > queue_minlength && count < numSamples * 2) { + int x = buffer[count]; + x += sample_queue.front(); + if (x > 32767) x = 32767; + if (x < -32767) x = -32767; + buffer[count++] = x; + sample_queue.pop(); + x = buffer[count]; + x += sample_queue.front(); + if (x > 32767) x = 32767; + if (x < -32767) x = -32767; + buffer[count++] = x; + sample_queue.pop(); + queue_size-=2; + } + push_sync.Leave(); +} + +void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) { +// static FILE *f; +// if (!f) +// f = fopen("d:\\hello.raw", "wb"); +// fwrite(buffer, num_stereo_samples * 4, 1, f); + if (queue_size == 0) + { + queue_size = queue_minlength; + for (int i = 0; i < queue_minlength; i++) + sample_queue.push((s16)0); + } + + static int PV1l=0,PV2l=0,PV3l=0,PV4l=0; + static int PV1r=0,PV2r=0,PV3r=0,PV4r=0; + static int acc=0; + +#ifdef _WIN32 + if (!GetAsyncKeyState(VK_TAB)) { + while (queue_size > queue_maxlength / 2) { + DSound::DSound_UpdateSound(); + Sleep(0); + } + } else { + return; + } +#else + while (queue_size > queue_maxlength) { + sleep(0); + } +#endif + //convert into config option? + const int mode = 2; + + push_sync.Enter(); + while (num_stereo_samples) + { + acc += sample_rate; + while (num_stereo_samples && (acc >= 48000)) + { + PV4l=PV3l; + PV3l=PV2l; + PV2l=PV1l; + PV1l=*(buffer++); //32bit processing + PV4r=PV3r; + PV3r=PV2r; + PV2r=PV1r; + PV1r=*(buffer++); //32bit processing + num_stereo_samples--; + acc-=48000; + } + + // defaults to nearest + s32 DataL = PV1l; + s32 DataR = PV1r; + + if (mode == 1) //linear + { + DataL = PV1l + ((PV2l - PV1l)*acc)/48000; + DataR = PV1r + ((PV2r - PV1r)*acc)/48000; + } + else if (mode == 2) //cubic + { + s32 a0l = PV1l - PV2l - PV4l + PV3l; + s32 a0r = PV1r - PV2r - PV4r + PV3r; + s32 a1l = PV4l - PV3l - a0l; + s32 a1r = PV4r - PV3r - a0r; + s32 a2l = PV1l - PV4l; + s32 a2r = PV1r - PV4r; + s32 a3l = PV2l; + s32 a3r = PV2r; + + s32 t0l = ((a0l )*acc)/48000; + s32 t0r = ((a0r )*acc)/48000; + s32 t1l = ((t0l+a1l)*acc)/48000; + s32 t1r = ((t0r+a1r)*acc)/48000; + s32 t2l = ((t1l+a2l)*acc)/48000; + s32 t2r = ((t1r+a2r)*acc)/48000; + s32 t3l = ((t2l+a3l)); + s32 t3r = ((t2r+a3r)); + + DataL = t3l; + DataR = t3r; + } + + int l = DataL, r = DataR; + if (l < -32767) l = -32767; + if (r < -32767) r = -32767; + if (l > 32767) l = 32767; + if (r > 32767) r = 32767; + sample_queue.push(l); + sample_queue.push(r); + } + push_sync.Leave(); +} diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/RegSettings.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/RegSettings.cpp index 0bb29c1389..eebd599054 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/RegSettings.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/RegSettings.cpp @@ -1,274 +1,274 @@ -// RegSettings.cpp -// -// Copyright (c) 2001 Magomed Abdurakhmanov -// maq@hotbox.ru, http://mickels.iwt.ru/en -// -// -// -// No warranties are given. Use at your own risk. -// -////////////////////////////////////////////////////////////////////// - -#include "stdafx.h" -#include "RegSettings.h" - -////////////////////////////////////////////////////////////////////// -// CWindowSettings - -#define S_WINDOW_PLACEMENT_VAL _T("WindowPlacement") - -CWindowSettings::CWindowSettings() -{ - m_WindowPlacement.length = sizeof(m_WindowPlacement); - m_WindowPlacement.flags = 0; - m_WindowPlacement.ptMinPosition.x = 0; - m_WindowPlacement.ptMinPosition.y = 0; - m_WindowPlacement.ptMaxPosition.x = 0; - m_WindowPlacement.ptMaxPosition.y = 0; - - CRect rc; - SystemParametersInfo(SPI_GETWORKAREA, 0, rc, 0); - rc.DeflateRect(100, 100); - m_WindowPlacement.rcNormalPosition = rc; - m_WindowPlacement.showCmd = SW_SHOWNORMAL; -} - - -bool CWindowSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) -{ - CRegKey reg; - DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ); - - if (err == ERROR_SUCCESS) - { - DWORD dwType = NULL; - DWORD dwSize = sizeof(m_WindowPlacement); - err = RegQueryValueEx(reg.m_hKey, CString(szPrefix) + S_WINDOW_PLACEMENT_VAL, NULL, &dwType, - (LPBYTE)&m_WindowPlacement, &dwSize); - } - - return(err == ERROR_SUCCESS); -} - - -bool CWindowSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const -{ - CRegKey reg; - DWORD err = reg.Create(hkRootKey, szRegKey); - - if (err == ERROR_SUCCESS) - { - err = RegSetValueEx(reg.m_hKey, CString(szPrefix) + S_WINDOW_PLACEMENT_VAL, NULL, REG_BINARY, - (LPBYTE)&m_WindowPlacement, sizeof(m_WindowPlacement)); - } - - return(err == ERROR_SUCCESS); -} - - -void CWindowSettings::GetFrom(CWindow& Wnd) -{ - ATLASSERT(Wnd.IsWindow()); - Wnd.GetWindowPlacement(&m_WindowPlacement); -} - - -void CWindowSettings::ApplyTo(CWindow& Wnd, int nCmdShow /* = SW_SHOWNORMAL*/) const -{ - ATLASSERT(Wnd.IsWindow()); - - Wnd.SetWindowPlacement(&m_WindowPlacement); - - if (SW_SHOWNORMAL != nCmdShow) - { - Wnd.ShowWindow(nCmdShow); - } - else - if (m_WindowPlacement.showCmd == SW_MINIMIZE || m_WindowPlacement.showCmd == SW_SHOWMINIMIZED) - { - Wnd.ShowWindow(SW_SHOWNORMAL); - } -} - - -////////////////////////////////////////////////////////////////////// -// CReBarSettings - -#define S_BAR_BANDCOUNT _T("BandCount") -#define S_BAR_ID_VAL _T("ID") -#define S_BAR_CX_VAL _T("CX") -#define S_BAR_BREAKLINE_VAL _T("BreakLine") - -CReBarSettings::CReBarSettings() -{ - m_pBands = NULL; - m_cbBandCount = 0; -} - - -CReBarSettings::~CReBarSettings() -{ - if (m_pBands != NULL) - { - delete[] m_pBands; - m_pBands = NULL; - } -} - - -bool CReBarSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) -{ - if (m_pBands != NULL) - { - delete[] m_pBands; - m_pBands = NULL; - } - - m_pBands = NULL; - m_cbBandCount = 0; - - CRegKey reg; - DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ); - - if (err == ERROR_SUCCESS) - { - reg.QueryDWORDValue(CString(szPrefix) + S_BAR_BANDCOUNT, m_cbBandCount); - - if (m_cbBandCount > 0) - { - m_pBands = new BandInfo[m_cbBandCount]; - } - - for (DWORD i = 0; i < m_cbBandCount; i++) - { - CString s; - s.Format(_T("%s%i_"), szPrefix, i); - reg.QueryDWORDValue(s + S_BAR_ID_VAL, m_pBands[i].ID); - reg.QueryDWORDValue(s + S_BAR_CX_VAL, m_pBands[i].cx); - - DWORD dw; - reg.QueryDWORDValue(s + S_BAR_BREAKLINE_VAL, dw); - m_pBands[i].BreakLine = dw != 0; - } - } - - return(err == ERROR_SUCCESS); -} - - -bool CReBarSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const -{ - CRegKey reg; - DWORD err = reg.Create(hkRootKey, szRegKey); - - if (err == ERROR_SUCCESS) - { - reg.SetDWORDValue(CString(szPrefix) + S_BAR_BANDCOUNT, m_cbBandCount); - - for (DWORD i = 0; i < m_cbBandCount; i++) - { - CString s; - s.Format(_T("%s%i_"), szPrefix, i); - reg.SetDWORDValue(s + S_BAR_ID_VAL, m_pBands[i].ID); - reg.SetDWORDValue(s + S_BAR_CX_VAL, m_pBands[i].cx); - - DWORD dw = m_pBands[i].BreakLine; - reg.SetDWORDValue(s + S_BAR_BREAKLINE_VAL, dw); - } - } - - return(err == ERROR_SUCCESS); -} - - -void CReBarSettings::GetFrom(CReBarCtrl& ReBar) -{ - ATLASSERT(ReBar.IsWindow()); - - if (m_pBands != NULL) - { - delete[] m_pBands; - } - - m_pBands = NULL; - m_cbBandCount = ReBar.GetBandCount(); - - if (m_cbBandCount > 0) - { - m_pBands = new BandInfo[m_cbBandCount]; - } - - for (UINT i = 0; i < m_cbBandCount; i++) - { - REBARBANDINFO rbi; - rbi.cbSize = sizeof(rbi); - rbi.fMask = RBBIM_ID | RBBIM_SIZE | RBBIM_STYLE; - ReBar.GetBandInfo(i, &rbi); - m_pBands[i].ID = rbi.wID; - m_pBands[i].cx = rbi.cx; - m_pBands[i].BreakLine = (rbi.fStyle & RBBS_BREAK) != 0; - } -} - - -void CReBarSettings::ApplyTo(CReBarCtrl& ReBar) const -{ - ATLASSERT(ReBar.IsWindow()); - - for (UINT i = 0; i < m_cbBandCount; i++) - { - ReBar.MoveBand(ReBar.IdToIndex(m_pBands[i].ID), i); - REBARBANDINFO rbi; - rbi.cbSize = sizeof(rbi); - rbi.fMask = RBBIM_ID | RBBIM_SIZE | RBBIM_STYLE; - ReBar.GetBandInfo(i, &rbi); - - rbi.cx = m_pBands[i].cx; - - if (m_pBands[i].BreakLine) - { - rbi.fStyle |= RBBS_BREAK; - } - else - { - rbi.fStyle &= (~RBBS_BREAK); - } - - ReBar.SetBandInfo(i, &rbi); - } -} - - -////////////////////////////////////////////////////////////////////// -// CSplitterSettings - -#define S_SPLITTER_POS _T("SplitterPos") - -bool CSplitterSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) -{ - CRegKey reg; - DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ); - - if (err == ERROR_SUCCESS) - { - reg.QueryDWORDValue(CString(szPrefix) + S_SPLITTER_POS, m_dwPos); - } - - return(err == ERROR_SUCCESS); -} - - -bool CSplitterSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const -{ - CRegKey reg; - DWORD err = reg.Create(hkRootKey, szRegKey); - - if (err == ERROR_SUCCESS) - { - reg.SetDWORDValue(CString(szPrefix) + S_SPLITTER_POS, m_dwPos); - } - - return(err == ERROR_SUCCESS); -} - - +// RegSettings.cpp +// +// Copyright (c) 2001 Magomed Abdurakhmanov +// maq@hotbox.ru, http://mickels.iwt.ru/en +// +// +// +// No warranties are given. Use at your own risk. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "RegSettings.h" + +////////////////////////////////////////////////////////////////////// +// CWindowSettings + +#define S_WINDOW_PLACEMENT_VAL _T("WindowPlacement") + +CWindowSettings::CWindowSettings() +{ + m_WindowPlacement.length = sizeof(m_WindowPlacement); + m_WindowPlacement.flags = 0; + m_WindowPlacement.ptMinPosition.x = 0; + m_WindowPlacement.ptMinPosition.y = 0; + m_WindowPlacement.ptMaxPosition.x = 0; + m_WindowPlacement.ptMaxPosition.y = 0; + + CRect rc; + SystemParametersInfo(SPI_GETWORKAREA, 0, rc, 0); + rc.DeflateRect(100, 100); + m_WindowPlacement.rcNormalPosition = rc; + m_WindowPlacement.showCmd = SW_SHOWNORMAL; +} + + +bool CWindowSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) +{ + CRegKey reg; + DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ); + + if (err == ERROR_SUCCESS) + { + DWORD dwType = NULL; + DWORD dwSize = sizeof(m_WindowPlacement); + err = RegQueryValueEx(reg.m_hKey, CString(szPrefix) + S_WINDOW_PLACEMENT_VAL, NULL, &dwType, + (LPBYTE)&m_WindowPlacement, &dwSize); + } + + return(err == ERROR_SUCCESS); +} + + +bool CWindowSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const +{ + CRegKey reg; + DWORD err = reg.Create(hkRootKey, szRegKey); + + if (err == ERROR_SUCCESS) + { + err = RegSetValueEx(reg.m_hKey, CString(szPrefix) + S_WINDOW_PLACEMENT_VAL, NULL, REG_BINARY, + (LPBYTE)&m_WindowPlacement, sizeof(m_WindowPlacement)); + } + + return(err == ERROR_SUCCESS); +} + + +void CWindowSettings::GetFrom(CWindow& Wnd) +{ + ATLASSERT(Wnd.IsWindow()); + Wnd.GetWindowPlacement(&m_WindowPlacement); +} + + +void CWindowSettings::ApplyTo(CWindow& Wnd, int nCmdShow /* = SW_SHOWNORMAL*/) const +{ + ATLASSERT(Wnd.IsWindow()); + + Wnd.SetWindowPlacement(&m_WindowPlacement); + + if (SW_SHOWNORMAL != nCmdShow) + { + Wnd.ShowWindow(nCmdShow); + } + else + if (m_WindowPlacement.showCmd == SW_MINIMIZE || m_WindowPlacement.showCmd == SW_SHOWMINIMIZED) + { + Wnd.ShowWindow(SW_SHOWNORMAL); + } +} + + +////////////////////////////////////////////////////////////////////// +// CReBarSettings + +#define S_BAR_BANDCOUNT _T("BandCount") +#define S_BAR_ID_VAL _T("ID") +#define S_BAR_CX_VAL _T("CX") +#define S_BAR_BREAKLINE_VAL _T("BreakLine") + +CReBarSettings::CReBarSettings() +{ + m_pBands = NULL; + m_cbBandCount = 0; +} + + +CReBarSettings::~CReBarSettings() +{ + if (m_pBands != NULL) + { + delete[] m_pBands; + m_pBands = NULL; + } +} + + +bool CReBarSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) +{ + if (m_pBands != NULL) + { + delete[] m_pBands; + m_pBands = NULL; + } + + m_pBands = NULL; + m_cbBandCount = 0; + + CRegKey reg; + DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ); + + if (err == ERROR_SUCCESS) + { + reg.QueryDWORDValue(CString(szPrefix) + S_BAR_BANDCOUNT, m_cbBandCount); + + if (m_cbBandCount > 0) + { + m_pBands = new BandInfo[m_cbBandCount]; + } + + for (DWORD i = 0; i < m_cbBandCount; i++) + { + CString s; + s.Format(_T("%s%i_"), szPrefix, i); + reg.QueryDWORDValue(s + S_BAR_ID_VAL, m_pBands[i].ID); + reg.QueryDWORDValue(s + S_BAR_CX_VAL, m_pBands[i].cx); + + DWORD dw; + reg.QueryDWORDValue(s + S_BAR_BREAKLINE_VAL, dw); + m_pBands[i].BreakLine = dw != 0; + } + } + + return(err == ERROR_SUCCESS); +} + + +bool CReBarSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const +{ + CRegKey reg; + DWORD err = reg.Create(hkRootKey, szRegKey); + + if (err == ERROR_SUCCESS) + { + reg.SetDWORDValue(CString(szPrefix) + S_BAR_BANDCOUNT, m_cbBandCount); + + for (DWORD i = 0; i < m_cbBandCount; i++) + { + CString s; + s.Format(_T("%s%i_"), szPrefix, i); + reg.SetDWORDValue(s + S_BAR_ID_VAL, m_pBands[i].ID); + reg.SetDWORDValue(s + S_BAR_CX_VAL, m_pBands[i].cx); + + DWORD dw = m_pBands[i].BreakLine; + reg.SetDWORDValue(s + S_BAR_BREAKLINE_VAL, dw); + } + } + + return(err == ERROR_SUCCESS); +} + + +void CReBarSettings::GetFrom(CReBarCtrl& ReBar) +{ + ATLASSERT(ReBar.IsWindow()); + + if (m_pBands != NULL) + { + delete[] m_pBands; + } + + m_pBands = NULL; + m_cbBandCount = ReBar.GetBandCount(); + + if (m_cbBandCount > 0) + { + m_pBands = new BandInfo[m_cbBandCount]; + } + + for (UINT i = 0; i < m_cbBandCount; i++) + { + REBARBANDINFO rbi; + rbi.cbSize = sizeof(rbi); + rbi.fMask = RBBIM_ID | RBBIM_SIZE | RBBIM_STYLE; + ReBar.GetBandInfo(i, &rbi); + m_pBands[i].ID = rbi.wID; + m_pBands[i].cx = rbi.cx; + m_pBands[i].BreakLine = (rbi.fStyle & RBBS_BREAK) != 0; + } +} + + +void CReBarSettings::ApplyTo(CReBarCtrl& ReBar) const +{ + ATLASSERT(ReBar.IsWindow()); + + for (UINT i = 0; i < m_cbBandCount; i++) + { + ReBar.MoveBand(ReBar.IdToIndex(m_pBands[i].ID), i); + REBARBANDINFO rbi; + rbi.cbSize = sizeof(rbi); + rbi.fMask = RBBIM_ID | RBBIM_SIZE | RBBIM_STYLE; + ReBar.GetBandInfo(i, &rbi); + + rbi.cx = m_pBands[i].cx; + + if (m_pBands[i].BreakLine) + { + rbi.fStyle |= RBBS_BREAK; + } + else + { + rbi.fStyle &= (~RBBS_BREAK); + } + + ReBar.SetBandInfo(i, &rbi); + } +} + + +////////////////////////////////////////////////////////////////////// +// CSplitterSettings + +#define S_SPLITTER_POS _T("SplitterPos") + +bool CSplitterSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) +{ + CRegKey reg; + DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ); + + if (err == ERROR_SUCCESS) + { + reg.QueryDWORDValue(CString(szPrefix) + S_SPLITTER_POS, m_dwPos); + } + + return(err == ERROR_SUCCESS); +} + + +bool CSplitterSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const +{ + CRegKey reg; + DWORD err = reg.Create(hkRootKey, szRegKey); + + if (err == ERROR_SUCCESS) + { + reg.SetDWORDValue(CString(szPrefix) + S_SPLITTER_POS, m_dwPos); + } + + return(err == ERROR_SUCCESS); +} + + diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/RegisterDlg.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/RegisterDlg.cpp index dc1c91bfb6..9e0889d3bb 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/RegisterDlg.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/RegisterDlg.cpp @@ -1,207 +1,207 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "../res/resource.h" -#include "RegisterDlg.h" - -#include "disassemble.h" -#include "gdsp_interpreter.h" -#include "RegSettings.h" - -CRegisterDlg::CRegisterDlg() - : m_CachedCounter(-1) -{} - - -BOOL CRegisterDlg::PreTranslateMessage(MSG* pMsg) -{ - return(IsDialogMessage(pMsg)); -} - - -BOOL CRegisterDlg::OnIdle() -{ - return(FALSE); -} - - -LRESULT CRegisterDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) -{ - CWindowSettings ws; - - if (ws.Load("Software\\Dolphin\\DSP", "Register")) - { - ws.ApplyTo(CWindow(m_hWnd), SW_SHOW); - } - - m_RegisterListViewCtrl.m_hWnd = GetDlgItem(IDC_DISASM_LIST); - - UIAddChildWindowContainer(m_hWnd); - - m_RegisterListViewCtrl.AddColumn(_T("General"), 0); - m_RegisterListViewCtrl.AddColumn(_T(" "), 1); - m_RegisterListViewCtrl.AddColumn(_T("Special"), 2); - m_RegisterListViewCtrl.AddColumn(_T("0"), 3); - - m_RegisterListViewCtrl.SetColumnWidth(0, 50); - m_RegisterListViewCtrl.SetColumnWidth(1, 100); - m_RegisterListViewCtrl.SetColumnWidth(2, 60); - m_RegisterListViewCtrl.SetColumnWidth(3, 100); - - m_RegisterListViewCtrl.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); - m_RegisterListViewCtrl.SetTextBkColor(GetSysColor(COLOR_3DLIGHT)); - - - for (uint16 i = 0; i < 16; i++) - { - // 0-15 - int Item = m_RegisterListViewCtrl.AddItem(0, 0, gd_dis_get_reg_name(i)); - - // 16-31 - m_RegisterListViewCtrl.AddItem(Item, 2, gd_dis_get_reg_name(16 + i)); - - // just for easy sort - m_RegisterListViewCtrl.SetItemData(Item, i); - } - - m_RegisterListViewCtrl.SortItems(CompareFunc, (LPARAM) this); - - UpdateRegisterListView(); - - return(TRUE); -} - - -LRESULT CRegisterDlg::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) -{ - CWindowSettings ws; - ws.GetFrom(CWindow(m_hWnd)); - ws.Save("Software\\Dolphin\\DSP", "Register"); - - return(0); -} - - -void CRegisterDlg::UpdateRegisterListView() -{ - if (m_CachedCounter == g_dsp.step_counter) - { - return; - } - - m_CachedCounter = g_dsp.step_counter; - - char Temp[256]; - - for (uint16 i = 0; i < 16; i++) - { - // 0-15 - if (m_CachedRegs[i] != g_dsp.r[i]) - { - m_CachedRegHasChanged[i] = true; - } - else - { - m_CachedRegHasChanged[i] = false; - } - - m_CachedRegs[i] = g_dsp.r[i]; - - sprintf_s(Temp, 256, "0x%04x", g_dsp.r[i]); - m_RegisterListViewCtrl.SetItemText(i, 1, Temp); - - // 16-31 - if (m_CachedRegs[16 + i] != g_dsp.r[16 + i]) - { - m_CachedRegHasChanged[16 + i] = true; - } - else - { - m_CachedRegHasChanged[16 + i] = false; - } - - m_CachedRegs[16 + i] = g_dsp.r[16 + i]; - - sprintf_s(Temp, 256, "0x%04x", g_dsp.r[16 + i]); - m_RegisterListViewCtrl.SetItemText(i, 3, Temp); - } -} - - -int CALLBACK CRegisterDlg::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) -{ - return(lParam1 > lParam2); -} - - -LRESULT CRegisterDlg::OnCustomDraw(int /*idCtrl*/, LPNMHDR pnmh, BOOL& _bHandled) -{ - int result = CDRF_DODEFAULT; - - NMLVCUSTOMDRAW* pLVCD = reinterpret_cast(pnmh); - - switch (pLVCD->nmcd.dwDrawStage) - { - case CDDS_PREPAINT: - result = CDRF_NOTIFYITEMDRAW; - break; - - case CDDS_ITEMPREPAINT: - result = CDRF_NOTIFYSUBITEMDRAW; - break; - - case (CDDS_ITEMPREPAINT | CDDS_SUBITEM): - { - pLVCD->nmcd.uItemState &= ~(CDIS_SELECTED | CDIS_FOCUS); - - int Offset = static_cast(m_RegisterListViewCtrl.GetItemData((int)pLVCD->nmcd.dwItemSpec)); - - size_t Register = -1; - - if (pLVCD->iSubItem == 1) - { - Register = Offset; - } - else if (pLVCD->iSubItem == 3) - { - Register = Offset + 16; - } - - if (Register != -1) - { - if (m_CachedRegHasChanged[Register]) - { - pLVCD->clrTextBk = RGB(0xFF, 192, 192); - } - else - { - pLVCD->clrTextBk = RGB(0xF0, 0xF0, 0xF0); - } - } - else - { - pLVCD->clrTextBk = RGB(192, 224, 192); - } - - - // uint16 CurrentAddress = static_cast(m_DisAsmListViewCtrl.GetItemData((int)pLVCD->nmcd.dwItemSpec)); - } - break; - } - - return(result); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "../res/resource.h" +#include "RegisterDlg.h" + +#include "disassemble.h" +#include "gdsp_interpreter.h" +#include "RegSettings.h" + +CRegisterDlg::CRegisterDlg() + : m_CachedCounter(-1) +{} + + +BOOL CRegisterDlg::PreTranslateMessage(MSG* pMsg) +{ + return(IsDialogMessage(pMsg)); +} + + +BOOL CRegisterDlg::OnIdle() +{ + return(FALSE); +} + + +LRESULT CRegisterDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) +{ + CWindowSettings ws; + + if (ws.Load("Software\\Dolphin\\DSP", "Register")) + { + ws.ApplyTo(CWindow(m_hWnd), SW_SHOW); + } + + m_RegisterListViewCtrl.m_hWnd = GetDlgItem(IDC_DISASM_LIST); + + UIAddChildWindowContainer(m_hWnd); + + m_RegisterListViewCtrl.AddColumn(_T("General"), 0); + m_RegisterListViewCtrl.AddColumn(_T(" "), 1); + m_RegisterListViewCtrl.AddColumn(_T("Special"), 2); + m_RegisterListViewCtrl.AddColumn(_T("0"), 3); + + m_RegisterListViewCtrl.SetColumnWidth(0, 50); + m_RegisterListViewCtrl.SetColumnWidth(1, 100); + m_RegisterListViewCtrl.SetColumnWidth(2, 60); + m_RegisterListViewCtrl.SetColumnWidth(3, 100); + + m_RegisterListViewCtrl.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); + m_RegisterListViewCtrl.SetTextBkColor(GetSysColor(COLOR_3DLIGHT)); + + + for (uint16 i = 0; i < 16; i++) + { + // 0-15 + int Item = m_RegisterListViewCtrl.AddItem(0, 0, gd_dis_get_reg_name(i)); + + // 16-31 + m_RegisterListViewCtrl.AddItem(Item, 2, gd_dis_get_reg_name(16 + i)); + + // just for easy sort + m_RegisterListViewCtrl.SetItemData(Item, i); + } + + m_RegisterListViewCtrl.SortItems(CompareFunc, (LPARAM) this); + + UpdateRegisterListView(); + + return(TRUE); +} + + +LRESULT CRegisterDlg::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) +{ + CWindowSettings ws; + ws.GetFrom(CWindow(m_hWnd)); + ws.Save("Software\\Dolphin\\DSP", "Register"); + + return(0); +} + + +void CRegisterDlg::UpdateRegisterListView() +{ + if (m_CachedCounter == g_dsp.step_counter) + { + return; + } + + m_CachedCounter = g_dsp.step_counter; + + char Temp[256]; + + for (uint16 i = 0; i < 16; i++) + { + // 0-15 + if (m_CachedRegs[i] != g_dsp.r[i]) + { + m_CachedRegHasChanged[i] = true; + } + else + { + m_CachedRegHasChanged[i] = false; + } + + m_CachedRegs[i] = g_dsp.r[i]; + + sprintf_s(Temp, 256, "0x%04x", g_dsp.r[i]); + m_RegisterListViewCtrl.SetItemText(i, 1, Temp); + + // 16-31 + if (m_CachedRegs[16 + i] != g_dsp.r[16 + i]) + { + m_CachedRegHasChanged[16 + i] = true; + } + else + { + m_CachedRegHasChanged[16 + i] = false; + } + + m_CachedRegs[16 + i] = g_dsp.r[16 + i]; + + sprintf_s(Temp, 256, "0x%04x", g_dsp.r[16 + i]); + m_RegisterListViewCtrl.SetItemText(i, 3, Temp); + } +} + + +int CALLBACK CRegisterDlg::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) +{ + return(lParam1 > lParam2); +} + + +LRESULT CRegisterDlg::OnCustomDraw(int /*idCtrl*/, LPNMHDR pnmh, BOOL& _bHandled) +{ + int result = CDRF_DODEFAULT; + + NMLVCUSTOMDRAW* pLVCD = reinterpret_cast(pnmh); + + switch (pLVCD->nmcd.dwDrawStage) + { + case CDDS_PREPAINT: + result = CDRF_NOTIFYITEMDRAW; + break; + + case CDDS_ITEMPREPAINT: + result = CDRF_NOTIFYSUBITEMDRAW; + break; + + case (CDDS_ITEMPREPAINT | CDDS_SUBITEM): + { + pLVCD->nmcd.uItemState &= ~(CDIS_SELECTED | CDIS_FOCUS); + + int Offset = static_cast(m_RegisterListViewCtrl.GetItemData((int)pLVCD->nmcd.dwItemSpec)); + + size_t Register = -1; + + if (pLVCD->iSubItem == 1) + { + Register = Offset; + } + else if (pLVCD->iSubItem == 3) + { + Register = Offset + 16; + } + + if (Register != -1) + { + if (m_CachedRegHasChanged[Register]) + { + pLVCD->clrTextBk = RGB(0xFF, 192, 192); + } + else + { + pLVCD->clrTextBk = RGB(0xF0, 0xF0, 0xF0); + } + } + else + { + pLVCD->clrTextBk = RGB(192, 224, 192); + } + + + // uint16 CurrentAddress = static_cast(m_DisAsmListViewCtrl.GetItemData((int)pLVCD->nmcd.dwItemSpec)); + } + break; + } + + return(result); +} diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/Tools.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/Tools.cpp index 5401bab086..e88de886f3 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/Tools.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/Tools.cpp @@ -1,93 +1,93 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include -#include - -#include "Common.h" -#include "Globals.h" - -#include "gdsp_interpreter.h" - -bool DumpDSPCode(uint32 _Address, uint32 _Length, uint32 crc) -{ - char szFilename[MAX_PATH]; - sprintf(szFilename, "c:\\_\\DSP_UC_%08X.bin", crc); - FILE* pFile = fopen(szFilename, "wb"); - - if (pFile != NULL) - { - fwrite(g_dspInitialize.pGetMemoryPointer(_Address), _Length, 1, pFile); - fclose(pFile); - return(true); - } - else - { - PanicAlert("Cant open file (%s) to dump UCode!!", szFilename); - } - - return(false); -} - - -uint32 GenerateCRC(const unsigned char* _pBuffer, int _pLength) -{ - unsigned long CRC = 0xFFFFFFFF; - - while (_pLength--) - { - unsigned long Temp = (unsigned long)((CRC & 0xFF) ^ *_pBuffer++); - - for (int j = 0; j < 8; j++) - { - if (Temp & 0x1) - { - Temp = (Temp >> 1) ^ 0xEDB88320; - } - else - { - Temp >>= 1; - } - } - - CRC = (CRC >> 8) ^ Temp; - } - - return(CRC ^ 0xFFFFFFFF); -} - - -bool DumpCWCode(uint32 _Address, uint32 _Length) -{ - FILE* pFile = fopen("d:\\DSP_UCode.bin", "wb"); - - if (pFile != NULL) - { - for (size_t i = _Address; i < _Address + _Length; i++) - { - uint16 val = Common::swap16(g_dsp.iram[i]); - fprintf(pFile, " cw 0x%04x \n", val); - } - - fclose(pFile); - return(true); - } - - return(false); -} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include +#include + +#include "Common.h" +#include "Globals.h" + +#include "gdsp_interpreter.h" + +bool DumpDSPCode(uint32 _Address, uint32 _Length, uint32 crc) +{ + char szFilename[MAX_PATH]; + sprintf(szFilename, "c:\\_\\DSP_UC_%08X.bin", crc); + FILE* pFile = fopen(szFilename, "wb"); + + if (pFile != NULL) + { + fwrite(g_dspInitialize.pGetMemoryPointer(_Address), _Length, 1, pFile); + fclose(pFile); + return(true); + } + else + { + PanicAlert("Cant open file (%s) to dump UCode!!", szFilename); + } + + return(false); +} + + +uint32 GenerateCRC(const unsigned char* _pBuffer, int _pLength) +{ + unsigned long CRC = 0xFFFFFFFF; + + while (_pLength--) + { + unsigned long Temp = (unsigned long)((CRC & 0xFF) ^ *_pBuffer++); + + for (int j = 0; j < 8; j++) + { + if (Temp & 0x1) + { + Temp = (Temp >> 1) ^ 0xEDB88320; + } + else + { + Temp >>= 1; + } + } + + CRC = (CRC >> 8) ^ Temp; + } + + return(CRC ^ 0xFFFFFFFF); +} + + +bool DumpCWCode(uint32 _Address, uint32 _Length) +{ + FILE* pFile = fopen("d:\\DSP_UCode.bin", "wb"); + + if (pFile != NULL) + { + for (size_t i = _Address; i < _Address + _Length; i++) + { + uint16 val = Common::swap16(g_dsp.iram[i]); + fprintf(pFile, " cw 0x%04x \n", val); + } + + fclose(pFile); + return(true); + } + + return(false); +} + + diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/disassemble.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/disassemble.cpp index 442d8036c4..99968a6f21 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/disassemble.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/disassemble.cpp @@ -1,622 +1,622 @@ -/*==================================================================== - - filename: disassemble.cpp - project: GameCube DSP Tool (gcdsp) - created: 2005.03.04 - mail: duddie@walla.com - - Copyright (c) 2005 Duddie - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - ====================================================================*/ - -#include -#include -#include - -#include "Globals.h" - -#include "disassemble.h" -#include "opcodes.h" -// #include "gdsp_tool.h" - -#ifdef _MSC_VER -#pragma warning(disable:4996) -#endif - -uint32 unk_opcodes[0x10000]; - -uint16 swap16(uint16 x); - - -// predefined labels -typedef struct pdlabel_t -{ - uint16 addr; - const char* name; - const char* description; -} pdlabels_t; - -const pdlabel_t pdlabels[] = -{ - {0xffa0, "COEF_A1_0", "COEF_A1_0",}, - {0xffa1, "COEF_A2_0", "COEF_A2_0",}, - {0xffa2, "COEF_A1_1", "COEF_A1_1",}, - {0xffa3, "COEF_A2_1", "COEF_A2_1",}, - {0xffa4, "COEF_A1_2", "COEF_A1_2",}, - {0xffa5, "COEF_A2_2", "COEF_A2_2",}, - {0xffa6, "COEF_A1_3", "COEF_A1_3",}, - {0xffa7, "COEF_A2_3", "COEF_A2_3",}, - {0xffa8, "COEF_A1_4", "COEF_A1_4",}, - {0xffa9, "COEF_A2_4", "COEF_A2_4",}, - {0xffaa, "COEF_A1_5", "COEF_A1_5",}, - {0xffab, "COEF_A2_5", "COEF_A2_5",}, - {0xffac, "COEF_A1_6", "COEF_A1_6",}, - {0xffad, "COEF_A2_6", "COEF_A2_6",}, - {0xffae, "COEF_A1_7", "COEF_A1_7",}, - {0xffaf, "COEF_A2_7", "COEF_A2_7",}, - {0xffc9, "DSCR", "DSP DMA Control Reg",}, - {0xffcb, "DSBL", "DSP DMA Block Length",}, - {0xffcd, "DSPA", "DSP DMA DMEM Address",}, - {0xffce, "DSMAH", "DSP DMA Mem Address H",}, - {0xffcf, "DSMAL", "DSP DMA Mem Address L",}, - {0xffd1, "SampleFormat", "SampleFormat",}, - - {0xffd3, "Unk Zelda", "Unk Zelda writes to it",}, - - {0xffd4, "ACSAH", "Accelerator start address H",}, - {0xffd5, "ACSAL", "Accelerator start address L",}, - {0xffd6, "ACEAH", "Accelerator end address H",}, - {0xffd7, "ACEAL", "Accelerator end address L",}, - {0xffd8, "ACCAH", "Accelerator current address H",}, - {0xffd9, "ACCAL", "Accelerator current address L",}, - {0xffda, "pred_scale", "pred_scale",}, - {0xffdb, "yn1", "yn1",}, - {0xffdc, "yn2", "yn2",}, - {0xffdd, "ARAM", "Direct Read from ARAM (uses ADPCM)",}, - {0xffde, "GAIN", "Gain",}, - {0xffef, "AMDM", "ARAM DMA Request Mask",}, - {0xfffb, "DIRQ", "DSP IRQ Request",}, - {0xfffc, "DMBH", "DSP Mailbox H",}, - {0xfffd, "DMBL", "DSP Mailbox L",}, - {0xfffe, "CMBH", "CPU Mailbox H",}, - {0xffff, "CMBL", "CPU Mailbox L",}, -}; - -pdlabel_t regnames[] = -{ - {0x00, "R00", "Register 00",}, - {0x01, "R01", "Register 01",}, - {0x02, "R02", "Register 02",}, - {0x03, "R03", "Register 03",}, - {0x04, "R04", "Register 04",}, - {0x05, "R05", "Register 05",}, - {0x06, "R06", "Register 06",}, - {0x07, "R07", "Register 07",}, - {0x08, "R08", "Register 08",}, - {0x09, "R09", "Register 09",}, - {0x0a, "R10", "Register 10",}, - {0x0b, "R11", "Register 11",}, - {0x0c, "ST0", "Call stack",}, - {0x0d, "ST1", "Data stack",}, - {0x0e, "ST2", "Loop address stack",}, - {0x0f, "ST3", "Loop counter",}, - {0x00, "ACH0", "Accumulator High 0",}, - {0x11, "ACH1", "Accumulator High 1",}, - {0x12, "CR", "Config Register",}, - {0x13, "SR", "Special Register",}, - {0x14, "PROD.L", "PROD L",}, - {0x15, "PROD.M1", "PROD M1",}, - {0x16, "PROD.H", "PROD H",}, - {0x17, "PROD.M2", "PROD M2",}, - {0x18, "AX0.L", "Additional Accumulators Low 0",}, - {0x19, "AX1.L", "Additional Accumulators Low 1",}, - {0x1a, "AX0.H", "Additional Accumulators High 0",}, - {0x1b, "AX1.H", "Additional Accumulators High 1",}, - {0x1c, "AC0.L", "Register 28",}, - {0x1d, "AC1.L", "Register 29",}, - {0x1e, "AC0.M", "Register 00",}, - {0x1f, "AC1.M", "Register 00",}, - -// additional to resolve special names - {0x20, "ACC0", "Accumulators 0",}, - {0x21, "ACC1", "Accumulators 1",}, - {0x22, "AX0", "Additional Accumulators 0",}, - {0x23, "AX1", "Additional Accumulators 1",}, -}; - -const char* pdname(uint16 val) -{ - static char tmpstr[12]; // nasty - - for (int i = 0; i < (int)(sizeof(pdlabels) / sizeof(pdlabel_t)); i++) - { - if (pdlabels[i].addr == val) - { - return(pdlabels[i].name); - } - } - - sprintf(tmpstr, "0x%04x", val); - return(tmpstr); -} - - -char* gd_dis_params(gd_globals_t* gdg, opc_t* opc, uint16 op1, uint16 op2, char* strbuf) -{ - char* buf = strbuf; - uint32 val; - int j; - - for (j = 0; j < opc->param_count; j++) - { - if (j > 0) - { - sprintf(buf, ", "); - buf += strlen(buf); - } - - if (opc->params[j].loc >= 1) - { - val = op2; - } - else - { - val = op1; - } - - val &= opc->params[j].mask; - - if (opc->params[j].lshift < 0) - { - val = val << (-opc->params[j].lshift); - } - else - { - val = val >> opc->params[j].lshift; - } - - uint32 type; - type = opc->params[j].type; - - if (type & P_REG) - { - if (type == P_ACCM_D) - { - val = (~val & 0x1) | ((type & P_REGS_MASK) >> 8); - } - else - { - val |= (type & P_REGS_MASK) >> 8; - } - - type &= ~P_REGS_MASK; - } - - switch (type) - { - case P_REG: - - if (gdg->decode_registers){sprintf(buf, "$%s", regnames[val].name);} - else {sprintf(buf, "$%d", val);} - - break; - - case P_PRG: - - if (gdg->decode_registers){sprintf(buf, "@$%s", regnames[val].name);} - else {sprintf(buf, "@$%d", val);} - - break; - - case P_VAL: - sprintf(buf, "0x%04x", val); - break; - - case P_IMM: - - if (opc->params[j].size != 2) - { - sprintf(buf, "#0x%02x", val); - } - else - { - sprintf(buf, "#0x%04x", val); - } - - break; - - case P_MEM: - - if (opc->params[j].size != 2) - { - val = (uint16)(sint8)val; - } - - if (gdg->decode_names) - { - sprintf(buf, "@%s", pdname(val)); - } - else - { - sprintf(buf, "@0x%04x", val); - } - - break; - - default: - ErrorLog("Unknown parameter type: %x\n", opc->params[j].type); - exit(-1); - break; - } - - buf += strlen(buf); - } - - return(strbuf); -} - - -gd_globals_t* gd_init() -{ - gd_globals_t* gdg = (gd_globals_t*)malloc(sizeof(gd_globals_t)); - memset(gdg, 0, sizeof(gd_globals_t)); - return(gdg); -} - - -uint16 gd_dis_get_opcode_size(gd_globals_t* gdg) -{ - opc_t* opc = 0; - opc_t* opc_ext = 0; - bool extended; - - if ((gdg->pc & 0x7fff) >= 0x1000) - { - return(1); - } - - uint32 op1 = swap16(gdg->binbuf[gdg->pc & 0x0fff]); - - for (uint32 j = 0; j < opcodes_size; j++) - { - uint16 mask; - - if (opcodes[j].size & P_EXT) - { - mask = opcodes[j].opcode_mask & 0xff00; - } - else - { - mask = opcodes[j].opcode_mask; - } - - if ((op1 & mask) == opcodes[j].opcode) - { - opc = &opcodes[j]; - break; - } - } - - if (!opc) - { - ErrorLog("get_opcode_size ARGH"); - exit(0); - } - - if (opc->size & P_EXT && op1 & 0x00ff) - { - extended = true; - } - else - { - extended = false; - } - - if (extended) - { - // opcode has an extension - // find opcode - for (uint32 j = 0; j < opcodes_ext_size; j++) - { - if ((op1 & opcodes_ext[j].opcode_mask) == opcodes_ext[j].opcode) - { - opc_ext = &opcodes_ext[j]; - break; - } - } - - if (!opc_ext) - { - ErrorLog("get_opcode_size ext ARGH"); - } - - return(opc_ext->size); - } - - return(opc->size & ~P_EXT); -} - - -char* gd_dis_opcode(gd_globals_t* gdg) -{ - uint32 j; - uint32 op1, op2; - opc_t* opc = NULL; - opc_t* opc_ext = NULL; - uint16 pc; - char* buf = gdg->buffer; - bool extended; - - pc = gdg->pc; - *buf = '\0'; - - if ((pc & 0x7fff) >= 0x1000) - { - gdg->pc++; - return(gdg->buffer); - } - - pc &= 0x0fff; - op1 = swap16(gdg->binbuf[pc]); - - // find opcode - for (j = 0; j < opcodes_size; j++) - { - uint16 mask; - - if (opcodes[j].size & P_EXT) - { - mask = opcodes[j].opcode_mask & 0xff00; - } - else - { - mask = opcodes[j].opcode_mask; - } - - if ((op1 & mask) == opcodes[j].opcode) - { - opc = &opcodes[j]; - break; - } - } - - if (opc->size & P_EXT && op1 & 0x00ff) - { - extended = true; - } - else - { - extended = false; - } - - if (extended) - { - // opcode has an extension - // find opcode - for (j = 0; j < opcodes_ext_size; j++) - { - if ((op1 & opcodes_ext[j].opcode_mask) == opcodes_ext[j].opcode) - { - opc_ext = &opcodes_ext[j]; - break; - } - } - } - - // printing - - if (gdg->show_pc){sprintf(buf, "%04x ", gdg->pc);} - - buf += strlen(buf); - - if ((opc->size & ~P_EXT) == 2) - { - op2 = swap16(gdg->binbuf[pc + 1]); - - if (gdg->show_hex){sprintf(buf, "%04x %04x ", op1, op2);} - } - else - { - op2 = 0; - - if (gdg->show_hex){sprintf(buf, "%04x ", op1);} - } - - buf += strlen(buf); - - char tmpbuf[20]; - - if (extended) - { - sprintf(tmpbuf, "%s%c%s", opc->name, gdg->ext_separator, opc_ext->name); - } - else - { - sprintf(tmpbuf, "%s", opc->name); - } - - if (gdg->print_tabs) - { - sprintf(buf, "%s\t", tmpbuf); - } - else - { - sprintf(buf, "%-12s", tmpbuf); - } - - buf += strlen(buf); - - if (opc->param_count > 0) - { - gd_dis_params(gdg, opc, op1, op2, buf); - } - - buf += strlen(buf); - - if (extended) - { - if (opc->param_count > 0) - { - sprintf(buf, " "); - } - - buf += strlen(buf); - - sprintf(buf, ": "); - buf += strlen(buf); - - if (opc_ext->param_count > 0) - { - gd_dis_params(gdg, opc_ext, op1, op2, buf); - } - - buf += strlen(buf); - } - - if (opc->opcode_mask == 0) - { - // unknown opcode - unk_opcodes[op1]++; - sprintf(buf, "\t\t; *** UNKNOWN OPCODE ***"); - } - - if (extended) - { - gdg->pc += opc_ext->size; - } - else - { - gdg->pc += opc->size & ~P_EXT; - } - - return(gdg->buffer); -} - - -bool gd_dis_file(gd_globals_t* gdg, char* name, FILE* output) -{ - FILE* in; - uint32 size; - - in = fopen(name, "rb"); - - if (in == NULL) - { - return(false); - } - - fseek(in, 0, SEEK_END); - size = ftell(in); - fseek(in, 0, SEEK_SET); - gdg->binbuf = (uint16*)malloc(size); - fread(gdg->binbuf, 1, size, in); - - gdg->buffer = (char*)malloc(256); - gdg->buffer_size = 256; - - for (gdg->pc = 0; gdg->pc < (size / 2);) - { - fprintf(output, "%s\n", gd_dis_opcode(gdg)); - } - - fclose(in); - - free(gdg->binbuf); - gdg->binbuf = NULL; - - free(gdg->buffer); - gdg->buffer = NULL; - gdg->buffer_size = 0; - - return(true); -} - - -void gd_dis_close_unkop() -{ - FILE* uo; - int i, j; - uint32 count = 0; - - uo = fopen("uo.bin", "wb"); - - if (uo) - { - fwrite(unk_opcodes, 1, sizeof(unk_opcodes), uo); - fclose(uo); - } - - uo = fopen("unkopc.txt", "w"); - - if (uo) - { - for (i = 0; i < 0x10000; i++) - { - if (unk_opcodes[i]) - { - count++; - fprintf(uo, "OP%04x\t%d", i, unk_opcodes[i]); - - for (j = 15; j >= 0; j--) - { - if ((j & 0x3) == 3) - { - fprintf(uo, "\tb"); - } - - fprintf(uo, "%d", (i >> j) & 0x1); - } - - fprintf(uo, "\n"); - } - } - - fprintf(uo, "Unknown opcodes count: %d\n", count); - fclose(uo); - } -} - - -void gd_dis_open_unkop() -{ - FILE* uo; - - uo = fopen("uo.bin", "rb"); - - if (uo) - { - fread(unk_opcodes, 1, sizeof(unk_opcodes), uo); - fclose(uo); - } - else - { - int i; - - for (i = 0; i < 0x10000; i++) - { - unk_opcodes[i] = 0; - } - } -} - - -const char* gd_dis_get_reg_name(uint16 reg) -{ - return(regnames[reg].name); -} - - +/*==================================================================== + + filename: disassemble.cpp + project: GameCube DSP Tool (gcdsp) + created: 2005.03.04 + mail: duddie@walla.com + + Copyright (c) 2005 Duddie + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + ====================================================================*/ + +#include +#include +#include + +#include "Globals.h" + +#include "disassemble.h" +#include "opcodes.h" +// #include "gdsp_tool.h" + +#ifdef _MSC_VER +#pragma warning(disable:4996) +#endif + +uint32 unk_opcodes[0x10000]; + +uint16 swap16(uint16 x); + + +// predefined labels +typedef struct pdlabel_t +{ + uint16 addr; + const char* name; + const char* description; +} pdlabels_t; + +const pdlabel_t pdlabels[] = +{ + {0xffa0, "COEF_A1_0", "COEF_A1_0",}, + {0xffa1, "COEF_A2_0", "COEF_A2_0",}, + {0xffa2, "COEF_A1_1", "COEF_A1_1",}, + {0xffa3, "COEF_A2_1", "COEF_A2_1",}, + {0xffa4, "COEF_A1_2", "COEF_A1_2",}, + {0xffa5, "COEF_A2_2", "COEF_A2_2",}, + {0xffa6, "COEF_A1_3", "COEF_A1_3",}, + {0xffa7, "COEF_A2_3", "COEF_A2_3",}, + {0xffa8, "COEF_A1_4", "COEF_A1_4",}, + {0xffa9, "COEF_A2_4", "COEF_A2_4",}, + {0xffaa, "COEF_A1_5", "COEF_A1_5",}, + {0xffab, "COEF_A2_5", "COEF_A2_5",}, + {0xffac, "COEF_A1_6", "COEF_A1_6",}, + {0xffad, "COEF_A2_6", "COEF_A2_6",}, + {0xffae, "COEF_A1_7", "COEF_A1_7",}, + {0xffaf, "COEF_A2_7", "COEF_A2_7",}, + {0xffc9, "DSCR", "DSP DMA Control Reg",}, + {0xffcb, "DSBL", "DSP DMA Block Length",}, + {0xffcd, "DSPA", "DSP DMA DMEM Address",}, + {0xffce, "DSMAH", "DSP DMA Mem Address H",}, + {0xffcf, "DSMAL", "DSP DMA Mem Address L",}, + {0xffd1, "SampleFormat", "SampleFormat",}, + + {0xffd3, "Unk Zelda", "Unk Zelda writes to it",}, + + {0xffd4, "ACSAH", "Accelerator start address H",}, + {0xffd5, "ACSAL", "Accelerator start address L",}, + {0xffd6, "ACEAH", "Accelerator end address H",}, + {0xffd7, "ACEAL", "Accelerator end address L",}, + {0xffd8, "ACCAH", "Accelerator current address H",}, + {0xffd9, "ACCAL", "Accelerator current address L",}, + {0xffda, "pred_scale", "pred_scale",}, + {0xffdb, "yn1", "yn1",}, + {0xffdc, "yn2", "yn2",}, + {0xffdd, "ARAM", "Direct Read from ARAM (uses ADPCM)",}, + {0xffde, "GAIN", "Gain",}, + {0xffef, "AMDM", "ARAM DMA Request Mask",}, + {0xfffb, "DIRQ", "DSP IRQ Request",}, + {0xfffc, "DMBH", "DSP Mailbox H",}, + {0xfffd, "DMBL", "DSP Mailbox L",}, + {0xfffe, "CMBH", "CPU Mailbox H",}, + {0xffff, "CMBL", "CPU Mailbox L",}, +}; + +pdlabel_t regnames[] = +{ + {0x00, "R00", "Register 00",}, + {0x01, "R01", "Register 01",}, + {0x02, "R02", "Register 02",}, + {0x03, "R03", "Register 03",}, + {0x04, "R04", "Register 04",}, + {0x05, "R05", "Register 05",}, + {0x06, "R06", "Register 06",}, + {0x07, "R07", "Register 07",}, + {0x08, "R08", "Register 08",}, + {0x09, "R09", "Register 09",}, + {0x0a, "R10", "Register 10",}, + {0x0b, "R11", "Register 11",}, + {0x0c, "ST0", "Call stack",}, + {0x0d, "ST1", "Data stack",}, + {0x0e, "ST2", "Loop address stack",}, + {0x0f, "ST3", "Loop counter",}, + {0x00, "ACH0", "Accumulator High 0",}, + {0x11, "ACH1", "Accumulator High 1",}, + {0x12, "CR", "Config Register",}, + {0x13, "SR", "Special Register",}, + {0x14, "PROD.L", "PROD L",}, + {0x15, "PROD.M1", "PROD M1",}, + {0x16, "PROD.H", "PROD H",}, + {0x17, "PROD.M2", "PROD M2",}, + {0x18, "AX0.L", "Additional Accumulators Low 0",}, + {0x19, "AX1.L", "Additional Accumulators Low 1",}, + {0x1a, "AX0.H", "Additional Accumulators High 0",}, + {0x1b, "AX1.H", "Additional Accumulators High 1",}, + {0x1c, "AC0.L", "Register 28",}, + {0x1d, "AC1.L", "Register 29",}, + {0x1e, "AC0.M", "Register 00",}, + {0x1f, "AC1.M", "Register 00",}, + +// additional to resolve special names + {0x20, "ACC0", "Accumulators 0",}, + {0x21, "ACC1", "Accumulators 1",}, + {0x22, "AX0", "Additional Accumulators 0",}, + {0x23, "AX1", "Additional Accumulators 1",}, +}; + +const char* pdname(uint16 val) +{ + static char tmpstr[12]; // nasty + + for (int i = 0; i < (int)(sizeof(pdlabels) / sizeof(pdlabel_t)); i++) + { + if (pdlabels[i].addr == val) + { + return(pdlabels[i].name); + } + } + + sprintf(tmpstr, "0x%04x", val); + return(tmpstr); +} + + +char* gd_dis_params(gd_globals_t* gdg, opc_t* opc, uint16 op1, uint16 op2, char* strbuf) +{ + char* buf = strbuf; + uint32 val; + int j; + + for (j = 0; j < opc->param_count; j++) + { + if (j > 0) + { + sprintf(buf, ", "); + buf += strlen(buf); + } + + if (opc->params[j].loc >= 1) + { + val = op2; + } + else + { + val = op1; + } + + val &= opc->params[j].mask; + + if (opc->params[j].lshift < 0) + { + val = val << (-opc->params[j].lshift); + } + else + { + val = val >> opc->params[j].lshift; + } + + uint32 type; + type = opc->params[j].type; + + if (type & P_REG) + { + if (type == P_ACCM_D) + { + val = (~val & 0x1) | ((type & P_REGS_MASK) >> 8); + } + else + { + val |= (type & P_REGS_MASK) >> 8; + } + + type &= ~P_REGS_MASK; + } + + switch (type) + { + case P_REG: + + if (gdg->decode_registers){sprintf(buf, "$%s", regnames[val].name);} + else {sprintf(buf, "$%d", val);} + + break; + + case P_PRG: + + if (gdg->decode_registers){sprintf(buf, "@$%s", regnames[val].name);} + else {sprintf(buf, "@$%d", val);} + + break; + + case P_VAL: + sprintf(buf, "0x%04x", val); + break; + + case P_IMM: + + if (opc->params[j].size != 2) + { + sprintf(buf, "#0x%02x", val); + } + else + { + sprintf(buf, "#0x%04x", val); + } + + break; + + case P_MEM: + + if (opc->params[j].size != 2) + { + val = (uint16)(sint8)val; + } + + if (gdg->decode_names) + { + sprintf(buf, "@%s", pdname(val)); + } + else + { + sprintf(buf, "@0x%04x", val); + } + + break; + + default: + ErrorLog("Unknown parameter type: %x\n", opc->params[j].type); + exit(-1); + break; + } + + buf += strlen(buf); + } + + return(strbuf); +} + + +gd_globals_t* gd_init() +{ + gd_globals_t* gdg = (gd_globals_t*)malloc(sizeof(gd_globals_t)); + memset(gdg, 0, sizeof(gd_globals_t)); + return(gdg); +} + + +uint16 gd_dis_get_opcode_size(gd_globals_t* gdg) +{ + opc_t* opc = 0; + opc_t* opc_ext = 0; + bool extended; + + if ((gdg->pc & 0x7fff) >= 0x1000) + { + return(1); + } + + uint32 op1 = swap16(gdg->binbuf[gdg->pc & 0x0fff]); + + for (uint32 j = 0; j < opcodes_size; j++) + { + uint16 mask; + + if (opcodes[j].size & P_EXT) + { + mask = opcodes[j].opcode_mask & 0xff00; + } + else + { + mask = opcodes[j].opcode_mask; + } + + if ((op1 & mask) == opcodes[j].opcode) + { + opc = &opcodes[j]; + break; + } + } + + if (!opc) + { + ErrorLog("get_opcode_size ARGH"); + exit(0); + } + + if (opc->size & P_EXT && op1 & 0x00ff) + { + extended = true; + } + else + { + extended = false; + } + + if (extended) + { + // opcode has an extension + // find opcode + for (uint32 j = 0; j < opcodes_ext_size; j++) + { + if ((op1 & opcodes_ext[j].opcode_mask) == opcodes_ext[j].opcode) + { + opc_ext = &opcodes_ext[j]; + break; + } + } + + if (!opc_ext) + { + ErrorLog("get_opcode_size ext ARGH"); + } + + return(opc_ext->size); + } + + return(opc->size & ~P_EXT); +} + + +char* gd_dis_opcode(gd_globals_t* gdg) +{ + uint32 j; + uint32 op1, op2; + opc_t* opc = NULL; + opc_t* opc_ext = NULL; + uint16 pc; + char* buf = gdg->buffer; + bool extended; + + pc = gdg->pc; + *buf = '\0'; + + if ((pc & 0x7fff) >= 0x1000) + { + gdg->pc++; + return(gdg->buffer); + } + + pc &= 0x0fff; + op1 = swap16(gdg->binbuf[pc]); + + // find opcode + for (j = 0; j < opcodes_size; j++) + { + uint16 mask; + + if (opcodes[j].size & P_EXT) + { + mask = opcodes[j].opcode_mask & 0xff00; + } + else + { + mask = opcodes[j].opcode_mask; + } + + if ((op1 & mask) == opcodes[j].opcode) + { + opc = &opcodes[j]; + break; + } + } + + if (opc->size & P_EXT && op1 & 0x00ff) + { + extended = true; + } + else + { + extended = false; + } + + if (extended) + { + // opcode has an extension + // find opcode + for (j = 0; j < opcodes_ext_size; j++) + { + if ((op1 & opcodes_ext[j].opcode_mask) == opcodes_ext[j].opcode) + { + opc_ext = &opcodes_ext[j]; + break; + } + } + } + + // printing + + if (gdg->show_pc){sprintf(buf, "%04x ", gdg->pc);} + + buf += strlen(buf); + + if ((opc->size & ~P_EXT) == 2) + { + op2 = swap16(gdg->binbuf[pc + 1]); + + if (gdg->show_hex){sprintf(buf, "%04x %04x ", op1, op2);} + } + else + { + op2 = 0; + + if (gdg->show_hex){sprintf(buf, "%04x ", op1);} + } + + buf += strlen(buf); + + char tmpbuf[20]; + + if (extended) + { + sprintf(tmpbuf, "%s%c%s", opc->name, gdg->ext_separator, opc_ext->name); + } + else + { + sprintf(tmpbuf, "%s", opc->name); + } + + if (gdg->print_tabs) + { + sprintf(buf, "%s\t", tmpbuf); + } + else + { + sprintf(buf, "%-12s", tmpbuf); + } + + buf += strlen(buf); + + if (opc->param_count > 0) + { + gd_dis_params(gdg, opc, op1, op2, buf); + } + + buf += strlen(buf); + + if (extended) + { + if (opc->param_count > 0) + { + sprintf(buf, " "); + } + + buf += strlen(buf); + + sprintf(buf, ": "); + buf += strlen(buf); + + if (opc_ext->param_count > 0) + { + gd_dis_params(gdg, opc_ext, op1, op2, buf); + } + + buf += strlen(buf); + } + + if (opc->opcode_mask == 0) + { + // unknown opcode + unk_opcodes[op1]++; + sprintf(buf, "\t\t; *** UNKNOWN OPCODE ***"); + } + + if (extended) + { + gdg->pc += opc_ext->size; + } + else + { + gdg->pc += opc->size & ~P_EXT; + } + + return(gdg->buffer); +} + + +bool gd_dis_file(gd_globals_t* gdg, char* name, FILE* output) +{ + FILE* in; + uint32 size; + + in = fopen(name, "rb"); + + if (in == NULL) + { + return(false); + } + + fseek(in, 0, SEEK_END); + size = ftell(in); + fseek(in, 0, SEEK_SET); + gdg->binbuf = (uint16*)malloc(size); + fread(gdg->binbuf, 1, size, in); + + gdg->buffer = (char*)malloc(256); + gdg->buffer_size = 256; + + for (gdg->pc = 0; gdg->pc < (size / 2);) + { + fprintf(output, "%s\n", gd_dis_opcode(gdg)); + } + + fclose(in); + + free(gdg->binbuf); + gdg->binbuf = NULL; + + free(gdg->buffer); + gdg->buffer = NULL; + gdg->buffer_size = 0; + + return(true); +} + + +void gd_dis_close_unkop() +{ + FILE* uo; + int i, j; + uint32 count = 0; + + uo = fopen("uo.bin", "wb"); + + if (uo) + { + fwrite(unk_opcodes, 1, sizeof(unk_opcodes), uo); + fclose(uo); + } + + uo = fopen("unkopc.txt", "w"); + + if (uo) + { + for (i = 0; i < 0x10000; i++) + { + if (unk_opcodes[i]) + { + count++; + fprintf(uo, "OP%04x\t%d", i, unk_opcodes[i]); + + for (j = 15; j >= 0; j--) + { + if ((j & 0x3) == 3) + { + fprintf(uo, "\tb"); + } + + fprintf(uo, "%d", (i >> j) & 0x1); + } + + fprintf(uo, "\n"); + } + } + + fprintf(uo, "Unknown opcodes count: %d\n", count); + fclose(uo); + } +} + + +void gd_dis_open_unkop() +{ + FILE* uo; + + uo = fopen("uo.bin", "rb"); + + if (uo) + { + fread(unk_opcodes, 1, sizeof(unk_opcodes), uo); + fclose(uo); + } + else + { + int i; + + for (i = 0; i < 0x10000; i++) + { + unk_opcodes[i] = 0; + } + } +} + + +const char* gd_dis_get_reg_name(uint16 reg) +{ + return(regnames[reg].name); +} + + diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.cpp index 1c37cb4918..2f0b1b8fcb 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.cpp @@ -1,113 +1,113 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Globals.h" -#include "gdsp_interface.h" - -extern uint16 dsp_swap16(uint16 x); - -// The hardware adpcm decoder :) -sint16 ADPCM_Step(uint32& _rSamplePos, uint32 _BaseAddress) -{ - sint16* pCoefTable = (sint16*)&gdsp_ifx_regs[DSP_COEF_A1_0]; - - if (((_rSamplePos) & 15) == 0) - { - gdsp_ifx_regs[DSP_PRED_SCALE] = g_dspInitialize.pARAM_Read_U8((_rSamplePos & ~15) >> 1); - _rSamplePos += 2; - } - - int scale = 1 << (gdsp_ifx_regs[DSP_PRED_SCALE] & 0xF); - int coef_idx = gdsp_ifx_regs[DSP_PRED_SCALE] >> 4; - - sint32 coef1 = pCoefTable[coef_idx * 2 + 0]; - sint32 coef2 = pCoefTable[coef_idx * 2 + 1]; - - int temp = (_rSamplePos & 1) ? - (g_dspInitialize.pARAM_Read_U8(_rSamplePos >> 1) & 0xF) : - (g_dspInitialize.pARAM_Read_U8(_rSamplePos >> 1) >> 4); - - if (temp >= 8) - temp -= 16; - - // 0x400 = 0.5 in 11-bit fixed point - int val = (scale * temp) + ((0x400 + coef1 * (sint16)gdsp_ifx_regs[DSP_YN1] + coef2 * (sint16)gdsp_ifx_regs[DSP_YN2]) >> 11); - - // Clamp values. - if (val > 0x7FFF) - val = 0x7FFF; - else if (val < -0x7FFF) - val = -0x7FFF; - - gdsp_ifx_regs[DSP_YN2] = gdsp_ifx_regs[DSP_YN1]; - gdsp_ifx_regs[DSP_YN1] = val; - - _rSamplePos++; - - // The advanced interpolation (linear, polyphase,...) is done by the UCode, so we don't - // need to bother with it here. - return val; -} - -extern void gdsp_generate_exception(uint8 level); -uint16 dsp_read_aram() -{ - // uint32 BaseAddress = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL]; - uint32 EndAddress = (gdsp_ifx_regs[DSP_ACEAH] << 16) | gdsp_ifx_regs[DSP_ACEAL]; - uint32 Address = (gdsp_ifx_regs[DSP_ACCAH] << 16) | gdsp_ifx_regs[DSP_ACCAL]; - - uint16 val; - - // lets the "hardware" decode - switch (gdsp_ifx_regs[DSP_FORMAT]) - { - case 0x00: - val = ADPCM_Step(Address, EndAddress); - break; - - case 0x0A: - val = (g_dspInitialize.pARAM_Read_U8(Address) << 8) | g_dspInitialize.pARAM_Read_U8(Address + 1); - - gdsp_ifx_regs[DSP_YN2] = gdsp_ifx_regs[DSP_YN1]; - gdsp_ifx_regs[DSP_YN1] = val; - - Address += 2; - break; - - default: - val = (g_dspInitialize.pARAM_Read_U8(Address) << 8) | g_dspInitialize.pARAM_Read_U8(Address + 1); - Address += 2; - ErrorLog("Unknown DSP Format %i", gdsp_ifx_regs[DSP_FORMAT]); - break; - } - - // check for loop - if (Address > EndAddress) - { - Address = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL]; - gdsp_generate_exception(3); - gdsp_generate_exception(5); - - // Somehow, YN1 and YN2 must be initialized with their "loop" values, so yeah, - // it seems likely that we should raise an exception to let the DSP program do that, - // at least if DSP_FORMAT == 0x0A. - } - - gdsp_ifx_regs[DSP_ACCAH] = Address >> 16; - gdsp_ifx_regs[DSP_ACCAL] = Address & 0xffff; - return(val); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Globals.h" +#include "gdsp_interface.h" + +extern uint16 dsp_swap16(uint16 x); + +// The hardware adpcm decoder :) +sint16 ADPCM_Step(uint32& _rSamplePos, uint32 _BaseAddress) +{ + sint16* pCoefTable = (sint16*)&gdsp_ifx_regs[DSP_COEF_A1_0]; + + if (((_rSamplePos) & 15) == 0) + { + gdsp_ifx_regs[DSP_PRED_SCALE] = g_dspInitialize.pARAM_Read_U8((_rSamplePos & ~15) >> 1); + _rSamplePos += 2; + } + + int scale = 1 << (gdsp_ifx_regs[DSP_PRED_SCALE] & 0xF); + int coef_idx = gdsp_ifx_regs[DSP_PRED_SCALE] >> 4; + + sint32 coef1 = pCoefTable[coef_idx * 2 + 0]; + sint32 coef2 = pCoefTable[coef_idx * 2 + 1]; + + int temp = (_rSamplePos & 1) ? + (g_dspInitialize.pARAM_Read_U8(_rSamplePos >> 1) & 0xF) : + (g_dspInitialize.pARAM_Read_U8(_rSamplePos >> 1) >> 4); + + if (temp >= 8) + temp -= 16; + + // 0x400 = 0.5 in 11-bit fixed point + int val = (scale * temp) + ((0x400 + coef1 * (sint16)gdsp_ifx_regs[DSP_YN1] + coef2 * (sint16)gdsp_ifx_regs[DSP_YN2]) >> 11); + + // Clamp values. + if (val > 0x7FFF) + val = 0x7FFF; + else if (val < -0x7FFF) + val = -0x7FFF; + + gdsp_ifx_regs[DSP_YN2] = gdsp_ifx_regs[DSP_YN1]; + gdsp_ifx_regs[DSP_YN1] = val; + + _rSamplePos++; + + // The advanced interpolation (linear, polyphase,...) is done by the UCode, so we don't + // need to bother with it here. + return val; +} + +extern void gdsp_generate_exception(uint8 level); +uint16 dsp_read_aram() +{ + // uint32 BaseAddress = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL]; + uint32 EndAddress = (gdsp_ifx_regs[DSP_ACEAH] << 16) | gdsp_ifx_regs[DSP_ACEAL]; + uint32 Address = (gdsp_ifx_regs[DSP_ACCAH] << 16) | gdsp_ifx_regs[DSP_ACCAL]; + + uint16 val; + + // lets the "hardware" decode + switch (gdsp_ifx_regs[DSP_FORMAT]) + { + case 0x00: + val = ADPCM_Step(Address, EndAddress); + break; + + case 0x0A: + val = (g_dspInitialize.pARAM_Read_U8(Address) << 8) | g_dspInitialize.pARAM_Read_U8(Address + 1); + + gdsp_ifx_regs[DSP_YN2] = gdsp_ifx_regs[DSP_YN1]; + gdsp_ifx_regs[DSP_YN1] = val; + + Address += 2; + break; + + default: + val = (g_dspInitialize.pARAM_Read_U8(Address) << 8) | g_dspInitialize.pARAM_Read_U8(Address + 1); + Address += 2; + ErrorLog("Unknown DSP Format %i", gdsp_ifx_regs[DSP_FORMAT]); + break; + } + + // check for loop + if (Address > EndAddress) + { + Address = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL]; + gdsp_generate_exception(3); + gdsp_generate_exception(5); + + // Somehow, YN1 and YN2 must be initialized with their "loop" values, so yeah, + // it seems likely that we should raise an exception to let the DSP program do that, + // at least if DSP_FORMAT == 0x0A. + } + + gdsp_ifx_regs[DSP_ACCAH] = Address >> 16; + gdsp_ifx_regs[DSP_ACCAL] = Address & 0xffff; + return(val); +} diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_ext_op.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_ext_op.cpp index 7b3fdb4215..51aee169ba 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_ext_op.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_ext_op.cpp @@ -1,284 +1,284 @@ -/*==================================================================== - - filename: opcodes.h - project: GameCube DSP Tool (gcdsp) - created: 2005.03.04 - mail: duddie@walla.com - - Copyright (c) 2005 Duddie - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - ====================================================================*/ -// -// -// At the moment just ls and sl are using the prolog -// perhaps all actions on r03 must be in the prolog -// -#include "Globals.h" - -#include "gdsp_opcodes_helper.h" - - -// -void dsp_op_ext_r_epi(uint16 _Opcode) -{ - uint8 op = (_Opcode >> 2) & 0x3; - uint8 reg = _Opcode & 0x3; - - switch (op) - { - case 0x00: - ErrorLog("dsp_op_ext_r_epi"); - break; - - case 0x01: - g_dsp.r[reg]--; - break; - - case 0x02: - g_dsp.r[reg]++; - break; - - case 0x03: - g_dsp.r[reg] += g_dsp.r[reg + 4]; - break; - } -} - - -void dsp_op_ext_mv(uint16 _Opcode) -{ - uint8 sreg = _Opcode & 0x3; - uint8 dreg = ((_Opcode >> 2) & 0x3); - - g_dsp.r[dreg + 0x18] = g_dsp.r[sreg + 0x1c]; -} - - -void dsp_op_ext_s(uint16 _Opcode) -{ - uint8 dreg = _Opcode & 0x3; - uint8 sreg = ((_Opcode >> 3) & 0x3) + 0x1c; - - dsp_dmem_write(g_dsp.r[dreg], g_dsp.r[sreg]); - - if (_Opcode & 0x04) - { - g_dsp.r[dreg] += g_dsp.r[dreg + 4]; - } - else - { - g_dsp.r[dreg]++; - } -} - - -void dsp_op_ext_l(uint16 _Opcode) -{ - uint8 sreg = _Opcode & 0x3; - uint8 dreg = ((_Opcode >> 3) & 0x7) + 0x18; - - uint16 val = dsp_dmem_read(g_dsp.r[sreg]); - g_dsp.r[dreg] = val; - - if (_Opcode & 0x04) - { - g_dsp.r[sreg] += g_dsp.r[sreg + 4]; - } - else - { - g_dsp.r[sreg]++; - } -} - - -void dsp_op_ext_ls_pro(uint16 _Opcode) -{ - uint8 areg = (_Opcode & 0x1) + 0x1e; - dsp_dmem_write(g_dsp.r[0x03], g_dsp.r[areg]); - - if (_Opcode & 0x8) - { - g_dsp.r[0x03] += g_dsp.r[0x07]; - } - else - { - g_dsp.r[0x03]++; - } -} - - -void dsp_op_ext_ls_epi(uint16 _Opcode) -{ - uint8 dreg = ((_Opcode >> 4) & 0x3) + 0x18; - uint16 val = dsp_dmem_read(g_dsp.r[0x00]); - dsp_op_write_reg(dreg, val); - - if (_Opcode & 0x4) - { - g_dsp.r[0x00] += g_dsp.r[0x04]; - } - else - { - g_dsp.r[0x00]++; - } -} - - -void dsp_op_ext_sl_pro(uint16 _Opcode) -{ - uint8 areg = (_Opcode & 0x1) + 0x1e; - dsp_dmem_write(g_dsp.r[0x00], g_dsp.r[areg]); - - if (_Opcode & 0x4) - { - g_dsp.r[0x00] += g_dsp.r[0x04]; - } - else - { - g_dsp.r[0x00]++; - } -} - - -void dsp_op_ext_sl_epi(uint16 _Opcode) -{ - uint8 dreg = ((_Opcode >> 4) & 0x3) + 0x18; - uint16 val = dsp_dmem_read(g_dsp.r[0x03]); - dsp_op_write_reg(dreg, val); - - if (_Opcode & 0x8) - { - g_dsp.r[0x03] += g_dsp.r[0x07]; - } - else - { - g_dsp.r[0x03]++; - } -} - - -void dsp_op_ext_ld(uint16 _Opcode) -{ - uint8 dreg1 = (((_Opcode >> 5) & 0x1) << 1) + 0x18; - uint8 dreg2 = (((_Opcode >> 4) & 0x1) << 1) + 0x19; - uint8 sreg = _Opcode & 0x3; - g_dsp.r[dreg1] = dsp_dmem_read(g_dsp.r[sreg]); - g_dsp.r[dreg2] = dsp_dmem_read(g_dsp.r[0x03]); - - if (_Opcode & 0x04) - { - g_dsp.r[sreg] += g_dsp.r[sreg + 0x04]; - } - else - { - g_dsp.r[sreg]++; - } - - if (_Opcode & 0x08) - { - g_dsp.r[0x03] += g_dsp.r[0x07]; - } - else - { - g_dsp.r[0x03]++; - } -} - - -// ================================================================================ -// -// -// -// ================================================================================ - -void dsp_op_ext_ops_pro(uint16 _Opcode) -{ - if ((_Opcode & 0xFF) == 0){return;} - - switch ((_Opcode >> 4) & 0xf) - { - case 0x00: - dsp_op_ext_r_epi(_Opcode); - break; - - case 0x01: - dsp_op_ext_mv(_Opcode); - break; - - case 0x02: - case 0x03: - dsp_op_ext_s(_Opcode); - break; - - case 0x04: - case 0x05: - case 0x06: - case 0x07: - dsp_op_ext_l(_Opcode); - break; - - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - - if (_Opcode & 0x2) - { - dsp_op_ext_sl_pro(_Opcode); - } - else - { - dsp_op_ext_ls_pro(_Opcode); - } - - return; - - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - dsp_op_ext_ld(_Opcode); - break; - } -} - - -void dsp_op_ext_ops_epi(uint16 _Opcode) -{ - if ((_Opcode & 0xFF) == 0){return;} - - switch ((_Opcode >> 4) & 0xf) - { - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - - if (_Opcode & 0x2) - { - dsp_op_ext_sl_epi(_Opcode); - } - else - { - dsp_op_ext_ls_epi(_Opcode); - } - - return; - } -} - - +/*==================================================================== + + filename: opcodes.h + project: GameCube DSP Tool (gcdsp) + created: 2005.03.04 + mail: duddie@walla.com + + Copyright (c) 2005 Duddie + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + ====================================================================*/ +// +// +// At the moment just ls and sl are using the prolog +// perhaps all actions on r03 must be in the prolog +// +#include "Globals.h" + +#include "gdsp_opcodes_helper.h" + + +// +void dsp_op_ext_r_epi(uint16 _Opcode) +{ + uint8 op = (_Opcode >> 2) & 0x3; + uint8 reg = _Opcode & 0x3; + + switch (op) + { + case 0x00: + ErrorLog("dsp_op_ext_r_epi"); + break; + + case 0x01: + g_dsp.r[reg]--; + break; + + case 0x02: + g_dsp.r[reg]++; + break; + + case 0x03: + g_dsp.r[reg] += g_dsp.r[reg + 4]; + break; + } +} + + +void dsp_op_ext_mv(uint16 _Opcode) +{ + uint8 sreg = _Opcode & 0x3; + uint8 dreg = ((_Opcode >> 2) & 0x3); + + g_dsp.r[dreg + 0x18] = g_dsp.r[sreg + 0x1c]; +} + + +void dsp_op_ext_s(uint16 _Opcode) +{ + uint8 dreg = _Opcode & 0x3; + uint8 sreg = ((_Opcode >> 3) & 0x3) + 0x1c; + + dsp_dmem_write(g_dsp.r[dreg], g_dsp.r[sreg]); + + if (_Opcode & 0x04) + { + g_dsp.r[dreg] += g_dsp.r[dreg + 4]; + } + else + { + g_dsp.r[dreg]++; + } +} + + +void dsp_op_ext_l(uint16 _Opcode) +{ + uint8 sreg = _Opcode & 0x3; + uint8 dreg = ((_Opcode >> 3) & 0x7) + 0x18; + + uint16 val = dsp_dmem_read(g_dsp.r[sreg]); + g_dsp.r[dreg] = val; + + if (_Opcode & 0x04) + { + g_dsp.r[sreg] += g_dsp.r[sreg + 4]; + } + else + { + g_dsp.r[sreg]++; + } +} + + +void dsp_op_ext_ls_pro(uint16 _Opcode) +{ + uint8 areg = (_Opcode & 0x1) + 0x1e; + dsp_dmem_write(g_dsp.r[0x03], g_dsp.r[areg]); + + if (_Opcode & 0x8) + { + g_dsp.r[0x03] += g_dsp.r[0x07]; + } + else + { + g_dsp.r[0x03]++; + } +} + + +void dsp_op_ext_ls_epi(uint16 _Opcode) +{ + uint8 dreg = ((_Opcode >> 4) & 0x3) + 0x18; + uint16 val = dsp_dmem_read(g_dsp.r[0x00]); + dsp_op_write_reg(dreg, val); + + if (_Opcode & 0x4) + { + g_dsp.r[0x00] += g_dsp.r[0x04]; + } + else + { + g_dsp.r[0x00]++; + } +} + + +void dsp_op_ext_sl_pro(uint16 _Opcode) +{ + uint8 areg = (_Opcode & 0x1) + 0x1e; + dsp_dmem_write(g_dsp.r[0x00], g_dsp.r[areg]); + + if (_Opcode & 0x4) + { + g_dsp.r[0x00] += g_dsp.r[0x04]; + } + else + { + g_dsp.r[0x00]++; + } +} + + +void dsp_op_ext_sl_epi(uint16 _Opcode) +{ + uint8 dreg = ((_Opcode >> 4) & 0x3) + 0x18; + uint16 val = dsp_dmem_read(g_dsp.r[0x03]); + dsp_op_write_reg(dreg, val); + + if (_Opcode & 0x8) + { + g_dsp.r[0x03] += g_dsp.r[0x07]; + } + else + { + g_dsp.r[0x03]++; + } +} + + +void dsp_op_ext_ld(uint16 _Opcode) +{ + uint8 dreg1 = (((_Opcode >> 5) & 0x1) << 1) + 0x18; + uint8 dreg2 = (((_Opcode >> 4) & 0x1) << 1) + 0x19; + uint8 sreg = _Opcode & 0x3; + g_dsp.r[dreg1] = dsp_dmem_read(g_dsp.r[sreg]); + g_dsp.r[dreg2] = dsp_dmem_read(g_dsp.r[0x03]); + + if (_Opcode & 0x04) + { + g_dsp.r[sreg] += g_dsp.r[sreg + 0x04]; + } + else + { + g_dsp.r[sreg]++; + } + + if (_Opcode & 0x08) + { + g_dsp.r[0x03] += g_dsp.r[0x07]; + } + else + { + g_dsp.r[0x03]++; + } +} + + +// ================================================================================ +// +// +// +// ================================================================================ + +void dsp_op_ext_ops_pro(uint16 _Opcode) +{ + if ((_Opcode & 0xFF) == 0){return;} + + switch ((_Opcode >> 4) & 0xf) + { + case 0x00: + dsp_op_ext_r_epi(_Opcode); + break; + + case 0x01: + dsp_op_ext_mv(_Opcode); + break; + + case 0x02: + case 0x03: + dsp_op_ext_s(_Opcode); + break; + + case 0x04: + case 0x05: + case 0x06: + case 0x07: + dsp_op_ext_l(_Opcode); + break; + + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + + if (_Opcode & 0x2) + { + dsp_op_ext_sl_pro(_Opcode); + } + else + { + dsp_op_ext_ls_pro(_Opcode); + } + + return; + + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + dsp_op_ext_ld(_Opcode); + break; + } +} + + +void dsp_op_ext_ops_epi(uint16 _Opcode) +{ + if ((_Opcode & 0xFF) == 0){return;} + + switch ((_Opcode >> 4) & 0xf) + { + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + + if (_Opcode & 0x2) + { + dsp_op_ext_sl_epi(_Opcode); + } + else + { + dsp_op_ext_ls_epi(_Opcode); + } + + return; + } +} + + diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interface.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interface.cpp index e77ae4da20..f19c84ad31 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interface.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interface.cpp @@ -1,357 +1,357 @@ -/*==================================================================== - - filename: gdsp_interface.h - project: GCemu - created: 2004-6-18 - mail: duddie@walla.com - - Copyright (c) 2005 Duddie & Tratax - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - ====================================================================*/ - -#include -#include "Globals.h" -#include "Thread.h" - -#include "gdsp_aram.h" -#include "gdsp_interpreter.h" -#include "gdsp_interface.h" - -#include "Tools.h" - -#ifndef NULL -#define NULL 0 -#endif - -#ifndef _WIN32 -#undef WITH_DSP_ON_THREAD -//TODO FIX -#endif - -const char* reg_names[] = -{ - // a0 - "COEF_A1_0", "COEF_A2_0", "COEF_A1_1", "COEF_A2_1", "COEF_A1_2", "COEF_A2_2", "COEF_A1_3", "COEF_A2_3", - "COEF_A1_4", "COEF_A2_4", "COEF_A1_5", "COEF_A2_5", "COEF_A1_6", "COEF_A2_6", "COEF_A1_7", "COEF_A2_7", - // b0 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - // c0 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, "DSCR", NULL, "DSBL", NULL, "DSPA", "DSMAH", "DSMAL", - // d0 - NULL, "SampleFormat", NULL, NULL, "ACSAH", "ACSAL", "ACEAH", "ACEAL", - "ACCAH", "ACCAL", "PRED_SCALE", "YN1", "YN2", "ARAM", "GAIN", NULL, - // e0 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, "AMDM", - // f0 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, "DMBH", "DMBL", "CMBH", "CMBL", -}; - - -void gdsp_dma(); - -#ifdef WITH_DSP_ON_THREAD -Common::CriticalSection g_CriticalSection; -#endif - -static volatile uint16 gdsp_mbox[2][2]; - -uint16 gdsp_ifx_regs[256]; - -void gdsp_ifx_init() -{ - int i; - - for (i = 0; i < 256; i++) - { - gdsp_ifx_regs[i] = 0; - } - - gdsp_mbox[0][0] = 0; - gdsp_mbox[0][1] = 0; - gdsp_mbox[1][0] = 0; - gdsp_mbox[1][1] = 0; -} - - -uint32 gdsp_mbox_peek(uint8 mbx) -{ -#if WITH_DSP_ON_THREAD - g_CriticalSection.Enter(); -#endif - uint32 value = ((gdsp_mbox[mbx][0] << 16) | gdsp_mbox[mbx][1]); -#if WITH_DSP_ON_THREAD - g_CriticalSection.Leave(); -#endif - return value; -} - - -void gdsp_mbox_write_h(uint8 mbx, uint16 val) -{ -#if WITH_DSP_ON_THREAD - g_CriticalSection.Enter(); -#endif - - gdsp_mbox[mbx][0] = val & 0x7fff; - -#if WITH_DSP_ON_THREAD - g_CriticalSection.Leave(); -#endif -} - - -void gdsp_mbox_write_l(uint8 mbx, uint16 val) -{ -#if WITH_DSP_ON_THREAD - g_CriticalSection.Enter(); -#endif - - gdsp_mbox[mbx][1] = val; - gdsp_mbox[mbx][0] |= 0x8000; - -#if WITH_DSP_ON_THREAD - g_CriticalSection.Leave(); -#endif - - if (mbx == GDSP_MBOX_DSP) - { - DebugLog("- Write DSP Mail: 0x%08x (pc=0x%04x)\n", gdsp_mbox_peek(GDSP_MBOX_DSP), g_dsp.err_pc); - } -} - - -uint16 gdsp_mbox_read_h(uint8 mbx) -{ - return (gdsp_mbox[mbx][0]); -} - - -uint16 gdsp_mbox_read_l(uint8 mbx) -{ - uint16 val; -#if WITH_DSP_ON_THREAD - g_CriticalSection.Enter(); -#endif - - val = gdsp_mbox[mbx][1]; - gdsp_mbox[mbx][0] &= ~0x8000; - -#if WITH_DSP_ON_THREAD - g_CriticalSection.Leave(); -#endif - return(val); -} - - -void gdsp_ifx_write(uint16 addr, uint16 val) -{ - addr &= 0xff; - - switch (addr & 0xff) - { - case 0xfb: // DIRQ - - if (val & 0x1) - { - g_dsp.irq_request(); - } - - break; - - case 0xfc: // DMBH - gdsp_mbox_write_h(GDSP_MBOX_DSP, val); - break; - - case 0xfd: // DMBL - gdsp_mbox_write_l(GDSP_MBOX_DSP, val); - break; - - case 0xcb: // DSBL - gdsp_ifx_regs[addr] = val; - gdsp_dma(); - gdsp_ifx_regs[DSP_DSCR] &= ~0x0004; - break; - - case 0xcd: - case 0xce: - case 0xcf: - case 0xc9: - gdsp_ifx_regs[addr] = val; - break; - - default: -/* if ((addr & 0xff) >= 0xa0 && reg_names[addr - 0xa0]) - DebugLog("%04x MW %s (%04x)\n", g_dsp.pc, reg_names[addr - 0xa0], val); - else - DebugLog("%04x MW %04x (%04x)\n", g_dsp.pc, addr, val);*/ - gdsp_ifx_regs[addr] = val; - break; - } -} - - -uint16 gdsp_ifx_read(uint16 addr) -{ - uint16 val; - - addr &= 0xff; - - switch (addr & 0xff) - { - case 0xfc: // DMBH - val = gdsp_mbox_read_h(GDSP_MBOX_DSP); - break; - - case 0xfe: // CMBH - val = gdsp_mbox_read_h(GDSP_MBOX_CPU); - break; - - case 0xff: // CMBL - val = gdsp_mbox_read_l(GDSP_MBOX_CPU); - break; - - case 0xc9: - val = gdsp_ifx_regs[addr]; - break; - - case 0xdd: - val = dsp_read_aram(); - break; - - default: - val = gdsp_ifx_regs[addr]; -/* if ((addr & 0xff) >= 0xc0 && reg_names[addr & 0x3f]) - printf("%04x MR %s (%04x)\n", g_dsp.pc, reg_names[addr & 0x3f], val); - else - printf("%04x MR %04x (%04x)\n", g_dsp.pc, addr, val);*/ - break; - } - - return(val); -} - - -void gdsp_idma_in(uint16 dsp_addr, uint32 addr, uint32 size) -{ - uint8* dst = ((uint8*)g_dsp.iram); - - for (uint32 i = 0; i < size; i += 2) - { - *(uint16*)&dst[dsp_addr + i] = *(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x0fffffff]; - } - - g_dsp.iram_crc = GenerateCRC(g_dsp.cpu_ram + (addr & 0x0fffffff), size); - DebugLog("*** Copy new UCode from 0x%08x to 0x%04x (crc: %8x)\n", addr, dsp_addr, g_dsp.iram_crc); - -#if DUMP_DSP_IMEM - DumpDSPCode(addr, size, g_dsp.iram_crc ); -#endif -} - - -void gdsp_idma_out(uint16 dsp_addr, uint32 addr, uint32 size) -{ - ErrorLog("*** idma_out IRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)\n", dsp_addr / 2, addr, size); -} - - -void gdsp_ddma_in(uint16 dsp_addr, uint32 addr, uint32 size) -{ - if ((addr & 0x7FFFFFFF) > 0x01FFFFFF) - { - ErrorLog("*** ddma_in read from invalid addr (0x%08x)\n", addr); - return; - } - - uint8* dst = ((uint8*)g_dsp.dram); - - for (uint32 i = 0; i < size; i += 2) - { - *(uint16*)&dst[dsp_addr + i] = *(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF]; - } - - DebugLog("*** ddma_in RAM (0x%08x) -> DRAM_DSP (0x%04x) : size (0x%08x)\n", addr, dsp_addr / 2, size); -} - - -void gdsp_ddma_out(uint16 dsp_addr, uint32 addr, uint32 size) -{ - if ((addr & 0x7FFFFFFF) > 0x01FFFFFF) - { - ErrorLog("*** gdsp_ddma_out to invalid addr (0x%08x)\n", addr); - return; - } - - uint8* src = ((uint8*)g_dsp.dram); - - for (uint32 i = 0; i < size; i += 2) - { - *(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF] = *(uint16*)&src[dsp_addr + i]; - } - - DebugLog("*** ddma_out DRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)\n", dsp_addr / 2, addr, size); -} - - -#define DSP_CR_IMEM (2) -#define DSP_CR_DMEM (0) -#define DSP_CR_TO_CPU (1) -#define DSP_CR_FROM_CPU (0) - -void gdsp_dma() -{ - uint16 ctl; - uint32 addr; - uint16 dsp_addr; - uint16 len; - - addr = (gdsp_ifx_regs[DSP_DSMAH] << 16) | gdsp_ifx_regs[DSP_DSMAL]; - ctl = gdsp_ifx_regs[DSP_DSCR]; - dsp_addr = gdsp_ifx_regs[DSP_DSPA] * 2; - len = gdsp_ifx_regs[DSP_DSBL]; - - if ((ctl > 3) || (len > 0x4000)) - { - ErrorLog("DMA ERROR pc: %04x ctl: %04x addr: %08x da: %04x size: %04x\n", g_dsp.pc, ctl, addr, dsp_addr, len); - exit(0); - } - - switch (ctl & 0x3) - { - case (DSP_CR_DMEM | DSP_CR_TO_CPU): - gdsp_ddma_out(dsp_addr, addr, len); - break; - - case (DSP_CR_DMEM | DSP_CR_FROM_CPU): - gdsp_ddma_in(dsp_addr, addr, len); - break; - - case (DSP_CR_IMEM | DSP_CR_TO_CPU): - gdsp_idma_out(dsp_addr, addr, len); - break; - - case (DSP_CR_IMEM | DSP_CR_FROM_CPU): - gdsp_idma_in(dsp_addr, addr, len); - break; - } -} - - +/*==================================================================== + + filename: gdsp_interface.h + project: GCemu + created: 2004-6-18 + mail: duddie@walla.com + + Copyright (c) 2005 Duddie & Tratax + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + ====================================================================*/ + +#include +#include "Globals.h" +#include "Thread.h" + +#include "gdsp_aram.h" +#include "gdsp_interpreter.h" +#include "gdsp_interface.h" + +#include "Tools.h" + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef _WIN32 +#undef WITH_DSP_ON_THREAD +//TODO FIX +#endif + +const char* reg_names[] = +{ + // a0 + "COEF_A1_0", "COEF_A2_0", "COEF_A1_1", "COEF_A2_1", "COEF_A1_2", "COEF_A2_2", "COEF_A1_3", "COEF_A2_3", + "COEF_A1_4", "COEF_A2_4", "COEF_A1_5", "COEF_A2_5", "COEF_A1_6", "COEF_A2_6", "COEF_A1_7", "COEF_A2_7", + // b0 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // c0 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, "DSCR", NULL, "DSBL", NULL, "DSPA", "DSMAH", "DSMAL", + // d0 + NULL, "SampleFormat", NULL, NULL, "ACSAH", "ACSAL", "ACEAH", "ACEAL", + "ACCAH", "ACCAL", "PRED_SCALE", "YN1", "YN2", "ARAM", "GAIN", NULL, + // e0 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, "AMDM", + // f0 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "DMBH", "DMBL", "CMBH", "CMBL", +}; + + +void gdsp_dma(); + +#ifdef WITH_DSP_ON_THREAD +Common::CriticalSection g_CriticalSection; +#endif + +static volatile uint16 gdsp_mbox[2][2]; + +uint16 gdsp_ifx_regs[256]; + +void gdsp_ifx_init() +{ + int i; + + for (i = 0; i < 256; i++) + { + gdsp_ifx_regs[i] = 0; + } + + gdsp_mbox[0][0] = 0; + gdsp_mbox[0][1] = 0; + gdsp_mbox[1][0] = 0; + gdsp_mbox[1][1] = 0; +} + + +uint32 gdsp_mbox_peek(uint8 mbx) +{ +#if WITH_DSP_ON_THREAD + g_CriticalSection.Enter(); +#endif + uint32 value = ((gdsp_mbox[mbx][0] << 16) | gdsp_mbox[mbx][1]); +#if WITH_DSP_ON_THREAD + g_CriticalSection.Leave(); +#endif + return value; +} + + +void gdsp_mbox_write_h(uint8 mbx, uint16 val) +{ +#if WITH_DSP_ON_THREAD + g_CriticalSection.Enter(); +#endif + + gdsp_mbox[mbx][0] = val & 0x7fff; + +#if WITH_DSP_ON_THREAD + g_CriticalSection.Leave(); +#endif +} + + +void gdsp_mbox_write_l(uint8 mbx, uint16 val) +{ +#if WITH_DSP_ON_THREAD + g_CriticalSection.Enter(); +#endif + + gdsp_mbox[mbx][1] = val; + gdsp_mbox[mbx][0] |= 0x8000; + +#if WITH_DSP_ON_THREAD + g_CriticalSection.Leave(); +#endif + + if (mbx == GDSP_MBOX_DSP) + { + DebugLog("- Write DSP Mail: 0x%08x (pc=0x%04x)\n", gdsp_mbox_peek(GDSP_MBOX_DSP), g_dsp.err_pc); + } +} + + +uint16 gdsp_mbox_read_h(uint8 mbx) +{ + return (gdsp_mbox[mbx][0]); +} + + +uint16 gdsp_mbox_read_l(uint8 mbx) +{ + uint16 val; +#if WITH_DSP_ON_THREAD + g_CriticalSection.Enter(); +#endif + + val = gdsp_mbox[mbx][1]; + gdsp_mbox[mbx][0] &= ~0x8000; + +#if WITH_DSP_ON_THREAD + g_CriticalSection.Leave(); +#endif + return(val); +} + + +void gdsp_ifx_write(uint16 addr, uint16 val) +{ + addr &= 0xff; + + switch (addr & 0xff) + { + case 0xfb: // DIRQ + + if (val & 0x1) + { + g_dsp.irq_request(); + } + + break; + + case 0xfc: // DMBH + gdsp_mbox_write_h(GDSP_MBOX_DSP, val); + break; + + case 0xfd: // DMBL + gdsp_mbox_write_l(GDSP_MBOX_DSP, val); + break; + + case 0xcb: // DSBL + gdsp_ifx_regs[addr] = val; + gdsp_dma(); + gdsp_ifx_regs[DSP_DSCR] &= ~0x0004; + break; + + case 0xcd: + case 0xce: + case 0xcf: + case 0xc9: + gdsp_ifx_regs[addr] = val; + break; + + default: +/* if ((addr & 0xff) >= 0xa0 && reg_names[addr - 0xa0]) + DebugLog("%04x MW %s (%04x)\n", g_dsp.pc, reg_names[addr - 0xa0], val); + else + DebugLog("%04x MW %04x (%04x)\n", g_dsp.pc, addr, val);*/ + gdsp_ifx_regs[addr] = val; + break; + } +} + + +uint16 gdsp_ifx_read(uint16 addr) +{ + uint16 val; + + addr &= 0xff; + + switch (addr & 0xff) + { + case 0xfc: // DMBH + val = gdsp_mbox_read_h(GDSP_MBOX_DSP); + break; + + case 0xfe: // CMBH + val = gdsp_mbox_read_h(GDSP_MBOX_CPU); + break; + + case 0xff: // CMBL + val = gdsp_mbox_read_l(GDSP_MBOX_CPU); + break; + + case 0xc9: + val = gdsp_ifx_regs[addr]; + break; + + case 0xdd: + val = dsp_read_aram(); + break; + + default: + val = gdsp_ifx_regs[addr]; +/* if ((addr & 0xff) >= 0xc0 && reg_names[addr & 0x3f]) + printf("%04x MR %s (%04x)\n", g_dsp.pc, reg_names[addr & 0x3f], val); + else + printf("%04x MR %04x (%04x)\n", g_dsp.pc, addr, val);*/ + break; + } + + return(val); +} + + +void gdsp_idma_in(uint16 dsp_addr, uint32 addr, uint32 size) +{ + uint8* dst = ((uint8*)g_dsp.iram); + + for (uint32 i = 0; i < size; i += 2) + { + *(uint16*)&dst[dsp_addr + i] = *(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x0fffffff]; + } + + g_dsp.iram_crc = GenerateCRC(g_dsp.cpu_ram + (addr & 0x0fffffff), size); + DebugLog("*** Copy new UCode from 0x%08x to 0x%04x (crc: %8x)\n", addr, dsp_addr, g_dsp.iram_crc); + +#if DUMP_DSP_IMEM + DumpDSPCode(addr, size, g_dsp.iram_crc ); +#endif +} + + +void gdsp_idma_out(uint16 dsp_addr, uint32 addr, uint32 size) +{ + ErrorLog("*** idma_out IRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)\n", dsp_addr / 2, addr, size); +} + + +void gdsp_ddma_in(uint16 dsp_addr, uint32 addr, uint32 size) +{ + if ((addr & 0x7FFFFFFF) > 0x01FFFFFF) + { + ErrorLog("*** ddma_in read from invalid addr (0x%08x)\n", addr); + return; + } + + uint8* dst = ((uint8*)g_dsp.dram); + + for (uint32 i = 0; i < size; i += 2) + { + *(uint16*)&dst[dsp_addr + i] = *(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF]; + } + + DebugLog("*** ddma_in RAM (0x%08x) -> DRAM_DSP (0x%04x) : size (0x%08x)\n", addr, dsp_addr / 2, size); +} + + +void gdsp_ddma_out(uint16 dsp_addr, uint32 addr, uint32 size) +{ + if ((addr & 0x7FFFFFFF) > 0x01FFFFFF) + { + ErrorLog("*** gdsp_ddma_out to invalid addr (0x%08x)\n", addr); + return; + } + + uint8* src = ((uint8*)g_dsp.dram); + + for (uint32 i = 0; i < size; i += 2) + { + *(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF] = *(uint16*)&src[dsp_addr + i]; + } + + DebugLog("*** ddma_out DRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)\n", dsp_addr / 2, addr, size); +} + + +#define DSP_CR_IMEM (2) +#define DSP_CR_DMEM (0) +#define DSP_CR_TO_CPU (1) +#define DSP_CR_FROM_CPU (0) + +void gdsp_dma() +{ + uint16 ctl; + uint32 addr; + uint16 dsp_addr; + uint16 len; + + addr = (gdsp_ifx_regs[DSP_DSMAH] << 16) | gdsp_ifx_regs[DSP_DSMAL]; + ctl = gdsp_ifx_regs[DSP_DSCR]; + dsp_addr = gdsp_ifx_regs[DSP_DSPA] * 2; + len = gdsp_ifx_regs[DSP_DSBL]; + + if ((ctl > 3) || (len > 0x4000)) + { + ErrorLog("DMA ERROR pc: %04x ctl: %04x addr: %08x da: %04x size: %04x\n", g_dsp.pc, ctl, addr, dsp_addr, len); + exit(0); + } + + switch (ctl & 0x3) + { + case (DSP_CR_DMEM | DSP_CR_TO_CPU): + gdsp_ddma_out(dsp_addr, addr, len); + break; + + case (DSP_CR_DMEM | DSP_CR_FROM_CPU): + gdsp_ddma_in(dsp_addr, addr, len); + break; + + case (DSP_CR_IMEM | DSP_CR_TO_CPU): + gdsp_idma_out(dsp_addr, addr, len); + break; + + case (DSP_CR_IMEM | DSP_CR_FROM_CPU): + gdsp_idma_in(dsp_addr, addr, len); + break; + } +} + + diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.cpp index 110409689f..a20a279d8f 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interpreter.cpp @@ -1,444 +1,444 @@ -/*==================================================================== - - filename: gdsp_interpreter.cpp - project: GCemu - created: 2004-6-18 - mail: duddie@walla.com - - Copyright (c) 2005 Duddie & Tratax - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - ====================================================================*/ - -#include -#include - -#include "gdsp_interface.h" -#include "gdsp_opcodes_helper.h" -#include "Tools.h" - -//------------------------------------------------------------------------------- - -SDSP g_dsp; - -uint16 SDSP::r[32]; -uint16 SDSP::pc = 0; -uint16 SDSP::err_pc = 0; -uint16* SDSP::iram = 0; -uint16* SDSP::dram = 0; -uint16* SDSP::irom = 0; -uint16* SDSP::drom = 0; -uint16* SDSP::coef = 0; -uint8* SDSP::cpu_ram = 0; -uint16 SDSP::cr = 0; -uint8 SDSP::reg_stack_ptr[4]; -// lets make stack depth to 32 for now -uint16 SDSP::reg_stack[4][DSP_STACK_DEPTH]; -void (*SDSP::irq_request)() = NULL; -bool SDSP::exception_in_progress_hack = false; - -// for debugger only -uint32 SDSP::iram_crc = 0; -uint64 SDSP::step_counter = 0; - - -//------------------------------------------------------------------------------- - -static bool CR_HALT = true; -static bool CR_EXTERNAL_INT = false; - -void UpdateCachedCR() -{ - CR_HALT = (g_dsp.cr & 0x4) != 0; - CR_EXTERNAL_INT = (g_dsp.cr & 0x02) != 0; -} - - - -//------------------------------------------------------------------------------- -void (*dsp_op[])(uint16 opc) = -{ - dsp_op0, dsp_op1, dsp_op2, dsp_op3, - dsp_op4, dsp_op5, dsp_op6, dsp_op7, - dsp_op8, dsp_op9, dsp_opab, dsp_opab, - dsp_opcd, dsp_opcd, dsp_ope, dsp_opf, -}; - -void dbg_error(char* err_msg) -{ - return; -} - - -void gdsp_init() -{ - g_dsp.irom = (uint16*)malloc(DSP_IROM_SIZE * sizeof(uint16)); - g_dsp.iram = (uint16*)malloc(DSP_IRAM_SIZE * sizeof(uint16)); - g_dsp.drom = (uint16*)malloc(DSP_DROM_SIZE * sizeof(uint16)); - g_dsp.dram = (uint16*)malloc(DSP_DRAM_SIZE * sizeof(uint16)); - g_dsp.coef = (uint16*)malloc(DSP_COEF_SIZE * sizeof(uint16)); - - for (int i = 0; i < DSP_IRAM_SIZE; i++) - { - g_dsp.iram[i] = 0x0021; // HALT opcode - } - - for (int i = 0; i < DSP_DRAM_SIZE; i++) - { - g_dsp.dram[i] = 0x0021; // HALT opcode - } - - for (int i = 0; i < 32; i++) - { - g_dsp.r[i] = 0; - } - - for (int i = 0; i < 4; i++) - { - g_dsp.reg_stack_ptr[i] = 0; - - for (int j = 0; j < DSP_STACK_DEPTH; j++) - { - g_dsp.reg_stack[i][j] = 0; - } - } - - // copied from a real console after the custom UCode has been loaded - g_dsp.r[0x08] = 0xffff; - g_dsp.r[0x09] = 0xffff; - g_dsp.r[0x0a] = 0xffff; - g_dsp.r[0x0b] = 0xffff; - - g_dsp.cr = 0x804; - gdsp_ifx_init(); - - UpdateCachedCR(); -} - - -void gdsp_reset() -{ -// _assert_msg_(0, "gdsp_reset()"); - _assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception"); - g_dsp.pc = DSP_RESET_VECTOR; - g_dsp.exception_in_progress_hack = false; -} - - -uint8 gdsp_exceptions = 0; -void gdsp_generate_exception(uint8 level) -{ - gdsp_exceptions |= 1 << level; -} - - -bool gdsp_load_rom(char* fname) -{ - FILE* pFile = fopen(fname, "rb"); - - if (pFile) - { - fread(g_dsp.irom, 1, DSP_IRAM_SIZE, pFile); - fclose(pFile); - return(true); - } - - return(false); -} - - -bool gdsp_load_coef(char* fname) -{ - FILE* pFile = fopen(fname, "rb"); - - if (pFile) - { - fread(g_dsp.coef, 1, DSP_COEF_SIZE, pFile); - fclose(pFile); - return(true); - } - - return(false); -} - - -void gdsp_write_cr(uint16 val) -{ - // reset - if (val & 0x0001) - { - gdsp_reset(); - } - - val &= ~0x0001; - - // update cr - g_dsp.cr = val; - - UpdateCachedCR(); -} - - -uint16 gdsp_read_cr() -{ - if (g_dsp.pc & 0x8000) - { - g_dsp.cr |= 0x800; - } - else - { - g_dsp.cr &= ~0x800; - } - - UpdateCachedCR(); - - return(g_dsp.cr); -} - - -// special loop step.. because exception in loop or loopi fails -// dunno how we have to fix it -// atm we execute this instructions directly inside the loop command -// so it cant be interrupted by an exception -void gdsp_loop_step() -{ - g_dsp.err_pc = g_dsp.pc; - uint16 opc = dsp_fetch_code(); - dsp_op[opc >> 12](opc); -} - -u16 HLE_ROM_80E7_81F8(); -void hacks(); -void gdsp_step() -{ - g_dsp.step_counter++; - - if (g_dsp.pc == 0x80e7) - { - //g_dsp.pc = HLE_ROM_80E7_81F8(); - } - - g_dsp.err_pc = g_dsp.pc; - -#if PROFILE - ProfilerAddDelta(g_dsp.err_pc, 1); - if (g_dsp.step_counter == 1) - { - ProfilerInit(); - } - - if ((g_dsp.step_counter & 0xFFFFF) == 0) - { - ProfilerDump(g_dsp.step_counter); - } - -#endif - - uint16 opc = dsp_fetch_code(); - dsp_op[opc >> 12](opc); - - uint16& rLoopCounter = g_dsp.r[DSP_REG_ST0 + 3]; - - if (rLoopCounter > 0) - { - const uint16& rCallAddress = g_dsp.r[DSP_REG_ST0 + 0]; - const uint16& rLoopAddress = g_dsp.r[DSP_REG_ST0 + 2]; - - if (g_dsp.pc == (rLoopAddress + 1)) - { - rLoopCounter--; - - if (rLoopCounter > 0) - { - g_dsp.pc = rCallAddress; - } - else - { - // end of loop - dsp_reg_load_stack(0); - dsp_reg_load_stack(2); - dsp_reg_load_stack(3); - } - } - } - - // check if there is an external interrupt - if (CR_EXTERNAL_INT) - { - if (dsp_SR_is_flag_set(FLAG_ENABLE_INTERUPT) && (g_dsp.exception_in_progress_hack == false)) - { - // level 7 is the interrupt exception - gdsp_generate_exception(7); - g_dsp.cr &= ~0x0002; - UpdateCachedCR(); - } - } - - // check exceptions - if ((gdsp_exceptions > 0) && (!g_dsp.exception_in_progress_hack)) - { - for (uint8 i=0; i<8; i++) - { - if (gdsp_exceptions & (1< 1024*1024*1) - - /* if (g_dsp.pc == 0x165) - { - PanicAlert("Opcode_06"); - - } - if (g_dsp.pc == 0x43b) - { - PanicAlert("Opcode_14"); - - } - if (g_dsp.pc == 0xb37) - { - PanicAlert("Opcode_08"); - - }*/ - /* if (g_dsp.pc == 0x1bc) - { - r30 = g_dsp.r[30]; - r31 = g_dsp.r[31]; - } - else if (g_dsp.pc == 0x384) - { - // if ((r30 == 0x1bc) && (r31 == 0xaff)) - { - //PanicAlert("%x, %x", r30, r31); - - const int numSamples = 0x280; - static short Buffer[numSamples]; - - uint16 bufferAddr = 0x280; //dsp_dmem_read(0xe44); - for (int i=0; i 1024*1024*2) - { - //PanicAlert("%x", bufferAddr); - g_wave_writer.Stop(); - exit(1); - } - } - } */ - - if (g_dsp.pc == 0x468) - { - int numSamples = g_dsp.r[25] / 2; - uint16 bufferAddr = g_dsp.r[27]; - - // PanicAlert("%x %x", bufferAddr, numSamples); - - short samples[1024]; - for (int i=0; i 1024*1024*2) - { - //PanicAlert("%x", bufferAddr); - g_wave_writer.Stop(); - exit(1); - } - } -} +/*==================================================================== + + filename: gdsp_interpreter.cpp + project: GCemu + created: 2004-6-18 + mail: duddie@walla.com + + Copyright (c) 2005 Duddie & Tratax + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + ====================================================================*/ + +#include +#include + +#include "gdsp_interface.h" +#include "gdsp_opcodes_helper.h" +#include "Tools.h" + +//------------------------------------------------------------------------------- + +SDSP g_dsp; + +uint16 SDSP::r[32]; +uint16 SDSP::pc = 0; +uint16 SDSP::err_pc = 0; +uint16* SDSP::iram = 0; +uint16* SDSP::dram = 0; +uint16* SDSP::irom = 0; +uint16* SDSP::drom = 0; +uint16* SDSP::coef = 0; +uint8* SDSP::cpu_ram = 0; +uint16 SDSP::cr = 0; +uint8 SDSP::reg_stack_ptr[4]; +// lets make stack depth to 32 for now +uint16 SDSP::reg_stack[4][DSP_STACK_DEPTH]; +void (*SDSP::irq_request)() = NULL; +bool SDSP::exception_in_progress_hack = false; + +// for debugger only +uint32 SDSP::iram_crc = 0; +uint64 SDSP::step_counter = 0; + + +//------------------------------------------------------------------------------- + +static bool CR_HALT = true; +static bool CR_EXTERNAL_INT = false; + +void UpdateCachedCR() +{ + CR_HALT = (g_dsp.cr & 0x4) != 0; + CR_EXTERNAL_INT = (g_dsp.cr & 0x02) != 0; +} + + + +//------------------------------------------------------------------------------- +void (*dsp_op[])(uint16 opc) = +{ + dsp_op0, dsp_op1, dsp_op2, dsp_op3, + dsp_op4, dsp_op5, dsp_op6, dsp_op7, + dsp_op8, dsp_op9, dsp_opab, dsp_opab, + dsp_opcd, dsp_opcd, dsp_ope, dsp_opf, +}; + +void dbg_error(char* err_msg) +{ + return; +} + + +void gdsp_init() +{ + g_dsp.irom = (uint16*)malloc(DSP_IROM_SIZE * sizeof(uint16)); + g_dsp.iram = (uint16*)malloc(DSP_IRAM_SIZE * sizeof(uint16)); + g_dsp.drom = (uint16*)malloc(DSP_DROM_SIZE * sizeof(uint16)); + g_dsp.dram = (uint16*)malloc(DSP_DRAM_SIZE * sizeof(uint16)); + g_dsp.coef = (uint16*)malloc(DSP_COEF_SIZE * sizeof(uint16)); + + for (int i = 0; i < DSP_IRAM_SIZE; i++) + { + g_dsp.iram[i] = 0x0021; // HALT opcode + } + + for (int i = 0; i < DSP_DRAM_SIZE; i++) + { + g_dsp.dram[i] = 0x0021; // HALT opcode + } + + for (int i = 0; i < 32; i++) + { + g_dsp.r[i] = 0; + } + + for (int i = 0; i < 4; i++) + { + g_dsp.reg_stack_ptr[i] = 0; + + for (int j = 0; j < DSP_STACK_DEPTH; j++) + { + g_dsp.reg_stack[i][j] = 0; + } + } + + // copied from a real console after the custom UCode has been loaded + g_dsp.r[0x08] = 0xffff; + g_dsp.r[0x09] = 0xffff; + g_dsp.r[0x0a] = 0xffff; + g_dsp.r[0x0b] = 0xffff; + + g_dsp.cr = 0x804; + gdsp_ifx_init(); + + UpdateCachedCR(); +} + + +void gdsp_reset() +{ +// _assert_msg_(0, "gdsp_reset()"); + _assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception"); + g_dsp.pc = DSP_RESET_VECTOR; + g_dsp.exception_in_progress_hack = false; +} + + +uint8 gdsp_exceptions = 0; +void gdsp_generate_exception(uint8 level) +{ + gdsp_exceptions |= 1 << level; +} + + +bool gdsp_load_rom(char* fname) +{ + FILE* pFile = fopen(fname, "rb"); + + if (pFile) + { + fread(g_dsp.irom, 1, DSP_IRAM_SIZE, pFile); + fclose(pFile); + return(true); + } + + return(false); +} + + +bool gdsp_load_coef(char* fname) +{ + FILE* pFile = fopen(fname, "rb"); + + if (pFile) + { + fread(g_dsp.coef, 1, DSP_COEF_SIZE, pFile); + fclose(pFile); + return(true); + } + + return(false); +} + + +void gdsp_write_cr(uint16 val) +{ + // reset + if (val & 0x0001) + { + gdsp_reset(); + } + + val &= ~0x0001; + + // update cr + g_dsp.cr = val; + + UpdateCachedCR(); +} + + +uint16 gdsp_read_cr() +{ + if (g_dsp.pc & 0x8000) + { + g_dsp.cr |= 0x800; + } + else + { + g_dsp.cr &= ~0x800; + } + + UpdateCachedCR(); + + return(g_dsp.cr); +} + + +// special loop step.. because exception in loop or loopi fails +// dunno how we have to fix it +// atm we execute this instructions directly inside the loop command +// so it cant be interrupted by an exception +void gdsp_loop_step() +{ + g_dsp.err_pc = g_dsp.pc; + uint16 opc = dsp_fetch_code(); + dsp_op[opc >> 12](opc); +} + +u16 HLE_ROM_80E7_81F8(); +void hacks(); +void gdsp_step() +{ + g_dsp.step_counter++; + + if (g_dsp.pc == 0x80e7) + { + //g_dsp.pc = HLE_ROM_80E7_81F8(); + } + + g_dsp.err_pc = g_dsp.pc; + +#if PROFILE + ProfilerAddDelta(g_dsp.err_pc, 1); + if (g_dsp.step_counter == 1) + { + ProfilerInit(); + } + + if ((g_dsp.step_counter & 0xFFFFF) == 0) + { + ProfilerDump(g_dsp.step_counter); + } + +#endif + + uint16 opc = dsp_fetch_code(); + dsp_op[opc >> 12](opc); + + uint16& rLoopCounter = g_dsp.r[DSP_REG_ST0 + 3]; + + if (rLoopCounter > 0) + { + const uint16& rCallAddress = g_dsp.r[DSP_REG_ST0 + 0]; + const uint16& rLoopAddress = g_dsp.r[DSP_REG_ST0 + 2]; + + if (g_dsp.pc == (rLoopAddress + 1)) + { + rLoopCounter--; + + if (rLoopCounter > 0) + { + g_dsp.pc = rCallAddress; + } + else + { + // end of loop + dsp_reg_load_stack(0); + dsp_reg_load_stack(2); + dsp_reg_load_stack(3); + } + } + } + + // check if there is an external interrupt + if (CR_EXTERNAL_INT) + { + if (dsp_SR_is_flag_set(FLAG_ENABLE_INTERUPT) && (g_dsp.exception_in_progress_hack == false)) + { + // level 7 is the interrupt exception + gdsp_generate_exception(7); + g_dsp.cr &= ~0x0002; + UpdateCachedCR(); + } + } + + // check exceptions + if ((gdsp_exceptions > 0) && (!g_dsp.exception_in_progress_hack)) + { + for (uint8 i=0; i<8; i++) + { + if (gdsp_exceptions & (1< 1024*1024*1) + + /* if (g_dsp.pc == 0x165) + { + PanicAlert("Opcode_06"); + + } + if (g_dsp.pc == 0x43b) + { + PanicAlert("Opcode_14"); + + } + if (g_dsp.pc == 0xb37) + { + PanicAlert("Opcode_08"); + + }*/ + /* if (g_dsp.pc == 0x1bc) + { + r30 = g_dsp.r[30]; + r31 = g_dsp.r[31]; + } + else if (g_dsp.pc == 0x384) + { + // if ((r30 == 0x1bc) && (r31 == 0xaff)) + { + //PanicAlert("%x, %x", r30, r31); + + const int numSamples = 0x280; + static short Buffer[numSamples]; + + uint16 bufferAddr = 0x280; //dsp_dmem_read(0xe44); + for (int i=0; i 1024*1024*2) + { + //PanicAlert("%x", bufferAddr); + g_wave_writer.Stop(); + exit(1); + } + } + } */ + + if (g_dsp.pc == 0x468) + { + int numSamples = g_dsp.r[25] / 2; + uint16 bufferAddr = g_dsp.r[27]; + + // PanicAlert("%x %x", bufferAddr, numSamples); + + short samples[1024]; + for (int i=0; i 1024*1024*2) + { + //PanicAlert("%x", bufferAddr); + g_wave_writer.Stop(); + exit(1); + } + } +} diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_memory.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_memory.cpp index e5a9829b7f..380c2c8396 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_memory.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_memory.cpp @@ -1,156 +1,156 @@ -/*==================================================================== - - filename: gdsp_memory.cpp - project: GCemu - created: 2004-6-18 - mail: duddie@walla.com - - Copyright (c) 2005 Duddie & Tratax - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - ====================================================================*/ - -#include -#include "Globals.h" -#include "gdsp_interpreter.h" -#include "gdsp_memory.h" -#include "gdsp_ifx.h" - -uint16 dsp_swap16(uint16 x) -{ - return((x >> 8) | (x << 8)); -} - - -uint16* gdsp_get_iram(void) -{ - return(g_dsp.iram); -} - - -uint16* gdsp_get_irom(void) -{ - return(g_dsp.irom); -} - - -uint16* gdsp_get_dram(void) -{ - return(g_dsp.dram); -} - - -uint16* gdsp_get_drom(void) -{ - return(g_dsp.drom); -} - - -uint16 dsp_imem_read(uint16 addr) -{ - uint16 opc; - - if (g_dsp.pc & 0x8000) - { - opc = g_dsp.irom[addr & DSP_IROM_MASK]; - } - else - { - opc = g_dsp.iram[addr & DSP_IRAM_MASK]; - } - - return(dsp_swap16(opc)); -} - - -uint16 dsp_dmem_read(uint16 addr) -{ - uint16 val; - - switch (addr >> 12) - { - case 0x0: // 0xxx DRAM - val = g_dsp.dram[addr & DSP_DRAM_MASK]; - val = dsp_swap16(val); - break; - - case 0x8: // 8xxx DROM - DebugLog("someone reads from ROM\n"); - val = g_dsp.drom[addr & DSP_DROM_MASK]; - val = dsp_swap16(val); - break; - - case 0x1: // 1xxx COEF - val = g_dsp.coef[addr & DSP_DROM_MASK]; - val = dsp_swap16(val); - break; - - case 0xf: // Fxxx HW regs - val = gdsp_ifx_read(addr); - break; - - default: // error -// ErrorLog("%04x DSP ERROR: Read from UNKNOWN (%04x) memory\n", g_dsp.pc, addr); - val = 0; - break; - } - - return(val); -} - - -bool dsp_dmem_write(uint16 addr, uint16 val) -{ - switch (addr >> 12) - { - case 0x8: // 8xxx DROM - DebugLog("someone writes to ROM\n"); - /* val = dsp_swap16(val); - g_dsp.drom[addr & DSP_DROM_MASK] = val;*/ - break; - - case 0xf: // Fxxx HW regs - gdsp_ifx_write(addr, val); - break; - - case 0x0: // 0xxx DRAM - val = dsp_swap16(val); - g_dsp.dram[addr & DSP_DRAM_MASK] = val; - break; - - default: // error - DebugLog("%04x DSP ERROR: Write to UNKNOWN (%04x) memory\n", g_dsp.pc, addr); - break; - } - - return(true); -} - - -uint16 dsp_fetch_code(void) -{ - uint16 opc = dsp_imem_read(g_dsp.pc); - g_dsp.pc++; - return(opc); -} - - -uint16 dsp_peek_code(void) -{ - return(dsp_imem_read(g_dsp.pc)); -} - - +/*==================================================================== + + filename: gdsp_memory.cpp + project: GCemu + created: 2004-6-18 + mail: duddie@walla.com + + Copyright (c) 2005 Duddie & Tratax + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + ====================================================================*/ + +#include +#include "Globals.h" +#include "gdsp_interpreter.h" +#include "gdsp_memory.h" +#include "gdsp_ifx.h" + +uint16 dsp_swap16(uint16 x) +{ + return((x >> 8) | (x << 8)); +} + + +uint16* gdsp_get_iram(void) +{ + return(g_dsp.iram); +} + + +uint16* gdsp_get_irom(void) +{ + return(g_dsp.irom); +} + + +uint16* gdsp_get_dram(void) +{ + return(g_dsp.dram); +} + + +uint16* gdsp_get_drom(void) +{ + return(g_dsp.drom); +} + + +uint16 dsp_imem_read(uint16 addr) +{ + uint16 opc; + + if (g_dsp.pc & 0x8000) + { + opc = g_dsp.irom[addr & DSP_IROM_MASK]; + } + else + { + opc = g_dsp.iram[addr & DSP_IRAM_MASK]; + } + + return(dsp_swap16(opc)); +} + + +uint16 dsp_dmem_read(uint16 addr) +{ + uint16 val; + + switch (addr >> 12) + { + case 0x0: // 0xxx DRAM + val = g_dsp.dram[addr & DSP_DRAM_MASK]; + val = dsp_swap16(val); + break; + + case 0x8: // 8xxx DROM + DebugLog("someone reads from ROM\n"); + val = g_dsp.drom[addr & DSP_DROM_MASK]; + val = dsp_swap16(val); + break; + + case 0x1: // 1xxx COEF + val = g_dsp.coef[addr & DSP_DROM_MASK]; + val = dsp_swap16(val); + break; + + case 0xf: // Fxxx HW regs + val = gdsp_ifx_read(addr); + break; + + default: // error +// ErrorLog("%04x DSP ERROR: Read from UNKNOWN (%04x) memory\n", g_dsp.pc, addr); + val = 0; + break; + } + + return(val); +} + + +bool dsp_dmem_write(uint16 addr, uint16 val) +{ + switch (addr >> 12) + { + case 0x8: // 8xxx DROM + DebugLog("someone writes to ROM\n"); + /* val = dsp_swap16(val); + g_dsp.drom[addr & DSP_DROM_MASK] = val;*/ + break; + + case 0xf: // Fxxx HW regs + gdsp_ifx_write(addr, val); + break; + + case 0x0: // 0xxx DRAM + val = dsp_swap16(val); + g_dsp.dram[addr & DSP_DRAM_MASK] = val; + break; + + default: // error + DebugLog("%04x DSP ERROR: Write to UNKNOWN (%04x) memory\n", g_dsp.pc, addr); + break; + } + + return(true); +} + + +uint16 dsp_fetch_code(void) +{ + uint16 opc = dsp_imem_read(g_dsp.pc); + g_dsp.pc++; + return(opc); +} + + +uint16 dsp_peek_code(void) +{ + return(dsp_imem_read(g_dsp.pc)); +} + + diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_opcodes.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_opcodes.cpp index 6680fa8cae..04e78d6a0f 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_opcodes.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_opcodes.cpp @@ -1,2230 +1,2230 @@ -// Change Log - -// fixed dsp_opc_mulx (regarding DSP 0.0.4.pdf) -// fixed dsp_opc_mulxmv (regarding DSP 0.0.4.pdf) -// fixed dsp_opc_mulxmvz (regarding DSP 0.0.4.pdf) -// dsp_opc_shifti: removed strange " >> 9" -// added masking for SR_COMPARE_FLAGS -// added "UNKNOWN_CW" but without a function (yet? :) -// added missing compare type to MISSING_COMPARES_JX ... but i dunno what it does - -// added "MULXMV" to another function table - -/*==================================================================== - - filename: gdsp_opcodes.cpp - project: GCemu - created: 2004-6-18 - mail: duddie@walla.com - - Copyright (c) 2005 Duddie & Tratax - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - ====================================================================*/ - -#include -#include "Globals.h" -#include "gdsp_opcodes.h" -#include "gdsp_memory.h" -#include "gdsp_interpreter.h" -#include "gdsp_registers.h" -#include "gdsp_opcodes_helper.h" -#include "gdsp_ext_op.h" - -#define SR_CMP_MASK 0x3f -#define DSP_REG_MASK 0x1f - - -void Update_SR_Register(sint64 _Value) -{ - g_dsp.r[R_SR] &= ~SR_CMP_MASK; - - if (_Value < 0) - { - g_dsp.r[R_SR] |= 0x8; - } - - if (_Value == 0) - { - g_dsp.r[R_SR] |= 0x4; - } - - // logic - if ((_Value >> 62) == 0) - { - g_dsp.r[R_SR] |= 0x20; - } -} - - -void Update_SR_Register(sint16 _Value) -{ - g_dsp.r[R_SR] &= ~SR_CMP_MASK; - - if (_Value < 0) - { - g_dsp.r[R_SR] |= 0x8; - } - - if (_Value == 0) - { - g_dsp.r[R_SR] |= 0x4; - } - - // logic - if ((_Value >> 14) == 0) - { - g_dsp.r[R_SR] |= 0x20; - } -} - - -sint8 GetMultiplyModifier() -{ - if (g_dsp.r[R_SR] & (1 << 13)) - { - return(1); - } - - return(2); -} - - -bool CheckCondition(uint8 _Condition) -{ - bool taken = false; - - switch (_Condition & 0xf) - { - case 0x0: - - if ((!(g_dsp.r[R_SR] & 0x02)) && (!(g_dsp.r[R_SR] & 0x08))) - { - taken = true; - } - - break; - - case 0x3: - - if ((g_dsp.r[R_SR] & 0x02) || (g_dsp.r[R_SR] & 0x04) || (g_dsp.r[R_SR] & 0x08)) - { - taken = true; - } - - break; - - // old from duddie - case 0x1: // seems okay - - if ((!(g_dsp.r[R_SR] & 0x02)) && (g_dsp.r[R_SR] & 0x08)) - { - taken = true; - } - - break; - - case 0x2: - - if (!(g_dsp.r[R_SR] & 0x08)) - { - taken = true; - } - - break; - - case 0x4: - - if (!(g_dsp.r[R_SR] & 0x04)) - { - taken = true; - } - - break; - - case 0x5: - - if (g_dsp.r[R_SR] & 0x04) - { - taken = true; - } - - break; - - case 0xc: - - if (!(g_dsp.r[R_SR] & 0x40)) - { - taken = true; - } - - break; - - case 0xd: - - if (g_dsp.r[R_SR] & 0x40) - { - taken = true; - } - - break; - - case 0xf: - taken = true; - break; - - default: - // DebugLog("Unknown condition check: 0x%04x\n", _Condition & 0xf); - break; - } - - return(taken); -} - - -// ======================================================================= - -void dsp_op_unknown(uint16 opc) -{ - _assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception"); - ErrorLog("dsp_op_unknown somewhere"); - g_dsp.pc = g_dsp.err_pc; -} - - -void dsp_opc_call(uint16 opc) -{ - uint16 dest = dsp_fetch_code(); - - if (CheckCondition(opc & 0xf)) - { - dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc); - g_dsp.pc = dest; - } -} - - -void dsp_opc_ifcc(uint16 opc) -{ - if (!CheckCondition(opc & 0xf)) - { - dsp_fetch_code(); // skip the next opcode - } -} - - -void dsp_opc_jcc(uint16 opc) -{ - uint16 dest = dsp_fetch_code(); - - if (CheckCondition(opc & 0xf)) - { - g_dsp.pc = dest; - } -} - - -void dsp_opc_jmpa(uint16 opc) -{ - uint8 reg; - uint16 addr; - - if ((opc & 0xf) != 0xf) - { - ErrorLog("dsp_opc_jmpa"); - } - - reg = (opc >> 5) & 0x7; - addr = dsp_op_read_reg(reg); - - if (opc & 0x0010) - { - // CALLA - dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc); - } - - g_dsp.pc = addr; -} - - -// NEW (added condition check) -void dsp_opc_ret(uint16 opc) -{ - if (CheckCondition(opc & 0xf)) - { - g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C); - } -} - - -void dsp_opc_rti(uint16 opc) -{ - if ((opc & 0xf) != 0xf) - { - ErrorLog("dsp_opc_rti"); - } - - g_dsp.r[R_SR] = dsp_reg_load_stack(DSP_STACK_D); - g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C); - - g_dsp.exception_in_progress_hack = false; -} - - -void dsp_opc_halt(uint16 opc) -{ - g_dsp.cr |= 0x4; - g_dsp.pc = g_dsp.err_pc; -} - - -void dsp_opc_loop(uint16 opc) -{ - uint16 reg = opc & 0x1f; - uint16 cnt = g_dsp.r[reg]; - uint16 loop_pc = g_dsp.pc; - - while (cnt--) - { - gdsp_loop_step(); - g_dsp.pc = loop_pc; - } - - g_dsp.pc = loop_pc + 1; -} - - -void dsp_opc_loopi(uint16 opc) -{ - uint16 cnt = opc & 0xff; - uint16 loop_pc = g_dsp.pc; - - while (cnt--) - { - gdsp_loop_step(); - g_dsp.pc = loop_pc; - } - - g_dsp.pc = loop_pc + 1; -} - - -void dsp_opc_bloop(uint16 opc) -{ - uint16 reg = opc & 0x1f; - uint16 cnt = g_dsp.r[reg]; - uint16 loop_pc = dsp_fetch_code(); - - if (cnt) - { - dsp_reg_store_stack(0, g_dsp.pc); - dsp_reg_store_stack(2, loop_pc); - dsp_reg_store_stack(3, cnt); - } - else - { - g_dsp.pc = loop_pc + 1; - } -} - - -void dsp_opc_bloopi(uint16 opc) -{ - uint16 cnt = opc & 0xff; - uint16 loop_pc = dsp_fetch_code(); - - if (cnt) - { - dsp_reg_store_stack(0, g_dsp.pc); - dsp_reg_store_stack(2, loop_pc); - dsp_reg_store_stack(3, cnt); - } - else - { - g_dsp.pc = loop_pc + 1; - } -} - - -//------------------------------------------------------------- - - -void dsp_opc_mrr(uint16 opc) -{ - uint8 sreg = opc & 0x1f; - uint8 dreg = (opc >> 5) & 0x1f; - - uint16 val = dsp_op_read_reg(sreg); - dsp_op_write_reg(dreg, val); -} - - -void dsp_opc_lrr(uint16 opc) -{ - uint8 sreg = (opc >> 5) & 0x3; - uint8 dreg = opc & 0x1f; - - uint16 val = dsp_dmem_read(g_dsp.r[sreg]); - dsp_op_write_reg(dreg, val); - - // post processing of source reg - switch ((opc >> 7) & 0x3) - { - case 0x0: // LRR - break; - - case 0x1: // LRRD - g_dsp.r[sreg]--; - break; - - case 0x2: // LRRI - g_dsp.r[sreg]++; - break; - - case 0x3: - g_dsp.r[sreg] += g_dsp.r[sreg + 4]; - break; - } -} - - -void dsp_opc_srr(uint16 opc) -{ - uint8 dreg = (opc >> 5) & 0x3; - uint8 sreg = opc & 0x1f; - - uint16 val = dsp_op_read_reg(sreg); - dsp_dmem_write(g_dsp.r[dreg], val); - - // post processing of dest reg - switch ((opc >> 7) & 0x3) - { - case 0x0: // SRR - break; - - case 0x1: // SRRD - g_dsp.r[dreg]--; - break; - - case 0x2: // SRRI - g_dsp.r[dreg]++; - break; - - case 0x3: // SRRX - g_dsp.r[dreg] += g_dsp.r[dreg + 4]; - break; - } -} - - -void dsp_opc_ilrr(uint16 opc) -{ - uint16 reg = opc & 0x3; - uint16 dreg = 0x1e + ((opc >> 8) & 1); - - // always to acc0 ? - g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]); - - switch ((opc >> 2) & 0x3) - { - case 0x0: // no change - break; - - case 0x1: // post decrement - g_dsp.r[reg]--; - break; - - case 0x2: // post increment - g_dsp.r[reg]++; - break; - - default: - ErrorLog("dsp_opc_ilrr"); - } -} - - -void dsp_opc_lri(uint16 opc) -{ - uint8 reg = opc & DSP_REG_MASK; - uint16 imm = dsp_fetch_code(); - dsp_op_write_reg(reg, imm); -} - - -void dsp_opc_lris(uint16 opc) -{ - uint8 reg = ((opc >> 8) & 0x7) + 0x18; - uint16 imm = (sint8)opc; - dsp_op_write_reg(reg, imm); -} - - -void dsp_opc_lr(uint16 opc) -{ - uint8 reg = opc & DSP_REG_MASK; - uint16 addr = dsp_fetch_code(); - uint16 val = dsp_dmem_read(addr); - dsp_op_write_reg(reg, val); -} - - -void dsp_opc_sr(uint16 opc) -{ - uint8 reg = opc & DSP_REG_MASK; - uint16 addr = dsp_fetch_code(); - uint16 val = dsp_op_read_reg(reg); - dsp_dmem_write(addr, val); -} - - -void dsp_opc_si(uint16 opc) -{ - uint16 addr = (sint8)opc; - uint16 imm = dsp_fetch_code(); - dsp_dmem_write(addr, imm); -} - - -void dsp_opc_tstaxh(uint16 opc) -{ - uint8 reg = (opc >> 8) & 0x1; - sint16 val = dsp_get_ax_h(reg); - - Update_SR_Register(val); -} - - -void dsp_opc_clr(uint16 opc) -{ - uint8 reg = (opc >> 11) & 0x1; - - dsp_set_long_acc(reg, 0); - - Update_SR_Register((sint64)0); -} - - -void dsp_opc_clrp(uint16 opc) -{ - g_dsp.r[0x14] = 0x0000; - g_dsp.r[0x15] = 0xfff0; - g_dsp.r[0x16] = 0x00ff; - g_dsp.r[0x17] = 0x0010; -} - - -// NEW -void dsp_opc_mulc(uint16 opc) -{ - // math new prod - uint8 sreg = (opc >> 11) & 0x1; - uint8 treg = (opc >> 12) & 0x1; - - sint64 prod = dsp_get_acc_m(sreg) * dsp_get_ax_h(treg) * GetMultiplyModifier(); - dsp_set_long_prod(prod); - - Update_SR_Register(prod); -} - - -// NEW -void dsp_opc_mulcmvz(uint16 opc) -{ - ErrorLog("dsp_opc_mulcmvz ni"); -} - - -// NEW -void dsp_opc_mulcmv(uint16 opc) -{ - ErrorLog("dsp_opc_mulcmv ni"); -} - - -void dsp_opc_cmpar(uint16 opc) -{ - uint8 rreg = ((opc >> 12) & 0x1) + 0x1a; - uint8 areg = (opc >> 11) & 0x1; - - // we compare - sint64 rr = (sint16)g_dsp.r[rreg]; - rr <<= 16; - - sint64 ar = dsp_get_long_acc(areg); - - Update_SR_Register(ar - rr); -} - - -void dsp_opc_cmp(uint16 opc) -{ - sint64 acc0 = dsp_get_long_acc(0); - sint64 acc1 = dsp_get_long_acc(1); - - Update_SR_Register(acc0 - acc1); -} - - -void dsp_opc_tsta(uint16 opc) -{ - uint8 reg = (opc >> 11) & 0x1; - sint64 acc = dsp_get_long_acc(reg); - - Update_SR_Register(acc); -} - - -// NEW -void dsp_opc_addaxl(uint16 opc) -{ - uint8 sreg = (opc >> 9) & 0x1; - uint8 dreg = (opc >> 8) & 0x1; - - sint64 acc = dsp_get_long_acc(dreg); - sint64 acx = dsp_get_ax_l(sreg); - - acc += acx; - - dsp_set_long_acc(dreg, acc); - - Update_SR_Register(acc); -} - - -// NEW -void dsp_opc_addarn(uint16 opc) -{ - uint8 dreg = opc & 0x3; - uint8 sreg = (opc >> 2) & 0x3; - - g_dsp.r[dreg] += (sint16)g_dsp.r[0x04 + sreg]; -} - - -// NEW -void dsp_opc_mulcac(uint16 opc) -{ - sint64 TempProd = dsp_get_long_prod(); - - // update prod - uint8 sreg = (opc >> 12) & 0x1; - sint64 Prod = (sint64)dsp_get_acc_m(sreg) * (sint64)dsp_get_acc_h(sreg) * GetMultiplyModifier(); - dsp_set_long_prod(Prod); - - // update acc - uint8 rreg = (opc >> 8) & 0x1; - dsp_set_long_acc(rreg, TempProd); -} - - -// NEW -void dsp_opc_movr(uint16 opc) -{ - uint8 areg = (opc >> 8) & 0x1; - uint8 sreg = ((opc >> 9) & 0x3) + 0x18; - - sint64 acc = (sint16)g_dsp.r[sreg]; - acc <<= 16; - acc &= ~0xffff; - - dsp_set_long_acc(areg, acc); - - Update_SR_Register(acc); -} - - -void dsp_opc_movax(uint16 opc) -{ - uint8 sreg = (opc >> 9) & 0x1; - uint8 dreg = (opc >> 8) & 0x1; - - g_dsp.r[0x1c + dreg] = g_dsp.r[0x18 + sreg]; - g_dsp.r[0x1e + dreg] = g_dsp.r[0x1a + sreg]; - - if ((sint16)g_dsp.r[0x1a + sreg] < 0) - { - g_dsp.r[0x10 + dreg] = 0xffff; - } - else - { - g_dsp.r[0x10 + dreg] = 0; - } - - dsp_opc_tsta(dreg << 11); -} - - -// NEW -void dsp_opc_xorr(uint16 opc) -{ - uint8 sreg = (opc >> 9) & 0x1; - uint8 dreg = (opc >> 8) & 0x1; - - g_dsp.r[0x1e + dreg] ^= g_dsp.r[0x1a + sreg]; - - dsp_opc_tsta(dreg << 11); -} - - -void dsp_opc_andr(uint16 opc) -{ - uint8 sreg = (opc >> 9) & 0x1; - uint8 dreg = (opc >> 8) & 0x1; - - g_dsp.r[0x1e + dreg] &= g_dsp.r[0x1a + sreg]; - - dsp_opc_tsta(dreg << 11); -} - - -// NEW -void dsp_opc_orr(uint16 opc) -{ - uint8 sreg = (opc >> 9) & 0x1; - uint8 dreg = (opc >> 8) & 0x1; - - g_dsp.r[0x1e + dreg] |= g_dsp.r[0x1a + sreg]; - - dsp_opc_tsta(dreg << 11); -} - - -// NEW -void dsp_opc_andc(uint16 opc) -{ - uint8 D = (opc >> 8) & 0x1; - - uint16 ac1 = dsp_get_acc_m(D); - uint16 ac2 = dsp_get_acc_m(1 - D); - - dsp_set_long_acc(D, ac1 & ac2); - - if ((ac1 & ac2) == 0) - { - g_dsp.r[R_SR] |= 0x20; - } - else - { - g_dsp.r[R_SR] &= ~0x20; - } -} - - -//------------------------------------------------------------- - -void dsp_opc_nx(uint16 opc) -{} - - -// NEW -void dsp_opc_andfc(uint16 opc) -{ - if (opc & 0xf) - { - ErrorLog("dsp_opc_andfc"); - } - - uint8 reg = (opc >> 8) & 0x1; - uint16 imm = dsp_fetch_code(); - uint16 val = dsp_get_acc_m(reg); - - if ((val & imm) == imm) - { - g_dsp.r[R_SR] |= 0x40; - } - else - { - g_dsp.r[R_SR] &= ~0x40; - } -} - - -void dsp_opc_andf(uint16 opc) -{ - uint8 reg; - uint16 imm; - uint16 val; - - if (opc & 0xf) - { - ErrorLog("dsp_opc_andf"); - } - - reg = 0x1e + ((opc >> 8) & 0x1); - imm = dsp_fetch_code(); - val = g_dsp.r[reg]; - - if ((val & imm) == 0) - { - g_dsp.r[R_SR] |= 0x40; - } - else - { - g_dsp.r[R_SR] &= ~0x40; - } -} - - -void dsp_opc_subf(uint16 opc) -{ - if (opc & 0xf) - { - ErrorLog("dsp_opc_subf"); - } - - uint8 reg = 0x1e + ((opc >> 8) & 0x1); - sint64 imm = (sint16)dsp_fetch_code(); - - sint64 val = (sint16)g_dsp.r[reg]; - sint64 res = val - imm; - - Update_SR_Register(res); -} - - -void dsp_opc_xori(uint16 opc) -{ - if (opc & 0xf) - { - ErrorLog("dsp_opc_xori"); - } - - uint8 reg = 0x1e + ((opc >> 8) & 0x1); - uint16 imm = dsp_fetch_code(); - g_dsp.r[reg] ^= imm; - - Update_SR_Register((sint16)g_dsp.r[reg]); -} - - -void dsp_opc_andi(uint16 opc) -{ - if (opc & 0xf) - { - ErrorLog("dsp_opc_andi"); - } - - uint8 reg = 0x1e + ((opc >> 8) & 0x1); - uint16 imm = dsp_fetch_code(); - g_dsp.r[reg] &= imm; - - Update_SR_Register((sint16)g_dsp.r[reg]); -} - - -// F|RES: i am not sure if this shouldnt be the whole ACC -// -void dsp_opc_ori(uint16 opc) -{ - if (opc & 0xf) - { - return(ErrorLog("dsp_opc_ori")); - } - - uint8 reg = 0x1e + ((opc >> 8) & 0x1); - uint16 imm = dsp_fetch_code(); - g_dsp.r[reg] |= imm; - - Update_SR_Register((sint16)g_dsp.r[reg]); -} - - -//------------------------------------------------------------- - -void dsp_opc_add(uint16 opc) -{ - uint8 areg = (opc >> 8) & 0x1; - sint64 acc0 = dsp_get_long_acc(0); - sint64 acc1 = dsp_get_long_acc(1); - - sint64 res = acc0 + acc1; - - dsp_set_long_acc(areg, res); - - Update_SR_Register(res); -} - - -//------------------------------------------------------------- - -void dsp_opc_addp(uint16 opc) -{ - uint8 dreg = (opc >> 8) & 0x1; - sint64 acc = dsp_get_long_acc(dreg); - acc = acc + dsp_get_long_prod(); - dsp_set_long_acc(dreg, acc); - - Update_SR_Register(acc); -} - - -void dsp_opc_cmpis(uint16 opc) -{ - uint8 areg = (opc >> 8) & 0x1; - - sint64 acc = dsp_get_long_acc(areg); - sint64 val = (sint8)opc; - val <<= 16; - - sint64 res = acc - val; - - Update_SR_Register(res); -} - - -// NEW -// verified at the console -void dsp_opc_addpaxz(uint16 opc) -{ - uint8 dreg = (opc >> 8) & 0x1; - uint8 sreg = (opc >> 9) & 0x1; - - sint64 prod = dsp_get_long_prod() & ~0x0ffff; - sint64 ax_h = dsp_get_long_acx(sreg); - sint64 acc = (prod + ax_h) & ~0x0ffff; - - dsp_set_long_acc(dreg, acc); - - Update_SR_Register(acc); -} - - -// NEW -void dsp_opc_movpz(uint16 opc) -{ - uint8 dreg = (opc >> 8) & 0x01; - - // overwrite acc and clear low part - sint64 prod = dsp_get_long_prod(); - sint64 acc = prod & ~0xffff; - dsp_set_long_acc(dreg, acc); - - Update_SR_Register(acc); -} - - -void dsp_opc_decm(uint16 opc) -{ - uint8 dreg = (opc >> 8) & 0x01; - - sint64 sub = 0x10000; - sint64 acc = dsp_get_long_acc(dreg); - acc -= sub; - dsp_set_long_acc(dreg, acc); - - Update_SR_Register(acc); -} - - -void dsp_opc_dec(uint16 opc) -{ - uint8 dreg = (opc >> 8) & 0x01; - - sint64 acc = dsp_get_long_acc(dreg) - 1; - dsp_set_long_acc(dreg, acc); - - Update_SR_Register(acc); -} - - -void dsp_opc_incm(uint16 opc) -{ - uint8 dreg = (opc >> 8) & 0x1; - - sint64 sub = 0x10000; - sint64 acc = dsp_get_long_acc(dreg); - acc += sub; - dsp_set_long_acc(dreg, acc); - - Update_SR_Register(acc); -} - - -void dsp_opc_inc(uint16 opc) -{ - uint8 dreg = (opc >> 8) & 0x1; - - sint64 acc = dsp_get_long_acc(dreg); - acc++; - dsp_set_long_acc(dreg, acc); - - Update_SR_Register(acc); -} - - -void dsp_opc_neg(uint16 opc) -{ - uint8 areg = (opc >> 8) & 0x1; - - sint64 acc = dsp_get_long_acc(areg); - acc = 0 - acc; - dsp_set_long_acc(areg, acc); - - Update_SR_Register(acc); -} - - -void dsp_opc_movnp(uint16 opc) -{ - ErrorLog("dsp_opc_movnp\n"); -} - - -// NEW -void dsp_opc_addax(uint16 opc) -{ - uint8 areg = (opc >> 8) & 0x1; - uint8 sreg = (opc >> 9) & 0x1; - - sint64 ax = dsp_get_long_acx(sreg); - sint64 acc = dsp_get_long_acc(areg); - acc += ax; - dsp_set_long_acc(areg, acc); - - Update_SR_Register(acc); -} - - -void dsp_opc_addr(uint16 opc) -{ - uint8 areg = (opc >> 8) & 0x1; - uint8 sreg = ((opc >> 9) & 0x3) + 0x18; - - sint64 ax = (sint16)g_dsp.r[sreg]; - ax <<= 16; - - sint64 acc = dsp_get_long_acc(areg); - acc += ax; - dsp_set_long_acc(areg, acc); - - Update_SR_Register(acc); -} - - -void dsp_opc_subr(uint16 opc) -{ - uint8 areg = (opc >> 8) & 0x1; - uint8 sreg = ((opc >> 9) & 0x3) + 0x18; - - sint64 ax = (sint16)g_dsp.r[sreg]; - ax <<= 16; - - sint64 acc = dsp_get_long_acc(areg); - acc -= ax; - dsp_set_long_acc(areg, acc); - - Update_SR_Register(acc); -} - -// NEW -void dsp_opc_subax(uint16 opc) -{ - int regD = (opc >> 8) & 0x1; - int regT = (opc >> 9) & 0x1; - - sint64 Acc = dsp_get_long_acc(regD) - dsp_get_long_acx(regT); - - dsp_set_long_acc(regD, Acc); - Update_SR_Register(Acc); -} - -void dsp_opc_addis(uint16 opc) -{ - uint8 areg = (opc >> 8) & 0x1; - - sint64 Imm = (sint8)opc; - Imm <<= 16; - sint64 acc = dsp_get_long_acc(areg); - acc += Imm; - dsp_set_long_acc(areg, acc); - - Update_SR_Register(acc); -} - - -void dsp_opc_addi(uint16 opc) -{ - uint8 areg = (opc >> 8) & 0x1; - - sint64 sub = (sint16)dsp_fetch_code(); - sub <<= 16; - sint64 acc = dsp_get_long_acc(areg); - acc += sub; - dsp_set_long_acc(areg, acc); - - Update_SR_Register(acc); -} - - -void dsp_opc_lsl16(uint16 opc) -{ - uint8 areg = (opc >> 8) & 0x1; - - sint64 acc = dsp_get_long_acc(areg); - acc <<= 16; - dsp_set_long_acc(areg, acc); - - Update_SR_Register(acc); -} - - -// NEW -void dsp_opc_madd(uint16 opc) -{ - uint8 sreg = (opc >> 8) & 0x1; - - sint64 prod = dsp_get_long_prod(); - prod += (sint64)dsp_get_ax_l(sreg) * (sint64)dsp_get_ax_h(sreg) * GetMultiplyModifier(); - dsp_set_long_prod(prod); -} - - -void dsp_opc_lsr16(uint16 opc) -{ - uint8 areg = (opc >> 8) & 0x1; - - sint64 acc = dsp_get_long_acc(areg); - acc >>= 16; - dsp_set_long_acc(areg, acc); - - Update_SR_Register(acc); -} - - -void dsp_opc_asr16(uint16 opc) -{ - uint8 areg = (opc >> 11) & 0x1; - - sint64 acc = dsp_get_long_acc(areg); - acc >>= 16; - dsp_set_long_acc(areg, acc); - - Update_SR_Register(acc); -} - - -union UOpcodeShifti -{ - uint16 Hex; - struct - { - signed shift : 6; - unsigned negating : 1; - unsigned arithmetic : 1; - unsigned areg : 1; - unsigned op : 7; - }; - struct - { - unsigned ushift : 6; - }; - UOpcodeShifti(uint16 _Hex) - : Hex(_Hex) {} -}; - -void dsp_opc_shifti(uint16 opc) -{ - UOpcodeShifti Opcode(opc); - - // direction: left - bool ShiftLeft = true; - uint16 shift = Opcode.ushift; - - if ((Opcode.negating) && (Opcode.shift < 0)) - { - ShiftLeft = false; - shift = -Opcode.shift; - } - - sint64 acc; - uint64 uacc; - - if (Opcode.arithmetic) - { - // arithmetic shift - uacc = dsp_get_long_acc(Opcode.areg); - - if (!ShiftLeft) - { - uacc >>= shift; - } - else - { - uacc <<= shift; - } - - acc = uacc; - } - else - { - acc = dsp_get_long_acc(Opcode.areg); - - if (!ShiftLeft) - { - acc >>= shift; - } - else - { - acc <<= shift; - } - } - - dsp_set_long_acc(Opcode.areg, acc); - - Update_SR_Register(acc); -} - - -//------------------------------------------------------------- -// hcs give me this code!! -void dsp_opc_dar(uint16 opc) -{ - uint8 reg = opc & 0x3; - - int temp = g_dsp.r[reg] + g_dsp.r[8]; - - if (temp <= 0x7ff){g_dsp.r[reg] = temp;} - else {g_dsp.r[reg]--;} -} - - -// hcs give me this code!! -void dsp_opc_iar(uint16 opc) -{ - uint8 reg = opc & 0x3; - - int temp = g_dsp.r[reg] + g_dsp.r[8]; - - if (temp <= 0x7ff){g_dsp.r[reg] = temp;} - else {g_dsp.r[reg]++;} -} - - -//------------------------------------------------------------- - -void dsp_opc_sbclr(uint16 opc) -{ - uint8 bit = (opc & 0xff) + 6; - g_dsp.r[R_SR] &= ~(1 << bit); -} - - -void dsp_opc_sbset(uint16 opc) -{ - uint8 bit = (opc & 0xff) + 6; - g_dsp.r[R_SR] |= (1 << bit); -} - - -void dsp_opc_srbith(uint16 opc) -{ - switch ((opc >> 8) & 0xf) - { - case 0xe: // SET40 - g_dsp.r[R_SR] &= ~(1 << 14); - break; - -/* case 0xf: // SET16 // that doesnt happen on a real console - g_dsp.r[R_SR] |= (1 << 14); - break;*/ - - default: - break; - } -} - - -//------------------------------------------------------------- - -void dsp_opc_movp(uint16 opc) -{ - uint8 dreg = (opc >> 8) & 0x1; - - sint64 prod = dsp_get_long_prod(); - sint64 acc = prod; - dsp_set_long_acc(dreg, acc); -} - - -void dsp_opc_mul(uint16 opc) -{ - uint8 sreg = (opc >> 11) & 0x1; - sint64 prod = (sint64)dsp_get_ax_h(sreg) * (sint64)dsp_get_ax_l(sreg) * GetMultiplyModifier(); - - dsp_set_long_prod(prod); - - Update_SR_Register(prod); -} - -// NEW -void dsp_opc_mulac(uint16 opc) -{ - // add old prod to acc - uint8 rreg = (opc >> 8) & 0x1; - sint64 acR = dsp_get_long_acc(rreg) + dsp_get_long_prod(); - dsp_set_long_acc(rreg, acR); - - // math new prod - uint8 sreg = (opc >> 11) & 0x1; - sint64 prod = dsp_get_ax_l(sreg) * dsp_get_ax_h(sreg) * GetMultiplyModifier(); - dsp_set_long_prod(prod); - - Update_SR_Register(prod); -} - - -void dsp_opc_mulmv(uint16 opc) -{ - uint8 rreg = (opc >> 8) & 0x1; - sint64 prod = dsp_get_long_prod(); - sint64 acc = prod; - dsp_set_long_acc(rreg, acc); - - uint8 areg = ((opc >> 11) & 0x1) + 0x18; - uint8 breg = ((opc >> 11) & 0x1) + 0x1a; - sint64 val1 = (sint16)g_dsp.r[areg]; - sint64 val2 = (sint16)g_dsp.r[breg]; - - prod = val1 * val2 * GetMultiplyModifier(); - - dsp_set_long_prod(prod); - - Update_SR_Register(prod); -} - - -// NEW -void dsp_opc_mulmvz(uint16 opc) -{ - uint8 sreg = (opc >> 11) & 0x1; - uint8 rreg = (opc >> 8) & 0x1; - - // overwrite acc and clear low part - sint64 prod = dsp_get_long_prod(); - sint64 acc = prod & ~0xffff; - dsp_set_long_acc(rreg, acc); - - // math prod - prod = (sint64)g_dsp.r[0x18 + sreg] * (sint64)g_dsp.r[0x1a + sreg] * GetMultiplyModifier(); - dsp_set_long_prod(prod); - - Update_SR_Register(prod); -} - - -// NEW -void dsp_opc_mulx(uint16 opc) -{ - uint8 sreg = ((opc >> 12) & 0x1); - uint8 treg = ((opc >> 11) & 0x1); - - sint64 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - sint64 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - - sint64 prod = val1 * val2 * GetMultiplyModifier(); - dsp_set_long_prod(prod); - - Update_SR_Register(prod); -} - - -// NEW -void dsp_opc_mulxac(uint16 opc) -{ - // add old prod to acc - uint8 rreg = (opc >> 8) & 0x1; - sint64 acR = dsp_get_long_acc(rreg) + dsp_get_long_prod(); - dsp_set_long_acc(rreg, acR); - - // math new prod - uint8 sreg = (opc >> 12) & 0x1; - uint8 treg = (opc >> 11) & 0x1; - - sint64 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - sint64 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - - sint64 prod = val1 * val2 * GetMultiplyModifier(); - dsp_set_long_prod(prod); - - Update_SR_Register(prod); -} - - -// NEW -void dsp_opc_mulxmv(uint16 opc) -{ - // add old prod to acc - uint8 rreg = ((opc >> 8) & 0x1); - sint64 acR = dsp_get_long_prod(); - dsp_set_long_acc(rreg, acR); - - // math new prod - uint8 sreg = (opc >> 12) & 0x1; - uint8 treg = (opc >> 11) & 0x1; - - sint64 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - sint64 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - - sint64 prod = val1 * val2 * GetMultiplyModifier(); - dsp_set_long_prod(prod); - - Update_SR_Register(prod); -} - - -// NEW -void dsp_opc_mulxmvz(uint16 opc) -{ - // overwrite acc and clear low part - uint8 rreg = (opc >> 8) & 0x1; - sint64 prod = dsp_get_long_prod(); - sint64 acc = prod & ~0xffff; - dsp_set_long_acc(rreg, acc); - - // math prod - uint8 sreg = (opc >> 12) & 0x1; - uint8 treg = (opc >> 11) & 0x1; - - sint64 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - sint64 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - - prod = val1 * val2 * GetMultiplyModifier(); - dsp_set_long_prod(prod); - - Update_SR_Register(prod); -} - - -// NEW -void dsp_opc_sub(uint16 opc) -{ - uint8 D = (opc >> 8) & 0x1; - sint64 Acc1 = dsp_get_long_acc(D); - sint64 Acc2 = dsp_get_long_acc(1 - D); - - Acc1 -= Acc2; - - dsp_set_long_acc(D, Acc1); -} - - -//------------------------------------------------------------- -// -// --- Table E -// -//------------------------------------------------------------- - -// NEW -void dsp_opc_maddx(uint16 opc) -{ - uint8 sreg = (opc >> 9) & 0x1; - uint8 treg = (opc >> 8) & 0x1; - - sint64 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - sint64 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - - sint64 prod = dsp_get_long_prod(); - prod += val1 * val2 * GetMultiplyModifier(); - dsp_set_long_prod(prod); -} - - -// NEW -void dsp_opc_msubx(uint16 opc) -{ - uint8 sreg = (opc >> 9) & 0x1; - uint8 treg = (opc >> 8) & 0x1; - - sint64 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - sint64 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - - sint64 prod = dsp_get_long_prod(); - prod -= val1 * val2 * GetMultiplyModifier(); - dsp_set_long_prod(prod); -} - - -// NEW -void dsp_opc_maddc(uint16 opc) -{ - uint sreg = (opc >> 9) & 0x1; - uint treg = (opc >> 8) & 0x1; - - sint64 val1 = dsp_get_acc_m(sreg); - sint64 val2 = dsp_get_ax_h(treg); - - sint64 prod = dsp_get_long_prod(); - prod += val1 * val2 * GetMultiplyModifier(); - dsp_set_long_prod(prod); -} - - -// NEW -void dsp_opc_msubc(uint16 opc) -{ - uint sreg = (opc >> 9) & 0x1; - uint treg = (opc >> 8) & 0x1; - - sint64 val1 = dsp_get_acc_m(sreg); - sint64 val2 = dsp_get_ax_h(treg); - - sint64 prod = dsp_get_long_prod(); - prod -= val1 * val2 * GetMultiplyModifier(); - dsp_set_long_prod(prod); -} - - -//------------------------------------------------------------- -void dsp_op0(uint16 opc) -{ - if (opc == 0) - { - return; - } - - switch ((opc >> 8) & 0xf) - { - case 0x0: - - switch ((opc >> 4) & 0xf) - { - case 0x0: - - switch (opc & 0xf) - { - case 0x4: - case 0x5: - case 0x6: - case 0x7: - dsp_opc_dar(opc); - break; - - case 0x8: - case 0x9: - case 0xa: - case 0xb: - dsp_opc_iar(opc); - break; - - default: - ErrorLog("dsp_op0"); - break; - } - - break; - - case 0x1: - dsp_opc_addarn(opc); - break; - - case 0x2: // HALT - dsp_opc_halt(opc); - break; - - case 0x4: // LOOP - case 0x5: // LOOP - dsp_opc_loop(opc); - break; - - case 0x6: // BLOOP - case 0x7: // BLOOP - dsp_opc_bloop(opc); - break; - - case 0x8: // LRI - case 0x9: // LRI - dsp_opc_lri(opc); - break; - - case 0xC: // LR - case 0xD: // LR - dsp_opc_lr(opc); - break; - - case 0xE: // SR - case 0xF: // SR - dsp_opc_sr(opc); - break; - - default: - ErrorLog("dsp_op0"); - break; - } - - break; - - case 0x2: - - switch ((opc >> 4) & 0xf) - { - case 0x0: // ADDI - dsp_opc_addi(opc); - break; - - case 0x1: // IL - dsp_opc_ilrr(opc); - break; - - case 0x2: // XORI - dsp_opc_xori(opc); - break; - - case 0x4: // ANDI - dsp_opc_andi(opc); - break; - - case 0x6: // ORI - dsp_opc_ori(opc); - break; - - case 0x7: // - dsp_opc_ifcc(opc); - break; - - case 0x8: // SUBF - dsp_opc_subf(opc); - break; - - case 0x9: // Jxx - dsp_opc_jcc(opc); - break; - - case 0xa: // ANDF - dsp_opc_andf(opc); - break; - - case 0xb: // CALL - dsp_opc_call(opc); - break; - - case 0xc: - dsp_opc_andfc(opc); - break; - - case 0xd: // RET - dsp_opc_ret(opc); - break; - - case 0xf: // RTI - dsp_opc_rti(opc); - break; - - default: - ErrorLog("dsp_op0"); - break; - } - - break; - - case 0x3: - - switch ((opc >> 4) & 0xf) - { - case 0x0: // ADDAI - dsp_opc_addi(opc); - break; - - case 0x1: // ILR - dsp_opc_ilrr(opc); - break; - - case 0x2: // XORI - dsp_opc_xori(opc); - break; - - case 0x4: // ANDI - dsp_opc_andi(opc); - break; - - case 0x6: // ORI - dsp_opc_ori(opc); - break; - - case 0x8: // SUBF - dsp_opc_subf(opc); - break; - - case 0xa: // ANDF - dsp_opc_andf(opc); - break; - - case 0xc: // ANDFC - dsp_opc_andfc(opc); - break; - - default: - ErrorLog("dsp_op0"); - break; - } - - break; - - case 0x4: - case 0x5: - dsp_opc_addis(opc); - break; - - case 0x6: // SUBISF - case 0x7: - dsp_opc_cmpis(opc); - break; - - case 0x8: // LRIS - case 0x9: - case 0xa: - case 0xb: - case 0xc: - case 0xd: - case 0xe: - case 0xf: - dsp_opc_lris(opc); - break; - - default: - ErrorLog("dsp_op0"); - break; - } -} - - -void dsp_op1(uint16 opc) -{ - switch ((opc >> 8) & 0xf) - { - case 0x0: - dsp_opc_loopi(opc); - break; - - case 0x1: // BLOOPI - dsp_opc_bloopi(opc); - break; - - case 0x2: // SBCLR - dsp_opc_sbclr(opc); - break; - - case 0x3: // SBSET - dsp_opc_sbset(opc); - break; - - case 0x4: // shifti - case 0x5: - dsp_opc_shifti(opc); - break; - - case 0x6: // SI - dsp_opc_si(opc); - break; - - case 0x7: // JMPA/CALLA - dsp_opc_jmpa(opc); - break; - - case 0x8: // LRRx - case 0x9: // LRRx - dsp_opc_lrr(opc); - break; - - case 0xa: // SRRx - case 0xb: // SRRx - dsp_opc_srr(opc); - break; - - case 0xc: // MRR - case 0xd: // MRR - case 0xe: // MRR - case 0xf: // MRR - dsp_opc_mrr(opc); - break; - - default: - ErrorLog("dsp_op1"); - break; - } -} - - -void dsp_op2(uint16 opc) -{ - // lrs, srs - uint8 reg = ((opc >> 8) & 0x7) + 0x18; - uint16 addr = (sint8) opc; - - if (opc & 0x0800) - { - // srs - dsp_dmem_write(addr, g_dsp.r[reg]); - } - else - { - // lrs - g_dsp.r[reg] = dsp_dmem_read(addr); - } -} - - -void dsp_op3(uint16 opc) -{ - dsp_op_ext_ops_pro(opc); - - switch ((opc >> 8) & 0xf) - { - case 0x0: - case 0x1: - case 0x2: - case 0x3: - dsp_opc_xorr(opc); - break; - - case 0x4: - case 0x5: - case 0x6: - case 0x7: - dsp_opc_andr(opc); - break; - - case 0x8: - case 0x9: - case 0xa: - case 0xb: - dsp_opc_orr(opc); - break; - - case 0xc: - case 0xd: - dsp_opc_andc(opc); - break; - - default: - ErrorLog("dsp_op3"); - break; - } - - dsp_op_ext_ops_epi(opc); -} - - -void dsp_op4(uint16 opc) -{ - dsp_op_ext_ops_pro(opc); - - switch ((opc >> 8) & 0xf) - { - case 0x0: - case 0x1: - case 0x2: - case 0x3: - case 0x4: - case 0x5: - case 0x6: - case 0x7: - dsp_opc_addr(opc); - break; - - case 0x8: - case 0x9: - case 0xa: - case 0xb: - dsp_opc_addax(opc); - break; - - case 0xc: - case 0xd: - dsp_opc_add(opc); - break; - - case 0xe: - case 0xf: - dsp_opc_addp(opc); - break; - - default: - ErrorLog("dsp_op4"); - break; - } - - dsp_op_ext_ops_epi(opc); -} - - -void dsp_op5(uint16 opc) -{ - dsp_op_ext_ops_pro(opc); - - switch ((opc >> 8) & 0xf) - { - case 0x0: - case 0x1: - case 0x2: - case 0x3: - case 0x4: - case 0x5: - case 0x6: - case 0x7: - dsp_opc_subr(opc); - break; - - case 0x8: - case 0x9: - case 0xa: - case 0xb: - dsp_opc_subax(opc); - break; - - case 0xc: - case 0xd: - dsp_opc_sub(opc); - break; - - default: - ErrorLog("dsp_op5: %x", (opc >> 8) & 0xf); - break; - } - - dsp_op_ext_ops_epi(opc); -} - - -void dsp_op6(uint16 opc) -{ - dsp_op_ext_ops_pro(opc); - - switch ((opc >> 8) & 0xf) - { - case 0x00: // MOVR - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - dsp_opc_movr(opc); - break; - - case 0x8: // MVAXA - case 0x9: - case 0xa: - case 0xb: - dsp_opc_movax(opc); - break; - - case 0xe: - case 0xf: - dsp_opc_movp(opc); - break; - - default: - ErrorLog("dsp_op6"); - break; - } - - dsp_op_ext_ops_epi(opc); -} - - -void dsp_op7(uint16 opc) -{ - dsp_op_ext_ops_pro(opc); - - switch ((opc >> 8) & 0xf) - { - case 0x0: - case 0x1: - case 0x2: - case 0x3: - dsp_opc_addaxl(opc); - break; - - case 0x4: - case 0x5: - dsp_opc_incm(opc); - break; - - case 0x6: - case 0x7: - dsp_opc_inc(opc); - break; - - case 0x8: - case 0x9: - dsp_opc_decm(opc); - break; - - case 0xa: - case 0xb: - dsp_opc_dec(opc); - break; - - case 0xc: - case 0xd: - dsp_opc_neg(opc); - break; - - case 0xe: - case 0xf: - dsp_opc_movnp(opc); - break; - - default: - ErrorLog("dsp_op7"); - break; - } - - dsp_op_ext_ops_epi(opc); -} - - -void dsp_op8(uint16 opc) -{ - dsp_op_ext_ops_pro(opc); - - switch ((opc >> 8) & 0xf) - { - case 0x0: - case 0x8: - dsp_opc_nx(opc); - break; - - case 0x1: // CLR 0 - case 0x9: // CLR 1 - dsp_opc_clr(opc); - break; - - case 0x2: // CMP - dsp_opc_cmp(opc); - break; - - case 0x4: // CLRP - dsp_opc_clrp(opc); - break; - - case 0x6: - case 0x7: - dsp_opc_tstaxh(opc); - break; - - case 0xc: - case 0xb: - case 0xe: // SET40 - case 0xd: - case 0xa: - case 0xf: - dsp_opc_srbith(opc); - break; - - default: - ErrorLog("dsp_op8"); - break; - } - - dsp_op_ext_ops_epi(opc); -} - - -void dsp_op9(uint16 opc) -{ - dsp_op_ext_ops_pro(opc); - - switch ((opc >> 8) & 0xf) - { - case 0x02: - case 0x03: - case 0x0a: - case 0x0b: - dsp_opc_mulmvz(opc); - break; - - case 0x04: - case 0x05: - case 0x0c: - case 0x0d: - dsp_opc_mulac(opc); - break; - - case 0x6: - case 0x7: - case 0xe: - case 0xf: - dsp_opc_mulmv(opc); - break; - - case 0x0: - case 0x8: - dsp_opc_mul(opc); - break; - - case 0x1: - case 0x9: - dsp_opc_asr16(opc); - break; - - default: - ErrorLog("dsp_op9"); - break; - } - - dsp_op_ext_ops_epi(opc); -} - - -void dsp_opab(uint16 opc) -{ - dsp_op_ext_ops_pro(opc); - - switch ((opc >> 8) & 0x7) - { - case 0x0: - dsp_opc_mulx(opc); - break; - - case 0x1: - dsp_opc_tsta(opc); - break; - - case 0x2: - case 0x3: - dsp_opc_mulxmvz(opc); - break; - - case 0x4: - case 0x5: - dsp_opc_mulxac(opc); - break; - - case 0x6: - case 0x7: - dsp_opc_mulxmv(opc); - break; - - default: - ErrorLog("dsp_opab"); - } - - dsp_op_ext_ops_epi(opc); -} - - -void dsp_opcd(uint16 opc) -{ - dsp_op_ext_ops_pro(opc); - - switch ((opc >> 8) & 0x7) - { - case 0x0: // MULC - dsp_opc_mulc(opc); - break; - - case 0x1: // CMPAR - dsp_opc_cmpar(opc); - break; - - case 0x2: // MULCMVZ - case 0x3: - dsp_opc_mulcmvz(opc); - break; - - case 0x4: // MULCAC - case 0x5: - dsp_opc_mulcac(opc); - break; - - case 0x6: // MULCMV - case 0x7: - dsp_opc_mulcmv(opc); - break; - - default: - ErrorLog("dsp_opcd"); - } - - dsp_op_ext_ops_epi(opc); -} - - -void dsp_ope(uint16 opc) -{ - dsp_op_ext_ops_pro(opc); - - switch ((opc >> 10) & 0x3) - { - case 0x00: // MADDX - dsp_opc_maddx(opc); - break; - - case 0x01: // MSUBX - dsp_opc_msubx(opc); - break; - - case 0x02: // MADDC - dsp_opc_maddc(opc); - break; - - case 0x03: // MSUBC - dsp_opc_msubc(opc); - break; - - default: - ErrorLog("dsp_ope"); - } - - dsp_op_ext_ops_epi(opc); -} - - -void dsp_opf(uint16 opc) -{ - dsp_op_ext_ops_pro(opc); - - switch ((opc >> 8) & 0xf) - { - case 0x0: - case 0x1: - dsp_opc_lsl16(opc); - break; - - case 0x02: - case 0x03: - dsp_opc_madd(opc); - break; - - case 0x4: - case 0x5: - dsp_opc_lsr16(opc); - break; - - case 0x8: - case 0x9: - case 0xa: - case 0xb: - dsp_opc_addpaxz(opc); - break; - - case 0xe: - case 0xf: - dsp_opc_movpz(opc); - break; - - default: - ErrorLog("dsp_opf"); - break; - } - - dsp_op_ext_ops_epi(opc); -} - - +// Change Log + +// fixed dsp_opc_mulx (regarding DSP 0.0.4.pdf) +// fixed dsp_opc_mulxmv (regarding DSP 0.0.4.pdf) +// fixed dsp_opc_mulxmvz (regarding DSP 0.0.4.pdf) +// dsp_opc_shifti: removed strange " >> 9" +// added masking for SR_COMPARE_FLAGS +// added "UNKNOWN_CW" but without a function (yet? :) +// added missing compare type to MISSING_COMPARES_JX ... but i dunno what it does + +// added "MULXMV" to another function table + +/*==================================================================== + + filename: gdsp_opcodes.cpp + project: GCemu + created: 2004-6-18 + mail: duddie@walla.com + + Copyright (c) 2005 Duddie & Tratax + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + ====================================================================*/ + +#include +#include "Globals.h" +#include "gdsp_opcodes.h" +#include "gdsp_memory.h" +#include "gdsp_interpreter.h" +#include "gdsp_registers.h" +#include "gdsp_opcodes_helper.h" +#include "gdsp_ext_op.h" + +#define SR_CMP_MASK 0x3f +#define DSP_REG_MASK 0x1f + + +void Update_SR_Register(sint64 _Value) +{ + g_dsp.r[R_SR] &= ~SR_CMP_MASK; + + if (_Value < 0) + { + g_dsp.r[R_SR] |= 0x8; + } + + if (_Value == 0) + { + g_dsp.r[R_SR] |= 0x4; + } + + // logic + if ((_Value >> 62) == 0) + { + g_dsp.r[R_SR] |= 0x20; + } +} + + +void Update_SR_Register(sint16 _Value) +{ + g_dsp.r[R_SR] &= ~SR_CMP_MASK; + + if (_Value < 0) + { + g_dsp.r[R_SR] |= 0x8; + } + + if (_Value == 0) + { + g_dsp.r[R_SR] |= 0x4; + } + + // logic + if ((_Value >> 14) == 0) + { + g_dsp.r[R_SR] |= 0x20; + } +} + + +sint8 GetMultiplyModifier() +{ + if (g_dsp.r[R_SR] & (1 << 13)) + { + return(1); + } + + return(2); +} + + +bool CheckCondition(uint8 _Condition) +{ + bool taken = false; + + switch (_Condition & 0xf) + { + case 0x0: + + if ((!(g_dsp.r[R_SR] & 0x02)) && (!(g_dsp.r[R_SR] & 0x08))) + { + taken = true; + } + + break; + + case 0x3: + + if ((g_dsp.r[R_SR] & 0x02) || (g_dsp.r[R_SR] & 0x04) || (g_dsp.r[R_SR] & 0x08)) + { + taken = true; + } + + break; + + // old from duddie + case 0x1: // seems okay + + if ((!(g_dsp.r[R_SR] & 0x02)) && (g_dsp.r[R_SR] & 0x08)) + { + taken = true; + } + + break; + + case 0x2: + + if (!(g_dsp.r[R_SR] & 0x08)) + { + taken = true; + } + + break; + + case 0x4: + + if (!(g_dsp.r[R_SR] & 0x04)) + { + taken = true; + } + + break; + + case 0x5: + + if (g_dsp.r[R_SR] & 0x04) + { + taken = true; + } + + break; + + case 0xc: + + if (!(g_dsp.r[R_SR] & 0x40)) + { + taken = true; + } + + break; + + case 0xd: + + if (g_dsp.r[R_SR] & 0x40) + { + taken = true; + } + + break; + + case 0xf: + taken = true; + break; + + default: + // DebugLog("Unknown condition check: 0x%04x\n", _Condition & 0xf); + break; + } + + return(taken); +} + + +// ======================================================================= + +void dsp_op_unknown(uint16 opc) +{ + _assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception"); + ErrorLog("dsp_op_unknown somewhere"); + g_dsp.pc = g_dsp.err_pc; +} + + +void dsp_opc_call(uint16 opc) +{ + uint16 dest = dsp_fetch_code(); + + if (CheckCondition(opc & 0xf)) + { + dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc); + g_dsp.pc = dest; + } +} + + +void dsp_opc_ifcc(uint16 opc) +{ + if (!CheckCondition(opc & 0xf)) + { + dsp_fetch_code(); // skip the next opcode + } +} + + +void dsp_opc_jcc(uint16 opc) +{ + uint16 dest = dsp_fetch_code(); + + if (CheckCondition(opc & 0xf)) + { + g_dsp.pc = dest; + } +} + + +void dsp_opc_jmpa(uint16 opc) +{ + uint8 reg; + uint16 addr; + + if ((opc & 0xf) != 0xf) + { + ErrorLog("dsp_opc_jmpa"); + } + + reg = (opc >> 5) & 0x7; + addr = dsp_op_read_reg(reg); + + if (opc & 0x0010) + { + // CALLA + dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc); + } + + g_dsp.pc = addr; +} + + +// NEW (added condition check) +void dsp_opc_ret(uint16 opc) +{ + if (CheckCondition(opc & 0xf)) + { + g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C); + } +} + + +void dsp_opc_rti(uint16 opc) +{ + if ((opc & 0xf) != 0xf) + { + ErrorLog("dsp_opc_rti"); + } + + g_dsp.r[R_SR] = dsp_reg_load_stack(DSP_STACK_D); + g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C); + + g_dsp.exception_in_progress_hack = false; +} + + +void dsp_opc_halt(uint16 opc) +{ + g_dsp.cr |= 0x4; + g_dsp.pc = g_dsp.err_pc; +} + + +void dsp_opc_loop(uint16 opc) +{ + uint16 reg = opc & 0x1f; + uint16 cnt = g_dsp.r[reg]; + uint16 loop_pc = g_dsp.pc; + + while (cnt--) + { + gdsp_loop_step(); + g_dsp.pc = loop_pc; + } + + g_dsp.pc = loop_pc + 1; +} + + +void dsp_opc_loopi(uint16 opc) +{ + uint16 cnt = opc & 0xff; + uint16 loop_pc = g_dsp.pc; + + while (cnt--) + { + gdsp_loop_step(); + g_dsp.pc = loop_pc; + } + + g_dsp.pc = loop_pc + 1; +} + + +void dsp_opc_bloop(uint16 opc) +{ + uint16 reg = opc & 0x1f; + uint16 cnt = g_dsp.r[reg]; + uint16 loop_pc = dsp_fetch_code(); + + if (cnt) + { + dsp_reg_store_stack(0, g_dsp.pc); + dsp_reg_store_stack(2, loop_pc); + dsp_reg_store_stack(3, cnt); + } + else + { + g_dsp.pc = loop_pc + 1; + } +} + + +void dsp_opc_bloopi(uint16 opc) +{ + uint16 cnt = opc & 0xff; + uint16 loop_pc = dsp_fetch_code(); + + if (cnt) + { + dsp_reg_store_stack(0, g_dsp.pc); + dsp_reg_store_stack(2, loop_pc); + dsp_reg_store_stack(3, cnt); + } + else + { + g_dsp.pc = loop_pc + 1; + } +} + + +//------------------------------------------------------------- + + +void dsp_opc_mrr(uint16 opc) +{ + uint8 sreg = opc & 0x1f; + uint8 dreg = (opc >> 5) & 0x1f; + + uint16 val = dsp_op_read_reg(sreg); + dsp_op_write_reg(dreg, val); +} + + +void dsp_opc_lrr(uint16 opc) +{ + uint8 sreg = (opc >> 5) & 0x3; + uint8 dreg = opc & 0x1f; + + uint16 val = dsp_dmem_read(g_dsp.r[sreg]); + dsp_op_write_reg(dreg, val); + + // post processing of source reg + switch ((opc >> 7) & 0x3) + { + case 0x0: // LRR + break; + + case 0x1: // LRRD + g_dsp.r[sreg]--; + break; + + case 0x2: // LRRI + g_dsp.r[sreg]++; + break; + + case 0x3: + g_dsp.r[sreg] += g_dsp.r[sreg + 4]; + break; + } +} + + +void dsp_opc_srr(uint16 opc) +{ + uint8 dreg = (opc >> 5) & 0x3; + uint8 sreg = opc & 0x1f; + + uint16 val = dsp_op_read_reg(sreg); + dsp_dmem_write(g_dsp.r[dreg], val); + + // post processing of dest reg + switch ((opc >> 7) & 0x3) + { + case 0x0: // SRR + break; + + case 0x1: // SRRD + g_dsp.r[dreg]--; + break; + + case 0x2: // SRRI + g_dsp.r[dreg]++; + break; + + case 0x3: // SRRX + g_dsp.r[dreg] += g_dsp.r[dreg + 4]; + break; + } +} + + +void dsp_opc_ilrr(uint16 opc) +{ + uint16 reg = opc & 0x3; + uint16 dreg = 0x1e + ((opc >> 8) & 1); + + // always to acc0 ? + g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]); + + switch ((opc >> 2) & 0x3) + { + case 0x0: // no change + break; + + case 0x1: // post decrement + g_dsp.r[reg]--; + break; + + case 0x2: // post increment + g_dsp.r[reg]++; + break; + + default: + ErrorLog("dsp_opc_ilrr"); + } +} + + +void dsp_opc_lri(uint16 opc) +{ + uint8 reg = opc & DSP_REG_MASK; + uint16 imm = dsp_fetch_code(); + dsp_op_write_reg(reg, imm); +} + + +void dsp_opc_lris(uint16 opc) +{ + uint8 reg = ((opc >> 8) & 0x7) + 0x18; + uint16 imm = (sint8)opc; + dsp_op_write_reg(reg, imm); +} + + +void dsp_opc_lr(uint16 opc) +{ + uint8 reg = opc & DSP_REG_MASK; + uint16 addr = dsp_fetch_code(); + uint16 val = dsp_dmem_read(addr); + dsp_op_write_reg(reg, val); +} + + +void dsp_opc_sr(uint16 opc) +{ + uint8 reg = opc & DSP_REG_MASK; + uint16 addr = dsp_fetch_code(); + uint16 val = dsp_op_read_reg(reg); + dsp_dmem_write(addr, val); +} + + +void dsp_opc_si(uint16 opc) +{ + uint16 addr = (sint8)opc; + uint16 imm = dsp_fetch_code(); + dsp_dmem_write(addr, imm); +} + + +void dsp_opc_tstaxh(uint16 opc) +{ + uint8 reg = (opc >> 8) & 0x1; + sint16 val = dsp_get_ax_h(reg); + + Update_SR_Register(val); +} + + +void dsp_opc_clr(uint16 opc) +{ + uint8 reg = (opc >> 11) & 0x1; + + dsp_set_long_acc(reg, 0); + + Update_SR_Register((sint64)0); +} + + +void dsp_opc_clrp(uint16 opc) +{ + g_dsp.r[0x14] = 0x0000; + g_dsp.r[0x15] = 0xfff0; + g_dsp.r[0x16] = 0x00ff; + g_dsp.r[0x17] = 0x0010; +} + + +// NEW +void dsp_opc_mulc(uint16 opc) +{ + // math new prod + uint8 sreg = (opc >> 11) & 0x1; + uint8 treg = (opc >> 12) & 0x1; + + sint64 prod = dsp_get_acc_m(sreg) * dsp_get_ax_h(treg) * GetMultiplyModifier(); + dsp_set_long_prod(prod); + + Update_SR_Register(prod); +} + + +// NEW +void dsp_opc_mulcmvz(uint16 opc) +{ + ErrorLog("dsp_opc_mulcmvz ni"); +} + + +// NEW +void dsp_opc_mulcmv(uint16 opc) +{ + ErrorLog("dsp_opc_mulcmv ni"); +} + + +void dsp_opc_cmpar(uint16 opc) +{ + uint8 rreg = ((opc >> 12) & 0x1) + 0x1a; + uint8 areg = (opc >> 11) & 0x1; + + // we compare + sint64 rr = (sint16)g_dsp.r[rreg]; + rr <<= 16; + + sint64 ar = dsp_get_long_acc(areg); + + Update_SR_Register(ar - rr); +} + + +void dsp_opc_cmp(uint16 opc) +{ + sint64 acc0 = dsp_get_long_acc(0); + sint64 acc1 = dsp_get_long_acc(1); + + Update_SR_Register(acc0 - acc1); +} + + +void dsp_opc_tsta(uint16 opc) +{ + uint8 reg = (opc >> 11) & 0x1; + sint64 acc = dsp_get_long_acc(reg); + + Update_SR_Register(acc); +} + + +// NEW +void dsp_opc_addaxl(uint16 opc) +{ + uint8 sreg = (opc >> 9) & 0x1; + uint8 dreg = (opc >> 8) & 0x1; + + sint64 acc = dsp_get_long_acc(dreg); + sint64 acx = dsp_get_ax_l(sreg); + + acc += acx; + + dsp_set_long_acc(dreg, acc); + + Update_SR_Register(acc); +} + + +// NEW +void dsp_opc_addarn(uint16 opc) +{ + uint8 dreg = opc & 0x3; + uint8 sreg = (opc >> 2) & 0x3; + + g_dsp.r[dreg] += (sint16)g_dsp.r[0x04 + sreg]; +} + + +// NEW +void dsp_opc_mulcac(uint16 opc) +{ + sint64 TempProd = dsp_get_long_prod(); + + // update prod + uint8 sreg = (opc >> 12) & 0x1; + sint64 Prod = (sint64)dsp_get_acc_m(sreg) * (sint64)dsp_get_acc_h(sreg) * GetMultiplyModifier(); + dsp_set_long_prod(Prod); + + // update acc + uint8 rreg = (opc >> 8) & 0x1; + dsp_set_long_acc(rreg, TempProd); +} + + +// NEW +void dsp_opc_movr(uint16 opc) +{ + uint8 areg = (opc >> 8) & 0x1; + uint8 sreg = ((opc >> 9) & 0x3) + 0x18; + + sint64 acc = (sint16)g_dsp.r[sreg]; + acc <<= 16; + acc &= ~0xffff; + + dsp_set_long_acc(areg, acc); + + Update_SR_Register(acc); +} + + +void dsp_opc_movax(uint16 opc) +{ + uint8 sreg = (opc >> 9) & 0x1; + uint8 dreg = (opc >> 8) & 0x1; + + g_dsp.r[0x1c + dreg] = g_dsp.r[0x18 + sreg]; + g_dsp.r[0x1e + dreg] = g_dsp.r[0x1a + sreg]; + + if ((sint16)g_dsp.r[0x1a + sreg] < 0) + { + g_dsp.r[0x10 + dreg] = 0xffff; + } + else + { + g_dsp.r[0x10 + dreg] = 0; + } + + dsp_opc_tsta(dreg << 11); +} + + +// NEW +void dsp_opc_xorr(uint16 opc) +{ + uint8 sreg = (opc >> 9) & 0x1; + uint8 dreg = (opc >> 8) & 0x1; + + g_dsp.r[0x1e + dreg] ^= g_dsp.r[0x1a + sreg]; + + dsp_opc_tsta(dreg << 11); +} + + +void dsp_opc_andr(uint16 opc) +{ + uint8 sreg = (opc >> 9) & 0x1; + uint8 dreg = (opc >> 8) & 0x1; + + g_dsp.r[0x1e + dreg] &= g_dsp.r[0x1a + sreg]; + + dsp_opc_tsta(dreg << 11); +} + + +// NEW +void dsp_opc_orr(uint16 opc) +{ + uint8 sreg = (opc >> 9) & 0x1; + uint8 dreg = (opc >> 8) & 0x1; + + g_dsp.r[0x1e + dreg] |= g_dsp.r[0x1a + sreg]; + + dsp_opc_tsta(dreg << 11); +} + + +// NEW +void dsp_opc_andc(uint16 opc) +{ + uint8 D = (opc >> 8) & 0x1; + + uint16 ac1 = dsp_get_acc_m(D); + uint16 ac2 = dsp_get_acc_m(1 - D); + + dsp_set_long_acc(D, ac1 & ac2); + + if ((ac1 & ac2) == 0) + { + g_dsp.r[R_SR] |= 0x20; + } + else + { + g_dsp.r[R_SR] &= ~0x20; + } +} + + +//------------------------------------------------------------- + +void dsp_opc_nx(uint16 opc) +{} + + +// NEW +void dsp_opc_andfc(uint16 opc) +{ + if (opc & 0xf) + { + ErrorLog("dsp_opc_andfc"); + } + + uint8 reg = (opc >> 8) & 0x1; + uint16 imm = dsp_fetch_code(); + uint16 val = dsp_get_acc_m(reg); + + if ((val & imm) == imm) + { + g_dsp.r[R_SR] |= 0x40; + } + else + { + g_dsp.r[R_SR] &= ~0x40; + } +} + + +void dsp_opc_andf(uint16 opc) +{ + uint8 reg; + uint16 imm; + uint16 val; + + if (opc & 0xf) + { + ErrorLog("dsp_opc_andf"); + } + + reg = 0x1e + ((opc >> 8) & 0x1); + imm = dsp_fetch_code(); + val = g_dsp.r[reg]; + + if ((val & imm) == 0) + { + g_dsp.r[R_SR] |= 0x40; + } + else + { + g_dsp.r[R_SR] &= ~0x40; + } +} + + +void dsp_opc_subf(uint16 opc) +{ + if (opc & 0xf) + { + ErrorLog("dsp_opc_subf"); + } + + uint8 reg = 0x1e + ((opc >> 8) & 0x1); + sint64 imm = (sint16)dsp_fetch_code(); + + sint64 val = (sint16)g_dsp.r[reg]; + sint64 res = val - imm; + + Update_SR_Register(res); +} + + +void dsp_opc_xori(uint16 opc) +{ + if (opc & 0xf) + { + ErrorLog("dsp_opc_xori"); + } + + uint8 reg = 0x1e + ((opc >> 8) & 0x1); + uint16 imm = dsp_fetch_code(); + g_dsp.r[reg] ^= imm; + + Update_SR_Register((sint16)g_dsp.r[reg]); +} + + +void dsp_opc_andi(uint16 opc) +{ + if (opc & 0xf) + { + ErrorLog("dsp_opc_andi"); + } + + uint8 reg = 0x1e + ((opc >> 8) & 0x1); + uint16 imm = dsp_fetch_code(); + g_dsp.r[reg] &= imm; + + Update_SR_Register((sint16)g_dsp.r[reg]); +} + + +// F|RES: i am not sure if this shouldnt be the whole ACC +// +void dsp_opc_ori(uint16 opc) +{ + if (opc & 0xf) + { + return(ErrorLog("dsp_opc_ori")); + } + + uint8 reg = 0x1e + ((opc >> 8) & 0x1); + uint16 imm = dsp_fetch_code(); + g_dsp.r[reg] |= imm; + + Update_SR_Register((sint16)g_dsp.r[reg]); +} + + +//------------------------------------------------------------- + +void dsp_opc_add(uint16 opc) +{ + uint8 areg = (opc >> 8) & 0x1; + sint64 acc0 = dsp_get_long_acc(0); + sint64 acc1 = dsp_get_long_acc(1); + + sint64 res = acc0 + acc1; + + dsp_set_long_acc(areg, res); + + Update_SR_Register(res); +} + + +//------------------------------------------------------------- + +void dsp_opc_addp(uint16 opc) +{ + uint8 dreg = (opc >> 8) & 0x1; + sint64 acc = dsp_get_long_acc(dreg); + acc = acc + dsp_get_long_prod(); + dsp_set_long_acc(dreg, acc); + + Update_SR_Register(acc); +} + + +void dsp_opc_cmpis(uint16 opc) +{ + uint8 areg = (opc >> 8) & 0x1; + + sint64 acc = dsp_get_long_acc(areg); + sint64 val = (sint8)opc; + val <<= 16; + + sint64 res = acc - val; + + Update_SR_Register(res); +} + + +// NEW +// verified at the console +void dsp_opc_addpaxz(uint16 opc) +{ + uint8 dreg = (opc >> 8) & 0x1; + uint8 sreg = (opc >> 9) & 0x1; + + sint64 prod = dsp_get_long_prod() & ~0x0ffff; + sint64 ax_h = dsp_get_long_acx(sreg); + sint64 acc = (prod + ax_h) & ~0x0ffff; + + dsp_set_long_acc(dreg, acc); + + Update_SR_Register(acc); +} + + +// NEW +void dsp_opc_movpz(uint16 opc) +{ + uint8 dreg = (opc >> 8) & 0x01; + + // overwrite acc and clear low part + sint64 prod = dsp_get_long_prod(); + sint64 acc = prod & ~0xffff; + dsp_set_long_acc(dreg, acc); + + Update_SR_Register(acc); +} + + +void dsp_opc_decm(uint16 opc) +{ + uint8 dreg = (opc >> 8) & 0x01; + + sint64 sub = 0x10000; + sint64 acc = dsp_get_long_acc(dreg); + acc -= sub; + dsp_set_long_acc(dreg, acc); + + Update_SR_Register(acc); +} + + +void dsp_opc_dec(uint16 opc) +{ + uint8 dreg = (opc >> 8) & 0x01; + + sint64 acc = dsp_get_long_acc(dreg) - 1; + dsp_set_long_acc(dreg, acc); + + Update_SR_Register(acc); +} + + +void dsp_opc_incm(uint16 opc) +{ + uint8 dreg = (opc >> 8) & 0x1; + + sint64 sub = 0x10000; + sint64 acc = dsp_get_long_acc(dreg); + acc += sub; + dsp_set_long_acc(dreg, acc); + + Update_SR_Register(acc); +} + + +void dsp_opc_inc(uint16 opc) +{ + uint8 dreg = (opc >> 8) & 0x1; + + sint64 acc = dsp_get_long_acc(dreg); + acc++; + dsp_set_long_acc(dreg, acc); + + Update_SR_Register(acc); +} + + +void dsp_opc_neg(uint16 opc) +{ + uint8 areg = (opc >> 8) & 0x1; + + sint64 acc = dsp_get_long_acc(areg); + acc = 0 - acc; + dsp_set_long_acc(areg, acc); + + Update_SR_Register(acc); +} + + +void dsp_opc_movnp(uint16 opc) +{ + ErrorLog("dsp_opc_movnp\n"); +} + + +// NEW +void dsp_opc_addax(uint16 opc) +{ + uint8 areg = (opc >> 8) & 0x1; + uint8 sreg = (opc >> 9) & 0x1; + + sint64 ax = dsp_get_long_acx(sreg); + sint64 acc = dsp_get_long_acc(areg); + acc += ax; + dsp_set_long_acc(areg, acc); + + Update_SR_Register(acc); +} + + +void dsp_opc_addr(uint16 opc) +{ + uint8 areg = (opc >> 8) & 0x1; + uint8 sreg = ((opc >> 9) & 0x3) + 0x18; + + sint64 ax = (sint16)g_dsp.r[sreg]; + ax <<= 16; + + sint64 acc = dsp_get_long_acc(areg); + acc += ax; + dsp_set_long_acc(areg, acc); + + Update_SR_Register(acc); +} + + +void dsp_opc_subr(uint16 opc) +{ + uint8 areg = (opc >> 8) & 0x1; + uint8 sreg = ((opc >> 9) & 0x3) + 0x18; + + sint64 ax = (sint16)g_dsp.r[sreg]; + ax <<= 16; + + sint64 acc = dsp_get_long_acc(areg); + acc -= ax; + dsp_set_long_acc(areg, acc); + + Update_SR_Register(acc); +} + +// NEW +void dsp_opc_subax(uint16 opc) +{ + int regD = (opc >> 8) & 0x1; + int regT = (opc >> 9) & 0x1; + + sint64 Acc = dsp_get_long_acc(regD) - dsp_get_long_acx(regT); + + dsp_set_long_acc(regD, Acc); + Update_SR_Register(Acc); +} + +void dsp_opc_addis(uint16 opc) +{ + uint8 areg = (opc >> 8) & 0x1; + + sint64 Imm = (sint8)opc; + Imm <<= 16; + sint64 acc = dsp_get_long_acc(areg); + acc += Imm; + dsp_set_long_acc(areg, acc); + + Update_SR_Register(acc); +} + + +void dsp_opc_addi(uint16 opc) +{ + uint8 areg = (opc >> 8) & 0x1; + + sint64 sub = (sint16)dsp_fetch_code(); + sub <<= 16; + sint64 acc = dsp_get_long_acc(areg); + acc += sub; + dsp_set_long_acc(areg, acc); + + Update_SR_Register(acc); +} + + +void dsp_opc_lsl16(uint16 opc) +{ + uint8 areg = (opc >> 8) & 0x1; + + sint64 acc = dsp_get_long_acc(areg); + acc <<= 16; + dsp_set_long_acc(areg, acc); + + Update_SR_Register(acc); +} + + +// NEW +void dsp_opc_madd(uint16 opc) +{ + uint8 sreg = (opc >> 8) & 0x1; + + sint64 prod = dsp_get_long_prod(); + prod += (sint64)dsp_get_ax_l(sreg) * (sint64)dsp_get_ax_h(sreg) * GetMultiplyModifier(); + dsp_set_long_prod(prod); +} + + +void dsp_opc_lsr16(uint16 opc) +{ + uint8 areg = (opc >> 8) & 0x1; + + sint64 acc = dsp_get_long_acc(areg); + acc >>= 16; + dsp_set_long_acc(areg, acc); + + Update_SR_Register(acc); +} + + +void dsp_opc_asr16(uint16 opc) +{ + uint8 areg = (opc >> 11) & 0x1; + + sint64 acc = dsp_get_long_acc(areg); + acc >>= 16; + dsp_set_long_acc(areg, acc); + + Update_SR_Register(acc); +} + + +union UOpcodeShifti +{ + uint16 Hex; + struct + { + signed shift : 6; + unsigned negating : 1; + unsigned arithmetic : 1; + unsigned areg : 1; + unsigned op : 7; + }; + struct + { + unsigned ushift : 6; + }; + UOpcodeShifti(uint16 _Hex) + : Hex(_Hex) {} +}; + +void dsp_opc_shifti(uint16 opc) +{ + UOpcodeShifti Opcode(opc); + + // direction: left + bool ShiftLeft = true; + uint16 shift = Opcode.ushift; + + if ((Opcode.negating) && (Opcode.shift < 0)) + { + ShiftLeft = false; + shift = -Opcode.shift; + } + + sint64 acc; + uint64 uacc; + + if (Opcode.arithmetic) + { + // arithmetic shift + uacc = dsp_get_long_acc(Opcode.areg); + + if (!ShiftLeft) + { + uacc >>= shift; + } + else + { + uacc <<= shift; + } + + acc = uacc; + } + else + { + acc = dsp_get_long_acc(Opcode.areg); + + if (!ShiftLeft) + { + acc >>= shift; + } + else + { + acc <<= shift; + } + } + + dsp_set_long_acc(Opcode.areg, acc); + + Update_SR_Register(acc); +} + + +//------------------------------------------------------------- +// hcs give me this code!! +void dsp_opc_dar(uint16 opc) +{ + uint8 reg = opc & 0x3; + + int temp = g_dsp.r[reg] + g_dsp.r[8]; + + if (temp <= 0x7ff){g_dsp.r[reg] = temp;} + else {g_dsp.r[reg]--;} +} + + +// hcs give me this code!! +void dsp_opc_iar(uint16 opc) +{ + uint8 reg = opc & 0x3; + + int temp = g_dsp.r[reg] + g_dsp.r[8]; + + if (temp <= 0x7ff){g_dsp.r[reg] = temp;} + else {g_dsp.r[reg]++;} +} + + +//------------------------------------------------------------- + +void dsp_opc_sbclr(uint16 opc) +{ + uint8 bit = (opc & 0xff) + 6; + g_dsp.r[R_SR] &= ~(1 << bit); +} + + +void dsp_opc_sbset(uint16 opc) +{ + uint8 bit = (opc & 0xff) + 6; + g_dsp.r[R_SR] |= (1 << bit); +} + + +void dsp_opc_srbith(uint16 opc) +{ + switch ((opc >> 8) & 0xf) + { + case 0xe: // SET40 + g_dsp.r[R_SR] &= ~(1 << 14); + break; + +/* case 0xf: // SET16 // that doesnt happen on a real console + g_dsp.r[R_SR] |= (1 << 14); + break;*/ + + default: + break; + } +} + + +//------------------------------------------------------------- + +void dsp_opc_movp(uint16 opc) +{ + uint8 dreg = (opc >> 8) & 0x1; + + sint64 prod = dsp_get_long_prod(); + sint64 acc = prod; + dsp_set_long_acc(dreg, acc); +} + + +void dsp_opc_mul(uint16 opc) +{ + uint8 sreg = (opc >> 11) & 0x1; + sint64 prod = (sint64)dsp_get_ax_h(sreg) * (sint64)dsp_get_ax_l(sreg) * GetMultiplyModifier(); + + dsp_set_long_prod(prod); + + Update_SR_Register(prod); +} + +// NEW +void dsp_opc_mulac(uint16 opc) +{ + // add old prod to acc + uint8 rreg = (opc >> 8) & 0x1; + sint64 acR = dsp_get_long_acc(rreg) + dsp_get_long_prod(); + dsp_set_long_acc(rreg, acR); + + // math new prod + uint8 sreg = (opc >> 11) & 0x1; + sint64 prod = dsp_get_ax_l(sreg) * dsp_get_ax_h(sreg) * GetMultiplyModifier(); + dsp_set_long_prod(prod); + + Update_SR_Register(prod); +} + + +void dsp_opc_mulmv(uint16 opc) +{ + uint8 rreg = (opc >> 8) & 0x1; + sint64 prod = dsp_get_long_prod(); + sint64 acc = prod; + dsp_set_long_acc(rreg, acc); + + uint8 areg = ((opc >> 11) & 0x1) + 0x18; + uint8 breg = ((opc >> 11) & 0x1) + 0x1a; + sint64 val1 = (sint16)g_dsp.r[areg]; + sint64 val2 = (sint16)g_dsp.r[breg]; + + prod = val1 * val2 * GetMultiplyModifier(); + + dsp_set_long_prod(prod); + + Update_SR_Register(prod); +} + + +// NEW +void dsp_opc_mulmvz(uint16 opc) +{ + uint8 sreg = (opc >> 11) & 0x1; + uint8 rreg = (opc >> 8) & 0x1; + + // overwrite acc and clear low part + sint64 prod = dsp_get_long_prod(); + sint64 acc = prod & ~0xffff; + dsp_set_long_acc(rreg, acc); + + // math prod + prod = (sint64)g_dsp.r[0x18 + sreg] * (sint64)g_dsp.r[0x1a + sreg] * GetMultiplyModifier(); + dsp_set_long_prod(prod); + + Update_SR_Register(prod); +} + + +// NEW +void dsp_opc_mulx(uint16 opc) +{ + uint8 sreg = ((opc >> 12) & 0x1); + uint8 treg = ((opc >> 11) & 0x1); + + sint64 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); + sint64 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); + + sint64 prod = val1 * val2 * GetMultiplyModifier(); + dsp_set_long_prod(prod); + + Update_SR_Register(prod); +} + + +// NEW +void dsp_opc_mulxac(uint16 opc) +{ + // add old prod to acc + uint8 rreg = (opc >> 8) & 0x1; + sint64 acR = dsp_get_long_acc(rreg) + dsp_get_long_prod(); + dsp_set_long_acc(rreg, acR); + + // math new prod + uint8 sreg = (opc >> 12) & 0x1; + uint8 treg = (opc >> 11) & 0x1; + + sint64 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); + sint64 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); + + sint64 prod = val1 * val2 * GetMultiplyModifier(); + dsp_set_long_prod(prod); + + Update_SR_Register(prod); +} + + +// NEW +void dsp_opc_mulxmv(uint16 opc) +{ + // add old prod to acc + uint8 rreg = ((opc >> 8) & 0x1); + sint64 acR = dsp_get_long_prod(); + dsp_set_long_acc(rreg, acR); + + // math new prod + uint8 sreg = (opc >> 12) & 0x1; + uint8 treg = (opc >> 11) & 0x1; + + sint64 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); + sint64 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); + + sint64 prod = val1 * val2 * GetMultiplyModifier(); + dsp_set_long_prod(prod); + + Update_SR_Register(prod); +} + + +// NEW +void dsp_opc_mulxmvz(uint16 opc) +{ + // overwrite acc and clear low part + uint8 rreg = (opc >> 8) & 0x1; + sint64 prod = dsp_get_long_prod(); + sint64 acc = prod & ~0xffff; + dsp_set_long_acc(rreg, acc); + + // math prod + uint8 sreg = (opc >> 12) & 0x1; + uint8 treg = (opc >> 11) & 0x1; + + sint64 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); + sint64 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); + + prod = val1 * val2 * GetMultiplyModifier(); + dsp_set_long_prod(prod); + + Update_SR_Register(prod); +} + + +// NEW +void dsp_opc_sub(uint16 opc) +{ + uint8 D = (opc >> 8) & 0x1; + sint64 Acc1 = dsp_get_long_acc(D); + sint64 Acc2 = dsp_get_long_acc(1 - D); + + Acc1 -= Acc2; + + dsp_set_long_acc(D, Acc1); +} + + +//------------------------------------------------------------- +// +// --- Table E +// +//------------------------------------------------------------- + +// NEW +void dsp_opc_maddx(uint16 opc) +{ + uint8 sreg = (opc >> 9) & 0x1; + uint8 treg = (opc >> 8) & 0x1; + + sint64 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); + sint64 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); + + sint64 prod = dsp_get_long_prod(); + prod += val1 * val2 * GetMultiplyModifier(); + dsp_set_long_prod(prod); +} + + +// NEW +void dsp_opc_msubx(uint16 opc) +{ + uint8 sreg = (opc >> 9) & 0x1; + uint8 treg = (opc >> 8) & 0x1; + + sint64 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); + sint64 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); + + sint64 prod = dsp_get_long_prod(); + prod -= val1 * val2 * GetMultiplyModifier(); + dsp_set_long_prod(prod); +} + + +// NEW +void dsp_opc_maddc(uint16 opc) +{ + uint sreg = (opc >> 9) & 0x1; + uint treg = (opc >> 8) & 0x1; + + sint64 val1 = dsp_get_acc_m(sreg); + sint64 val2 = dsp_get_ax_h(treg); + + sint64 prod = dsp_get_long_prod(); + prod += val1 * val2 * GetMultiplyModifier(); + dsp_set_long_prod(prod); +} + + +// NEW +void dsp_opc_msubc(uint16 opc) +{ + uint sreg = (opc >> 9) & 0x1; + uint treg = (opc >> 8) & 0x1; + + sint64 val1 = dsp_get_acc_m(sreg); + sint64 val2 = dsp_get_ax_h(treg); + + sint64 prod = dsp_get_long_prod(); + prod -= val1 * val2 * GetMultiplyModifier(); + dsp_set_long_prod(prod); +} + + +//------------------------------------------------------------- +void dsp_op0(uint16 opc) +{ + if (opc == 0) + { + return; + } + + switch ((opc >> 8) & 0xf) + { + case 0x0: + + switch ((opc >> 4) & 0xf) + { + case 0x0: + + switch (opc & 0xf) + { + case 0x4: + case 0x5: + case 0x6: + case 0x7: + dsp_opc_dar(opc); + break; + + case 0x8: + case 0x9: + case 0xa: + case 0xb: + dsp_opc_iar(opc); + break; + + default: + ErrorLog("dsp_op0"); + break; + } + + break; + + case 0x1: + dsp_opc_addarn(opc); + break; + + case 0x2: // HALT + dsp_opc_halt(opc); + break; + + case 0x4: // LOOP + case 0x5: // LOOP + dsp_opc_loop(opc); + break; + + case 0x6: // BLOOP + case 0x7: // BLOOP + dsp_opc_bloop(opc); + break; + + case 0x8: // LRI + case 0x9: // LRI + dsp_opc_lri(opc); + break; + + case 0xC: // LR + case 0xD: // LR + dsp_opc_lr(opc); + break; + + case 0xE: // SR + case 0xF: // SR + dsp_opc_sr(opc); + break; + + default: + ErrorLog("dsp_op0"); + break; + } + + break; + + case 0x2: + + switch ((opc >> 4) & 0xf) + { + case 0x0: // ADDI + dsp_opc_addi(opc); + break; + + case 0x1: // IL + dsp_opc_ilrr(opc); + break; + + case 0x2: // XORI + dsp_opc_xori(opc); + break; + + case 0x4: // ANDI + dsp_opc_andi(opc); + break; + + case 0x6: // ORI + dsp_opc_ori(opc); + break; + + case 0x7: // + dsp_opc_ifcc(opc); + break; + + case 0x8: // SUBF + dsp_opc_subf(opc); + break; + + case 0x9: // Jxx + dsp_opc_jcc(opc); + break; + + case 0xa: // ANDF + dsp_opc_andf(opc); + break; + + case 0xb: // CALL + dsp_opc_call(opc); + break; + + case 0xc: + dsp_opc_andfc(opc); + break; + + case 0xd: // RET + dsp_opc_ret(opc); + break; + + case 0xf: // RTI + dsp_opc_rti(opc); + break; + + default: + ErrorLog("dsp_op0"); + break; + } + + break; + + case 0x3: + + switch ((opc >> 4) & 0xf) + { + case 0x0: // ADDAI + dsp_opc_addi(opc); + break; + + case 0x1: // ILR + dsp_opc_ilrr(opc); + break; + + case 0x2: // XORI + dsp_opc_xori(opc); + break; + + case 0x4: // ANDI + dsp_opc_andi(opc); + break; + + case 0x6: // ORI + dsp_opc_ori(opc); + break; + + case 0x8: // SUBF + dsp_opc_subf(opc); + break; + + case 0xa: // ANDF + dsp_opc_andf(opc); + break; + + case 0xc: // ANDFC + dsp_opc_andfc(opc); + break; + + default: + ErrorLog("dsp_op0"); + break; + } + + break; + + case 0x4: + case 0x5: + dsp_opc_addis(opc); + break; + + case 0x6: // SUBISF + case 0x7: + dsp_opc_cmpis(opc); + break; + + case 0x8: // LRIS + case 0x9: + case 0xa: + case 0xb: + case 0xc: + case 0xd: + case 0xe: + case 0xf: + dsp_opc_lris(opc); + break; + + default: + ErrorLog("dsp_op0"); + break; + } +} + + +void dsp_op1(uint16 opc) +{ + switch ((opc >> 8) & 0xf) + { + case 0x0: + dsp_opc_loopi(opc); + break; + + case 0x1: // BLOOPI + dsp_opc_bloopi(opc); + break; + + case 0x2: // SBCLR + dsp_opc_sbclr(opc); + break; + + case 0x3: // SBSET + dsp_opc_sbset(opc); + break; + + case 0x4: // shifti + case 0x5: + dsp_opc_shifti(opc); + break; + + case 0x6: // SI + dsp_opc_si(opc); + break; + + case 0x7: // JMPA/CALLA + dsp_opc_jmpa(opc); + break; + + case 0x8: // LRRx + case 0x9: // LRRx + dsp_opc_lrr(opc); + break; + + case 0xa: // SRRx + case 0xb: // SRRx + dsp_opc_srr(opc); + break; + + case 0xc: // MRR + case 0xd: // MRR + case 0xe: // MRR + case 0xf: // MRR + dsp_opc_mrr(opc); + break; + + default: + ErrorLog("dsp_op1"); + break; + } +} + + +void dsp_op2(uint16 opc) +{ + // lrs, srs + uint8 reg = ((opc >> 8) & 0x7) + 0x18; + uint16 addr = (sint8) opc; + + if (opc & 0x0800) + { + // srs + dsp_dmem_write(addr, g_dsp.r[reg]); + } + else + { + // lrs + g_dsp.r[reg] = dsp_dmem_read(addr); + } +} + + +void dsp_op3(uint16 opc) +{ + dsp_op_ext_ops_pro(opc); + + switch ((opc >> 8) & 0xf) + { + case 0x0: + case 0x1: + case 0x2: + case 0x3: + dsp_opc_xorr(opc); + break; + + case 0x4: + case 0x5: + case 0x6: + case 0x7: + dsp_opc_andr(opc); + break; + + case 0x8: + case 0x9: + case 0xa: + case 0xb: + dsp_opc_orr(opc); + break; + + case 0xc: + case 0xd: + dsp_opc_andc(opc); + break; + + default: + ErrorLog("dsp_op3"); + break; + } + + dsp_op_ext_ops_epi(opc); +} + + +void dsp_op4(uint16 opc) +{ + dsp_op_ext_ops_pro(opc); + + switch ((opc >> 8) & 0xf) + { + case 0x0: + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + dsp_opc_addr(opc); + break; + + case 0x8: + case 0x9: + case 0xa: + case 0xb: + dsp_opc_addax(opc); + break; + + case 0xc: + case 0xd: + dsp_opc_add(opc); + break; + + case 0xe: + case 0xf: + dsp_opc_addp(opc); + break; + + default: + ErrorLog("dsp_op4"); + break; + } + + dsp_op_ext_ops_epi(opc); +} + + +void dsp_op5(uint16 opc) +{ + dsp_op_ext_ops_pro(opc); + + switch ((opc >> 8) & 0xf) + { + case 0x0: + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + dsp_opc_subr(opc); + break; + + case 0x8: + case 0x9: + case 0xa: + case 0xb: + dsp_opc_subax(opc); + break; + + case 0xc: + case 0xd: + dsp_opc_sub(opc); + break; + + default: + ErrorLog("dsp_op5: %x", (opc >> 8) & 0xf); + break; + } + + dsp_op_ext_ops_epi(opc); +} + + +void dsp_op6(uint16 opc) +{ + dsp_op_ext_ops_pro(opc); + + switch ((opc >> 8) & 0xf) + { + case 0x00: // MOVR + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + dsp_opc_movr(opc); + break; + + case 0x8: // MVAXA + case 0x9: + case 0xa: + case 0xb: + dsp_opc_movax(opc); + break; + + case 0xe: + case 0xf: + dsp_opc_movp(opc); + break; + + default: + ErrorLog("dsp_op6"); + break; + } + + dsp_op_ext_ops_epi(opc); +} + + +void dsp_op7(uint16 opc) +{ + dsp_op_ext_ops_pro(opc); + + switch ((opc >> 8) & 0xf) + { + case 0x0: + case 0x1: + case 0x2: + case 0x3: + dsp_opc_addaxl(opc); + break; + + case 0x4: + case 0x5: + dsp_opc_incm(opc); + break; + + case 0x6: + case 0x7: + dsp_opc_inc(opc); + break; + + case 0x8: + case 0x9: + dsp_opc_decm(opc); + break; + + case 0xa: + case 0xb: + dsp_opc_dec(opc); + break; + + case 0xc: + case 0xd: + dsp_opc_neg(opc); + break; + + case 0xe: + case 0xf: + dsp_opc_movnp(opc); + break; + + default: + ErrorLog("dsp_op7"); + break; + } + + dsp_op_ext_ops_epi(opc); +} + + +void dsp_op8(uint16 opc) +{ + dsp_op_ext_ops_pro(opc); + + switch ((opc >> 8) & 0xf) + { + case 0x0: + case 0x8: + dsp_opc_nx(opc); + break; + + case 0x1: // CLR 0 + case 0x9: // CLR 1 + dsp_opc_clr(opc); + break; + + case 0x2: // CMP + dsp_opc_cmp(opc); + break; + + case 0x4: // CLRP + dsp_opc_clrp(opc); + break; + + case 0x6: + case 0x7: + dsp_opc_tstaxh(opc); + break; + + case 0xc: + case 0xb: + case 0xe: // SET40 + case 0xd: + case 0xa: + case 0xf: + dsp_opc_srbith(opc); + break; + + default: + ErrorLog("dsp_op8"); + break; + } + + dsp_op_ext_ops_epi(opc); +} + + +void dsp_op9(uint16 opc) +{ + dsp_op_ext_ops_pro(opc); + + switch ((opc >> 8) & 0xf) + { + case 0x02: + case 0x03: + case 0x0a: + case 0x0b: + dsp_opc_mulmvz(opc); + break; + + case 0x04: + case 0x05: + case 0x0c: + case 0x0d: + dsp_opc_mulac(opc); + break; + + case 0x6: + case 0x7: + case 0xe: + case 0xf: + dsp_opc_mulmv(opc); + break; + + case 0x0: + case 0x8: + dsp_opc_mul(opc); + break; + + case 0x1: + case 0x9: + dsp_opc_asr16(opc); + break; + + default: + ErrorLog("dsp_op9"); + break; + } + + dsp_op_ext_ops_epi(opc); +} + + +void dsp_opab(uint16 opc) +{ + dsp_op_ext_ops_pro(opc); + + switch ((opc >> 8) & 0x7) + { + case 0x0: + dsp_opc_mulx(opc); + break; + + case 0x1: + dsp_opc_tsta(opc); + break; + + case 0x2: + case 0x3: + dsp_opc_mulxmvz(opc); + break; + + case 0x4: + case 0x5: + dsp_opc_mulxac(opc); + break; + + case 0x6: + case 0x7: + dsp_opc_mulxmv(opc); + break; + + default: + ErrorLog("dsp_opab"); + } + + dsp_op_ext_ops_epi(opc); +} + + +void dsp_opcd(uint16 opc) +{ + dsp_op_ext_ops_pro(opc); + + switch ((opc >> 8) & 0x7) + { + case 0x0: // MULC + dsp_opc_mulc(opc); + break; + + case 0x1: // CMPAR + dsp_opc_cmpar(opc); + break; + + case 0x2: // MULCMVZ + case 0x3: + dsp_opc_mulcmvz(opc); + break; + + case 0x4: // MULCAC + case 0x5: + dsp_opc_mulcac(opc); + break; + + case 0x6: // MULCMV + case 0x7: + dsp_opc_mulcmv(opc); + break; + + default: + ErrorLog("dsp_opcd"); + } + + dsp_op_ext_ops_epi(opc); +} + + +void dsp_ope(uint16 opc) +{ + dsp_op_ext_ops_pro(opc); + + switch ((opc >> 10) & 0x3) + { + case 0x00: // MADDX + dsp_opc_maddx(opc); + break; + + case 0x01: // MSUBX + dsp_opc_msubx(opc); + break; + + case 0x02: // MADDC + dsp_opc_maddc(opc); + break; + + case 0x03: // MSUBC + dsp_opc_msubc(opc); + break; + + default: + ErrorLog("dsp_ope"); + } + + dsp_op_ext_ops_epi(opc); +} + + +void dsp_opf(uint16 opc) +{ + dsp_op_ext_ops_pro(opc); + + switch ((opc >> 8) & 0xf) + { + case 0x0: + case 0x1: + dsp_opc_lsl16(opc); + break; + + case 0x02: + case 0x03: + dsp_opc_madd(opc); + break; + + case 0x4: + case 0x5: + dsp_opc_lsr16(opc); + break; + + case 0x8: + case 0x9: + case 0xa: + case 0xb: + dsp_opc_addpaxz(opc); + break; + + case 0xe: + case 0xf: + dsp_opc_movpz(opc); + break; + + default: + ErrorLog("dsp_opf"); + break; + } + + dsp_op_ext_ops_epi(opc); +} + + diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_registers.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_registers.cpp index bef62309f9..3d70274479 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_registers.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_registers.cpp @@ -1,62 +1,62 @@ -/*==================================================================== - - filename: gdsp_registers.cpp - project: GCemu - created: 2004-6-18 - mail: duddie@walla.com - - Copyright (c) 2005 Duddie & Tratax - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - ====================================================================*/ - -#include "Globals.h" -#include "gdsp_registers.h" -#include "gdsp_interpreter.h" - - - -void dsp_reg_stack_push(uint8 stack_reg) -{ - g_dsp.reg_stack_ptr[stack_reg]++; - g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK; - g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]] = g_dsp.r[DSP_REG_ST0 + stack_reg]; -} - - -void dsp_reg_stack_pop(uint8 stack_reg) -{ - g_dsp.r[DSP_REG_ST0 + stack_reg] = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]]; - g_dsp.reg_stack_ptr[stack_reg]--; - g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK; -} - - -void dsp_reg_store_stack(uint8 stack_reg, uint16 val) -{ - dsp_reg_stack_push(stack_reg); - g_dsp.r[DSP_REG_ST0 + stack_reg] = val; -} - - -uint16 dsp_reg_load_stack(uint8 stack_reg) -{ - uint16 val = g_dsp.r[DSP_REG_ST0 + stack_reg]; - dsp_reg_stack_pop(stack_reg); - return(val); -} - - +/*==================================================================== + + filename: gdsp_registers.cpp + project: GCemu + created: 2004-6-18 + mail: duddie@walla.com + + Copyright (c) 2005 Duddie & Tratax + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + ====================================================================*/ + +#include "Globals.h" +#include "gdsp_registers.h" +#include "gdsp_interpreter.h" + + + +void dsp_reg_stack_push(uint8 stack_reg) +{ + g_dsp.reg_stack_ptr[stack_reg]++; + g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK; + g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]] = g_dsp.r[DSP_REG_ST0 + stack_reg]; +} + + +void dsp_reg_stack_pop(uint8 stack_reg) +{ + g_dsp.r[DSP_REG_ST0 + stack_reg] = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]]; + g_dsp.reg_stack_ptr[stack_reg]--; + g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK; +} + + +void dsp_reg_store_stack(uint8 stack_reg, uint16 val) +{ + dsp_reg_stack_push(stack_reg); + g_dsp.r[DSP_REG_ST0 + stack_reg] = val; +} + + +uint16 dsp_reg_load_stack(uint8 stack_reg) +{ + uint16 val = g_dsp.r[DSP_REG_ST0 + stack_reg]; + dsp_reg_stack_pop(stack_reg); + return(val); +} + + diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp index f07630a682..49c5f4e1b3 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp @@ -1,432 +1,432 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Common.h" -#include "Globals.h" -#include "WaveFile.h" -#include "CommonTypes.h" -#include "Mixer.h" - -#include "gdsp_interpreter.h" -#include "gdsp_interface.h" -#include "disassemble.h" - -#ifdef _WIN32 - #include "DisAsmDlg.h" - #include "DSoundStream.h" - #include "Logging/Console.h" // For wprintf, ClearScreen - #include "Logging/Logging.h" // For Logging - - HINSTANCE g_hInstance = NULL; - HANDLE g_hDSPThread = NULL; - CRITICAL_SECTION g_CriticalSection; - CDisAsmDlg g_Dialog; -#else - #define WINAPI - #define LPVOID void* - #include - #include - #include - #include - #include "AOSoundStream.h" - pthread_t g_hDSPThread = NULL; -#endif - -#include "ChunkFile.h" - - -// ======================================================================================= -// Globals -// -------------- -DSPInitialize g_dspInitialize; - -#define GDSP_MBOX_CPU 0 -#define GDSP_MBOX_DSP 1 - -uint32 g_LastDMAAddress = 0; -uint32 g_LastDMASize = 0; - -extern u32 m_addressPBs; -bool AXTask(u32& _uMail); - -bool bCanWork = false; - -// Set this if you want to log audio. search for log_ai in this file to see the filename. -static bool log_ai = false; -WaveFileWriter g_wave_writer; - -// ============== - - -#ifdef _WIN32 -BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle - DWORD dwReason, // reason called - LPVOID lpvReserved) // reserved -{ - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - break; - - case DLL_PROCESS_DETACH: - break; - - default: - break; - } - - g_hInstance = hinstDLL; - return(TRUE); -} -#endif - -void GetDllInfo(PLUGIN_INFO* _PluginInfo) -{ - _PluginInfo->Version = 0x0100; - _PluginInfo->Type = PLUGIN_TYPE_DSP; - -#ifdef DEBUGFAST - sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin (DebugFast)"); -#else -#ifndef _DEBUG - sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin"); -#else - sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin (Debug)"); -#endif -#endif -} - - -void DllAbout(HWND _hParent) -{} - - -void DllConfig(HWND _hParent) -{} - - -void DSP_DoState(unsigned char **ptr, int mode) { - PointerWrap p(ptr, mode); -} - -void DllDebugger(HWND _hParent, bool Show) -{ -#ifdef _WIN32 - #if defined (_DEBUG) || defined (DEBUGFAST) - g_Dialog.Create(NULL); //_hParent); - g_Dialog.ShowWindow(SW_SHOW); - MoveWindow(g_Dialog.m_hWnd, 450,0, 780,530, true); - - // Open the console window - startConsoleWin(155, 100, "Sound Debugging"); // give room for 100 rows - wprintf("DllDebugger > Console opened\n"); - // TODO: Make this adjustable from the Debugging window - MoveWindow(GetConsoleHwnd(), 0,400, 1280,500, true); - #else - MessageBox(0, "Can't open debugging window in Release build of this plugin.", "DSP LLE", 0); - #endif -#endif -} - - -// ======================================================================================= -// Regular thread -// -------------- -#ifdef _WIN32 -DWORD WINAPI dsp_thread(LPVOID lpParameter) -#else -void* dsp_thread(void* lpParameter) -#endif -{ - while (1) - { - if (!gdsp_run()) - { - ErrorLog("*** DSP: CRITICAL ERROR ***\n"); - //return 0; - exit(0); - } - } -} -// ============== - - -// ======================================================================================= -// Debug thread -// -------------- -#ifdef _WIN32 -DWORD WINAPI dsp_thread_debug(LPVOID lpParameter) -#else -void* dsp_thread_debug(void* lpParameter) -#endif -{ - - //if (g_hDSPThread) - //{ - // return NULL; // enable this to disable the plugin - //} -#ifdef _WIN32 - - while (1) - { - Logging(); // logging - - if (g_Dialog.CanDoStep()) - { - gdsp_runx(1); - } - else - { - Sleep(100); - } - } -#endif - return NULL; -} -// ============== - - -void DSP_DebugBreak() -{ -#ifdef _WIN32 -#if defined(_DEBUG) || defined(DEBUGFAST) - g_Dialog.DebugBreak(); -#endif -#endif -} - - -void dspi_req_dsp_irq() -{ - g_dspInitialize.pGenerateDSPInterrupt(); -} - - -void DSP_Initialize(DSPInitialize _dspInitialize) -{ - bCanWork = true; - g_dspInitialize = _dspInitialize; - - gdsp_init(); - g_dsp.step_counter = 0; - g_dsp.cpu_ram = g_dspInitialize.pGetMemoryPointer(0); - g_dsp.irq_request = dspi_req_dsp_irq; - gdsp_reset(); - - if (!gdsp_load_rom((char *)DSP_ROM_FILE)) - { - bCanWork = false; - PanicAlert("No DSP ROM"); - ErrorLog("Cannot load DSP ROM\n"); - } - - if (!gdsp_load_coef((char *)DSP_COEF_FILE)) - { - bCanWork = false; - PanicAlert("No DSP COEF"); - ErrorLog("Cannot load DSP COEF\n"); - } - - if(!bCanWork) - return; // TODO: Don't let it work - -// --------------------------------------------------------------------------------------- -// First create DSP_UCode.bin by setting "#define DUMP_DSP_IMEM 1" in Globals.h. Then -// make the disassembled file here. -// -------------- -// Dump UCode to file... - - FILE* t = fopen("C:\\_\\DSP_UC_09CD143F.txt", "wb"); - if (t != NULL) - { - gd_globals_t gdg; - gd_dis_file(&gdg, (char *)"C:\\_\\DSP_UC_09CD143F.bin", t); - fclose(t); - } -// -------------- - -#ifdef _WIN32 -#if defined(_DEBUG) || defined(DEBUGFAST) - g_hDSPThread = CreateThread(NULL, 0, dsp_thread_debug, 0, 0, NULL); -#else - g_hDSPThread = CreateThread(NULL, 0, dsp_thread, 0, 0, NULL); -#endif // DEBUG -#else -#if _DEBUG - pthread_create(&g_hDSPThread, NULL, dsp_thread_debug, (void *)NULL); -#else - pthread_create(&g_hDSPThread, NULL, dsp_thread, (void *)NULL); -#endif // DEBUG -#endif // WIN32 - - if (log_ai) { - g_wave_writer.Start("C:\\_\\ai_log.wav"); - g_wave_writer.SetSkipSilence(false); - } - -#ifdef _WIN32 - InitializeCriticalSection(&g_CriticalSection); - DSound::DSound_StartSound((HWND)g_dspInitialize.hWnd, 48000, Mixer); -#else - AOSound::AOSound_StartSound(48000, Mixer); -#endif -} - - -void DSP_Shutdown(void) -{ - if (log_ai) - g_wave_writer.Stop(); -#ifdef _WIN32 - if (g_hDSPThread != NULL) - { - TerminateThread(g_hDSPThread, 0); - } -#else - pthread_cancel(g_hDSPThread); -#endif - -} - -u16 DSP_WriteControlRegister(u16 _uFlag) -{ - gdsp_write_cr(_uFlag); - return(gdsp_read_cr()); -} - -u16 DSP_ReadControlRegister() -{ - return(gdsp_read_cr()); -} - -u16 DSP_ReadMailboxHigh(bool _CPUMailbox) -{ - if (_CPUMailbox) - { - return(gdsp_mbox_read_h(GDSP_MBOX_CPU)); - } - else - { - return(gdsp_mbox_read_h(GDSP_MBOX_DSP)); - } -} - -u16 DSP_ReadMailboxLow(bool _CPUMailbox) -{ - if (_CPUMailbox) - { - return(gdsp_mbox_read_l(GDSP_MBOX_CPU)); - } - else - { - return(gdsp_mbox_read_l(GDSP_MBOX_DSP)); - } -} - -void DSP_WriteMailboxHigh(bool _CPUMailbox, u16 _uHighMail) -{ - if (_CPUMailbox) - { - if (gdsp_mbox_peek(GDSP_MBOX_CPU) & 0x80000000) - { - ErrorLog("Mailbox isnt empty ... strange"); - } - -#if PROFILE - if ((_uHighMail) == 0xBABE) - { - ProfilerStart(); - } -#endif - - gdsp_mbox_write_h(GDSP_MBOX_CPU, _uHighMail); - } - else - { - ErrorLog("CPU cant write to DSP mailbox"); - } -} - -void DSP_WriteMailboxLow(bool _CPUMailbox, u16 _uLowMail) -{ - if (_CPUMailbox) - { - gdsp_mbox_write_l(GDSP_MBOX_CPU, _uLowMail); - - u32 uAddress = gdsp_mbox_peek(GDSP_MBOX_CPU); - u16 errpc = g_dsp.err_pc; - - DebugLog("Write CPU Mail: 0x%08x (pc=0x%04x)\n", uAddress, errpc); - - // --------------------------------------------------------------------------------------- - // I couldn't find any better way to detect the AX mails so this had to do. Please feel free - // to change it. - // -------------- - if ((errpc == 0x0054 || errpc == 0x0055) && m_addressPBs == 0) - { - DebugLog("AXTask ======== 0x%08x (pc=0x%04x)", uAddress, errpc); - AXTask(uAddress); - } - } - else - { - ErrorLog("CPU cant write to DSP mailbox"); - } -} - - -void DSP_Update(int cycles) -{ - if (g_hDSPThread) - { - return; - } - #ifdef _WIN32 - if (g_Dialog.CanDoStep()) - { - gdsp_runx(100); // cycles - } - #endif -} - - -void DSP_SendAIBuffer(unsigned int address, int sample_rate) -{ - short samples[16] = {0}; // interleaved stereo - if (address) { - for (int i = 0; i < 16; i++) { - samples[i] = Memory_Read_U16(address + i * 2); - } - if (log_ai) - g_wave_writer.AddStereoSamples(samples, 8); - } - Mixer_PushSamples(samples, 32 / 4, sample_rate); - - static int counter = 0; - counter++; -#ifdef _WIN32 - if ((counter & 255) == 0) - DSound::DSound_UpdateSound(); -#endif -} - - - -void __Log(int, const char *fmt, ...) -{ - //DebugLog(fmt); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "Globals.h" +#include "WaveFile.h" +#include "CommonTypes.h" +#include "Mixer.h" + +#include "gdsp_interpreter.h" +#include "gdsp_interface.h" +#include "disassemble.h" + +#ifdef _WIN32 + #include "DisAsmDlg.h" + #include "DSoundStream.h" + #include "Logging/Console.h" // For wprintf, ClearScreen + #include "Logging/Logging.h" // For Logging + + HINSTANCE g_hInstance = NULL; + HANDLE g_hDSPThread = NULL; + CRITICAL_SECTION g_CriticalSection; + CDisAsmDlg g_Dialog; +#else + #define WINAPI + #define LPVOID void* + #include + #include + #include + #include + #include "AOSoundStream.h" + pthread_t g_hDSPThread = NULL; +#endif + +#include "ChunkFile.h" + + +// ======================================================================================= +// Globals +// -------------- +DSPInitialize g_dspInitialize; + +#define GDSP_MBOX_CPU 0 +#define GDSP_MBOX_DSP 1 + +uint32 g_LastDMAAddress = 0; +uint32 g_LastDMASize = 0; + +extern u32 m_addressPBs; +bool AXTask(u32& _uMail); + +bool bCanWork = false; + +// Set this if you want to log audio. search for log_ai in this file to see the filename. +static bool log_ai = false; +WaveFileWriter g_wave_writer; + +// ============== + + +#ifdef _WIN32 +BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle + DWORD dwReason, // reason called + LPVOID lpvReserved) // reserved +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + break; + + case DLL_PROCESS_DETACH: + break; + + default: + break; + } + + g_hInstance = hinstDLL; + return(TRUE); +} +#endif + +void GetDllInfo(PLUGIN_INFO* _PluginInfo) +{ + _PluginInfo->Version = 0x0100; + _PluginInfo->Type = PLUGIN_TYPE_DSP; + +#ifdef DEBUGFAST + sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin (DebugFast)"); +#else +#ifndef _DEBUG + sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin"); +#else + sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin (Debug)"); +#endif +#endif +} + + +void DllAbout(HWND _hParent) +{} + + +void DllConfig(HWND _hParent) +{} + + +void DSP_DoState(unsigned char **ptr, int mode) { + PointerWrap p(ptr, mode); +} + +void DllDebugger(HWND _hParent, bool Show) +{ +#ifdef _WIN32 + #if defined (_DEBUG) || defined (DEBUGFAST) + g_Dialog.Create(NULL); //_hParent); + g_Dialog.ShowWindow(SW_SHOW); + MoveWindow(g_Dialog.m_hWnd, 450,0, 780,530, true); + + // Open the console window + startConsoleWin(155, 100, "Sound Debugging"); // give room for 100 rows + wprintf("DllDebugger > Console opened\n"); + // TODO: Make this adjustable from the Debugging window + MoveWindow(GetConsoleHwnd(), 0,400, 1280,500, true); + #else + MessageBox(0, "Can't open debugging window in Release build of this plugin.", "DSP LLE", 0); + #endif +#endif +} + + +// ======================================================================================= +// Regular thread +// -------------- +#ifdef _WIN32 +DWORD WINAPI dsp_thread(LPVOID lpParameter) +#else +void* dsp_thread(void* lpParameter) +#endif +{ + while (1) + { + if (!gdsp_run()) + { + ErrorLog("*** DSP: CRITICAL ERROR ***\n"); + //return 0; + exit(0); + } + } +} +// ============== + + +// ======================================================================================= +// Debug thread +// -------------- +#ifdef _WIN32 +DWORD WINAPI dsp_thread_debug(LPVOID lpParameter) +#else +void* dsp_thread_debug(void* lpParameter) +#endif +{ + + //if (g_hDSPThread) + //{ + // return NULL; // enable this to disable the plugin + //} +#ifdef _WIN32 + + while (1) + { + Logging(); // logging + + if (g_Dialog.CanDoStep()) + { + gdsp_runx(1); + } + else + { + Sleep(100); + } + } +#endif + return NULL; +} +// ============== + + +void DSP_DebugBreak() +{ +#ifdef _WIN32 +#if defined(_DEBUG) || defined(DEBUGFAST) + g_Dialog.DebugBreak(); +#endif +#endif +} + + +void dspi_req_dsp_irq() +{ + g_dspInitialize.pGenerateDSPInterrupt(); +} + + +void DSP_Initialize(DSPInitialize _dspInitialize) +{ + bCanWork = true; + g_dspInitialize = _dspInitialize; + + gdsp_init(); + g_dsp.step_counter = 0; + g_dsp.cpu_ram = g_dspInitialize.pGetMemoryPointer(0); + g_dsp.irq_request = dspi_req_dsp_irq; + gdsp_reset(); + + if (!gdsp_load_rom((char *)DSP_ROM_FILE)) + { + bCanWork = false; + PanicAlert("No DSP ROM"); + ErrorLog("Cannot load DSP ROM\n"); + } + + if (!gdsp_load_coef((char *)DSP_COEF_FILE)) + { + bCanWork = false; + PanicAlert("No DSP COEF"); + ErrorLog("Cannot load DSP COEF\n"); + } + + if(!bCanWork) + return; // TODO: Don't let it work + +// --------------------------------------------------------------------------------------- +// First create DSP_UCode.bin by setting "#define DUMP_DSP_IMEM 1" in Globals.h. Then +// make the disassembled file here. +// -------------- +// Dump UCode to file... + + FILE* t = fopen("C:\\_\\DSP_UC_09CD143F.txt", "wb"); + if (t != NULL) + { + gd_globals_t gdg; + gd_dis_file(&gdg, (char *)"C:\\_\\DSP_UC_09CD143F.bin", t); + fclose(t); + } +// -------------- + +#ifdef _WIN32 +#if defined(_DEBUG) || defined(DEBUGFAST) + g_hDSPThread = CreateThread(NULL, 0, dsp_thread_debug, 0, 0, NULL); +#else + g_hDSPThread = CreateThread(NULL, 0, dsp_thread, 0, 0, NULL); +#endif // DEBUG +#else +#if _DEBUG + pthread_create(&g_hDSPThread, NULL, dsp_thread_debug, (void *)NULL); +#else + pthread_create(&g_hDSPThread, NULL, dsp_thread, (void *)NULL); +#endif // DEBUG +#endif // WIN32 + + if (log_ai) { + g_wave_writer.Start("C:\\_\\ai_log.wav"); + g_wave_writer.SetSkipSilence(false); + } + +#ifdef _WIN32 + InitializeCriticalSection(&g_CriticalSection); + DSound::DSound_StartSound((HWND)g_dspInitialize.hWnd, 48000, Mixer); +#else + AOSound::AOSound_StartSound(48000, Mixer); +#endif +} + + +void DSP_Shutdown(void) +{ + if (log_ai) + g_wave_writer.Stop(); +#ifdef _WIN32 + if (g_hDSPThread != NULL) + { + TerminateThread(g_hDSPThread, 0); + } +#else + pthread_cancel(g_hDSPThread); +#endif + +} + +u16 DSP_WriteControlRegister(u16 _uFlag) +{ + gdsp_write_cr(_uFlag); + return(gdsp_read_cr()); +} + +u16 DSP_ReadControlRegister() +{ + return(gdsp_read_cr()); +} + +u16 DSP_ReadMailboxHigh(bool _CPUMailbox) +{ + if (_CPUMailbox) + { + return(gdsp_mbox_read_h(GDSP_MBOX_CPU)); + } + else + { + return(gdsp_mbox_read_h(GDSP_MBOX_DSP)); + } +} + +u16 DSP_ReadMailboxLow(bool _CPUMailbox) +{ + if (_CPUMailbox) + { + return(gdsp_mbox_read_l(GDSP_MBOX_CPU)); + } + else + { + return(gdsp_mbox_read_l(GDSP_MBOX_DSP)); + } +} + +void DSP_WriteMailboxHigh(bool _CPUMailbox, u16 _uHighMail) +{ + if (_CPUMailbox) + { + if (gdsp_mbox_peek(GDSP_MBOX_CPU) & 0x80000000) + { + ErrorLog("Mailbox isnt empty ... strange"); + } + +#if PROFILE + if ((_uHighMail) == 0xBABE) + { + ProfilerStart(); + } +#endif + + gdsp_mbox_write_h(GDSP_MBOX_CPU, _uHighMail); + } + else + { + ErrorLog("CPU cant write to DSP mailbox"); + } +} + +void DSP_WriteMailboxLow(bool _CPUMailbox, u16 _uLowMail) +{ + if (_CPUMailbox) + { + gdsp_mbox_write_l(GDSP_MBOX_CPU, _uLowMail); + + u32 uAddress = gdsp_mbox_peek(GDSP_MBOX_CPU); + u16 errpc = g_dsp.err_pc; + + DebugLog("Write CPU Mail: 0x%08x (pc=0x%04x)\n", uAddress, errpc); + + // --------------------------------------------------------------------------------------- + // I couldn't find any better way to detect the AX mails so this had to do. Please feel free + // to change it. + // -------------- + if ((errpc == 0x0054 || errpc == 0x0055) && m_addressPBs == 0) + { + DebugLog("AXTask ======== 0x%08x (pc=0x%04x)", uAddress, errpc); + AXTask(uAddress); + } + } + else + { + ErrorLog("CPU cant write to DSP mailbox"); + } +} + + +void DSP_Update(int cycles) +{ + if (g_hDSPThread) + { + return; + } + #ifdef _WIN32 + if (g_Dialog.CanDoStep()) + { + gdsp_runx(100); // cycles + } + #endif +} + + +void DSP_SendAIBuffer(unsigned int address, int sample_rate) +{ + short samples[16] = {0}; // interleaved stereo + if (address) { + for (int i = 0; i < 16; i++) { + samples[i] = Memory_Read_U16(address + i * 2); + } + if (log_ai) + g_wave_writer.AddStereoSamples(samples, 8); + } + Mixer_PushSamples(samples, 32 / 4, sample_rate); + + static int counter = 0; + counter++; +#ifdef _WIN32 + if ((counter & 255) == 0) + DSound::DSound_UpdateSound(); +#endif +} + + + +void __Log(int, const char *fmt, ...) +{ + //DebugLog(fmt); +} diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/opcodes.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/opcodes.cpp index 029bf6e288..16fc50030d 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/opcodes.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/opcodes.cpp @@ -1,237 +1,237 @@ -/*==================================================================== - - filename: opcodes.cpp - project: GameCube DSP Tool (gcdsp) - created: 2005.03.04 - mail: duddie@walla.com - - Copyright (c) 2005 Duddie - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - ====================================================================*/ - -#include "Globals.h" -#include "opcodes.h" - -opc_t opcodes[] = -{ - {"NOP", 0x0000, 0xffff, 1, 0, {},}, - {"HALT", 0x0021, 0xffff, 1, 0, {},}, - {"RET", 0x02df, 0xffff, 1, 0, {},}, - {"RETEQ", 0x02d5, 0xffff, 1, 0, {},}, - {"RETNZ", 0x02dd, 0xffff, 1, 0, {},}, - {"RTI", 0x02ff, 0xffff, 1, 0, {},}, - {"CALL", 0x02bf, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, - - {"CALLNE", 0x02b4, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, - - {"IF_0", 0x0270, 0xffff, 1, 0, {},}, - {"IF_1", 0x0271, 0xffff, 1, 0, {},}, - {"IF_2", 0x0272, 0xffff, 1, 0, {},}, - {"IF_3", 0x0273, 0xffff, 1, 0, {},}, - {"IF_E", 0x0274, 0xffff, 1, 0, {},}, - {"IF_Q", 0x0275, 0xffff, 1, 0, {},}, - {"IF_R", 0x027c, 0xffff, 1, 0, {},}, - {"IF_Z", 0x027d, 0xffff, 1, 0, {},}, - {"IF_P", 0x027f, 0xffff, 1, 0, {},}, - - {"JX0", 0x0290, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, - {"JX1", 0x0291, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, - {"JX2", 0x0292, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, - {"JX3", 0x0293, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, - {"JNE", 0x0294, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, - {"JEQ", 0x0295, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, - {"JZR", 0x029c, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, - {"JNZ", 0x029d, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, - {"JMP", 0x029f, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, - - {"DAR", 0x0004, 0xfffc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},}, - {"IAR", 0x0008, 0xfffc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},}, - - {"CALLR", 0x171f, 0xff1f, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}},}, - {"JMPR", 0x170f, 0xff1f, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}},}, - - {"SBCLR", 0x1200, 0xfff8, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}},}, - {"SBSET", 0x1300, 0xfff8, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}},}, - - {"LSL", 0x1400, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}},}, - {"LSR", 0x1440, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}},}, - {"ASL", 0x1480, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x007f}},}, - {"ASR", 0x14c0, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x007f}},}, - - - {"LRI", 0x0080, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_IMM, 2, 1, 0, 0xffff}},}, - {"LR", 0x00c0, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_MEM, 2, 1, 0, 0xffff}},}, - {"SR", 0x00e0, 0xffe0, 2, 2, {{P_MEM, 2, 1, 0, 0xffff}, {P_REG, 1, 0, 0, 0x001f}},}, - - {"MRR", 0x1c00, 0xfc00, 1, 2, {{P_REG, 1, 0, 5, 0x03e0}, {P_REG, 1, 0, 0, 0x001f}},}, - - {"SI", 0x1600, 0xff00, 2, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_IMM, 2, 1, 0, 0xffff}},}, - - {"LRS", 0x2000, 0xf800, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_MEM, 1, 0, 0, 0x00ff}},}, - {"SRS", 0x2800, 0xf800, 1, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_REG18, 1, 0, 8, 0x0700}},}, - - {"LRIS", 0x0800, 0xf800, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_IMM, 1, 0, 0, 0x00ff}},}, - - {"ADDIS", 0x0400, 0xfe00, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}},}, - {"CMPIS", 0x0600, 0xfe00, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}},}, - - {"ANDI", 0x0240, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, - {"ANDF", 0x02c0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, - - {"XORI", 0x0220, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, - {"ANDCF", 0x02a0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, - - {"ORI", 0x0260, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, - {"ORF", 0x02e0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, - - {"ADDI", 0x0200, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, // missing S64 - {"CMPI", 0x0280, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, // missing S64 - - {"ILRR", 0x0210, 0xfedc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},}, - {"ILRRI", 0x0218, 0xfedc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},}, - - // load and store value pointed by indexing reg and increment; LRR/SRR variants - {"LRRI", 0x1900, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},}, - {"LRRD", 0x1880, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},}, - {"LRRN", 0x1980, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},}, - {"LRR", 0x1800, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},}, - {"SRRI", 0x1b00, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},}, - {"SRRD", 0x1a80, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},}, - {"SRRN", 0x1b80, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},}, - {"SRR", 0x1a00, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},}, - - {"LOOPI", 0x1000, 0xff00, 1, 1, {{P_IMM, 1, 0, 0, 0x00ff}},}, - {"BLOOPI", 0x1100, 0xff00, 2, 2, {{P_IMM, 1, 0, 0, 0x00ff}, {P_VAL, 2, 1, 0, 0xffff}},}, - {"LOOP", 0x0040, 0xffe0, 1, 1, {{P_REG, 1, 0, 0, 0x001f}},}, - {"BLOOP", 0x0060, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_VAL, 2, 1, 0, 0xffff}},}, - - - - // opcodes that can be extended - // extended opcodes, note size of opcode will be set to 0 - - {"NX", 0x8000, 0xffff, 1 | P_EXT, 0, {},}, - - {"S40", 0x8e00, 0xffff, 1 | P_EXT, 0, {},}, - {"S16", 0x8f00, 0xffff, 1 | P_EXT, 0, {},}, - {"M2", 0x8a00, 0xffff, 1 | P_EXT, 0, {},}, - {"M0", 0x8b00, 0xffff, 1 | P_EXT, 0, {},}, - {"CLR15", 0x8c00, 0xffff, 1 | P_EXT, 0, {},}, - {"SET15", 0x8d00, 0xffff, 1 | P_EXT, 0, {},}, - - {"DECM", 0x7800, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, - {"INCM", 0x7400, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, - {"DEC", 0x7a00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, - {"INC", 0x7600, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, - - {"NEG", 0x7c00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, - - {"TST", 0xb100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},}, - {"TSTAXH", 0x8600, 0xfeff, 1 | P_EXT, 1, {{P_REG1A, 1, 0, 8, 0x0100}},}, - {"CMP", 0x8200, 0xffff, 1 | P_EXT, 0, {},}, - {"CMPAXH", 0xc100, 0xe7ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}},}, - - {"CLR", 0x8100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},}, - {"CLRP", 0x8400, 0xffff, 1 | P_EXT, 0, {},}, - - {"MOV", 0x6c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},}, - {"MOVAX", 0x6800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},}, - {"MOVR", 0x6000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},}, - {"MOVP", 0x6e00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, - {"MOVPZ", 0xfe00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, - - {"ADDPAXZ", 0xf800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG1A, 1, 0, 8, 0x0100}},}, - {"ADDP", 0x4e00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, - - {"LSL16", 0xf000, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, - {"LSR16", 0xf400, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, - {"ASR16", 0x9100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},}, - - {"XORR", 0x3000, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},}, - {"ANDR", 0x3400, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},}, - {"ORR", 0x3800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},}, - {"ANDC", 0x3C00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, - {"ORC", 0x3E00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, - - {"MULX", 0xa000, 0xe7ff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}},}, - {"MULXAC", 0xa400, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},}, - {"MULXMV", 0xa600, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},}, - {"MULXMVZ", 0xa200, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},}, - - {"MUL", 0x9000, 0xf7ff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}},}, - {"MULAC", 0x9400, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},}, - {"MULMV", 0x9600, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},}, - {"MULMVZ", 0x9200, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},}, - - {"MULC", 0xc000, 0xe7ff, 1 | P_EXT, 2, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}},}, - {"MULCAC", 0xc400, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},}, - {"MULCMV", 0xc600, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},}, - {"MULCMVZ", 0xc200, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},}, - - {"ADDR", 0x4000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},}, - {"ADDAX", 0x4800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},}, - {"ADD", 0x4c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},}, - {"ADDAXL", 0x7000, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},}, - - {"SUBR", 0x5000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},}, - {"SUBAX", 0x5800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},}, - {"SUB", 0x5c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},}, - - {"MADD", 0xf200, 0xfeff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}},}, - {"MSUB", 0xf600, 0xfeff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}},}, - {"MADDX", 0xe000, 0xfcff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},}, - {"MSUBX", 0xe400, 0xfcff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},}, - {"MADDC", 0xe800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},}, - {"MSUBC", 0xec00, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},}, - - // assemble CW - {"CW", 0x0000, 0xffff, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}},}, - // unknown opcode for disassemble - {"CW", 0x0000, 0x0000, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}},}, -}; -opc_t opcodes_ext[] = -{ - {"L", 0x0040, 0x00c4, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}},}, - {"LN", 0x0044, 0x00c4, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}},}, - {"LS", 0x0080, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},}, - {"LSN", 0x0084, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},}, - {"LSM", 0x0088, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},}, - {"LSNM", 0x008c, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},}, - {"SL", 0x0082, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},}, - {"SLN", 0x0086, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},}, - {"SLM", 0x008a, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},}, - {"SLNM", 0x008e, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},}, - {"S", 0x0020, 0x00e4, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}},}, - {"SN", 0x0024, 0x00e4, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}},}, - {"LDX", 0x00c0, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},}, - {"LDXN", 0x00c4, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},}, - {"LDXM", 0x00c8, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},}, - {"LDXNM", 0x00cc, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},}, - {"LD", 0x00c0, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},}, - {"LDN", 0x00c4, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},}, - {"LDM", 0x00c8, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},}, - {"LDNM", 0x00cc, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},}, - {"MV", 0x0010, 0x00f0, 1, 2, {{P_REG18, 1, 0, 2, 0x000c}, {P_REG1C, 1, 0, 0, 0x0003}},}, - {"DR", 0x0004, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},}, - {"IR", 0x0008, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},}, - {"NR", 0x000c, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},}, - {"XXX", 0x0000, 0x0000, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}},}, -}; - -const uint32 opcodes_size = sizeof(opcodes) / sizeof(opc_t); -const uint32 opcodes_ext_size = sizeof(opcodes_ext) / sizeof(opc_t); - +/*==================================================================== + + filename: opcodes.cpp + project: GameCube DSP Tool (gcdsp) + created: 2005.03.04 + mail: duddie@walla.com + + Copyright (c) 2005 Duddie + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + ====================================================================*/ + +#include "Globals.h" +#include "opcodes.h" + +opc_t opcodes[] = +{ + {"NOP", 0x0000, 0xffff, 1, 0, {},}, + {"HALT", 0x0021, 0xffff, 1, 0, {},}, + {"RET", 0x02df, 0xffff, 1, 0, {},}, + {"RETEQ", 0x02d5, 0xffff, 1, 0, {},}, + {"RETNZ", 0x02dd, 0xffff, 1, 0, {},}, + {"RTI", 0x02ff, 0xffff, 1, 0, {},}, + {"CALL", 0x02bf, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, + + {"CALLNE", 0x02b4, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, + + {"IF_0", 0x0270, 0xffff, 1, 0, {},}, + {"IF_1", 0x0271, 0xffff, 1, 0, {},}, + {"IF_2", 0x0272, 0xffff, 1, 0, {},}, + {"IF_3", 0x0273, 0xffff, 1, 0, {},}, + {"IF_E", 0x0274, 0xffff, 1, 0, {},}, + {"IF_Q", 0x0275, 0xffff, 1, 0, {},}, + {"IF_R", 0x027c, 0xffff, 1, 0, {},}, + {"IF_Z", 0x027d, 0xffff, 1, 0, {},}, + {"IF_P", 0x027f, 0xffff, 1, 0, {},}, + + {"JX0", 0x0290, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, + {"JX1", 0x0291, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, + {"JX2", 0x0292, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, + {"JX3", 0x0293, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, + {"JNE", 0x0294, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, + {"JEQ", 0x0295, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, + {"JZR", 0x029c, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, + {"JNZ", 0x029d, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, + {"JMP", 0x029f, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},}, + + {"DAR", 0x0004, 0xfffc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},}, + {"IAR", 0x0008, 0xfffc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},}, + + {"CALLR", 0x171f, 0xff1f, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}},}, + {"JMPR", 0x170f, 0xff1f, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}},}, + + {"SBCLR", 0x1200, 0xfff8, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}},}, + {"SBSET", 0x1300, 0xfff8, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}},}, + + {"LSL", 0x1400, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}},}, + {"LSR", 0x1440, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}},}, + {"ASL", 0x1480, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x007f}},}, + {"ASR", 0x14c0, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x007f}},}, + + + {"LRI", 0x0080, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_IMM, 2, 1, 0, 0xffff}},}, + {"LR", 0x00c0, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_MEM, 2, 1, 0, 0xffff}},}, + {"SR", 0x00e0, 0xffe0, 2, 2, {{P_MEM, 2, 1, 0, 0xffff}, {P_REG, 1, 0, 0, 0x001f}},}, + + {"MRR", 0x1c00, 0xfc00, 1, 2, {{P_REG, 1, 0, 5, 0x03e0}, {P_REG, 1, 0, 0, 0x001f}},}, + + {"SI", 0x1600, 0xff00, 2, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_IMM, 2, 1, 0, 0xffff}},}, + + {"LRS", 0x2000, 0xf800, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_MEM, 1, 0, 0, 0x00ff}},}, + {"SRS", 0x2800, 0xf800, 1, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_REG18, 1, 0, 8, 0x0700}},}, + + {"LRIS", 0x0800, 0xf800, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_IMM, 1, 0, 0, 0x00ff}},}, + + {"ADDIS", 0x0400, 0xfe00, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}},}, + {"CMPIS", 0x0600, 0xfe00, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}},}, + + {"ANDI", 0x0240, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, + {"ANDF", 0x02c0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, + + {"XORI", 0x0220, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, + {"ANDCF", 0x02a0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, + + {"ORI", 0x0260, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, + {"ORF", 0x02e0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, + + {"ADDI", 0x0200, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, // missing S64 + {"CMPI", 0x0280, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, // missing S64 + + {"ILRR", 0x0210, 0xfedc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},}, + {"ILRRI", 0x0218, 0xfedc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},}, + + // load and store value pointed by indexing reg and increment; LRR/SRR variants + {"LRRI", 0x1900, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},}, + {"LRRD", 0x1880, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},}, + {"LRRN", 0x1980, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},}, + {"LRR", 0x1800, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},}, + {"SRRI", 0x1b00, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},}, + {"SRRD", 0x1a80, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},}, + {"SRRN", 0x1b80, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},}, + {"SRR", 0x1a00, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},}, + + {"LOOPI", 0x1000, 0xff00, 1, 1, {{P_IMM, 1, 0, 0, 0x00ff}},}, + {"BLOOPI", 0x1100, 0xff00, 2, 2, {{P_IMM, 1, 0, 0, 0x00ff}, {P_VAL, 2, 1, 0, 0xffff}},}, + {"LOOP", 0x0040, 0xffe0, 1, 1, {{P_REG, 1, 0, 0, 0x001f}},}, + {"BLOOP", 0x0060, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_VAL, 2, 1, 0, 0xffff}},}, + + + + // opcodes that can be extended + // extended opcodes, note size of opcode will be set to 0 + + {"NX", 0x8000, 0xffff, 1 | P_EXT, 0, {},}, + + {"S40", 0x8e00, 0xffff, 1 | P_EXT, 0, {},}, + {"S16", 0x8f00, 0xffff, 1 | P_EXT, 0, {},}, + {"M2", 0x8a00, 0xffff, 1 | P_EXT, 0, {},}, + {"M0", 0x8b00, 0xffff, 1 | P_EXT, 0, {},}, + {"CLR15", 0x8c00, 0xffff, 1 | P_EXT, 0, {},}, + {"SET15", 0x8d00, 0xffff, 1 | P_EXT, 0, {},}, + + {"DECM", 0x7800, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, + {"INCM", 0x7400, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, + {"DEC", 0x7a00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, + {"INC", 0x7600, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, + + {"NEG", 0x7c00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, + + {"TST", 0xb100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},}, + {"TSTAXH", 0x8600, 0xfeff, 1 | P_EXT, 1, {{P_REG1A, 1, 0, 8, 0x0100}},}, + {"CMP", 0x8200, 0xffff, 1 | P_EXT, 0, {},}, + {"CMPAXH", 0xc100, 0xe7ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}},}, + + {"CLR", 0x8100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},}, + {"CLRP", 0x8400, 0xffff, 1 | P_EXT, 0, {},}, + + {"MOV", 0x6c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},}, + {"MOVAX", 0x6800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},}, + {"MOVR", 0x6000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},}, + {"MOVP", 0x6e00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, + {"MOVPZ", 0xfe00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, + + {"ADDPAXZ", 0xf800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG1A, 1, 0, 8, 0x0100}},}, + {"ADDP", 0x4e00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, + + {"LSL16", 0xf000, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, + {"LSR16", 0xf400, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, + {"ASR16", 0x9100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},}, + + {"XORR", 0x3000, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},}, + {"ANDR", 0x3400, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},}, + {"ORR", 0x3800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},}, + {"ANDC", 0x3C00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, + {"ORC", 0x3E00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},}, + + {"MULX", 0xa000, 0xe7ff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}},}, + {"MULXAC", 0xa400, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},}, + {"MULXMV", 0xa600, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},}, + {"MULXMVZ", 0xa200, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},}, + + {"MUL", 0x9000, 0xf7ff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}},}, + {"MULAC", 0x9400, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},}, + {"MULMV", 0x9600, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},}, + {"MULMVZ", 0x9200, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},}, + + {"MULC", 0xc000, 0xe7ff, 1 | P_EXT, 2, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}},}, + {"MULCAC", 0xc400, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},}, + {"MULCMV", 0xc600, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},}, + {"MULCMVZ", 0xc200, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},}, + + {"ADDR", 0x4000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},}, + {"ADDAX", 0x4800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},}, + {"ADD", 0x4c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},}, + {"ADDAXL", 0x7000, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},}, + + {"SUBR", 0x5000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},}, + {"SUBAX", 0x5800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},}, + {"SUB", 0x5c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},}, + + {"MADD", 0xf200, 0xfeff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}},}, + {"MSUB", 0xf600, 0xfeff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}},}, + {"MADDX", 0xe000, 0xfcff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},}, + {"MSUBX", 0xe400, 0xfcff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},}, + {"MADDC", 0xe800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},}, + {"MSUBC", 0xec00, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},}, + + // assemble CW + {"CW", 0x0000, 0xffff, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}},}, + // unknown opcode for disassemble + {"CW", 0x0000, 0x0000, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}},}, +}; +opc_t opcodes_ext[] = +{ + {"L", 0x0040, 0x00c4, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}},}, + {"LN", 0x0044, 0x00c4, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}},}, + {"LS", 0x0080, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},}, + {"LSN", 0x0084, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},}, + {"LSM", 0x0088, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},}, + {"LSNM", 0x008c, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},}, + {"SL", 0x0082, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},}, + {"SLN", 0x0086, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},}, + {"SLM", 0x008a, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},}, + {"SLNM", 0x008e, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},}, + {"S", 0x0020, 0x00e4, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}},}, + {"SN", 0x0024, 0x00e4, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}},}, + {"LDX", 0x00c0, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},}, + {"LDXN", 0x00c4, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},}, + {"LDXM", 0x00c8, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},}, + {"LDXNM", 0x00cc, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},}, + {"LD", 0x00c0, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},}, + {"LDN", 0x00c4, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},}, + {"LDM", 0x00c8, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},}, + {"LDNM", 0x00cc, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},}, + {"MV", 0x0010, 0x00f0, 1, 2, {{P_REG18, 1, 0, 2, 0x000c}, {P_REG1C, 1, 0, 0, 0x0003}},}, + {"DR", 0x0004, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},}, + {"IR", 0x0008, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},}, + {"NR", 0x000c, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},}, + {"XXX", 0x0000, 0x0000, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}},}, +}; + +const uint32 opcodes_size = sizeof(opcodes) / sizeof(opc_t); +const uint32 opcodes_ext_size = sizeof(opcodes_ext) / sizeof(opc_t); + diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/stdafx.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/stdafx.cpp index 5d19def11f..9a2f6b5212 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/stdafx.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/stdafx.cpp @@ -1,19 +1,19 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "stdafx.h" - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" + diff --git a/Source/Plugins/Plugin_DSP_NULL/Src/DSPHandler.cpp b/Source/Plugins/Plugin_DSP_NULL/Src/DSPHandler.cpp index a1e365e5ab..635f344a0e 100644 --- a/Source/Plugins/Plugin_DSP_NULL/Src/DSPHandler.cpp +++ b/Source/Plugins/Plugin_DSP_NULL/Src/DSPHandler.cpp @@ -1,86 +1,86 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "DSPHandler.h" - -CDSPHandler* CDSPHandler::m_pInstance = NULL; - -CDSPHandler::CDSPHandler() - : m_pUCode(NULL), - m_bHalt(false), - m_bAssertInt(false) -{ - SetUCode(UCODE_ROM); - m_DSPControl.DSPHalt = 1; - m_DSPControl.DSPInit = 1; -} - -CDSPHandler::~CDSPHandler() -{ - delete m_pUCode; - m_pUCode = NULL; -} - -void CDSPHandler::Update() -{ - if (m_pUCode != NULL) - m_pUCode->Update(); -} - -unsigned short CDSPHandler::WriteControlRegister(unsigned short _Value) -{ - UDSPControl Temp(_Value); - if (Temp.DSPReset) - { - SetUCode(UCODE_ROM); - Temp.DSPReset = 0; - } - if (Temp.DSPInit == 0) - { - // copy 128 byte from ARAM 0x000000 to IMEM - SetUCode(UCODE_INIT_AUDIO_SYSTEM); - Temp.DSPInitCode = 0; - // MessageBox(NULL, "UCODE_INIT_AUDIO_SYSTEM", "DSP-HLE", MB_OK); - } - - m_DSPControl.Hex = Temp.Hex; - return m_DSPControl.Hex; -} - -unsigned short CDSPHandler::ReadControlRegister() -{ - return m_DSPControl.Hex; -} - -void CDSPHandler::SendMailToDSP(u32 _uMail) -{ - if (m_pUCode != NULL) - m_pUCode->HandleMail(_uMail); -} - -IUCode* CDSPHandler::GetUCode() -{ - return m_pUCode; -} - -void CDSPHandler::SetUCode(u32 _crc) -{ - delete m_pUCode; - m_pUCode = NULL; - m_MailHandler.Clear(); - m_pUCode = UCodeFactory(_crc, m_MailHandler); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "DSPHandler.h" + +CDSPHandler* CDSPHandler::m_pInstance = NULL; + +CDSPHandler::CDSPHandler() + : m_pUCode(NULL), + m_bHalt(false), + m_bAssertInt(false) +{ + SetUCode(UCODE_ROM); + m_DSPControl.DSPHalt = 1; + m_DSPControl.DSPInit = 1; +} + +CDSPHandler::~CDSPHandler() +{ + delete m_pUCode; + m_pUCode = NULL; +} + +void CDSPHandler::Update() +{ + if (m_pUCode != NULL) + m_pUCode->Update(); +} + +unsigned short CDSPHandler::WriteControlRegister(unsigned short _Value) +{ + UDSPControl Temp(_Value); + if (Temp.DSPReset) + { + SetUCode(UCODE_ROM); + Temp.DSPReset = 0; + } + if (Temp.DSPInit == 0) + { + // copy 128 byte from ARAM 0x000000 to IMEM + SetUCode(UCODE_INIT_AUDIO_SYSTEM); + Temp.DSPInitCode = 0; + // MessageBox(NULL, "UCODE_INIT_AUDIO_SYSTEM", "DSP-HLE", MB_OK); + } + + m_DSPControl.Hex = Temp.Hex; + return m_DSPControl.Hex; +} + +unsigned short CDSPHandler::ReadControlRegister() +{ + return m_DSPControl.Hex; +} + +void CDSPHandler::SendMailToDSP(u32 _uMail) +{ + if (m_pUCode != NULL) + m_pUCode->HandleMail(_uMail); +} + +IUCode* CDSPHandler::GetUCode() +{ + return m_pUCode; +} + +void CDSPHandler::SetUCode(u32 _crc) +{ + delete m_pUCode; + m_pUCode = NULL; + m_MailHandler.Clear(); + m_pUCode = UCodeFactory(_crc, m_MailHandler); +} diff --git a/Source/Plugins/Plugin_DSP_NULL/Src/Globals.cpp b/Source/Plugins/Plugin_DSP_NULL/Src/Globals.cpp index e29f88d607..aefbaf43db 100644 --- a/Source/Plugins/Plugin_DSP_NULL/Src/Globals.cpp +++ b/Source/Plugins/Plugin_DSP_NULL/Src/Globals.cpp @@ -1,53 +1,53 @@ -#include -#include - -#include "Common.h" -#include "Globals.h" - -void __Log(int, const char *fmt, ...) -{ - DebugLog(fmt); -} - -void DebugLog(const char* _fmt, ...) -{ -#ifdef _DEBUG - char Msg[512]; - va_list ap; - - va_start(ap, _fmt); - vsprintf(Msg, _fmt, ap); - va_end(ap); - - g_dspInitialize.pLog(Msg, FALSE); -#endif -} - -extern u8* g_pMemory; - -// TODO: Wii support? Most likely audio data still must be in the old 24MB TRAM. -#define RAM_MASK 0x1FFFFFF - -u8 Memory_Read_U8(u32 _uAddress) -{ - _uAddress &= RAM_MASK; - return g_pMemory[_uAddress]; -} - -u16 Memory_Read_U16(u32 _uAddress) -{ - _uAddress &= RAM_MASK; - return Common::swap16(*(u16*)&g_pMemory[_uAddress]); -} - -u32 Memory_Read_U32(u32 _uAddress) -{ - _uAddress &= RAM_MASK; - return Common::swap32(*(u32*)&g_pMemory[_uAddress]); -} - -float Memory_Read_Float(u32 _uAddress) -{ - u32 uTemp = Memory_Read_U32(_uAddress); - return *(float*)&uTemp; -} +#include +#include + +#include "Common.h" +#include "Globals.h" + +void __Log(int, const char *fmt, ...) +{ + DebugLog(fmt); +} + +void DebugLog(const char* _fmt, ...) +{ +#ifdef _DEBUG + char Msg[512]; + va_list ap; + + va_start(ap, _fmt); + vsprintf(Msg, _fmt, ap); + va_end(ap); + + g_dspInitialize.pLog(Msg, FALSE); +#endif +} + +extern u8* g_pMemory; + +// TODO: Wii support? Most likely audio data still must be in the old 24MB TRAM. +#define RAM_MASK 0x1FFFFFF + +u8 Memory_Read_U8(u32 _uAddress) +{ + _uAddress &= RAM_MASK; + return g_pMemory[_uAddress]; +} + +u16 Memory_Read_U16(u32 _uAddress) +{ + _uAddress &= RAM_MASK; + return Common::swap16(*(u16*)&g_pMemory[_uAddress]); +} + +u32 Memory_Read_U32(u32 _uAddress) +{ + _uAddress &= RAM_MASK; + return Common::swap32(*(u32*)&g_pMemory[_uAddress]); +} + +float Memory_Read_Float(u32 _uAddress) +{ + u32 uTemp = Memory_Read_U32(_uAddress); + return *(float*)&uTemp; +} diff --git a/Source/Plugins/Plugin_DSP_NULL/Src/MailHandler.cpp b/Source/Plugins/Plugin_DSP_NULL/Src/MailHandler.cpp index 2119351e14..dd7b806599 100644 --- a/Source/Plugins/Plugin_DSP_NULL/Src/MailHandler.cpp +++ b/Source/Plugins/Plugin_DSP_NULL/Src/MailHandler.cpp @@ -1,96 +1,96 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "MailHandler.h" - -CMailHandler::CMailHandler() -{ - -} - -CMailHandler::~CMailHandler() -{ - Clear(); -} - -void CMailHandler::PushMail(u32 _Mail) -{ - m_Mails.push(_Mail); - - Update(); -} - -u16 CMailHandler::ReadDSPMailboxHigh() -{ - // check if we have a mail for the core - if (!m_Mails.empty()) - { - u16 result = (m_Mails.front() >> 16) & 0xFFFF; - Update(); - return result; - } - - return 0x00; -} - -u16 CMailHandler::ReadDSPMailboxLow() -{ - // check if we have a mail for the core - if (!m_Mails.empty()) - { - u16 result = m_Mails.front() & 0xFFFF; - m_Mails.pop(); - - Update(); - - return(result); - } - - return 0x00; -} - -void CMailHandler::Clear() -{ - while (!m_Mails.empty()) - m_Mails.pop(); -} - -bool CMailHandler::IsEmpty() -{ - return m_Mails.empty(); -} - -void CMailHandler::Halt(bool _Halt) -{ - if (_Halt) - { - Clear(); - m_Mails.push(0x80544348); - } - - Update(); -} - -void CMailHandler::Update() -{ - if (!IsEmpty()) - { - // g_dspInitialize.pGenerateDSPInterrupt(); - } -} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "MailHandler.h" + +CMailHandler::CMailHandler() +{ + +} + +CMailHandler::~CMailHandler() +{ + Clear(); +} + +void CMailHandler::PushMail(u32 _Mail) +{ + m_Mails.push(_Mail); + + Update(); +} + +u16 CMailHandler::ReadDSPMailboxHigh() +{ + // check if we have a mail for the core + if (!m_Mails.empty()) + { + u16 result = (m_Mails.front() >> 16) & 0xFFFF; + Update(); + return result; + } + + return 0x00; +} + +u16 CMailHandler::ReadDSPMailboxLow() +{ + // check if we have a mail for the core + if (!m_Mails.empty()) + { + u16 result = m_Mails.front() & 0xFFFF; + m_Mails.pop(); + + Update(); + + return(result); + } + + return 0x00; +} + +void CMailHandler::Clear() +{ + while (!m_Mails.empty()) + m_Mails.pop(); +} + +bool CMailHandler::IsEmpty() +{ + return m_Mails.empty(); +} + +void CMailHandler::Halt(bool _Halt) +{ + if (_Halt) + { + Clear(); + m_Mails.push(0x80544348); + } + + Update(); +} + +void CMailHandler::Update() +{ + if (!IsEmpty()) + { + // g_dspInitialize.pGenerateDSPInterrupt(); + } +} + + diff --git a/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_AX.cpp b/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_AX.cpp index 4b39845f42..efda14a103 100644 --- a/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_AX.cpp +++ b/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_AX.cpp @@ -1,574 +1,574 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Common.h" -#include "../Globals.h" - -#include "../MailHandler.h" - -#include "UCodes.h" -#include "UCode_AXStructs.h" -#include "UCode_AX.h" - -CUCode_AX::CUCode_AX(CMailHandler& _rMailHandler, bool wii) - : IUCode(_rMailHandler) - , m_addressPBs(0xFFFFFFFF) - , wii_mode(wii) -{ - // we got loaded - m_rMailHandler.PushMail(0xDCD10000); - m_rMailHandler.PushMail(0x80000000); // handshake ??? only (crc == 0xe2136399) needs it ... - - templbuffer = new int[1024 * 1024]; - temprbuffer = new int[1024 * 1024]; -} - -CUCode_AX::~CUCode_AX() -{ - m_rMailHandler.Clear(); - delete [] templbuffer; - delete [] temprbuffer; -} - -void CUCode_AX::HandleMail(u32 _uMail) -{ - if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST) - { - // a new List - } - else - { - AXTask(_uMail); - } -} - -s16 CUCode_AX::ADPCM_Step(AXParamBlock& pb, u32& samplePos, u32 newSamplePos, u16 frac) -{ - PBADPCMInfo &adpcm = pb.adpcm; - - while (samplePos < newSamplePos) - { - if ((samplePos & 15) == 0) - { - adpcm.pred_scale = g_dspInitialize.pARAM_Read_U8((samplePos & ~15) >> 1); - samplePos += 2; - newSamplePos += 2; - } - - int scale = 1 << (adpcm.pred_scale & 0xF); - int coef_idx = adpcm.pred_scale >> 4; - - s32 coef1 = adpcm.coefs[coef_idx * 2 + 0]; - s32 coef2 = adpcm.coefs[coef_idx * 2 + 1]; - - int temp = (samplePos & 1) ? - (g_dspInitialize.pARAM_Read_U8(samplePos >> 1) & 0xF) : - (g_dspInitialize.pARAM_Read_U8(samplePos >> 1) >> 4); - - if (temp >= 8) - temp -= 16; - - // 0x400 = 0.5 in 11-bit fixed point - int val = (scale * temp) + ((0x400 + coef1 * adpcm.yn1 + coef2 * adpcm.yn2) >> 11); - - if (val > 0x7FFF) - val = 0x7FFF; - else if (val < -0x7FFF) - val = -0x7FFF; - - adpcm.yn2 = adpcm.yn1; - adpcm.yn1 = val; - - samplePos++; - } - - return adpcm.yn1; -} - -void ADPCM_Loop(AXParamBlock& pb) -{ - if (!pb.is_stream) - { - pb.adpcm.yn1 = pb.adpcm_loop_info.yn1; - pb.adpcm.yn2 = pb.adpcm_loop_info.yn2; - pb.adpcm.pred_scale = pb.adpcm_loop_info.pred_scale; - } - //else stream and we should not attempt to replace values -} - -void CUCode_AX::MixAdd(short* _pBuffer, int _iSize) -{ - AXParamBlock PBs[NUMBER_OF_PBS]; - - if (_iSize > 1024 * 1024) - _iSize = 1024 * 1024; - - memset(templbuffer, 0, _iSize * sizeof(int)); - memset(temprbuffer, 0, _iSize * sizeof(int)); - // read out pbs - int numberOfPBs = ReadOutPBs(PBs, NUMBER_OF_PBS); - - float ratioFactor = 32000.0f / 44100.0f; - - for (int i = 0; i < numberOfPBs; i++) - { - AXParamBlock& pb = PBs[i]; - - if (pb.running) - { - // ======================================================================================= - // Set initial parameters - // --------------------------------------------------------------------------------------- - //constants - const u32 loopPos = (pb.audio_addr.loop_addr_hi << 16) | pb.audio_addr.loop_addr_lo; - const u32 sampleEnd = (pb.audio_addr.end_addr_hi << 16) | pb.audio_addr.end_addr_lo; - const u32 ratio = (u32)(((pb.src.ratio_hi << 16) + pb.src.ratio_lo) * ratioFactor); - - //variables - u32 samplePos = (pb.audio_addr.cur_addr_hi << 16) | pb.audio_addr.cur_addr_lo; - u32 frac = pb.src.cur_addr_frac; - // ======================================================================================= - - - - // ======================================================================================= - // Handle no-src streams - No src streams have pb.src_type == 2 and have pb.src.ratio_hi = 0 - // and pb.src.ratio_lo = 0. We handle that by setting the sampling ratio integer to 1. This - // makes samplePos update in the correct way. - // --------------------------------------------------------------------------------------- - // Stream settings - // src_type = 2 (most other games have src_type = 0) - // --------------------------------------------------------------------------------------- - // Affected games: - // Baten Kaitos - Eternal Wings (2003) - // Baten Kaitos - Origins (2006)? - // ? - // --------------------------------------------------------------------------------------- - if(pb.src_type == 2) - { - pb.src.ratio_hi = 1; - } - // ======================================================================================= - - - // ======================================================================================= - // Games that use looping to play non-looping music streams. SSBM has info in all pb.adpcm_loop_info - // parameters but has pb.audio_addr.looping = 0. If we treat these streams like any other looping - // streams the music works. - // --------------------------------------------------------------------------------------- - if(pb.adpcm_loop_info.pred_scale || pb.adpcm_loop_info.yn1 || pb.adpcm_loop_info.yn2) - { - pb.audio_addr.looping = 1; - } - // ======================================================================================= - - - // ======================================================================================= - // Streaming music and volume - A lot of music in Paper Mario use the exat same settings, namely - // these: - // Base settings - // is_stream = 1 - // src_type = 0 - // coef (unknown1) = 1 - // PBAudioAddr - // audio_addr.looping = 1 (adpcm_loop_info.pred_scale = value, .yn1 = 0, .yn2 = 0) - // However. Some of the ingame music and seemingly randomly some other music incorrectly get - // volume = 0 for both left and right. There's also an issue of a hanging very similar to the Baten - // hanging. The Baten issue fixed itself when the music stream was allowed to play to the end and - // then stop. However, all five music streams that is playing when the gate locks up in Paper Mario - // is loooping streams... I don't know what may be wrong. - // --------------------------------------------------------------------------------------- - // A game that may be used as a comparison is Starfox Assault also has is_stream = 1, but it - // has src_type = 1, coef (unknown1) = 0 and its pb.src.ratio_lo (fraction) != 0 - // ======================================================================================= - - - // ======================================================================================= - // Walk through _iSize - for (int s = 0; s < _iSize; s++) - { - int sample = 0; - frac += ratio; - u32 newSamplePos = samplePos + (frac >> 16); //whole number of frac - - - // ======================================================================================= - // Process sample format - // --------------------------------------------------------------------------------------- - switch (pb.audio_addr.sample_format) - { - case AUDIOFORMAT_PCM8: - pb.adpcm.yn2 = pb.adpcm.yn1; //save last sample - pb.adpcm.yn1 = ((s8)g_dspInitialize.pARAM_Read_U8(samplePos)) << 8; - - if (pb.src_type == SRCTYPE_NEAREST) - { - sample = pb.adpcm.yn1; - } - else //linear interpolation - { - sample = (pb.adpcm.yn1 * (u16)frac + pb.adpcm.yn2 * (u16)(0xFFFF - frac)) >> 16; - } - - samplePos = newSamplePos; - break; - - case AUDIOFORMAT_PCM16: - pb.adpcm.yn2 = pb.adpcm.yn1; //save last sample - pb.adpcm.yn1 = (s16)(u16)((g_dspInitialize.pARAM_Read_U8(samplePos * 2) << 8) | (g_dspInitialize.pARAM_Read_U8((samplePos * 2 + 1)))); - if (pb.src_type == SRCTYPE_NEAREST) - sample = pb.adpcm.yn1; - else //linear interpolation - sample = (pb.adpcm.yn1 * (u16)frac + pb.adpcm.yn2 * (u16)(0xFFFF - frac)) >> 16; - - samplePos = newSamplePos; - break; - - case AUDIOFORMAT_ADPCM: - sample = ADPCM_Step(pb, samplePos, newSamplePos, frac); - break; - - default: - break; - } - // ======================================================================================= - - - // ======================================================================================= - // Volume control - frac &= 0xffff; - - int vol = pb.vol_env.cur_volume >> 9; - sample = sample * vol >> 8; - - if (pb.mixer_control & MIXCONTROL_RAMPING) - { - int x = pb.vol_env.cur_volume; - x += pb.vol_env.cur_volume_delta; - if (x < 0) x = 0; - if (x >= 0x7fff) x = 0x7fff; - pb.vol_env.cur_volume = x; // maybe not per sample?? :P - } - - int leftmix = pb.mixer.volume_left >> 5; - int rightmix = pb.mixer.volume_right >> 5; - // ======================================================================================= - - - int left = sample * leftmix >> 8; - int right = sample * rightmix >> 8; - - //adpcm has to walk from oldSamplePos to samplePos here - templbuffer[s] += left; - temprbuffer[s] += right; - - if (samplePos >= sampleEnd) - { - if (pb.audio_addr.looping == 1) - { - samplePos = loopPos; - if (pb.audio_addr.sample_format == AUDIOFORMAT_ADPCM) - ADPCM_Loop(pb); - } - else - { - pb.running = 0; - break; - } - } - } // end of the _iSize loop - // ======================================================================================= - - - pb.src.cur_addr_frac = (u16)frac; - pb.audio_addr.cur_addr_hi = samplePos >> 16; - pb.audio_addr.cur_addr_lo = (u16)samplePos; - } - } - - for (int i = 0; i < _iSize; i++) - { - // Clamp into 16-bit. Maybe we should add a volume compressor here. - int left = templbuffer[i]; - int right = temprbuffer[i]; - if (left < -32767) left = -32767; - if (left > 32767) left = 32767; - if (right < -32767) right = -32767; - if (right > 32767) right = 32767; - *_pBuffer++ += left; - *_pBuffer++ += right; - } - - // write back out pbs - WriteBackPBs(PBs, numberOfPBs); -} - -void CUCode_AX::Update() -{ - // check if we have to sent something - if (!m_rMailHandler.IsEmpty()) - { - g_dspInitialize.pGenerateDSPInterrupt(); - } -} - -// AX seems to bootup one task only and waits for resume-callbacks -// everytime the DSP has "spare time" it sends a resume-mail to the CPU -// and the __DSPHandler calls a AX-Callback which generates a new AXFrame -bool CUCode_AX::AXTask(u32& _uMail) -{ - u32 uAddress = _uMail; - DebugLog("AXTask - AXCommandList-Addr: 0x%08x", uAddress); - - u32 Addr__AXStudio; - u32 Addr__AXOutSBuffer; - u32 Addr__AXOutSBuffer_1; - u32 Addr__AXOutSBuffer_2; - u32 Addr__A; - u32 Addr__12; - u32 Addr__4_1; - u32 Addr__4_2; - u32 Addr__5_1; - u32 Addr__5_2; - u32 Addr__6; - u32 Addr__9; - - bool bExecuteList = true; - - while (bExecuteList) - { - static int last_valid_command = 0; - u16 iCommand = Memory_Read_U16(uAddress); - uAddress += 2; - switch (iCommand) - { - case AXLIST_STUDIOADDR: //00 - Addr__AXStudio = Memory_Read_U32(uAddress); - uAddress += 4; - if (wii_mode) - uAddress += 6; - DebugLog("AXLIST studio address: %08x", Addr__AXStudio); - break; - - case 0x001: - { - u32 address = Memory_Read_U32(uAddress); - uAddress += 4; - u16 param1 = Memory_Read_U16(uAddress); - uAddress += 2; - u16 param2 = Memory_Read_U16(uAddress); - uAddress += 2; - u16 param3 = Memory_Read_U16(uAddress); - uAddress += 2; - DebugLog("AXLIST 1: %08x, %04x, %04x, %04x", address, param1, param2, param3); - } - break; - - // - // Somewhere we should be getting a bitmask of AX_SYNC values - // that tells us what has been updated - // Dunno if important - // - case AXLIST_PBADDR: //02 - { - m_addressPBs = Memory_Read_U32(uAddress); - uAddress += 4; - - DebugLog("AXLIST PB address: %08x", m_addressPBs); - } - break; - - case 0x0003: - DebugLog("AXLIST command 0x0003 ????"); - break; - - case 0x0004: - Addr__4_1 = Memory_Read_U32(uAddress); - uAddress += 4; - Addr__4_2 = Memory_Read_U32(uAddress); - uAddress += 4; - DebugLog("AXLIST 4_1 4_2 addresses: %08x %08x", Addr__4_1, Addr__4_2); - break; - - case 0x0005: - Addr__5_1 = Memory_Read_U32(uAddress); - uAddress += 4; - Addr__5_2 = Memory_Read_U32(uAddress); - uAddress += 4; - DebugLog("AXLIST 5_1 5_2 addresses: %08x %08x", Addr__5_1, Addr__5_2); - break; - - case 0x0006: - Addr__6 = Memory_Read_U32(uAddress); - uAddress += 4; - DebugLog("AXLIST 6 address: %08x", Addr__6); - break; - - case AXLIST_SBUFFER: - // Hopefully this is where in main ram to write. - Addr__AXOutSBuffer = Memory_Read_U32(uAddress); - uAddress += 4; - if (wii_mode) { - uAddress += 12; - } - DebugLog("AXLIST OutSBuffer address: %08x", Addr__AXOutSBuffer); - break; - - case 0x0009: - Addr__9 = Memory_Read_U32(uAddress); - uAddress += 4; - DebugLog("AXLIST 6 address: %08x", Addr__9); - break; - - case AXLIST_COMPRESSORTABLE: // 0xa - Addr__A = Memory_Read_U32(uAddress); - uAddress += 4; - if (wii_mode) { - // There's one more here. -// uAddress += 4; - } - DebugLog("AXLIST CompressorTable address: %08x", Addr__A); - break; - - case 0x000e: - Addr__AXOutSBuffer_1 = Memory_Read_U32(uAddress); - uAddress += 4; - Addr__AXOutSBuffer_2 = Memory_Read_U32(uAddress); - uAddress += 4; - DebugLog("AXLIST sbuf2 addresses: %08x %08x", Addr__AXOutSBuffer_1, Addr__AXOutSBuffer_2); - break; - - case AXLIST_END: - bExecuteList = false; - DebugLog("AXLIST end"); - break; - - case 0x0010: //Super Monkey Ball 2 - DebugLog("AXLIST unknown"); - //should probably read/skip stuff here - uAddress += 8; - break; - - case 0x0011: - uAddress += 4; - break; - - case 0x0012: - Addr__12 = Memory_Read_U16(uAddress); - uAddress += 2; - break; - - case 0x0013: - uAddress += 6 * 4; // 6 Addresses. - break; - - case 0x000d: - if (wii_mode) { - uAddress += 4 * 4; // 4 addresses. another aux? - break; - } - // non-wii : fall through - - case 0x000b: - if (wii_mode) { - uAddress += 2; // one 0x8000 in rabbids - uAddress += 4 * 2; // then two RAM addressses - break; - } - // non-wii : fall through - - default: - { - static bool bFirst = true; - if (bFirst == true) - { - char szTemp[2048]; - sprintf(szTemp, "Unknown AX-Command 0x%x (address: 0x%08x). Last valid: %02x\n", - iCommand, uAddress - 2, last_valid_command); - int num = -32; - while (num < 64+32) - { - char szTemp2[128] = ""; - sprintf(szTemp2, "%s0x%04x\n", num == 0 ? ">>" : " ", Memory_Read_U16(uAddress + num)); - strcat(szTemp, szTemp2); - num += 2; - } - - PanicAlert(szTemp); - bFirst = false; - } - - // unknown command so stop the execution of this TaskList - bExecuteList = false; - } - break; - } - if (bExecuteList) - last_valid_command = iCommand; - } - DebugLog("AXTask - done, send resume"); - - // i hope resume is okay AX - m_rMailHandler.PushMail(0xDCD10001); - return true; -} - -int CUCode_AX::ReadOutPBs(AXParamBlock* _pPBs, int _num) -{ - int count = 0; - u32 blockAddr = m_addressPBs; - - // reading and 'halfword' swap - for (int i = 0; i < _num; i++) - { - const short *pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr); - if (pSrc != NULL) - { - short *pDest = (short *)&_pPBs[i]; - for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++) - { - pDest[p] = Common::swap16(pSrc[p]); - } - blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo; - count++; - } - else - break; - } - - // return the number of readed PBs - return count; -} - -void CUCode_AX::WriteBackPBs(AXParamBlock* _pPBs, int _num) -{ - u32 blockAddr = m_addressPBs; - - // write back and 'halfword'swap - for (int i = 0; i < _num; i++) - { - short* pSrc = (short*)&_pPBs[i]; - short* pDest = (short*)g_dspInitialize.pGetMemoryPointer(blockAddr); - for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++) - { - pDest[p] = Common::swap16(pSrc[p]); - } - - // next block - blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo; - } -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "../Globals.h" + +#include "../MailHandler.h" + +#include "UCodes.h" +#include "UCode_AXStructs.h" +#include "UCode_AX.h" + +CUCode_AX::CUCode_AX(CMailHandler& _rMailHandler, bool wii) + : IUCode(_rMailHandler) + , m_addressPBs(0xFFFFFFFF) + , wii_mode(wii) +{ + // we got loaded + m_rMailHandler.PushMail(0xDCD10000); + m_rMailHandler.PushMail(0x80000000); // handshake ??? only (crc == 0xe2136399) needs it ... + + templbuffer = new int[1024 * 1024]; + temprbuffer = new int[1024 * 1024]; +} + +CUCode_AX::~CUCode_AX() +{ + m_rMailHandler.Clear(); + delete [] templbuffer; + delete [] temprbuffer; +} + +void CUCode_AX::HandleMail(u32 _uMail) +{ + if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST) + { + // a new List + } + else + { + AXTask(_uMail); + } +} + +s16 CUCode_AX::ADPCM_Step(AXParamBlock& pb, u32& samplePos, u32 newSamplePos, u16 frac) +{ + PBADPCMInfo &adpcm = pb.adpcm; + + while (samplePos < newSamplePos) + { + if ((samplePos & 15) == 0) + { + adpcm.pred_scale = g_dspInitialize.pARAM_Read_U8((samplePos & ~15) >> 1); + samplePos += 2; + newSamplePos += 2; + } + + int scale = 1 << (adpcm.pred_scale & 0xF); + int coef_idx = adpcm.pred_scale >> 4; + + s32 coef1 = adpcm.coefs[coef_idx * 2 + 0]; + s32 coef2 = adpcm.coefs[coef_idx * 2 + 1]; + + int temp = (samplePos & 1) ? + (g_dspInitialize.pARAM_Read_U8(samplePos >> 1) & 0xF) : + (g_dspInitialize.pARAM_Read_U8(samplePos >> 1) >> 4); + + if (temp >= 8) + temp -= 16; + + // 0x400 = 0.5 in 11-bit fixed point + int val = (scale * temp) + ((0x400 + coef1 * adpcm.yn1 + coef2 * adpcm.yn2) >> 11); + + if (val > 0x7FFF) + val = 0x7FFF; + else if (val < -0x7FFF) + val = -0x7FFF; + + adpcm.yn2 = adpcm.yn1; + adpcm.yn1 = val; + + samplePos++; + } + + return adpcm.yn1; +} + +void ADPCM_Loop(AXParamBlock& pb) +{ + if (!pb.is_stream) + { + pb.adpcm.yn1 = pb.adpcm_loop_info.yn1; + pb.adpcm.yn2 = pb.adpcm_loop_info.yn2; + pb.adpcm.pred_scale = pb.adpcm_loop_info.pred_scale; + } + //else stream and we should not attempt to replace values +} + +void CUCode_AX::MixAdd(short* _pBuffer, int _iSize) +{ + AXParamBlock PBs[NUMBER_OF_PBS]; + + if (_iSize > 1024 * 1024) + _iSize = 1024 * 1024; + + memset(templbuffer, 0, _iSize * sizeof(int)); + memset(temprbuffer, 0, _iSize * sizeof(int)); + // read out pbs + int numberOfPBs = ReadOutPBs(PBs, NUMBER_OF_PBS); + + float ratioFactor = 32000.0f / 44100.0f; + + for (int i = 0; i < numberOfPBs; i++) + { + AXParamBlock& pb = PBs[i]; + + if (pb.running) + { + // ======================================================================================= + // Set initial parameters + // --------------------------------------------------------------------------------------- + //constants + const u32 loopPos = (pb.audio_addr.loop_addr_hi << 16) | pb.audio_addr.loop_addr_lo; + const u32 sampleEnd = (pb.audio_addr.end_addr_hi << 16) | pb.audio_addr.end_addr_lo; + const u32 ratio = (u32)(((pb.src.ratio_hi << 16) + pb.src.ratio_lo) * ratioFactor); + + //variables + u32 samplePos = (pb.audio_addr.cur_addr_hi << 16) | pb.audio_addr.cur_addr_lo; + u32 frac = pb.src.cur_addr_frac; + // ======================================================================================= + + + + // ======================================================================================= + // Handle no-src streams - No src streams have pb.src_type == 2 and have pb.src.ratio_hi = 0 + // and pb.src.ratio_lo = 0. We handle that by setting the sampling ratio integer to 1. This + // makes samplePos update in the correct way. + // --------------------------------------------------------------------------------------- + // Stream settings + // src_type = 2 (most other games have src_type = 0) + // --------------------------------------------------------------------------------------- + // Affected games: + // Baten Kaitos - Eternal Wings (2003) + // Baten Kaitos - Origins (2006)? + // ? + // --------------------------------------------------------------------------------------- + if(pb.src_type == 2) + { + pb.src.ratio_hi = 1; + } + // ======================================================================================= + + + // ======================================================================================= + // Games that use looping to play non-looping music streams. SSBM has info in all pb.adpcm_loop_info + // parameters but has pb.audio_addr.looping = 0. If we treat these streams like any other looping + // streams the music works. + // --------------------------------------------------------------------------------------- + if(pb.adpcm_loop_info.pred_scale || pb.adpcm_loop_info.yn1 || pb.adpcm_loop_info.yn2) + { + pb.audio_addr.looping = 1; + } + // ======================================================================================= + + + // ======================================================================================= + // Streaming music and volume - A lot of music in Paper Mario use the exat same settings, namely + // these: + // Base settings + // is_stream = 1 + // src_type = 0 + // coef (unknown1) = 1 + // PBAudioAddr + // audio_addr.looping = 1 (adpcm_loop_info.pred_scale = value, .yn1 = 0, .yn2 = 0) + // However. Some of the ingame music and seemingly randomly some other music incorrectly get + // volume = 0 for both left and right. There's also an issue of a hanging very similar to the Baten + // hanging. The Baten issue fixed itself when the music stream was allowed to play to the end and + // then stop. However, all five music streams that is playing when the gate locks up in Paper Mario + // is loooping streams... I don't know what may be wrong. + // --------------------------------------------------------------------------------------- + // A game that may be used as a comparison is Starfox Assault also has is_stream = 1, but it + // has src_type = 1, coef (unknown1) = 0 and its pb.src.ratio_lo (fraction) != 0 + // ======================================================================================= + + + // ======================================================================================= + // Walk through _iSize + for (int s = 0; s < _iSize; s++) + { + int sample = 0; + frac += ratio; + u32 newSamplePos = samplePos + (frac >> 16); //whole number of frac + + + // ======================================================================================= + // Process sample format + // --------------------------------------------------------------------------------------- + switch (pb.audio_addr.sample_format) + { + case AUDIOFORMAT_PCM8: + pb.adpcm.yn2 = pb.adpcm.yn1; //save last sample + pb.adpcm.yn1 = ((s8)g_dspInitialize.pARAM_Read_U8(samplePos)) << 8; + + if (pb.src_type == SRCTYPE_NEAREST) + { + sample = pb.adpcm.yn1; + } + else //linear interpolation + { + sample = (pb.adpcm.yn1 * (u16)frac + pb.adpcm.yn2 * (u16)(0xFFFF - frac)) >> 16; + } + + samplePos = newSamplePos; + break; + + case AUDIOFORMAT_PCM16: + pb.adpcm.yn2 = pb.adpcm.yn1; //save last sample + pb.adpcm.yn1 = (s16)(u16)((g_dspInitialize.pARAM_Read_U8(samplePos * 2) << 8) | (g_dspInitialize.pARAM_Read_U8((samplePos * 2 + 1)))); + if (pb.src_type == SRCTYPE_NEAREST) + sample = pb.adpcm.yn1; + else //linear interpolation + sample = (pb.adpcm.yn1 * (u16)frac + pb.adpcm.yn2 * (u16)(0xFFFF - frac)) >> 16; + + samplePos = newSamplePos; + break; + + case AUDIOFORMAT_ADPCM: + sample = ADPCM_Step(pb, samplePos, newSamplePos, frac); + break; + + default: + break; + } + // ======================================================================================= + + + // ======================================================================================= + // Volume control + frac &= 0xffff; + + int vol = pb.vol_env.cur_volume >> 9; + sample = sample * vol >> 8; + + if (pb.mixer_control & MIXCONTROL_RAMPING) + { + int x = pb.vol_env.cur_volume; + x += pb.vol_env.cur_volume_delta; + if (x < 0) x = 0; + if (x >= 0x7fff) x = 0x7fff; + pb.vol_env.cur_volume = x; // maybe not per sample?? :P + } + + int leftmix = pb.mixer.volume_left >> 5; + int rightmix = pb.mixer.volume_right >> 5; + // ======================================================================================= + + + int left = sample * leftmix >> 8; + int right = sample * rightmix >> 8; + + //adpcm has to walk from oldSamplePos to samplePos here + templbuffer[s] += left; + temprbuffer[s] += right; + + if (samplePos >= sampleEnd) + { + if (pb.audio_addr.looping == 1) + { + samplePos = loopPos; + if (pb.audio_addr.sample_format == AUDIOFORMAT_ADPCM) + ADPCM_Loop(pb); + } + else + { + pb.running = 0; + break; + } + } + } // end of the _iSize loop + // ======================================================================================= + + + pb.src.cur_addr_frac = (u16)frac; + pb.audio_addr.cur_addr_hi = samplePos >> 16; + pb.audio_addr.cur_addr_lo = (u16)samplePos; + } + } + + for (int i = 0; i < _iSize; i++) + { + // Clamp into 16-bit. Maybe we should add a volume compressor here. + int left = templbuffer[i]; + int right = temprbuffer[i]; + if (left < -32767) left = -32767; + if (left > 32767) left = 32767; + if (right < -32767) right = -32767; + if (right > 32767) right = 32767; + *_pBuffer++ += left; + *_pBuffer++ += right; + } + + // write back out pbs + WriteBackPBs(PBs, numberOfPBs); +} + +void CUCode_AX::Update() +{ + // check if we have to sent something + if (!m_rMailHandler.IsEmpty()) + { + g_dspInitialize.pGenerateDSPInterrupt(); + } +} + +// AX seems to bootup one task only and waits for resume-callbacks +// everytime the DSP has "spare time" it sends a resume-mail to the CPU +// and the __DSPHandler calls a AX-Callback which generates a new AXFrame +bool CUCode_AX::AXTask(u32& _uMail) +{ + u32 uAddress = _uMail; + DebugLog("AXTask - AXCommandList-Addr: 0x%08x", uAddress); + + u32 Addr__AXStudio; + u32 Addr__AXOutSBuffer; + u32 Addr__AXOutSBuffer_1; + u32 Addr__AXOutSBuffer_2; + u32 Addr__A; + u32 Addr__12; + u32 Addr__4_1; + u32 Addr__4_2; + u32 Addr__5_1; + u32 Addr__5_2; + u32 Addr__6; + u32 Addr__9; + + bool bExecuteList = true; + + while (bExecuteList) + { + static int last_valid_command = 0; + u16 iCommand = Memory_Read_U16(uAddress); + uAddress += 2; + switch (iCommand) + { + case AXLIST_STUDIOADDR: //00 + Addr__AXStudio = Memory_Read_U32(uAddress); + uAddress += 4; + if (wii_mode) + uAddress += 6; + DebugLog("AXLIST studio address: %08x", Addr__AXStudio); + break; + + case 0x001: + { + u32 address = Memory_Read_U32(uAddress); + uAddress += 4; + u16 param1 = Memory_Read_U16(uAddress); + uAddress += 2; + u16 param2 = Memory_Read_U16(uAddress); + uAddress += 2; + u16 param3 = Memory_Read_U16(uAddress); + uAddress += 2; + DebugLog("AXLIST 1: %08x, %04x, %04x, %04x", address, param1, param2, param3); + } + break; + + // + // Somewhere we should be getting a bitmask of AX_SYNC values + // that tells us what has been updated + // Dunno if important + // + case AXLIST_PBADDR: //02 + { + m_addressPBs = Memory_Read_U32(uAddress); + uAddress += 4; + + DebugLog("AXLIST PB address: %08x", m_addressPBs); + } + break; + + case 0x0003: + DebugLog("AXLIST command 0x0003 ????"); + break; + + case 0x0004: + Addr__4_1 = Memory_Read_U32(uAddress); + uAddress += 4; + Addr__4_2 = Memory_Read_U32(uAddress); + uAddress += 4; + DebugLog("AXLIST 4_1 4_2 addresses: %08x %08x", Addr__4_1, Addr__4_2); + break; + + case 0x0005: + Addr__5_1 = Memory_Read_U32(uAddress); + uAddress += 4; + Addr__5_2 = Memory_Read_U32(uAddress); + uAddress += 4; + DebugLog("AXLIST 5_1 5_2 addresses: %08x %08x", Addr__5_1, Addr__5_2); + break; + + case 0x0006: + Addr__6 = Memory_Read_U32(uAddress); + uAddress += 4; + DebugLog("AXLIST 6 address: %08x", Addr__6); + break; + + case AXLIST_SBUFFER: + // Hopefully this is where in main ram to write. + Addr__AXOutSBuffer = Memory_Read_U32(uAddress); + uAddress += 4; + if (wii_mode) { + uAddress += 12; + } + DebugLog("AXLIST OutSBuffer address: %08x", Addr__AXOutSBuffer); + break; + + case 0x0009: + Addr__9 = Memory_Read_U32(uAddress); + uAddress += 4; + DebugLog("AXLIST 6 address: %08x", Addr__9); + break; + + case AXLIST_COMPRESSORTABLE: // 0xa + Addr__A = Memory_Read_U32(uAddress); + uAddress += 4; + if (wii_mode) { + // There's one more here. +// uAddress += 4; + } + DebugLog("AXLIST CompressorTable address: %08x", Addr__A); + break; + + case 0x000e: + Addr__AXOutSBuffer_1 = Memory_Read_U32(uAddress); + uAddress += 4; + Addr__AXOutSBuffer_2 = Memory_Read_U32(uAddress); + uAddress += 4; + DebugLog("AXLIST sbuf2 addresses: %08x %08x", Addr__AXOutSBuffer_1, Addr__AXOutSBuffer_2); + break; + + case AXLIST_END: + bExecuteList = false; + DebugLog("AXLIST end"); + break; + + case 0x0010: //Super Monkey Ball 2 + DebugLog("AXLIST unknown"); + //should probably read/skip stuff here + uAddress += 8; + break; + + case 0x0011: + uAddress += 4; + break; + + case 0x0012: + Addr__12 = Memory_Read_U16(uAddress); + uAddress += 2; + break; + + case 0x0013: + uAddress += 6 * 4; // 6 Addresses. + break; + + case 0x000d: + if (wii_mode) { + uAddress += 4 * 4; // 4 addresses. another aux? + break; + } + // non-wii : fall through + + case 0x000b: + if (wii_mode) { + uAddress += 2; // one 0x8000 in rabbids + uAddress += 4 * 2; // then two RAM addressses + break; + } + // non-wii : fall through + + default: + { + static bool bFirst = true; + if (bFirst == true) + { + char szTemp[2048]; + sprintf(szTemp, "Unknown AX-Command 0x%x (address: 0x%08x). Last valid: %02x\n", + iCommand, uAddress - 2, last_valid_command); + int num = -32; + while (num < 64+32) + { + char szTemp2[128] = ""; + sprintf(szTemp2, "%s0x%04x\n", num == 0 ? ">>" : " ", Memory_Read_U16(uAddress + num)); + strcat(szTemp, szTemp2); + num += 2; + } + + PanicAlert(szTemp); + bFirst = false; + } + + // unknown command so stop the execution of this TaskList + bExecuteList = false; + } + break; + } + if (bExecuteList) + last_valid_command = iCommand; + } + DebugLog("AXTask - done, send resume"); + + // i hope resume is okay AX + m_rMailHandler.PushMail(0xDCD10001); + return true; +} + +int CUCode_AX::ReadOutPBs(AXParamBlock* _pPBs, int _num) +{ + int count = 0; + u32 blockAddr = m_addressPBs; + + // reading and 'halfword' swap + for (int i = 0; i < _num; i++) + { + const short *pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr); + if (pSrc != NULL) + { + short *pDest = (short *)&_pPBs[i]; + for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++) + { + pDest[p] = Common::swap16(pSrc[p]); + } + blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo; + count++; + } + else + break; + } + + // return the number of readed PBs + return count; +} + +void CUCode_AX::WriteBackPBs(AXParamBlock* _pPBs, int _num) +{ + u32 blockAddr = m_addressPBs; + + // write back and 'halfword'swap + for (int i = 0; i < _num; i++) + { + short* pSrc = (short*)&_pPBs[i]; + short* pDest = (short*)g_dspInitialize.pGetMemoryPointer(blockAddr); + for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++) + { + pDest[p] = Common::swap16(pSrc[p]); + } + + // next block + blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo; + } +} diff --git a/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_CARD.cpp b/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_CARD.cpp index de9e919946..2f52357abf 100644 --- a/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_CARD.cpp +++ b/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_CARD.cpp @@ -1,63 +1,63 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Common.h" -#include "../Globals.h" -#include "../DSPHandler.h" -#include "UCodes.h" -#include "UCode_CARD.h" - - -CUCode_CARD::CUCode_CARD(CMailHandler& _rMailHandler) - : IUCode(_rMailHandler) -{ - DebugLog("CUCode_CARD - initialized"); - m_rMailHandler.PushMail(DSP_INIT); -} - - -CUCode_CARD::~CUCode_CARD() -{ - m_rMailHandler.Clear(); -} - - -void CUCode_CARD::Update() -{ - // check if we have to sent something - if (!m_rMailHandler.IsEmpty()) - { - g_dspInitialize.pGenerateDSPInterrupt(); - } -} - -void CUCode_CARD::HandleMail(u32 _uMail) -{ - if (_uMail == 0xFF000000) // unlock card - { - // m_Mails.push(0x00000001); // ACK (actualy anything != 0) - } - else - { - DebugLog("CUCode_CARD - unknown cmd: %x (size %i)", _uMail); - } - - m_rMailHandler.PushMail(DSP_DONE); - CDSPHandler::GetInstance().SetUCode(UCODE_ROM); -} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "../Globals.h" +#include "../DSPHandler.h" +#include "UCodes.h" +#include "UCode_CARD.h" + + +CUCode_CARD::CUCode_CARD(CMailHandler& _rMailHandler) + : IUCode(_rMailHandler) +{ + DebugLog("CUCode_CARD - initialized"); + m_rMailHandler.PushMail(DSP_INIT); +} + + +CUCode_CARD::~CUCode_CARD() +{ + m_rMailHandler.Clear(); +} + + +void CUCode_CARD::Update() +{ + // check if we have to sent something + if (!m_rMailHandler.IsEmpty()) + { + g_dspInitialize.pGenerateDSPInterrupt(); + } +} + +void CUCode_CARD::HandleMail(u32 _uMail) +{ + if (_uMail == 0xFF000000) // unlock card + { + // m_Mails.push(0x00000001); // ACK (actualy anything != 0) + } + else + { + DebugLog("CUCode_CARD - unknown cmd: %x (size %i)", _uMail); + } + + m_rMailHandler.PushMail(DSP_DONE); + CDSPHandler::GetInstance().SetUCode(UCODE_ROM); +} + + diff --git a/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_InitAudioSystem.cpp b/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_InitAudioSystem.cpp index 741fd446f2..5d0dac45b8 100644 --- a/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_InitAudioSystem.cpp +++ b/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_InitAudioSystem.cpp @@ -1,54 +1,54 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Common.h" -#include "../Globals.h" -#include "../DSPHandler.h" -#include "UCodes.h" -#include "UCode_InitAudioSystem.h" - -CUCode_InitAudioSystem::CUCode_InitAudioSystem(CMailHandler& _rMailHandler) - : IUCode(_rMailHandler) - , m_BootTask_numSteps(0) - , m_NextParameter(0) - , IsInitialized(false) -{ - DebugLog("CUCode_InitAudioSystem - initialized"); -} - - -CUCode_InitAudioSystem::~CUCode_InitAudioSystem() -{} - - -void CUCode_InitAudioSystem::Init() -{} - - -void CUCode_InitAudioSystem::Update() -{ - if (m_rMailHandler.IsEmpty()) - { - m_rMailHandler.PushMail(0x80544348); - // HALT - } -} - -void CUCode_InitAudioSystem::HandleMail(u32 _uMail) -{} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "../Globals.h" +#include "../DSPHandler.h" +#include "UCodes.h" +#include "UCode_InitAudioSystem.h" + +CUCode_InitAudioSystem::CUCode_InitAudioSystem(CMailHandler& _rMailHandler) + : IUCode(_rMailHandler) + , m_BootTask_numSteps(0) + , m_NextParameter(0) + , IsInitialized(false) +{ + DebugLog("CUCode_InitAudioSystem - initialized"); +} + + +CUCode_InitAudioSystem::~CUCode_InitAudioSystem() +{} + + +void CUCode_InitAudioSystem::Init() +{} + + +void CUCode_InitAudioSystem::Update() +{ + if (m_rMailHandler.IsEmpty()) + { + m_rMailHandler.PushMail(0x80544348); + // HALT + } +} + +void CUCode_InitAudioSystem::HandleMail(u32 _uMail) +{} + + diff --git a/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_Jac.cpp b/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_Jac.cpp index a1f6ff3544..96a7355dd2 100644 --- a/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_Jac.cpp +++ b/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_Jac.cpp @@ -1,162 +1,162 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Common.h" -#include "../Globals.h" -#include "UCodes.h" -#include "UCode_Jac.h" -#include "../MailHandler.h" - -CUCode_Jac::CUCode_Jac(CMailHandler& _rMailHandler) - : IUCode(_rMailHandler) - , m_bListInProgress(false) -{ - DebugLog("CUCode_Jac: init"); - m_rMailHandler.PushMail(0xDCD10000); - m_rMailHandler.PushMail(0x80000000); -} - - -CUCode_Jac::~CUCode_Jac() -{ - m_rMailHandler.Clear(); -} - - -void CUCode_Jac::HandleMail(u32 _uMail) -{ - // this is prolly totally bullshit and should work like the zelda one... - // but i am to lazy to change it atm - - if (m_bListInProgress == false) - { - // get the command to find out how much steps it has - switch (_uMail & 0xFFFF) - { - // release halt - case 0x00: - // m_Mails.push(0x80000000); - g_dspInitialize.pGenerateDSPInterrupt(); - break; - - case 0x40: - m_step = 0; - ((u32*)m_Buffer)[m_step++] = _uMail; - m_bListInProgress = true; - m_numSteps = 5; - break; - - case 0x2000: - case 0x4000: - m_step = 0; - ((u32*)m_Buffer)[m_step++] = _uMail; - m_bListInProgress = true; - m_numSteps = 3; - break; - - default: - PanicAlert("UCode Jac"); - DebugLog("UCode Jac - unknown cmd: %x", _uMail & 0xFFFF); - break; - } - } - else - { - ((u32*)m_Buffer)[m_step] = _uMail; - m_step++; - - if (m_step == m_numSteps) - { - ExecuteList(); - m_bListInProgress = false; - } - } -} - - -void CUCode_Jac::Update() -{ - // check if we have to sent something -/* if (!g_MailHandler.empty()) - { - g_dspInitialize.pGenerateDSPInterrupt(); - }*/ -} - - -void CUCode_Jac::ExecuteList() -{ - // begin with the list - m_readOffset = 0; - - u16 cmd = Read16(); - u16 sync = Read16(); - - DebugLog("=============================================================================="); - DebugLog("UCode Jac - execute dlist (cmd: 0x%04x : sync: 0x%04x)", cmd, sync); - - switch (cmd) - { - // ============================================================================== - // DsetupTable - // ============================================================================== - case 0x40: - { - u32 tmp[4]; - tmp[0] = Read32(); - tmp[1] = Read32(); - tmp[2] = Read32(); - tmp[3] = Read32(); - - DebugLog("DsetupTable"); - DebugLog("???: 0x%08x", tmp[0]); - DebugLog("DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]); - DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]); - DebugLog("???: 0x%08x", tmp[3]); - } - break; - - // ============================================================================== - // UpdateDSPChannel - // ============================================================================== - case 0x2000: - case 0x4000: // animal crossing - { - u32 tmp[3]; - tmp[0] = Read32(); - tmp[1] = Read32(); - tmp[2] = Read32(); - - DebugLog("UpdateDSPChannel"); - DebugLog("audiomemory: 0x%08x", tmp[0]); - DebugLog("audiomemory: 0x%08x", tmp[1]); - DebugLog("DSPADPCM_FILTER (size: 0x40): 0x%08x", tmp[2]); - } - break; - - default: - PanicAlert("UCode Jac unknown cmd: %s (size %)", cmd, m_numSteps); - DebugLog("Jac UCode - unknown cmd: %x (size %i)", cmd, m_numSteps); - break; - } - - // sync, we are rdy - m_rMailHandler.PushMail(DSP_SYNC); - m_rMailHandler.PushMail(0xF3550000 | sync); -} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "../Globals.h" +#include "UCodes.h" +#include "UCode_Jac.h" +#include "../MailHandler.h" + +CUCode_Jac::CUCode_Jac(CMailHandler& _rMailHandler) + : IUCode(_rMailHandler) + , m_bListInProgress(false) +{ + DebugLog("CUCode_Jac: init"); + m_rMailHandler.PushMail(0xDCD10000); + m_rMailHandler.PushMail(0x80000000); +} + + +CUCode_Jac::~CUCode_Jac() +{ + m_rMailHandler.Clear(); +} + + +void CUCode_Jac::HandleMail(u32 _uMail) +{ + // this is prolly totally bullshit and should work like the zelda one... + // but i am to lazy to change it atm + + if (m_bListInProgress == false) + { + // get the command to find out how much steps it has + switch (_uMail & 0xFFFF) + { + // release halt + case 0x00: + // m_Mails.push(0x80000000); + g_dspInitialize.pGenerateDSPInterrupt(); + break; + + case 0x40: + m_step = 0; + ((u32*)m_Buffer)[m_step++] = _uMail; + m_bListInProgress = true; + m_numSteps = 5; + break; + + case 0x2000: + case 0x4000: + m_step = 0; + ((u32*)m_Buffer)[m_step++] = _uMail; + m_bListInProgress = true; + m_numSteps = 3; + break; + + default: + PanicAlert("UCode Jac"); + DebugLog("UCode Jac - unknown cmd: %x", _uMail & 0xFFFF); + break; + } + } + else + { + ((u32*)m_Buffer)[m_step] = _uMail; + m_step++; + + if (m_step == m_numSteps) + { + ExecuteList(); + m_bListInProgress = false; + } + } +} + + +void CUCode_Jac::Update() +{ + // check if we have to sent something +/* if (!g_MailHandler.empty()) + { + g_dspInitialize.pGenerateDSPInterrupt(); + }*/ +} + + +void CUCode_Jac::ExecuteList() +{ + // begin with the list + m_readOffset = 0; + + u16 cmd = Read16(); + u16 sync = Read16(); + + DebugLog("=============================================================================="); + DebugLog("UCode Jac - execute dlist (cmd: 0x%04x : sync: 0x%04x)", cmd, sync); + + switch (cmd) + { + // ============================================================================== + // DsetupTable + // ============================================================================== + case 0x40: + { + u32 tmp[4]; + tmp[0] = Read32(); + tmp[1] = Read32(); + tmp[2] = Read32(); + tmp[3] = Read32(); + + DebugLog("DsetupTable"); + DebugLog("???: 0x%08x", tmp[0]); + DebugLog("DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]); + DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]); + DebugLog("???: 0x%08x", tmp[3]); + } + break; + + // ============================================================================== + // UpdateDSPChannel + // ============================================================================== + case 0x2000: + case 0x4000: // animal crossing + { + u32 tmp[3]; + tmp[0] = Read32(); + tmp[1] = Read32(); + tmp[2] = Read32(); + + DebugLog("UpdateDSPChannel"); + DebugLog("audiomemory: 0x%08x", tmp[0]); + DebugLog("audiomemory: 0x%08x", tmp[1]); + DebugLog("DSPADPCM_FILTER (size: 0x40): 0x%08x", tmp[2]); + } + break; + + default: + PanicAlert("UCode Jac unknown cmd: %s (size %)", cmd, m_numSteps); + DebugLog("Jac UCode - unknown cmd: %x (size %i)", cmd, m_numSteps); + break; + } + + // sync, we are rdy + m_rMailHandler.PushMail(DSP_SYNC); + m_rMailHandler.PushMail(0xF3550000 | sync); +} + + diff --git a/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_ROM.cpp b/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_ROM.cpp index 435852fd1a..8505e12dd0 100644 --- a/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_ROM.cpp +++ b/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_ROM.cpp @@ -1,113 +1,113 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Common.h" -#include "../Globals.h" -#include "../DSPHandler.h" -#include "UCodes.h" -#include "UCode_ROM.h" - -CUCode_Rom::CUCode_Rom(CMailHandler& _rMailHandler) - : IUCode(_rMailHandler) - , m_BootTask_numSteps(0) - , m_NextParameter(0) -{ - DebugLog("UCode_Rom - initialized"); - m_rMailHandler.Clear(); - m_rMailHandler.PushMail(0x8071FEED); -} - -CUCode_Rom::~CUCode_Rom() -{} - -void CUCode_Rom::Update() -{} - -void CUCode_Rom::HandleMail(u32 _uMail) -{ - if (m_NextParameter == 0) - { - // wait for beginning of UCode - if ((_uMail & 0xFFFF0000) != 0x80F30000) - { - u32 Message = 0xFEEE0000 | (_uMail & 0xFFFF); - m_rMailHandler.PushMail(Message); - } - else - { - m_NextParameter = _uMail; - } - } - else - { - switch (m_NextParameter) - { - case 0x80F3A001: - m_CurrentUCode.m_RAMAddress = _uMail; - break; - - case 0x80F3A002: - m_CurrentUCode.m_Length = _uMail; - break; - - case 0x80F3C002: - m_CurrentUCode.m_IMEMAddress = _uMail; - break; - - case 0x80F3B002: - m_CurrentUCode.m_Unk = _uMail; - break; - - case 0x80F3D001: - { - m_CurrentUCode.m_StartPC = _uMail; - BootUCode(); - return; // FIXES THE OVERWRITE - } - break; - } - - // THE GODDAMN OVERWRITE WAS HERE. Without the return above, since BootUCode may delete "this", well ... - m_NextParameter = 0; - } -} - -void CUCode_Rom::BootUCode() -{ - // simple non-scientific crc invented by ector :P - // too annoying to change now, and probably good enough anyway - u32 crc = 0; - - for (u32 i = 0; i < m_CurrentUCode.m_Length; i++) - { - crc ^= Memory_Read_U8(m_CurrentUCode.m_RAMAddress + i); - //let's rol - crc = (crc << 3) | (crc >> 29); - } - - DebugLog("CurrentUCode SOURCE Addr: 0x%08x", m_CurrentUCode.m_RAMAddress); - DebugLog("CurrentUCode Length: 0x%08x", m_CurrentUCode.m_Length); - DebugLog("CurrentUCode DEST Addr: 0x%08x", m_CurrentUCode.m_IMEMAddress); - DebugLog("CurrentUCode ???: 0x%08x", m_CurrentUCode.m_Unk); - DebugLog("CurrentUCode init_vector: 0x%08x", m_CurrentUCode.m_StartPC); - DebugLog("CurrentUCode CRC: 0x%08x", crc); - DebugLog("BootTask - done"); - - CDSPHandler::GetInstance().SetUCode(crc); -} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "../Globals.h" +#include "../DSPHandler.h" +#include "UCodes.h" +#include "UCode_ROM.h" + +CUCode_Rom::CUCode_Rom(CMailHandler& _rMailHandler) + : IUCode(_rMailHandler) + , m_BootTask_numSteps(0) + , m_NextParameter(0) +{ + DebugLog("UCode_Rom - initialized"); + m_rMailHandler.Clear(); + m_rMailHandler.PushMail(0x8071FEED); +} + +CUCode_Rom::~CUCode_Rom() +{} + +void CUCode_Rom::Update() +{} + +void CUCode_Rom::HandleMail(u32 _uMail) +{ + if (m_NextParameter == 0) + { + // wait for beginning of UCode + if ((_uMail & 0xFFFF0000) != 0x80F30000) + { + u32 Message = 0xFEEE0000 | (_uMail & 0xFFFF); + m_rMailHandler.PushMail(Message); + } + else + { + m_NextParameter = _uMail; + } + } + else + { + switch (m_NextParameter) + { + case 0x80F3A001: + m_CurrentUCode.m_RAMAddress = _uMail; + break; + + case 0x80F3A002: + m_CurrentUCode.m_Length = _uMail; + break; + + case 0x80F3C002: + m_CurrentUCode.m_IMEMAddress = _uMail; + break; + + case 0x80F3B002: + m_CurrentUCode.m_Unk = _uMail; + break; + + case 0x80F3D001: + { + m_CurrentUCode.m_StartPC = _uMail; + BootUCode(); + return; // FIXES THE OVERWRITE + } + break; + } + + // THE GODDAMN OVERWRITE WAS HERE. Without the return above, since BootUCode may delete "this", well ... + m_NextParameter = 0; + } +} + +void CUCode_Rom::BootUCode() +{ + // simple non-scientific crc invented by ector :P + // too annoying to change now, and probably good enough anyway + u32 crc = 0; + + for (u32 i = 0; i < m_CurrentUCode.m_Length; i++) + { + crc ^= Memory_Read_U8(m_CurrentUCode.m_RAMAddress + i); + //let's rol + crc = (crc << 3) | (crc >> 29); + } + + DebugLog("CurrentUCode SOURCE Addr: 0x%08x", m_CurrentUCode.m_RAMAddress); + DebugLog("CurrentUCode Length: 0x%08x", m_CurrentUCode.m_Length); + DebugLog("CurrentUCode DEST Addr: 0x%08x", m_CurrentUCode.m_IMEMAddress); + DebugLog("CurrentUCode ???: 0x%08x", m_CurrentUCode.m_Unk); + DebugLog("CurrentUCode init_vector: 0x%08x", m_CurrentUCode.m_StartPC); + DebugLog("CurrentUCode CRC: 0x%08x", crc); + DebugLog("BootTask - done"); + + CDSPHandler::GetInstance().SetUCode(crc); +} + + diff --git a/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_Zelda.cpp b/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_Zelda.cpp index 68734d669c..14d3f232fe 100644 --- a/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_Zelda.cpp +++ b/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCode_Zelda.cpp @@ -1,166 +1,166 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -// Games that uses this UCode: -// Zelda: The Windwaker, Mario Sunshine, Mario Kart - -#include "Common.h" -#include "../Globals.h" -#include "UCodes.h" -#include "UCode_Zelda.h" -#include "../MailHandler.h" - - -CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler) - : IUCode(_rMailHandler) - , m_numSteps(0) - , m_bListInProgress(false) - , m_step(0) - , m_readOffset(0) -{ - DebugLog("UCode_Zelda - add boot mails for handshake"); - m_rMailHandler.PushMail(DSP_INIT); - m_rMailHandler.PushMail(0x80000000); // handshake - memset(m_Buffer, 0, sizeof(m_Buffer)); -} - - -CUCode_Zelda::~CUCode_Zelda() -{ - m_rMailHandler.Clear(); -} - - -void CUCode_Zelda::Update() -{ - // check if we have to sent something - if (!m_rMailHandler.IsEmpty()) - g_dspInitialize.pGenerateDSPInterrupt(); -} - - -void CUCode_Zelda::HandleMail(u32 _uMail) -{ - if (m_bListInProgress == false) - { - m_bListInProgress = true; - m_numSteps = _uMail; - m_step = 0; - } - else - { - if (m_step < 0 || m_step >= sizeof(m_Buffer)/4) - PanicAlert("m_step out of range"); - ((u32*)m_Buffer)[m_step] = _uMail; - m_step++; - - if (m_step == m_numSteps) - { - ExecuteList(); - m_bListInProgress = false; - } - } -} - - -void CUCode_Zelda::ExecuteList() -{ - // begin with the list - m_readOffset = 0; - - u32 Temp = Read32(); - u32 Command = (Temp >> 24) & 0x7f; - u32 Sync = Temp >> 16; - - DebugLog("=============================================================================="); - DebugLog("Zelda UCode - execute dlist (cmd: 0x%04x : sync: 0x%04x)", Command, Sync); - - switch (Command) - { - // DsetupTable ... zelda ww jumps to 0x0095 - case 0x01: - { - u32 tmp[4]; - tmp[0] = Read32(); - tmp[1] = Read32(); - tmp[2] = Read32(); - tmp[3] = Read32(); - - DebugLog("DsetupTable"); - DebugLog("???: 0x%08x", tmp[0]); - DebugLog("DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]); - DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]); - DebugLog("???: 0x%08x", tmp[3]); - } - break; - - // SyncFrame ... zelda ww jumps to 0x0243 - case 0x02: - { - u32 tmp[3]; - tmp[0] = Read32(); - tmp[1] = Read32(); - tmp[2] = Read32(); - - DebugLog("DsyncFrame"); - DebugLog("???: 0x%08x", tmp[0]); - DebugLog("???: 0x%08x", tmp[1]); - DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]); - } - break; - -/* - case 0x03: break; // dunno ... zelda ww jmps to 0x0073 - case 0x04: break; // dunno ... zelda ww jmps to 0x0580 - case 0x05: break; // dunno ... zelda ww jmps to 0x0592 - case 0x06: break; // dunno ... zelda ww jmps to 0x0469 - - case 0x07: break; // dunno ... zelda ww jmps to 0x044d - case 0x08: break; // Mixer ... zelda ww jmps to 0x0485 - case 0x09: break; // dunno ... zelda ww jmps to 0x044d - */ - - // DsetDolbyDelay ... zelda ww jumps to 0x00b2 - case 0x0d: - { - u32 tmp[2]; - tmp[0] = Read32(); - tmp[1] = Read32(); - - DebugLog("DSetDolbyDelay"); - DebugLog("DOLBY2_DELAY_BUF (size 0x960): 0x%08x", tmp[0]); - DebugLog("DSPRES_FILTER (size 0x500): 0x%08x", tmp[1]); - } - break; - - // Set VARAM - case 0x0e: -// MessageBox(NULL, "Zelda VARAM", "cmd", MB_OK); - break; - - // default ... zelda ww jumps to 0x0043 - default: - PanicAlert("Zelda UCode - unknown cmd: %x (size %i)", Command, m_numSteps); - break; - } - - // sync, we are rdy - m_rMailHandler.PushMail(DSP_SYNC); - m_rMailHandler.PushMail(0xF3550000 | Sync); -} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +// Games that uses this UCode: +// Zelda: The Windwaker, Mario Sunshine, Mario Kart + +#include "Common.h" +#include "../Globals.h" +#include "UCodes.h" +#include "UCode_Zelda.h" +#include "../MailHandler.h" + + +CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler) + : IUCode(_rMailHandler) + , m_numSteps(0) + , m_bListInProgress(false) + , m_step(0) + , m_readOffset(0) +{ + DebugLog("UCode_Zelda - add boot mails for handshake"); + m_rMailHandler.PushMail(DSP_INIT); + m_rMailHandler.PushMail(0x80000000); // handshake + memset(m_Buffer, 0, sizeof(m_Buffer)); +} + + +CUCode_Zelda::~CUCode_Zelda() +{ + m_rMailHandler.Clear(); +} + + +void CUCode_Zelda::Update() +{ + // check if we have to sent something + if (!m_rMailHandler.IsEmpty()) + g_dspInitialize.pGenerateDSPInterrupt(); +} + + +void CUCode_Zelda::HandleMail(u32 _uMail) +{ + if (m_bListInProgress == false) + { + m_bListInProgress = true; + m_numSteps = _uMail; + m_step = 0; + } + else + { + if (m_step < 0 || m_step >= sizeof(m_Buffer)/4) + PanicAlert("m_step out of range"); + ((u32*)m_Buffer)[m_step] = _uMail; + m_step++; + + if (m_step == m_numSteps) + { + ExecuteList(); + m_bListInProgress = false; + } + } +} + + +void CUCode_Zelda::ExecuteList() +{ + // begin with the list + m_readOffset = 0; + + u32 Temp = Read32(); + u32 Command = (Temp >> 24) & 0x7f; + u32 Sync = Temp >> 16; + + DebugLog("=============================================================================="); + DebugLog("Zelda UCode - execute dlist (cmd: 0x%04x : sync: 0x%04x)", Command, Sync); + + switch (Command) + { + // DsetupTable ... zelda ww jumps to 0x0095 + case 0x01: + { + u32 tmp[4]; + tmp[0] = Read32(); + tmp[1] = Read32(); + tmp[2] = Read32(); + tmp[3] = Read32(); + + DebugLog("DsetupTable"); + DebugLog("???: 0x%08x", tmp[0]); + DebugLog("DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]); + DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]); + DebugLog("???: 0x%08x", tmp[3]); + } + break; + + // SyncFrame ... zelda ww jumps to 0x0243 + case 0x02: + { + u32 tmp[3]; + tmp[0] = Read32(); + tmp[1] = Read32(); + tmp[2] = Read32(); + + DebugLog("DsyncFrame"); + DebugLog("???: 0x%08x", tmp[0]); + DebugLog("???: 0x%08x", tmp[1]); + DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]); + } + break; + +/* + case 0x03: break; // dunno ... zelda ww jmps to 0x0073 + case 0x04: break; // dunno ... zelda ww jmps to 0x0580 + case 0x05: break; // dunno ... zelda ww jmps to 0x0592 + case 0x06: break; // dunno ... zelda ww jmps to 0x0469 + + case 0x07: break; // dunno ... zelda ww jmps to 0x044d + case 0x08: break; // Mixer ... zelda ww jmps to 0x0485 + case 0x09: break; // dunno ... zelda ww jmps to 0x044d + */ + + // DsetDolbyDelay ... zelda ww jumps to 0x00b2 + case 0x0d: + { + u32 tmp[2]; + tmp[0] = Read32(); + tmp[1] = Read32(); + + DebugLog("DSetDolbyDelay"); + DebugLog("DOLBY2_DELAY_BUF (size 0x960): 0x%08x", tmp[0]); + DebugLog("DSPRES_FILTER (size 0x500): 0x%08x", tmp[1]); + } + break; + + // Set VARAM + case 0x0e: +// MessageBox(NULL, "Zelda VARAM", "cmd", MB_OK); + break; + + // default ... zelda ww jumps to 0x0043 + default: + PanicAlert("Zelda UCode - unknown cmd: %x (size %i)", Command, m_numSteps); + break; + } + + // sync, we are rdy + m_rMailHandler.PushMail(DSP_SYNC); + m_rMailHandler.PushMail(0xF3550000 | Sync); +} + + diff --git a/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCodes.cpp b/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCodes.cpp index 28cfaeca52..1ba4474510 100644 --- a/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCodes.cpp +++ b/Source/Plugins/Plugin_DSP_NULL/Src/UCodes/UCodes.cpp @@ -1,87 +1,87 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Common.h" -#include "../Globals.h" - -#include "UCodes.h" - -#include "UCode_AX.h" -#include "UCode_Zelda.h" -#include "UCode_Jac.h" -#include "UCode_ROM.h" -#include "UCode_CARD.h" -#include "UCode_InitAudioSystem.h" - -IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler) -{ - switch (_CRC) - { - case UCODE_ROM: - return new CUCode_Rom(_rMailHandler); - - case UCODE_INIT_AUDIO_SYSTEM: - return new CUCode_InitAudioSystem(_rMailHandler); - - case 0x65d6cc6f: // CARD - return new CUCode_CARD(_rMailHandler); - - case 0x088e38a5: // IPL - JAP - case 0xd73338cf: // IPL - case 0x42f64ac4: // Luigi (after fix) - case 0x4be6a5cb: // AC, Pikmin (after fix) - DebugLog("JAC ucode chosen"); - return new CUCode_Jac(_rMailHandler); - - case 0x3ad3b7ac: // Naruto3 - case 0x3daf59b9: // Alien Hominid - case 0x4e8a8b21: // spdemo, ctaxi, 18 wheeler, disney, monkeyball2,cubivore,puzzlecollection,wario, - // capcom vs snk, naruto2, lost kingdoms, star fox, mario party 4, mortal kombat, - // smugglers run warzone, smash brothers, sonic mega collection, ZooCube - // nddemo, starfox - case 0x07f88145: // bustamove, ikaruga, fzero, robotech battle cry, star soldier, soul calibur2, - // Zelda:OOT, Tony hawk, viewtiful joe - case 0xe2136399: // billy hatcher, dragonballz, mario party 5, TMNT, ava1080 - DebugLog("AX ucode chosen, yay!"); - return new CUCode_AX(_rMailHandler); - - case 0x6CA33A6D: // DK Jungle Beat - case 0x86840740: // zelda - case 0x56d36052: // mario - case 0x2fcdf1ec: // mariokart, zelda 4 swords - DebugLog("Zelda ucode chosen"); - return new CUCode_Zelda(_rMailHandler); - - // WII CRCs - case 0x6c3f6f94: // zelda - PAL - case 0xd643001f: // mario galaxy - PAL - DebugLog("Zelda Wii ucode chosen"); - return new CUCode_Zelda(_rMailHandler); - - case 0x347112ba: // raving rabbits - DebugLog("Wii - AX chosen"); - return new CUCode_AX(_rMailHandler, true); - - default: - PanicAlert("Unknown ucode (CRC = %08x) - forcing AX", _CRC); - return new CUCode_AX(_rMailHandler); - } - - return NULL; -} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "../Globals.h" + +#include "UCodes.h" + +#include "UCode_AX.h" +#include "UCode_Zelda.h" +#include "UCode_Jac.h" +#include "UCode_ROM.h" +#include "UCode_CARD.h" +#include "UCode_InitAudioSystem.h" + +IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler) +{ + switch (_CRC) + { + case UCODE_ROM: + return new CUCode_Rom(_rMailHandler); + + case UCODE_INIT_AUDIO_SYSTEM: + return new CUCode_InitAudioSystem(_rMailHandler); + + case 0x65d6cc6f: // CARD + return new CUCode_CARD(_rMailHandler); + + case 0x088e38a5: // IPL - JAP + case 0xd73338cf: // IPL + case 0x42f64ac4: // Luigi (after fix) + case 0x4be6a5cb: // AC, Pikmin (after fix) + DebugLog("JAC ucode chosen"); + return new CUCode_Jac(_rMailHandler); + + case 0x3ad3b7ac: // Naruto3 + case 0x3daf59b9: // Alien Hominid + case 0x4e8a8b21: // spdemo, ctaxi, 18 wheeler, disney, monkeyball2,cubivore,puzzlecollection,wario, + // capcom vs snk, naruto2, lost kingdoms, star fox, mario party 4, mortal kombat, + // smugglers run warzone, smash brothers, sonic mega collection, ZooCube + // nddemo, starfox + case 0x07f88145: // bustamove, ikaruga, fzero, robotech battle cry, star soldier, soul calibur2, + // Zelda:OOT, Tony hawk, viewtiful joe + case 0xe2136399: // billy hatcher, dragonballz, mario party 5, TMNT, ava1080 + DebugLog("AX ucode chosen, yay!"); + return new CUCode_AX(_rMailHandler); + + case 0x6CA33A6D: // DK Jungle Beat + case 0x86840740: // zelda + case 0x56d36052: // mario + case 0x2fcdf1ec: // mariokart, zelda 4 swords + DebugLog("Zelda ucode chosen"); + return new CUCode_Zelda(_rMailHandler); + + // WII CRCs + case 0x6c3f6f94: // zelda - PAL + case 0xd643001f: // mario galaxy - PAL + DebugLog("Zelda Wii ucode chosen"); + return new CUCode_Zelda(_rMailHandler); + + case 0x347112ba: // raving rabbits + DebugLog("Wii - AX chosen"); + return new CUCode_AX(_rMailHandler, true); + + default: + PanicAlert("Unknown ucode (CRC = %08x) - forcing AX", _CRC); + return new CUCode_AX(_rMailHandler); + } + + return NULL; +} + + diff --git a/Source/Plugins/Plugin_DSP_NULL/Src/main.cpp b/Source/Plugins/Plugin_DSP_NULL/Src/main.cpp index 3967a5461b..1fcf631f92 100644 --- a/Source/Plugins/Plugin_DSP_NULL/Src/main.cpp +++ b/Source/Plugins/Plugin_DSP_NULL/Src/main.cpp @@ -1,203 +1,203 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -//#include "Common.h" -#include "ChunkFile.h" -#include "pluginspecs_dsp.h" - -#include "DSPHandler.h" - -DSPInitialize g_dspInitialize; -u8* g_pMemory; - -struct DSPState -{ - u32 CPUMailbox; - bool CPUMailbox_Written[2]; - - u32 DSPMailbox; - bool DSPMailbox_Read[2]; - - DSPState() - { - CPUMailbox = 0x00000000; - CPUMailbox_Written[0] = false; - CPUMailbox_Written[1] = false; - - DSPMailbox = 0x00000000; - DSPMailbox_Read[0] = true; - DSPMailbox_Read[1] = true; - } -}; - -DSPState g_dspState; - -#ifdef _WIN32 -HINSTANCE g_hInstance = NULL; - -BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle - DWORD dwReason, // reason called - LPVOID lpvReserved) // reserved -{ - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - break; - - case DLL_PROCESS_DETACH: - break; - - default: - break; - } - - g_hInstance = hinstDLL; - return(TRUE); -} - -#endif - -void DllDebugger(HWND _hParent) -{ - // TODO: implement -} - -void GetDllInfo(PLUGIN_INFO* _PluginInfo) -{ - _PluginInfo->Version = 0x0100; - _PluginInfo->Type = PLUGIN_TYPE_DSP; -#ifdef DEBUGFAST - sprintf(_PluginInfo->Name, "Dolphin DSP-NULL Plugin (DebugFast) "); -#else -#ifndef _DEBUG - sprintf(_PluginInfo->Name, "Dolphin DSP-NULL Plugin "); -#else - sprintf(_PluginInfo->Name, "Dolphin DSP-NULL Plugin (Debug) "); -#endif -#endif -} - -void DllAbout(HWND _hParent) -{ -} - -void DllConfig(HWND _hParent) -{ -} - -void DSP_Initialize(DSPInitialize _dspInitialize) -{ - g_dspInitialize = _dspInitialize; - - g_pMemory = g_dspInitialize.pGetMemoryPointer(0); - - CDSPHandler::CreateInstance(); -} - -void DSP_Shutdown() -{ - - CDSPHandler::Destroy(); -} - -void DSP_DoState(unsigned char **ptr, int mode) { - PointerWrap p(ptr, mode); -} - -unsigned short DSP_ReadMailboxHigh(bool _CPUMailbox) -{ - if (_CPUMailbox) - { - return (g_dspState.CPUMailbox >> 16) & 0xFFFF; - } - else - { - return CDSPHandler::GetInstance().AccessMailHandler().ReadDSPMailboxHigh(); - } -} - -unsigned short DSP_ReadMailboxLow(bool _CPUMailbox) -{ - if (_CPUMailbox) - { - return g_dspState.CPUMailbox & 0xFFFF; - } - else - { - return CDSPHandler::GetInstance().AccessMailHandler().ReadDSPMailboxLow(); - } -} - -void Update_DSP_WriteRegister() -{ - // check if the whole message is complete and if we can send it - if (g_dspState.CPUMailbox_Written[0] && g_dspState.CPUMailbox_Written[1]) - { - CDSPHandler::GetInstance().SendMailToDSP(g_dspState.CPUMailbox); - g_dspState.CPUMailbox_Written[0] = g_dspState.CPUMailbox_Written[1] = false; - g_dspState.CPUMailbox = 0; // Mail sent so clear it to show that it is progressed - } -} - -void DSP_WriteMailboxHigh(bool _CPUMailbox, unsigned short _Value) -{ - if (_CPUMailbox) - { - g_dspState.CPUMailbox = (g_dspState.CPUMailbox & 0xFFFF) | (_Value << 16); - g_dspState.CPUMailbox_Written[0] = true; - - Update_DSP_WriteRegister(); - } - else - { - PanicAlert("CPU can't write %08x to DSP mailbox", _Value); - } -} - -void DSP_WriteMailboxLow(bool _CPUMailbox, unsigned short _Value) -{ - if (_CPUMailbox) - { - g_dspState.CPUMailbox = (g_dspState.CPUMailbox & 0xFFFF0000) | _Value; - g_dspState.CPUMailbox_Written[1] = true; - - Update_DSP_WriteRegister(); - } - else - { - PanicAlert("CPU can't write %08x to DSP mailbox", _Value); - } -} - -unsigned short DSP_WriteControlRegister(unsigned short _Value) -{ - return CDSPHandler::GetInstance().WriteControlRegister(_Value); -} - -unsigned short DSP_ReadControlRegister() -{ - return CDSPHandler::GetInstance().ReadControlRegister(); -} - -void DSP_Update(int cycles) -{ - CDSPHandler::GetInstance().Update(); -} - -void DSP_SendAIBuffer(unsigned int address, int sample_rate) -{ -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +//#include "Common.h" +#include "ChunkFile.h" +#include "pluginspecs_dsp.h" + +#include "DSPHandler.h" + +DSPInitialize g_dspInitialize; +u8* g_pMemory; + +struct DSPState +{ + u32 CPUMailbox; + bool CPUMailbox_Written[2]; + + u32 DSPMailbox; + bool DSPMailbox_Read[2]; + + DSPState() + { + CPUMailbox = 0x00000000; + CPUMailbox_Written[0] = false; + CPUMailbox_Written[1] = false; + + DSPMailbox = 0x00000000; + DSPMailbox_Read[0] = true; + DSPMailbox_Read[1] = true; + } +}; + +DSPState g_dspState; + +#ifdef _WIN32 +HINSTANCE g_hInstance = NULL; + +BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle + DWORD dwReason, // reason called + LPVOID lpvReserved) // reserved +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + break; + + case DLL_PROCESS_DETACH: + break; + + default: + break; + } + + g_hInstance = hinstDLL; + return(TRUE); +} + +#endif + +void DllDebugger(HWND _hParent) +{ + // TODO: implement +} + +void GetDllInfo(PLUGIN_INFO* _PluginInfo) +{ + _PluginInfo->Version = 0x0100; + _PluginInfo->Type = PLUGIN_TYPE_DSP; +#ifdef DEBUGFAST + sprintf(_PluginInfo->Name, "Dolphin DSP-NULL Plugin (DebugFast) "); +#else +#ifndef _DEBUG + sprintf(_PluginInfo->Name, "Dolphin DSP-NULL Plugin "); +#else + sprintf(_PluginInfo->Name, "Dolphin DSP-NULL Plugin (Debug) "); +#endif +#endif +} + +void DllAbout(HWND _hParent) +{ +} + +void DllConfig(HWND _hParent) +{ +} + +void DSP_Initialize(DSPInitialize _dspInitialize) +{ + g_dspInitialize = _dspInitialize; + + g_pMemory = g_dspInitialize.pGetMemoryPointer(0); + + CDSPHandler::CreateInstance(); +} + +void DSP_Shutdown() +{ + + CDSPHandler::Destroy(); +} + +void DSP_DoState(unsigned char **ptr, int mode) { + PointerWrap p(ptr, mode); +} + +unsigned short DSP_ReadMailboxHigh(bool _CPUMailbox) +{ + if (_CPUMailbox) + { + return (g_dspState.CPUMailbox >> 16) & 0xFFFF; + } + else + { + return CDSPHandler::GetInstance().AccessMailHandler().ReadDSPMailboxHigh(); + } +} + +unsigned short DSP_ReadMailboxLow(bool _CPUMailbox) +{ + if (_CPUMailbox) + { + return g_dspState.CPUMailbox & 0xFFFF; + } + else + { + return CDSPHandler::GetInstance().AccessMailHandler().ReadDSPMailboxLow(); + } +} + +void Update_DSP_WriteRegister() +{ + // check if the whole message is complete and if we can send it + if (g_dspState.CPUMailbox_Written[0] && g_dspState.CPUMailbox_Written[1]) + { + CDSPHandler::GetInstance().SendMailToDSP(g_dspState.CPUMailbox); + g_dspState.CPUMailbox_Written[0] = g_dspState.CPUMailbox_Written[1] = false; + g_dspState.CPUMailbox = 0; // Mail sent so clear it to show that it is progressed + } +} + +void DSP_WriteMailboxHigh(bool _CPUMailbox, unsigned short _Value) +{ + if (_CPUMailbox) + { + g_dspState.CPUMailbox = (g_dspState.CPUMailbox & 0xFFFF) | (_Value << 16); + g_dspState.CPUMailbox_Written[0] = true; + + Update_DSP_WriteRegister(); + } + else + { + PanicAlert("CPU can't write %08x to DSP mailbox", _Value); + } +} + +void DSP_WriteMailboxLow(bool _CPUMailbox, unsigned short _Value) +{ + if (_CPUMailbox) + { + g_dspState.CPUMailbox = (g_dspState.CPUMailbox & 0xFFFF0000) | _Value; + g_dspState.CPUMailbox_Written[1] = true; + + Update_DSP_WriteRegister(); + } + else + { + PanicAlert("CPU can't write %08x to DSP mailbox", _Value); + } +} + +unsigned short DSP_WriteControlRegister(unsigned short _Value) +{ + return CDSPHandler::GetInstance().WriteControlRegister(_Value); +} + +unsigned short DSP_ReadControlRegister() +{ + return CDSPHandler::GetInstance().ReadControlRegister(); +} + +void DSP_Update(int cycles) +{ + CDSPHandler::GetInstance().Update(); +} + +void DSP_SendAIBuffer(unsigned int address, int sample_rate) +{ +} diff --git a/Source/Plugins/Plugin_PadSimple/Src/DirectInputBase.cpp b/Source/Plugins/Plugin_PadSimple/Src/DirectInputBase.cpp index c7966b69d3..7bb77f02be 100644 --- a/Source/Plugins/Plugin_PadSimple/Src/DirectInputBase.cpp +++ b/Source/Plugins/Plugin_PadSimple/Src/DirectInputBase.cpp @@ -1,189 +1,189 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "stdafx.h" -#include "DirectInputBase.h" - -DInput::DInput() - : g_pDI(NULL), - g_pKeyboard(NULL) -{} - - -DInput::~DInput() -{ - Free(); -} - -void DInput::DIKToString(unsigned int keycode, char *keyStr) -{ - switch(keycode) { - case DIK_RETURN: - sprintf(keyStr, "Enter"); - break; - case DIK_UP: - sprintf(keyStr, "Up"); - break; - case DIK_DOWN: - sprintf(keyStr, "Down"); - break; - case DIK_LEFT: - sprintf(keyStr, "Left"); - break; - case DIK_RIGHT: - sprintf(keyStr, "Right"); - break; - case DIK_HOME: - strcpy(keyStr, "Home"); - break; - case DIK_END: - strcpy(keyStr, "End"); - break; - case DIK_INSERT: - strcpy(keyStr, "Ins"); - break; - case DIK_DELETE: - strcpy(keyStr, "Del"); - break; - case DIK_PGUP: - strcpy(keyStr, "PgUp"); - break; - case DIK_PGDN: - strcpy(keyStr, "PgDn"); - break; - case DIK_NUMPAD0: - strcpy(keyStr, "Num 0"); - break; - case DIK_NUMPAD1: - strcpy(keyStr, "Num 1"); - break; - case DIK_NUMPAD2: - strcpy(keyStr, "Num 2"); - break; - case DIK_NUMPAD3: - strcpy(keyStr, "Num 3"); - break; - case DIK_NUMPAD4: - strcpy(keyStr, "Num 4"); - break; - case DIK_NUMPAD5: - strcpy(keyStr, "Num 5"); - break; - case DIK_NUMPAD6: - strcpy(keyStr, "Num 6"); - break; - case DIK_NUMPAD7: - strcpy(keyStr, "Num 7"); - break; - case DIK_NUMPAD8: - strcpy(keyStr, "Num 8"); - break; - case DIK_NUMPAD9: - strcpy(keyStr, "Num 9"); - break; - case DIK_NUMPADSLASH: - strcpy(keyStr, "Num /"); - break; - default: - GetKeyNameText(keycode << 16, keyStr, 64); - break; +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" +#include "DirectInputBase.h" + +DInput::DInput() + : g_pDI(NULL), + g_pKeyboard(NULL) +{} + + +DInput::~DInput() +{ + Free(); +} + +void DInput::DIKToString(unsigned int keycode, char *keyStr) +{ + switch(keycode) { + case DIK_RETURN: + sprintf(keyStr, "Enter"); + break; + case DIK_UP: + sprintf(keyStr, "Up"); + break; + case DIK_DOWN: + sprintf(keyStr, "Down"); + break; + case DIK_LEFT: + sprintf(keyStr, "Left"); + break; + case DIK_RIGHT: + sprintf(keyStr, "Right"); + break; + case DIK_HOME: + strcpy(keyStr, "Home"); + break; + case DIK_END: + strcpy(keyStr, "End"); + break; + case DIK_INSERT: + strcpy(keyStr, "Ins"); + break; + case DIK_DELETE: + strcpy(keyStr, "Del"); + break; + case DIK_PGUP: + strcpy(keyStr, "PgUp"); + break; + case DIK_PGDN: + strcpy(keyStr, "PgDn"); + break; + case DIK_NUMPAD0: + strcpy(keyStr, "Num 0"); + break; + case DIK_NUMPAD1: + strcpy(keyStr, "Num 1"); + break; + case DIK_NUMPAD2: + strcpy(keyStr, "Num 2"); + break; + case DIK_NUMPAD3: + strcpy(keyStr, "Num 3"); + break; + case DIK_NUMPAD4: + strcpy(keyStr, "Num 4"); + break; + case DIK_NUMPAD5: + strcpy(keyStr, "Num 5"); + break; + case DIK_NUMPAD6: + strcpy(keyStr, "Num 6"); + break; + case DIK_NUMPAD7: + strcpy(keyStr, "Num 7"); + break; + case DIK_NUMPAD8: + strcpy(keyStr, "Num 8"); + break; + case DIK_NUMPAD9: + strcpy(keyStr, "Num 9"); + break; + case DIK_NUMPADSLASH: + strcpy(keyStr, "Num /"); + break; + default: + GetKeyNameText(keycode << 16, keyStr, 64); + break; } -} - -HRESULT DInput::Init(HWND hWnd) -{ - HRESULT hr; - DWORD dwCoopFlags; - dwCoopFlags = DISCL_FOREGROUND | DISCL_NOWINKEY; - - // Create a DInput object - if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, - IID_IDirectInput8, (VOID* *)&g_pDI, NULL))) - { - MessageBox(0, "Direct Input Create Failed", 0, MB_ICONERROR); - return(hr); - } - - if (FAILED(hr = g_pDI->CreateDevice(GUID_SysKeyboard, &g_pKeyboard, NULL))) - { - MessageBox(0, "Couldn't access keyboard", 0, MB_ICONERROR); - Free(); - return(hr); - } - - g_pKeyboard->SetDataFormat(&c_dfDIKeyboard); - g_pKeyboard->SetCooperativeLevel(hWnd, dwCoopFlags); - g_pKeyboard->Acquire(); - - return(S_OK); -} - -void DInput::Free() -{ - if (g_pKeyboard) - { - g_pKeyboard->Unacquire(); - g_pKeyboard->Release(); - g_pKeyboard = 0; - } - - if (g_pDI) - { - g_pDI->Release(); - g_pDI = 0; - } -} - -// Desc: Read the input device's state when in immediate mode and display it. -HRESULT DInput::Read() -{ - HRESULT hr; - - if (NULL == g_pKeyboard) - { - return(S_OK); - } - - // Get the input's device state, and put the state in dims - ZeroMemory(diks, sizeof(diks)); - hr = g_pKeyboard->GetDeviceState(sizeof(diks), diks); - - //for (int i=0; i<256; i++) - // if (diks[i])MessageBox(0,"DSFJDKSF|",0,0); - if (FAILED(hr)) - { - // DirectInput may be telling us that the input stream has been - // interrupted. We aren't tracking any state between polls, so - // we don't have any special reset that needs to be done. - // We just re-acquire and try again. - - // If input is lost then acquire and keep trying - hr = g_pKeyboard->Acquire(); - - while (hr == DIERR_INPUTLOST) - { - hr = g_pKeyboard->Acquire(); - } - - // hr may be DIERR_OTHERAPPHASPRIO or other errors. This - // may occur when the app is minimized or in the process of - // switching, so just try again later - return(S_OK); - } - - return(S_OK); -} +} + +HRESULT DInput::Init(HWND hWnd) +{ + HRESULT hr; + DWORD dwCoopFlags; + dwCoopFlags = DISCL_FOREGROUND | DISCL_NOWINKEY; + + // Create a DInput object + if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, + IID_IDirectInput8, (VOID* *)&g_pDI, NULL))) + { + MessageBox(0, "Direct Input Create Failed", 0, MB_ICONERROR); + return(hr); + } + + if (FAILED(hr = g_pDI->CreateDevice(GUID_SysKeyboard, &g_pKeyboard, NULL))) + { + MessageBox(0, "Couldn't access keyboard", 0, MB_ICONERROR); + Free(); + return(hr); + } + + g_pKeyboard->SetDataFormat(&c_dfDIKeyboard); + g_pKeyboard->SetCooperativeLevel(hWnd, dwCoopFlags); + g_pKeyboard->Acquire(); + + return(S_OK); +} + +void DInput::Free() +{ + if (g_pKeyboard) + { + g_pKeyboard->Unacquire(); + g_pKeyboard->Release(); + g_pKeyboard = 0; + } + + if (g_pDI) + { + g_pDI->Release(); + g_pDI = 0; + } +} + +// Desc: Read the input device's state when in immediate mode and display it. +HRESULT DInput::Read() +{ + HRESULT hr; + + if (NULL == g_pKeyboard) + { + return(S_OK); + } + + // Get the input's device state, and put the state in dims + ZeroMemory(diks, sizeof(diks)); + hr = g_pKeyboard->GetDeviceState(sizeof(diks), diks); + + //for (int i=0; i<256; i++) + // if (diks[i])MessageBox(0,"DSFJDKSF|",0,0); + if (FAILED(hr)) + { + // DirectInput may be telling us that the input stream has been + // interrupted. We aren't tracking any state between polls, so + // we don't have any special reset that needs to be done. + // We just re-acquire and try again. + + // If input is lost then acquire and keep trying + hr = g_pKeyboard->Acquire(); + + while (hr == DIERR_INPUTLOST) + { + hr = g_pKeyboard->Acquire(); + } + + // hr may be DIERR_OTHERAPPHASPRIO or other errors. This + // may occur when the app is minimized or in the process of + // switching, so just try again later + return(S_OK); + } + + return(S_OK); +} diff --git a/Source/Plugins/Plugin_PadSimple/Src/GUI/ConfigDlg.cpp b/Source/Plugins/Plugin_PadSimple/Src/GUI/ConfigDlg.cpp index 28901395f5..95882a560f 100644 --- a/Source/Plugins/Plugin_PadSimple/Src/GUI/ConfigDlg.cpp +++ b/Source/Plugins/Plugin_PadSimple/Src/GUI/ConfigDlg.cpp @@ -1,339 +1,339 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -#include "ConfigDlg.h" -#include "../PadSimple.h" - -#ifdef _WIN32 -#include "XInput.h" -#include "../DirectInputBase.h" - -DInput m_dinput; -#endif - -BEGIN_EVENT_TABLE(ConfigDialog,wxDialog) - EVT_CLOSE(ConfigDialog::OnClose) - EVT_BUTTON(ID_CLOSE,ConfigDialog::OnCloseClick) - EVT_BUTTON(ID_PAD_ABOUT,ConfigDialog::DllAbout) - EVT_CHECKBOX(ID_ATTACHED,ConfigDialog::ControllerSettingsChanged) - EVT_CHECKBOX(ID_X360PAD,ConfigDialog::ControllerSettingsChanged) - EVT_CHOICE(ID_X360PAD_CHOICE,ConfigDialog::ControllerSettingsChanged) - EVT_CHECKBOX(ID_RUMBLE,ConfigDialog::ControllerSettingsChanged) - EVT_CHECKBOX(ID_DISABLE,ConfigDialog::ControllerSettingsChanged) - EVT_BUTTON(CTL_A,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_B,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_X,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_Y,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_Z,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_START,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_L,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_R,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_MAINUP,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_MAINDOWN,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_MAINLEFT,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_MAINRIGHT,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_SUBUP,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_SUBDOWN,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_SUBLEFT,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_SUBRIGHT,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_DPADUP,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_DPADDOWN,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_DPADLEFT,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_DPADRIGHT,ConfigDialog::OnButtonClick) - EVT_BUTTON(CTL_HALFPRESS,ConfigDialog::OnButtonClick) -END_EVENT_TABLE() - -ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) -: wxDialog(parent, id, title, position, size, style) -{ -#ifdef _WIN32 - m_dinput.Init((HWND)parent); -#endif - clickedButton = NULL; - CreateGUIControls(); - Fit(); -} - -ConfigDialog::~ConfigDialog() -{ -} - -inline void AddControl(wxPanel *pan, wxButton **button, wxStaticBoxSizer *sizer, - const char *name, int ctl, int controller) -{ - wxBoxSizer *hButton = new wxBoxSizer(wxHORIZONTAL); - char keyStr[10] = {0}; - - hButton->Add(new wxStaticText(pan, 0, wxString::FromAscii(name), - wxDefaultPosition, wxDefaultSize), 0, - wxALIGN_CENTER_VERTICAL|wxALL); -#ifdef _WIN32 - DInput::DIKToString(pad[controller].keyForControl[ctl], keyStr); -#else - XKeyToString(pad[controller].keyForControl[ctl], keyStr); -#endif - - *button = new wxButton(pan, ctl, wxString::FromAscii(keyStr), - wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS); - - hButton->Add(*button, 0, wxALIGN_RIGHT|wxALL); - - sizer->Add(hButton, 0, wxALIGN_RIGHT|wxALL); -} - -void ConfigDialog::CreateGUIControls() -{ - // Notebook - m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize); - - // Controller pages - m_Controller[0] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE1, wxDefaultPosition, wxDefaultSize); - m_Notebook->AddPage(m_Controller[0], wxT("Controller 1")); - m_Controller[1] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE2, wxDefaultPosition, wxDefaultSize); - m_Notebook->AddPage(m_Controller[1], wxT("Controller 2")); - m_Controller[2] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE3, wxDefaultPosition, wxDefaultSize); - m_Notebook->AddPage(m_Controller[2], wxT("Controller 3")); - m_Controller[3] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE4, wxDefaultPosition, wxDefaultSize); - m_Notebook->AddPage(m_Controller[3], wxT("Controller 4")); - - // Standard buttons - m_Close = new wxButton(this, ID_CLOSE, wxT("Close"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_About = new wxButton(this, ID_PAD_ABOUT, wxT("About"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - - // Put notebook and standard buttons in sizers - wxBoxSizer* sSButtons; - sSButtons = new wxBoxSizer(wxHORIZONTAL); - sSButtons->Add(m_About,0,wxALL, 5); - sSButtons->Add(0, 0, 1, wxEXPAND, 5); - sSButtons->Add(m_Close, 0, wxALL, 5); - - wxBoxSizer* sMain; - sMain = new wxBoxSizer(wxVERTICAL); - sMain->Add(m_Notebook, 1, wxEXPAND|wxALL, 5); - sMain->Add(sSButtons, 0, wxEXPAND, 5); - - this->SetSizer(sMain); - this->Layout(); - -#ifdef _WIN32 - // Add connected XPads - for (int x = 0; x < 4; x++) - { - XINPUT_STATE xstate; - DWORD xresult = XInputGetState(x, &xstate); - - if (xresult == ERROR_SUCCESS) - { - arrayStringFor_X360Pad.Add(wxString::Format("%i", x+1)); - } - } -#endif - - for(int i = 0; i < 4; i++) - { - sbDevice[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Controller Settings")); - sDevice[i] = new wxBoxSizer(wxHORIZONTAL); - m_Attached[i] = new wxCheckBox(m_Controller[i], ID_ATTACHED, wxT("Controller attached"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); -#ifdef _WIN32 - m_X360Pad[i] = new wxCheckBox(m_Controller[i], ID_X360PAD, wxT("Enable X360Pad"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_X360PadC[i] = new wxChoice(m_Controller[i], ID_X360PAD_CHOICE, wxDefaultPosition, wxDefaultSize, arrayStringFor_X360Pad, 0, wxDefaultValidator); - m_Rumble[i] = new wxCheckBox(m_Controller[i], ID_RUMBLE, wxT("Enable rumble"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); -#endif - m_Disable[i] = new wxCheckBox(m_Controller[i], ID_DISABLE, wxT("Disable when Dolphin is not in focus"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_Attached[i]->SetValue(pad[i].bAttached); -#ifdef _WIN32 - if (arrayStringFor_X360Pad.IsEmpty()) - { - m_X360Pad[i]->SetLabel(wxT("Enable X360Pad - No pad connected")); - m_X360Pad[i]->SetValue(false); - m_X360Pad[i]->Enable(false); - pad[i].bEnableXPad = false; - m_X360PadC[i]->Hide(); - m_Rumble[i]->Hide(); - } - else - { - m_X360Pad[i]->SetValue(pad[i].bEnableXPad); - m_X360PadC[i]->SetSelection(pad[i].XPadPlayer); - m_X360PadC[i]->Enable(m_X360Pad[i]->IsChecked()); - m_Rumble[i]->SetValue(pad[i].bRumble); - m_Rumble[i]->Enable(m_X360Pad[i]->IsChecked()); - } -#endif - m_Disable[i]->SetValue(pad[i].bDisable); - - sDevice[i]->Add(m_Attached[i], 0, wxEXPAND|wxALL, 1); - sDevice[i]->AddStretchSpacer(); -#ifdef _WIN32 - sDevice[i]->Add(m_X360Pad[i], 0, wxEXPAND|wxALL, 1); - sDevice[i]->Add(m_X360PadC[i], 0, wxEXPAND|wxALL, 1); - sDevice[i]->Add(m_Rumble[i], 0, wxEXPAND|wxALL, 1); - sDevice[i]->AddStretchSpacer(); -#endif - sDevice[i]->Add(m_Disable[i], 0, wxEXPAND|wxALL, 1); - sbDevice[i]->Add(sDevice[i], 0, wxEXPAND|wxALL, 1); - - sButtons[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Buttons")); - - AddControl(m_Controller[i], &(m_ButtonA[i]), sButtons[i], "A: ", CTL_A, i); - AddControl(m_Controller[i], &(m_ButtonB[i]), sButtons[i], "B: ", CTL_B, i); - AddControl(m_Controller[i], &(m_ButtonX[i]), sButtons[i], "X: ", CTL_X, i); - AddControl(m_Controller[i], &(m_ButtonY[i]), sButtons[i], "Y: ", CTL_Y, i); - AddControl(m_Controller[i], &(m_ButtonZ[i]), sButtons[i], "Z: ", CTL_Z, i); - AddControl(m_Controller[i], &(m_ButtonStart[i]), sButtons[i], "Start: ", CTL_START, i); - - sTriggers[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Triggers")); - - AddControl(m_Controller[i], &(m_ButtonL[i]), sTriggers[i], " L: ", CTL_L, i); - AddControl(m_Controller[i], &(m_ButtonR[i]), sTriggers[i], " R: ", CTL_R, i); - - sModifiers[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Modifiers")); - - AddControl(m_Controller[i], &(m_HalfPress[i]), sModifiers[i], "1/2 Press: ", CTL_HALFPRESS, i); - - sStick[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Main Stick")); - - AddControl(m_Controller[i], &(m_StickUp[i]), sStick[i], "Up: ", CTL_MAINUP, i); - AddControl(m_Controller[i], &(m_StickDown[i]), sStick[i], "Down: ", CTL_MAINDOWN, i); - AddControl(m_Controller[i], &(m_StickLeft[i]), sStick[i], "Left: ", CTL_MAINLEFT, i); - AddControl(m_Controller[i], &(m_StickRight[i]), sStick[i], "Right: ", CTL_MAINRIGHT, i); - - sDPad[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("D-Pad")); - - AddControl(m_Controller[i], &(m_DPadUp[i]), sDPad[i], "Up: ", CTL_DPADUP, i); - AddControl(m_Controller[i], &(m_DPadDown[i]), sDPad[i], "Down: ", CTL_DPADDOWN, i); - AddControl(m_Controller[i], &(m_DPadLeft[i]), sDPad[i], "Left: ", CTL_DPADLEFT, i); - AddControl(m_Controller[i], &(m_DPadRight[i]), sDPad[i], "Right: ", CTL_DPADRIGHT, i); - - sCStick[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("C-Stick")); - - AddControl(m_Controller[i], &(m_CStickUp[i]), sCStick[i], "Up: ", CTL_SUBUP, i); - AddControl(m_Controller[i], &(m_CStickDown[i]), sCStick[i], "Down: ", CTL_SUBDOWN, i); - AddControl(m_Controller[i], &(m_CStickLeft[i]), sCStick[i], "Left: ", CTL_SUBLEFT, i); - AddControl(m_Controller[i], &(m_CStickRight[i]), sCStick[i], "Right: ", CTL_SUBRIGHT, i); - - sPage[i] = new wxGridBagSizer(0, 0); - sPage[i]->SetFlexibleDirection(wxBOTH); - sPage[i]->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED); - sPage[i]->Add(sbDevice[i], wxGBPosition(0, 0), wxGBSpan(1, 5), wxEXPAND|wxALL, 1); - sPage[i]->Add(sButtons[i], wxGBPosition(1, 0), wxGBSpan(2, 1), wxALL, 1); - sPage[i]->Add(sTriggers[i], wxGBPosition(1, 1), wxGBSpan(1, 1), wxEXPAND|wxALL, 1); - sPage[i]->Add(sModifiers[i], wxGBPosition(2, 1), wxGBSpan(1, 1), wxALL, 1); - sPage[i]->Add(sStick[i], wxGBPosition(1, 2), wxGBSpan(2, 1), wxALL, 1); - sPage[i]->Add(sDPad[i], wxGBPosition(1, 3), wxGBSpan(2, 1), wxALL, 1); - sPage[i]->Add(sCStick[i], wxGBPosition(1, 4), wxGBSpan(2, 1), wxALL, 1); - m_Controller[i]->SetSizer(sPage[i]); - sPage[i]->Layout(); - } -} - -void ConfigDialog::OnClose(wxCloseEvent& event) -{ -#ifdef _WIN32 - m_dinput.Free(); -#endif - EndModal(0); -} - -void ConfigDialog::OnKeyDown(wxKeyEvent& event) -{ - if(clickedButton != NULL) - { - int page = m_Notebook->GetSelection(); - -#ifdef _WIN32 - m_dinput.Read(); - for(int i = 0; i < 255; i++) - { - if(m_dinput.diks[i]) - { - char keyStr[10] = {0}; - pad[page].keyForControl[clickedButton->GetId()] = i; - DInput::DIKToString(i, keyStr); - clickedButton->SetLabel(wxString::FromAscii(keyStr)); - break; - } - } -#else - pad[page].keyForControl[clickedButton->GetId()] = wxCharCodeWXToX(event.GetKeyCode()); - clickedButton->SetLabel(wxString::Format(_T("%c"), event.GetKeyCode())); -#endif - clickedButton->Disconnect(); - } - - clickedButton = NULL; - event.Skip(); -} - -void ConfigDialog::OnCloseClick(wxCommandEvent& event) -{ - Close(); -} - -void ConfigDialog::ControllerSettingsChanged(wxCommandEvent& event) -{ - int page = m_Notebook->GetSelection(); - - switch (event.GetId()) - { - case ID_ATTACHED: - pad[page].bAttached = m_Attached[page]->GetValue(); - break; - case ID_X360PAD: - pad[page].bEnableXPad = event.IsChecked(); - m_Rumble[page]->Enable(event.IsChecked()); - m_X360PadC[page]->Enable(event.IsChecked()); - break; - case ID_X360PAD_CHOICE: - pad[page].XPadPlayer = event.GetSelection(); - break; - case ID_RUMBLE: - pad[page].bRumble = m_Rumble[page]->GetValue(); - break; - case ID_DISABLE: - pad[page].bDisable = m_Disable[page]->GetValue(); - break; - } -} - -void ConfigDialog::OnButtonClick(wxCommandEvent& event) -{ - if(clickedButton) - { - clickedButton->SetLabel(oldLabel); - } - clickedButton = (wxButton *)event.GetEventObject(); - oldLabel = clickedButton->GetLabel(); - clickedButton->SetLabel(_("Press Key")); - - clickedButton->Connect(wxID_ANY, wxEVT_KEY_DOWN, - wxKeyEventHandler(ConfigDialog::OnKeyDown), - (wxObject*)NULL, this); -} -void ConfigDialog::DllAbout(wxCommandEvent& event) -{ - wxString message; -#ifdef _WIN32 - message = _("A simple keyboard and XInput plugin for dolphin."); -#else - message = _("A simple keyboard plugin for dolphin."); -#endif - - wxMessageBox(_T("Dolphin PadSimple Plugin\nBy ector and F|RES\n\n" + message), - _T("Dolphin PadSimple"), wxOK, this); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#include "ConfigDlg.h" +#include "../PadSimple.h" + +#ifdef _WIN32 +#include "XInput.h" +#include "../DirectInputBase.h" + +DInput m_dinput; +#endif + +BEGIN_EVENT_TABLE(ConfigDialog,wxDialog) + EVT_CLOSE(ConfigDialog::OnClose) + EVT_BUTTON(ID_CLOSE,ConfigDialog::OnCloseClick) + EVT_BUTTON(ID_PAD_ABOUT,ConfigDialog::DllAbout) + EVT_CHECKBOX(ID_ATTACHED,ConfigDialog::ControllerSettingsChanged) + EVT_CHECKBOX(ID_X360PAD,ConfigDialog::ControllerSettingsChanged) + EVT_CHOICE(ID_X360PAD_CHOICE,ConfigDialog::ControllerSettingsChanged) + EVT_CHECKBOX(ID_RUMBLE,ConfigDialog::ControllerSettingsChanged) + EVT_CHECKBOX(ID_DISABLE,ConfigDialog::ControllerSettingsChanged) + EVT_BUTTON(CTL_A,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_B,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_X,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_Y,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_Z,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_START,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_L,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_R,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_MAINUP,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_MAINDOWN,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_MAINLEFT,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_MAINRIGHT,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_SUBUP,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_SUBDOWN,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_SUBLEFT,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_SUBRIGHT,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_DPADUP,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_DPADDOWN,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_DPADLEFT,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_DPADRIGHT,ConfigDialog::OnButtonClick) + EVT_BUTTON(CTL_HALFPRESS,ConfigDialog::OnButtonClick) +END_EVENT_TABLE() + +ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) +: wxDialog(parent, id, title, position, size, style) +{ +#ifdef _WIN32 + m_dinput.Init((HWND)parent); +#endif + clickedButton = NULL; + CreateGUIControls(); + Fit(); +} + +ConfigDialog::~ConfigDialog() +{ +} + +inline void AddControl(wxPanel *pan, wxButton **button, wxStaticBoxSizer *sizer, + const char *name, int ctl, int controller) +{ + wxBoxSizer *hButton = new wxBoxSizer(wxHORIZONTAL); + char keyStr[10] = {0}; + + hButton->Add(new wxStaticText(pan, 0, wxString::FromAscii(name), + wxDefaultPosition, wxDefaultSize), 0, + wxALIGN_CENTER_VERTICAL|wxALL); +#ifdef _WIN32 + DInput::DIKToString(pad[controller].keyForControl[ctl], keyStr); +#else + XKeyToString(pad[controller].keyForControl[ctl], keyStr); +#endif + + *button = new wxButton(pan, ctl, wxString::FromAscii(keyStr), + wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS); + + hButton->Add(*button, 0, wxALIGN_RIGHT|wxALL); + + sizer->Add(hButton, 0, wxALIGN_RIGHT|wxALL); +} + +void ConfigDialog::CreateGUIControls() +{ + // Notebook + m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize); + + // Controller pages + m_Controller[0] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE1, wxDefaultPosition, wxDefaultSize); + m_Notebook->AddPage(m_Controller[0], wxT("Controller 1")); + m_Controller[1] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE2, wxDefaultPosition, wxDefaultSize); + m_Notebook->AddPage(m_Controller[1], wxT("Controller 2")); + m_Controller[2] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE3, wxDefaultPosition, wxDefaultSize); + m_Notebook->AddPage(m_Controller[2], wxT("Controller 3")); + m_Controller[3] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE4, wxDefaultPosition, wxDefaultSize); + m_Notebook->AddPage(m_Controller[3], wxT("Controller 4")); + + // Standard buttons + m_Close = new wxButton(this, ID_CLOSE, wxT("Close"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_About = new wxButton(this, ID_PAD_ABOUT, wxT("About"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + + // Put notebook and standard buttons in sizers + wxBoxSizer* sSButtons; + sSButtons = new wxBoxSizer(wxHORIZONTAL); + sSButtons->Add(m_About,0,wxALL, 5); + sSButtons->Add(0, 0, 1, wxEXPAND, 5); + sSButtons->Add(m_Close, 0, wxALL, 5); + + wxBoxSizer* sMain; + sMain = new wxBoxSizer(wxVERTICAL); + sMain->Add(m_Notebook, 1, wxEXPAND|wxALL, 5); + sMain->Add(sSButtons, 0, wxEXPAND, 5); + + this->SetSizer(sMain); + this->Layout(); + +#ifdef _WIN32 + // Add connected XPads + for (int x = 0; x < 4; x++) + { + XINPUT_STATE xstate; + DWORD xresult = XInputGetState(x, &xstate); + + if (xresult == ERROR_SUCCESS) + { + arrayStringFor_X360Pad.Add(wxString::Format("%i", x+1)); + } + } +#endif + + for(int i = 0; i < 4; i++) + { + sbDevice[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Controller Settings")); + sDevice[i] = new wxBoxSizer(wxHORIZONTAL); + m_Attached[i] = new wxCheckBox(m_Controller[i], ID_ATTACHED, wxT("Controller attached"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); +#ifdef _WIN32 + m_X360Pad[i] = new wxCheckBox(m_Controller[i], ID_X360PAD, wxT("Enable X360Pad"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_X360PadC[i] = new wxChoice(m_Controller[i], ID_X360PAD_CHOICE, wxDefaultPosition, wxDefaultSize, arrayStringFor_X360Pad, 0, wxDefaultValidator); + m_Rumble[i] = new wxCheckBox(m_Controller[i], ID_RUMBLE, wxT("Enable rumble"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); +#endif + m_Disable[i] = new wxCheckBox(m_Controller[i], ID_DISABLE, wxT("Disable when Dolphin is not in focus"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_Attached[i]->SetValue(pad[i].bAttached); +#ifdef _WIN32 + if (arrayStringFor_X360Pad.IsEmpty()) + { + m_X360Pad[i]->SetLabel(wxT("Enable X360Pad - No pad connected")); + m_X360Pad[i]->SetValue(false); + m_X360Pad[i]->Enable(false); + pad[i].bEnableXPad = false; + m_X360PadC[i]->Hide(); + m_Rumble[i]->Hide(); + } + else + { + m_X360Pad[i]->SetValue(pad[i].bEnableXPad); + m_X360PadC[i]->SetSelection(pad[i].XPadPlayer); + m_X360PadC[i]->Enable(m_X360Pad[i]->IsChecked()); + m_Rumble[i]->SetValue(pad[i].bRumble); + m_Rumble[i]->Enable(m_X360Pad[i]->IsChecked()); + } +#endif + m_Disable[i]->SetValue(pad[i].bDisable); + + sDevice[i]->Add(m_Attached[i], 0, wxEXPAND|wxALL, 1); + sDevice[i]->AddStretchSpacer(); +#ifdef _WIN32 + sDevice[i]->Add(m_X360Pad[i], 0, wxEXPAND|wxALL, 1); + sDevice[i]->Add(m_X360PadC[i], 0, wxEXPAND|wxALL, 1); + sDevice[i]->Add(m_Rumble[i], 0, wxEXPAND|wxALL, 1); + sDevice[i]->AddStretchSpacer(); +#endif + sDevice[i]->Add(m_Disable[i], 0, wxEXPAND|wxALL, 1); + sbDevice[i]->Add(sDevice[i], 0, wxEXPAND|wxALL, 1); + + sButtons[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Buttons")); + + AddControl(m_Controller[i], &(m_ButtonA[i]), sButtons[i], "A: ", CTL_A, i); + AddControl(m_Controller[i], &(m_ButtonB[i]), sButtons[i], "B: ", CTL_B, i); + AddControl(m_Controller[i], &(m_ButtonX[i]), sButtons[i], "X: ", CTL_X, i); + AddControl(m_Controller[i], &(m_ButtonY[i]), sButtons[i], "Y: ", CTL_Y, i); + AddControl(m_Controller[i], &(m_ButtonZ[i]), sButtons[i], "Z: ", CTL_Z, i); + AddControl(m_Controller[i], &(m_ButtonStart[i]), sButtons[i], "Start: ", CTL_START, i); + + sTriggers[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Triggers")); + + AddControl(m_Controller[i], &(m_ButtonL[i]), sTriggers[i], " L: ", CTL_L, i); + AddControl(m_Controller[i], &(m_ButtonR[i]), sTriggers[i], " R: ", CTL_R, i); + + sModifiers[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Modifiers")); + + AddControl(m_Controller[i], &(m_HalfPress[i]), sModifiers[i], "1/2 Press: ", CTL_HALFPRESS, i); + + sStick[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Main Stick")); + + AddControl(m_Controller[i], &(m_StickUp[i]), sStick[i], "Up: ", CTL_MAINUP, i); + AddControl(m_Controller[i], &(m_StickDown[i]), sStick[i], "Down: ", CTL_MAINDOWN, i); + AddControl(m_Controller[i], &(m_StickLeft[i]), sStick[i], "Left: ", CTL_MAINLEFT, i); + AddControl(m_Controller[i], &(m_StickRight[i]), sStick[i], "Right: ", CTL_MAINRIGHT, i); + + sDPad[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("D-Pad")); + + AddControl(m_Controller[i], &(m_DPadUp[i]), sDPad[i], "Up: ", CTL_DPADUP, i); + AddControl(m_Controller[i], &(m_DPadDown[i]), sDPad[i], "Down: ", CTL_DPADDOWN, i); + AddControl(m_Controller[i], &(m_DPadLeft[i]), sDPad[i], "Left: ", CTL_DPADLEFT, i); + AddControl(m_Controller[i], &(m_DPadRight[i]), sDPad[i], "Right: ", CTL_DPADRIGHT, i); + + sCStick[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("C-Stick")); + + AddControl(m_Controller[i], &(m_CStickUp[i]), sCStick[i], "Up: ", CTL_SUBUP, i); + AddControl(m_Controller[i], &(m_CStickDown[i]), sCStick[i], "Down: ", CTL_SUBDOWN, i); + AddControl(m_Controller[i], &(m_CStickLeft[i]), sCStick[i], "Left: ", CTL_SUBLEFT, i); + AddControl(m_Controller[i], &(m_CStickRight[i]), sCStick[i], "Right: ", CTL_SUBRIGHT, i); + + sPage[i] = new wxGridBagSizer(0, 0); + sPage[i]->SetFlexibleDirection(wxBOTH); + sPage[i]->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED); + sPage[i]->Add(sbDevice[i], wxGBPosition(0, 0), wxGBSpan(1, 5), wxEXPAND|wxALL, 1); + sPage[i]->Add(sButtons[i], wxGBPosition(1, 0), wxGBSpan(2, 1), wxALL, 1); + sPage[i]->Add(sTriggers[i], wxGBPosition(1, 1), wxGBSpan(1, 1), wxEXPAND|wxALL, 1); + sPage[i]->Add(sModifiers[i], wxGBPosition(2, 1), wxGBSpan(1, 1), wxALL, 1); + sPage[i]->Add(sStick[i], wxGBPosition(1, 2), wxGBSpan(2, 1), wxALL, 1); + sPage[i]->Add(sDPad[i], wxGBPosition(1, 3), wxGBSpan(2, 1), wxALL, 1); + sPage[i]->Add(sCStick[i], wxGBPosition(1, 4), wxGBSpan(2, 1), wxALL, 1); + m_Controller[i]->SetSizer(sPage[i]); + sPage[i]->Layout(); + } +} + +void ConfigDialog::OnClose(wxCloseEvent& event) +{ +#ifdef _WIN32 + m_dinput.Free(); +#endif + EndModal(0); +} + +void ConfigDialog::OnKeyDown(wxKeyEvent& event) +{ + if(clickedButton != NULL) + { + int page = m_Notebook->GetSelection(); + +#ifdef _WIN32 + m_dinput.Read(); + for(int i = 0; i < 255; i++) + { + if(m_dinput.diks[i]) + { + char keyStr[10] = {0}; + pad[page].keyForControl[clickedButton->GetId()] = i; + DInput::DIKToString(i, keyStr); + clickedButton->SetLabel(wxString::FromAscii(keyStr)); + break; + } + } +#else + pad[page].keyForControl[clickedButton->GetId()] = wxCharCodeWXToX(event.GetKeyCode()); + clickedButton->SetLabel(wxString::Format(_T("%c"), event.GetKeyCode())); +#endif + clickedButton->Disconnect(); + } + + clickedButton = NULL; + event.Skip(); +} + +void ConfigDialog::OnCloseClick(wxCommandEvent& event) +{ + Close(); +} + +void ConfigDialog::ControllerSettingsChanged(wxCommandEvent& event) +{ + int page = m_Notebook->GetSelection(); + + switch (event.GetId()) + { + case ID_ATTACHED: + pad[page].bAttached = m_Attached[page]->GetValue(); + break; + case ID_X360PAD: + pad[page].bEnableXPad = event.IsChecked(); + m_Rumble[page]->Enable(event.IsChecked()); + m_X360PadC[page]->Enable(event.IsChecked()); + break; + case ID_X360PAD_CHOICE: + pad[page].XPadPlayer = event.GetSelection(); + break; + case ID_RUMBLE: + pad[page].bRumble = m_Rumble[page]->GetValue(); + break; + case ID_DISABLE: + pad[page].bDisable = m_Disable[page]->GetValue(); + break; + } +} + +void ConfigDialog::OnButtonClick(wxCommandEvent& event) +{ + if(clickedButton) + { + clickedButton->SetLabel(oldLabel); + } + clickedButton = (wxButton *)event.GetEventObject(); + oldLabel = clickedButton->GetLabel(); + clickedButton->SetLabel(_("Press Key")); + + clickedButton->Connect(wxID_ANY, wxEVT_KEY_DOWN, + wxKeyEventHandler(ConfigDialog::OnKeyDown), + (wxObject*)NULL, this); +} +void ConfigDialog::DllAbout(wxCommandEvent& event) +{ + wxString message; +#ifdef _WIN32 + message = _("A simple keyboard and XInput plugin for dolphin."); +#else + message = _("A simple keyboard plugin for dolphin."); +#endif + + wxMessageBox(_T("Dolphin PadSimple Plugin\nBy ector and F|RES\n\n" + message), + _T("Dolphin PadSimple"), wxOK, this); +} diff --git a/Source/Plugins/Plugin_PadSimple/Src/stdafx.cpp b/Source/Plugins/Plugin_PadSimple/Src/stdafx.cpp index 428bdfaf8b..1dc71df3a9 100644 --- a/Source/Plugins/Plugin_PadSimple/Src/stdafx.cpp +++ b/Source/Plugins/Plugin_PadSimple/Src/stdafx.cpp @@ -1,18 +1,18 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "stdafx.h" +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" diff --git a/Source/Plugins/Plugin_VideoDX9/Src/BPStructs.cpp b/Source/Plugins/Plugin_VideoDX9/Src/BPStructs.cpp index ddadbe50c5..07117fc44f 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/BPStructs.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/BPStructs.cpp @@ -1,825 +1,825 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "D3DBase.h" - -#include "Config.h" -#include "Common.h" -#include "Profiler.h" -#include "BPStructs.h" -#include "OpcodeDecoding.h" -#include "TextureCache.h" -#include "TextureDecoder.h" -#include "VertexManager.h" -#include "PixelShader.h" -#include "Utils.h" - -#include "main.h" //for the plugin interface - -bool textureChanged[8]; - -const bool renderFog = false; - -// State translation lookup tables -const D3DBLEND d3dSrcFactors[8] = -{ - D3DBLEND_ZERO, - D3DBLEND_ONE, - D3DBLEND_DESTCOLOR, - D3DBLEND_INVDESTCOLOR, - D3DBLEND_SRCALPHA, - D3DBLEND_INVSRCALPHA, - D3DBLEND_DESTALPHA, - D3DBLEND_INVDESTALPHA -}; - -const D3DBLEND d3dDestFactors[8] = -{ - D3DBLEND_ZERO, - D3DBLEND_ONE, - D3DBLEND_SRCCOLOR, - D3DBLEND_INVSRCCOLOR, - D3DBLEND_SRCALPHA, - D3DBLEND_INVSRCALPHA, - D3DBLEND_DESTALPHA, - D3DBLEND_INVDESTALPHA -}; - -const D3DCULL d3dCullModes[4] = -{ - D3DCULL_NONE, - D3DCULL_CCW, - D3DCULL_CW, - D3DCULL_CCW -}; - -const D3DCMPFUNC d3dCmpFuncs[8] = -{ - D3DCMP_NEVER, - D3DCMP_LESS, - D3DCMP_EQUAL, - D3DCMP_LESSEQUAL, - D3DCMP_GREATER, - D3DCMP_NOTEQUAL, - D3DCMP_GREATEREQUAL, - D3DCMP_ALWAYS -}; - -const D3DTEXTUREFILTERTYPE d3dMipFilters[4] = -{ - D3DTEXF_NONE, - D3DTEXF_POINT, - D3DTEXF_ANISOTROPIC, - D3DTEXF_LINEAR, //reserved -}; - -const D3DTEXTUREADDRESS d3dClamps[4] = -{ - D3DTADDRESS_CLAMP, - D3DTADDRESS_WRAP, - D3DTADDRESS_MIRROR, - D3DTADDRESS_WRAP //reserved -}; - -void BPInit() -{ - memset(&bpmem, 0, sizeof(bpmem)); - bpmem.bpMask = 0xFFFFFF; -} - -using namespace D3D; -// __________________________________________________________________________________________________ -// BPWritten -// -void BPWritten(int addr, int changes, int newval) -{ - switch(addr) - { - case BPMEM_GENMODE: - if (changes) - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - - // dev->SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]); - Renderer::SetRenderState( D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode] ); - - if (bpmem.genMode.cullmode == 3) - { - // dev->SetRenderState(D3DRS_COLORWRITEENABLE, 0); - Renderer::SetRenderState( D3DRS_COLORWRITEENABLE, 0 ); - } - else - { - DWORD write = 0; - if (bpmem.blendmode.alphaupdate) - write = D3DCOLORWRITEENABLE_ALPHA; - if (bpmem.blendmode.colorupdate) - write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; - - // dev->SetRenderState(D3DRS_COLORWRITEENABLE, write); - Renderer::SetRenderState( D3DRS_COLORWRITEENABLE, write ); - } - } - break; - case BPMEM_IND_MTX+0: - case BPMEM_IND_MTX+1: - case BPMEM_IND_MTX+2: - case BPMEM_IND_MTX+3: - case BPMEM_IND_MTX+4: - case BPMEM_IND_MTX+5: - case BPMEM_IND_MTX+6: - case BPMEM_IND_MTX+7: - case BPMEM_IND_MTX+8: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - // PixelShaderMngr::SetIndMatrixChanged((addr-BPMEM_IND_MTX)/3); - } - break; - case BPMEM_RAS1_SS0: - case BPMEM_RAS1_SS1: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - // PixelShaderMngr::SetIndTexScaleChanged(); - } - break; - - case BPMEM_ZMODE: - if (changes) - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - if (bpmem.zmode.testenable) - { - // dev->SetRenderState(D3DRS_ZENABLE, TRUE); - // dev->SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable); - // dev->SetRenderState(D3DRS_ZFUNC,d3dCmpFuncs[bpmem.zmode.func]); - - Renderer::SetRenderState( D3DRS_ZENABLE, TRUE ); - Renderer::SetRenderState( D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable ); - Renderer::SetRenderState( D3DRS_ZFUNC, d3dCmpFuncs[bpmem.zmode.func] ); - } - else - { - // if the test is disabled write is disabled too - // dev->SetRenderState(D3DRS_ZENABLE, FALSE); - // dev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - - Renderer::SetRenderState( D3DRS_ZENABLE, FALSE ); - Renderer::SetRenderState( D3DRS_ZWRITEENABLE, FALSE ); - } - } - break; - - case BPMEM_ALPHACOMPARE: - if (changes) - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - float f[4] = - { - bpmem.alphaFunc.ref0/255.0f, - bpmem.alphaFunc.ref1/255.0f, - 0,0 - }; - dev->SetPixelShaderConstantF(PS_CONST_ALPHAREF,f,1); - - if (D3D::GetShaderVersion() == PSNONE) - { - // dev->SetRenderState(D3DRS_ALPHATESTENABLE, (Compare)bpmem.alphaFunc.comp0 != COMPARE_ALWAYS); - // dev->SetRenderState(D3DRS_ALPHAREF, bpmem.alphaFunc.ref0*4); - // dev->SetRenderState(D3DRS_ALPHAFUNC, d3dCmpFuncs[bpmem.alphaFunc.comp0]); - - Renderer::SetRenderState( D3DRS_ALPHATESTENABLE, (Compare)bpmem.alphaFunc.comp0 != COMPARE_ALWAYS ); - Renderer::SetRenderState( D3DRS_ALPHAREF, bpmem.alphaFunc.ref0 * 4 ); - Renderer::SetRenderState( D3DRS_ALPHAFUNC, d3dCmpFuncs[bpmem.alphaFunc.comp0] ); - } - // Normally, use texkill in pixel shader to emulate alpha test - } - break; - - case BPMEM_CONSTANTALPHA: - if (changes) - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - float f[4] = { - bpmem.dstalpha.alpha/255.0f,0,0,0 - }; - dev->SetPixelShaderConstantF(PS_CONST_CONSTALPHA,f,1); - } - break; - - case BPMEM_LINEPTWIDTH: - { - // We can't change line width in D3D unless we use ID3DXLine - //bpmem.lineptwidth.linesize); - float psize = float(bpmem.lineptwidth.pointsize) * 6.0f; - - Renderer::SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&psize)); - } - break; - - case 0x43: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - } - break; - - case BPMEM_BLENDMODE: - if (changes & 0xFFFF) - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - if (changes & 1) - { - // dev->SetRenderState(D3DRS_ALPHABLENDENABLE,bpmem.blendmode.blendenable); - Renderer::SetRenderState( D3DRS_ALPHABLENDENABLE, bpmem.blendmode.blendenable ); - } - if (changes & 2) {} // Logic op blending. D3D can't do this but can fake some modes. - if (changes & 4) { - // Dithering is pointless. Will make things uglier and will be different from GC. - // dev->SetRenderState(D3DRS_DITHERENABLE,bpmem.blendmode.dither); - } - D3DBLEND src = d3dSrcFactors[bpmem.blendmode.srcfactor]; - D3DBLEND dst = d3dDestFactors[bpmem.blendmode.dstfactor]; - - if (changes & 0x700) - { - // dev->SetRenderState(D3DRS_SRCBLEND, src); - Renderer::SetRenderState( D3DRS_SRCBLEND, src ); - } - if (changes & 0xE0) { - if (!bpmem.blendmode.subtract) - { - // dev->SetRenderState(D3DRS_DESTBLEND, dst); - Renderer::SetRenderState( D3DRS_DESTBLEND, dst ); - } - else - { - // dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); - Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE ); - } - } - if (changes & 0x800) { - if (bpmem.blendmode.subtract) - { - // dev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); - // dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); - Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE ); - Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE ); - } - else - { - // dev->SetRenderState(D3DRS_SRCBLEND, src); - // dev->SetRenderState(D3DRS_DESTBLEND, dst); - - Renderer::SetRenderState( D3DRS_SRCBLEND, src ); - Renderer::SetRenderState( D3DRS_DESTBLEND, dst ); - } - - // dev->SetRenderState(D3DRS_BLENDOP,bpmem.blendmode.subtract?D3DBLENDOP_SUBTRACT:D3DBLENDOP_ADD); - Renderer::SetRenderState( D3DRS_BLENDOP, bpmem.blendmode.subtract ? D3DBLENDOP_SUBTRACT : D3DBLENDOP_ADD ); - } - //if (bpmem.blendmode.logicopenable) // && bpmem.blendmode.logicmode == 4) - // MessageBox(0,"LOGIC",0,0); - - if (changes & 0x18) - { - // Color Mask - DWORD write = 0; - if (bpmem.blendmode.alphaupdate) - write = D3DCOLORWRITEENABLE_ALPHA; - if (bpmem.blendmode.colorupdate) - write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; - - // dev->SetRenderState(D3DRS_COLORWRITEENABLE, write); - Renderer::SetRenderState( D3DRS_COLORWRITEENABLE, write ); - } - } - break; - - case BPMEM_FOGRANGE: - if(changes) { - // TODO(XK): Fog range format - //Renderer::SetRenderState(D3DRS_FOGSTART, ... - //Renderer::SetRenderState(D3DRS_FOGEND, ... - } - break; - - case BPMEM_FOGPARAM0: - { - // u32 fogATemp = bpmem.fog.a<<12; - // float fogA = *(float*)(&fogATemp); - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - } - break; - - case BPMEM_FOGBEXPONENT: - case BPMEM_FOGBMAGNITUDE: - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - } - break; - - case BPMEM_FOGPARAM3: - //fog settings - if(changes) { - static bool bFog = false; - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - - if(!renderFog) - break; - - /// u32 fogCTemp = bpmem.fog.c_proj_fsel.cShifted12 << 12; - // float fogC = *(float*)(&fogCTemp); - - - //printf("%f %f magnitude: %x\n", bpmem.fog.a.GetA(),bpmem.fog.c_proj_fsel.GetC(), bpmem.fog.b_magnitude); - switch(bpmem.fog.c_proj_fsel.fsel) - { - case 0: // Off - if(bFog) { - Renderer::SetRenderState(D3DRS_FOGENABLE, false); - bFog = false; - } - break; - case 2: // Linear - Renderer::SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR); - break; - case 4: // exp - Renderer::SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_EXP); - break; - case 5: // exp2 - Renderer::SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_EXP2); - break; - case 6: // Backward exp - case 7: // Backward exp2 - PanicAlert("Backward Exponential Fog Detected"); - // TODO: Figure out how to do these in any rendering API - //TEV_FSEL_BX, TEV_FSEL_BX2? - default: - PanicAlert("Non-Emulated Fog selection %d\n", bpmem.fog.c_proj_fsel.fsel); - break; - } - - if(bpmem.fog.c_proj_fsel.fsel > 0 && !bFog) { - Renderer::SetRenderState(D3DRS_FOGENABLE, true); - bFog = true; - } - - } - break; - - case BPMEM_FOGCOLOR: - if(changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - - if(!renderFog) - break; - - // dev->SetRenderState(D3DRS_FOGCOLOR,bpmem.fog.color); - int fogcolor[3] = { ((bpmem.fog.color>>16)&0xff), ((bpmem.fog.color>>8)&0xff), (bpmem.fog.color&0xff)}; - //D3DCOLOR_RGBA(fogcolor[0], fogcolor[1], fogcolor[2], 0) - Renderer::SetRenderState(D3DRS_FOGCOLOR, bpmem.fog.color); - } - break; - - case BPMEM_TEXINVALIDATE: - //TexCache_Invalidate(); - break; - - case BPMEM_SCISSOROFFSET: //TODO: investigate - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - } - break; - - case BPMEM_SCISSORTL: - case BPMEM_SCISSORBR: - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - int xoff = bpmem.scissorOffset.x*2-342; - int yoff = bpmem.scissorOffset.y*2-342; - RECT rc; - rc.left=bpmem.scissorTL.x + xoff - 342 -1; - if (rc.left<0) rc.left=0; - rc.top=bpmem.scissorTL.y + yoff - 342 -1; - if (rc.top<0) rc.top=0; - rc.right=bpmem.scissorBR.x + xoff - 342 +2; - if (rc.right>640) rc.right=640; - rc.bottom=bpmem.scissorBR.y + yoff - 342 +2; - if (rc.bottom>480) rc.bottom=480; - char temp[256]; - sprintf(temp,"ScissorRect: %i %i %i %i",rc.left,rc.top,rc.right,rc.bottom); - g_VideoInitialize.pLog(temp, FALSE); - - // dev->SetRenderState(D3DRS_SCISSORTESTENABLE,TRUE); - Renderer::SetRenderState( D3DRS_SCISSORTESTENABLE, TRUE ); - - Renderer::SetScissorBox(rc); - } - break; - case BPMEM_ZTEX1: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - //PRIM_LOG("ztex bias=0x%x\n", bpmem.ztex1.bias); - //PixelShaderMngr::SetZTextureBias(bpmem.ztex1.bias); - } - break; - case BPMEM_ZTEX2: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; -#ifdef _DEBUG - const char* pzop[] = {"DISABLE", "ADD", "REPLACE", "?"}; - const char* pztype[] = {"Z8", "Z16", "Z24", "?"}; - DebugLog("ztex op=%s, type=%s\n", pzop[bpmem.ztex2.op], pztype[bpmem.ztex2.type]); -#endif - } - break; - - case 0xf6: // ksel0 - case 0xf7: // ksel1 - case 0xf8: // ksel2 - case 0xf9: // ksel3 - case 0xfa: // ksel4 - case 0xfb: // ksel5 - case 0xfc: // ksel6 - case 0xfd: // ksel7 - if (changes) - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - // PixelShaderMngr::SetTevKSelChanged(addr-0xf6); - } - break; - - default: - switch(addr & 0xF8) //texture sampler filter - { - case 0x80: // TEX MODE 0 - case 0xA0: - if (changes) - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - FourTexUnits &tex = bpmem.tex[(addr&0xE0)==0xA0]; - int stage = (addr&3);//(addr>>4)&2; - TexMode0 &tm0 = tex.texMode0[stage]; - - D3DTEXTUREFILTERTYPE min, mag, mip; - if (g_Config.bForceFiltering) - { - min = mag = mip = D3DTEXF_LINEAR; - } - else - { - min = (tm0.min_filter&4) ? D3DTEXF_LINEAR : D3DTEXF_POINT; - mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT; - mip = d3dMipFilters[tm0.min_filter&3]; - } - if ((addr & 0xE0) == 0xA0) - stage += 4; - - if (g_Config.bForceMaxAniso) - { - mag = D3DTEXF_ANISOTROPIC; - mip = D3DTEXF_ANISOTROPIC; - min = D3DTEXF_ANISOTROPIC; - } - dev->SetSamplerState(stage, D3DSAMP_MINFILTER, min); - dev->SetSamplerState(stage, D3DSAMP_MAGFILTER, mag); - dev->SetSamplerState(stage, D3DSAMP_MIPFILTER, mip); - - dev->SetSamplerState(stage, D3DSAMP_MAXANISOTROPY,16); - dev->SetSamplerState(stage, D3DSAMP_ADDRESSU,d3dClamps[tm0.wrap_s]); - dev->SetSamplerState(stage, D3DSAMP_ADDRESSV,d3dClamps[tm0.wrap_t]); - //wip - //dev->SetSamplerState(stage,D3DSAMP_MIPMAPLODBIAS,tm0.lod_bias/4.0f); - //char temp[256]; - //sprintf(temp,"lod %f",tm0.lod_bias/4.0f); - //g_VideoInitialize.pLog(temp); - } - break; - case 0x84://TEX MODE 1 - case 0xA4: - break; - case 0x88://TEX IMAGE 0 - case 0xA8: - if (changes) - { - textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; - VertexManager::Flush(); - } - break; - case 0x8C://TEX IMAGE 1 - case 0xAC: - if (changes) - { - textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; - VertexManager::Flush(); - } - break; - case 0x90://TEX IMAGE 2 - case 0xB0: - if (changes) - { - textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; - VertexManager::Flush(); - } - break; - case 0x94://TEX IMAGE 3 - case 0xB4: - if (changes) - { - textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; - VertexManager::Flush(); - } - break; - case 0x98://TEX TLUT - case 0xB8: - if (changes) - { - textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; - VertexManager::Flush(); - } - break; - case 0x9C://TEX UNKNOWN - case 0xBC: - break; - default: - switch(addr&0xF0) { - case 0x30: - { - int tc = addr&0x1; - int stage = (addr>>1)&0x7; - TCoordInfo &tci = bpmem.texcoords[stage]; - //TCInfo &t = (tc?tci.s:tc.t); - // cylindric wrapping here - //dev->SetRenderState(D3DRS_WRAP0+stage, D3DWRAPCOORD_0); - } - break; - case 0xC0: - case 0xD0: - if (changes) - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - // PixelShaderMngr::SetTevCombinerChanged((addr&0x1f)/2); - } - break; - - case 0xE0: - if (addr<0xe8) - { - if (addr&1) - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - static int lastRGBA[2][4] = { - {0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE}, - {0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE} - }; - //Terrible hack - //The reason is that there are two sets of registers - //overloaded here... - int num = (addr >> 1) & 0x3; - int type = bpmem.tevregs[num].high.type; - int colorbase = type ? PS_CONST_KCOLORS : PS_CONST_COLORS; - int r=bpmem.tevregs[num].low.a, a=bpmem.tevregs[num].low.b; - int b=bpmem.tevregs[num].high.a, g=bpmem.tevregs[num].high.b; - int rgba = ((a<<24) | (r << 16) | (g << 8) | b) & 0xFCFCFCFC; //let's not detect minimal changes - if (rgba != lastRGBA[type][num]) - { - VertexManager::Flush(); - lastRGBA[type][num] = rgba; - float temp[4] = { - r/255.0f, g/255.0f, b/255.0f, a/255.0f - }; - D3D::dev->SetPixelShaderConstantF(colorbase + num, temp, 1); - } - } - } - break; - case 0x20: - case 0x80: - case 0x90: - case 0xA0: - case 0xB0: - default: - if (changes) - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - } - break; - } - break; - - } - break; - } -} - -// __________________________________________________________________________________________________ -// LoadBPReg -// -void LoadBPReg(u32 value0) -{ - DVSTARTPROFILE(); - - //handle the mask register - int opcode = value0 >> 24; - int oldval = ((u32*)&bpmem)[opcode]; - int newval = (((u32*)&bpmem)[opcode] & ~bpmem.bpMask) | (value0 & bpmem.bpMask); - int changes = (oldval ^ newval) & 0xFFFFFF; - //reset the mask register - if(opcode != 0xFE) - bpmem.bpMask = 0xFFFFFF; - - switch (opcode) - { - case 0x45: //GXSetDrawDone - VertexManager::Flush(); - switch (value0 & 0xFF) - { - case 0x02: - g_VideoInitialize.pSetPEFinish(); // may generate interrupt - DebugLog("GXSetDrawDone SetPEFinish (value: 0x%02X)", (value0 & 0xFFFF)); - break; - - default: - DebugLog("GXSetDrawDone ??? (value 0x%02X)", (value0 & 0xFFFF)); - break; - } - break; - - case BPMEM_PE_TOKEN_ID: - g_VideoInitialize.pSetPEToken(static_cast(value0 & 0xFFFF), FALSE); - DebugLog("SetPEToken 0x%04x", (value0 & 0xFFFF)); - break; - - case BPMEM_PE_TOKEN_INT_ID: - g_VideoInitialize.pSetPEToken(static_cast(value0 & 0xFFFF), TRUE); - DebugLog("SetPEToken + INT 0x%04x", (value0 & 0xFFFF)); - break; - - case 0x67: // set gp metric? - break; - - case 0x52: - { - VertexManager::Flush(); - - ((u32*)&bpmem)[opcode] = newval; - RECT rc = { - (LONG)(bpmem.copyTexSrcXY.x*Renderer::GetXScale()), - (LONG)(bpmem.copyTexSrcXY.y*Renderer::GetYScale()), - (LONG)((bpmem.copyTexSrcXY.x+bpmem.copyTexSrcWH.x)*Renderer::GetXScale()), - (LONG)((bpmem.copyTexSrcXY.y+bpmem.copyTexSrcWH.y)*Renderer::GetYScale()) - }; - - UPE_Copy PE_copy; - PE_copy.Hex = bpmem.triggerEFBCopy; - - // clamp0 - // clamp1 - // target_pixel_format - // gamma - // scale_something - // clear - // frame_to_field - // copy_to_xfb - - // ???: start Mem to/from EFB transfer -/* bool bMip = false; // ignored - if (bpmem.triggerEFBCopy & EFBCOPY_GENERATEMIPS) - bMip = true;*/ - - if (PE_copy.copy_to_xfb == 0) // bpmem.triggerEFBCopy & EFBCOPY_EFBTOTEXTURE) - { - // EFB to texture - // for some reason it sets bpmem.zcontrol.pixel_format to PIXELFMT_Z24 every time a zbuffer format is given as a dest to GXSetTexCopyDst - TextureCache::CopyEFBToRenderTarget(bpmem.copyTexDest<<5, &rc); - } - else - { - // EFB to XFB - // MessageBox(0, "WASDF", 0, 0); - Renderer::SwapBuffers(); - DebugLog("Renderer::SwapBuffers()"); - g_VideoInitialize.pCopiedToXFB(); - } - - // clearing - if (PE_copy.clear) // bpmem.triggerEFBCopy & EFBCOPY_CLEAR) - { - // it seems that the GC is able to alpha blend on color-fill - // we cant do that so if alpha is != 255 we skip it - - // clear color - u32 clearColor = (bpmem.clearcolorAR<<16)|bpmem.clearcolorGB; - if (bpmem.blendmode.colorupdate) - { - D3DRECT drc; - drc.x1 = rc.left; - drc.x2 = rc.right; - drc.y1 = rc.top; - drc.y2 = rc.bottom; - //D3D::dev->Clear(1, &drc, D3DCLEAR_STENCIL|D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,clearColor,1.0f,0); - //if ((clearColor>>24) == 255) - D3D::dev->ColorFill(D3D::GetBackBufferSurface(), &rc, clearColor); - } - else - { - // TODO: - // bpmem.blendmode.alphaupdate - // bpmem.blendmode.colorupdate - // i dunno how to implement a clear on alpha only or color only - } - - // clear z-buffer - if (bpmem.zmode.updateenable) - { - float clearZ = (float)bpmem.clearZValue / float(0xFFFFFF); - if (clearZ > 1.0f) clearZ = 1.0f; - if (clearZ < 0.0f) clearZ = 0.0f; - - D3D::dev->Clear(0, 0, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0, clearZ, 0); - } - } - } - break; - - case 0x65: //GXLoadTlut - { - VertexManager::Flush(); - ((u32*)&bpmem)[opcode] = newval; - - u32 tlutTMemAddr = (value0&0x3FF)<<9; - u32 tlutXferCount = (value0&0x1FFC00)>>5; - //do the transfer!! - memcpy(texMem + tlutTMemAddr, g_VideoInitialize.pGetMemoryPointer((bpmem.tlutXferSrc&0xFFFFF)<<5), tlutXferCount); - // TODO(ector) : kill all textures that use this palette - // Not sure if it's a good idea, though. For now, we hash texture palettes - } - break; - } - - //notify the video handling so it can update render states - BPWritten(opcode, changes, newval); - ((u32*)&bpmem)[opcode] = newval; -} - -void BPReload() -{ - for (int i=0; i<254; i++) - BPWritten(i, 0xFFFFFF, ((u32*)&bpmem)[i]); -} - -void ActivateTextures() -{ - for (int i = 0; i < 8; i++) - { - //TODO(ector): this should be a speedup - //if (textureChanged[i] || ASK TEXCACHE ABOUT SENTINEL VALUE) - { - FourTexUnits &tex = bpmem.tex[i>>2]; - TextureCache::Load(i, - (tex.texImage3[i&3].image_base) << 5, - tex.texImage0[i&3].width+1, - tex.texImage0[i&3].height+1, - tex.texImage0[i&3].format, - tex.texTlut[i&3].tmem_offset<<9, - tex.texTlut[i&3].tlut_format); - } - textureChanged[i] = false; - } -} - - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "D3DBase.h" + +#include "Config.h" +#include "Common.h" +#include "Profiler.h" +#include "BPStructs.h" +#include "OpcodeDecoding.h" +#include "TextureCache.h" +#include "TextureDecoder.h" +#include "VertexManager.h" +#include "PixelShader.h" +#include "Utils.h" + +#include "main.h" //for the plugin interface + +bool textureChanged[8]; + +const bool renderFog = false; + +// State translation lookup tables +const D3DBLEND d3dSrcFactors[8] = +{ + D3DBLEND_ZERO, + D3DBLEND_ONE, + D3DBLEND_DESTCOLOR, + D3DBLEND_INVDESTCOLOR, + D3DBLEND_SRCALPHA, + D3DBLEND_INVSRCALPHA, + D3DBLEND_DESTALPHA, + D3DBLEND_INVDESTALPHA +}; + +const D3DBLEND d3dDestFactors[8] = +{ + D3DBLEND_ZERO, + D3DBLEND_ONE, + D3DBLEND_SRCCOLOR, + D3DBLEND_INVSRCCOLOR, + D3DBLEND_SRCALPHA, + D3DBLEND_INVSRCALPHA, + D3DBLEND_DESTALPHA, + D3DBLEND_INVDESTALPHA +}; + +const D3DCULL d3dCullModes[4] = +{ + D3DCULL_NONE, + D3DCULL_CCW, + D3DCULL_CW, + D3DCULL_CCW +}; + +const D3DCMPFUNC d3dCmpFuncs[8] = +{ + D3DCMP_NEVER, + D3DCMP_LESS, + D3DCMP_EQUAL, + D3DCMP_LESSEQUAL, + D3DCMP_GREATER, + D3DCMP_NOTEQUAL, + D3DCMP_GREATEREQUAL, + D3DCMP_ALWAYS +}; + +const D3DTEXTUREFILTERTYPE d3dMipFilters[4] = +{ + D3DTEXF_NONE, + D3DTEXF_POINT, + D3DTEXF_ANISOTROPIC, + D3DTEXF_LINEAR, //reserved +}; + +const D3DTEXTUREADDRESS d3dClamps[4] = +{ + D3DTADDRESS_CLAMP, + D3DTADDRESS_WRAP, + D3DTADDRESS_MIRROR, + D3DTADDRESS_WRAP //reserved +}; + +void BPInit() +{ + memset(&bpmem, 0, sizeof(bpmem)); + bpmem.bpMask = 0xFFFFFF; +} + +using namespace D3D; +// __________________________________________________________________________________________________ +// BPWritten +// +void BPWritten(int addr, int changes, int newval) +{ + switch(addr) + { + case BPMEM_GENMODE: + if (changes) + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + + // dev->SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]); + Renderer::SetRenderState( D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode] ); + + if (bpmem.genMode.cullmode == 3) + { + // dev->SetRenderState(D3DRS_COLORWRITEENABLE, 0); + Renderer::SetRenderState( D3DRS_COLORWRITEENABLE, 0 ); + } + else + { + DWORD write = 0; + if (bpmem.blendmode.alphaupdate) + write = D3DCOLORWRITEENABLE_ALPHA; + if (bpmem.blendmode.colorupdate) + write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; + + // dev->SetRenderState(D3DRS_COLORWRITEENABLE, write); + Renderer::SetRenderState( D3DRS_COLORWRITEENABLE, write ); + } + } + break; + case BPMEM_IND_MTX+0: + case BPMEM_IND_MTX+1: + case BPMEM_IND_MTX+2: + case BPMEM_IND_MTX+3: + case BPMEM_IND_MTX+4: + case BPMEM_IND_MTX+5: + case BPMEM_IND_MTX+6: + case BPMEM_IND_MTX+7: + case BPMEM_IND_MTX+8: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + // PixelShaderMngr::SetIndMatrixChanged((addr-BPMEM_IND_MTX)/3); + } + break; + case BPMEM_RAS1_SS0: + case BPMEM_RAS1_SS1: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + // PixelShaderMngr::SetIndTexScaleChanged(); + } + break; + + case BPMEM_ZMODE: + if (changes) + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + if (bpmem.zmode.testenable) + { + // dev->SetRenderState(D3DRS_ZENABLE, TRUE); + // dev->SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable); + // dev->SetRenderState(D3DRS_ZFUNC,d3dCmpFuncs[bpmem.zmode.func]); + + Renderer::SetRenderState( D3DRS_ZENABLE, TRUE ); + Renderer::SetRenderState( D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable ); + Renderer::SetRenderState( D3DRS_ZFUNC, d3dCmpFuncs[bpmem.zmode.func] ); + } + else + { + // if the test is disabled write is disabled too + // dev->SetRenderState(D3DRS_ZENABLE, FALSE); + // dev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + + Renderer::SetRenderState( D3DRS_ZENABLE, FALSE ); + Renderer::SetRenderState( D3DRS_ZWRITEENABLE, FALSE ); + } + } + break; + + case BPMEM_ALPHACOMPARE: + if (changes) + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + float f[4] = + { + bpmem.alphaFunc.ref0/255.0f, + bpmem.alphaFunc.ref1/255.0f, + 0,0 + }; + dev->SetPixelShaderConstantF(PS_CONST_ALPHAREF,f,1); + + if (D3D::GetShaderVersion() == PSNONE) + { + // dev->SetRenderState(D3DRS_ALPHATESTENABLE, (Compare)bpmem.alphaFunc.comp0 != COMPARE_ALWAYS); + // dev->SetRenderState(D3DRS_ALPHAREF, bpmem.alphaFunc.ref0*4); + // dev->SetRenderState(D3DRS_ALPHAFUNC, d3dCmpFuncs[bpmem.alphaFunc.comp0]); + + Renderer::SetRenderState( D3DRS_ALPHATESTENABLE, (Compare)bpmem.alphaFunc.comp0 != COMPARE_ALWAYS ); + Renderer::SetRenderState( D3DRS_ALPHAREF, bpmem.alphaFunc.ref0 * 4 ); + Renderer::SetRenderState( D3DRS_ALPHAFUNC, d3dCmpFuncs[bpmem.alphaFunc.comp0] ); + } + // Normally, use texkill in pixel shader to emulate alpha test + } + break; + + case BPMEM_CONSTANTALPHA: + if (changes) + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + float f[4] = { + bpmem.dstalpha.alpha/255.0f,0,0,0 + }; + dev->SetPixelShaderConstantF(PS_CONST_CONSTALPHA,f,1); + } + break; + + case BPMEM_LINEPTWIDTH: + { + // We can't change line width in D3D unless we use ID3DXLine + //bpmem.lineptwidth.linesize); + float psize = float(bpmem.lineptwidth.pointsize) * 6.0f; + + Renderer::SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&psize)); + } + break; + + case 0x43: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + } + break; + + case BPMEM_BLENDMODE: + if (changes & 0xFFFF) + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + if (changes & 1) + { + // dev->SetRenderState(D3DRS_ALPHABLENDENABLE,bpmem.blendmode.blendenable); + Renderer::SetRenderState( D3DRS_ALPHABLENDENABLE, bpmem.blendmode.blendenable ); + } + if (changes & 2) {} // Logic op blending. D3D can't do this but can fake some modes. + if (changes & 4) { + // Dithering is pointless. Will make things uglier and will be different from GC. + // dev->SetRenderState(D3DRS_DITHERENABLE,bpmem.blendmode.dither); + } + D3DBLEND src = d3dSrcFactors[bpmem.blendmode.srcfactor]; + D3DBLEND dst = d3dDestFactors[bpmem.blendmode.dstfactor]; + + if (changes & 0x700) + { + // dev->SetRenderState(D3DRS_SRCBLEND, src); + Renderer::SetRenderState( D3DRS_SRCBLEND, src ); + } + if (changes & 0xE0) { + if (!bpmem.blendmode.subtract) + { + // dev->SetRenderState(D3DRS_DESTBLEND, dst); + Renderer::SetRenderState( D3DRS_DESTBLEND, dst ); + } + else + { + // dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE ); + } + } + if (changes & 0x800) { + if (bpmem.blendmode.subtract) + { + // dev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); + // dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE ); + Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE ); + } + else + { + // dev->SetRenderState(D3DRS_SRCBLEND, src); + // dev->SetRenderState(D3DRS_DESTBLEND, dst); + + Renderer::SetRenderState( D3DRS_SRCBLEND, src ); + Renderer::SetRenderState( D3DRS_DESTBLEND, dst ); + } + + // dev->SetRenderState(D3DRS_BLENDOP,bpmem.blendmode.subtract?D3DBLENDOP_SUBTRACT:D3DBLENDOP_ADD); + Renderer::SetRenderState( D3DRS_BLENDOP, bpmem.blendmode.subtract ? D3DBLENDOP_SUBTRACT : D3DBLENDOP_ADD ); + } + //if (bpmem.blendmode.logicopenable) // && bpmem.blendmode.logicmode == 4) + // MessageBox(0,"LOGIC",0,0); + + if (changes & 0x18) + { + // Color Mask + DWORD write = 0; + if (bpmem.blendmode.alphaupdate) + write = D3DCOLORWRITEENABLE_ALPHA; + if (bpmem.blendmode.colorupdate) + write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; + + // dev->SetRenderState(D3DRS_COLORWRITEENABLE, write); + Renderer::SetRenderState( D3DRS_COLORWRITEENABLE, write ); + } + } + break; + + case BPMEM_FOGRANGE: + if(changes) { + // TODO(XK): Fog range format + //Renderer::SetRenderState(D3DRS_FOGSTART, ... + //Renderer::SetRenderState(D3DRS_FOGEND, ... + } + break; + + case BPMEM_FOGPARAM0: + { + // u32 fogATemp = bpmem.fog.a<<12; + // float fogA = *(float*)(&fogATemp); + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + } + break; + + case BPMEM_FOGBEXPONENT: + case BPMEM_FOGBMAGNITUDE: + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + } + break; + + case BPMEM_FOGPARAM3: + //fog settings + if(changes) { + static bool bFog = false; + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + + if(!renderFog) + break; + + /// u32 fogCTemp = bpmem.fog.c_proj_fsel.cShifted12 << 12; + // float fogC = *(float*)(&fogCTemp); + + + //printf("%f %f magnitude: %x\n", bpmem.fog.a.GetA(),bpmem.fog.c_proj_fsel.GetC(), bpmem.fog.b_magnitude); + switch(bpmem.fog.c_proj_fsel.fsel) + { + case 0: // Off + if(bFog) { + Renderer::SetRenderState(D3DRS_FOGENABLE, false); + bFog = false; + } + break; + case 2: // Linear + Renderer::SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR); + break; + case 4: // exp + Renderer::SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_EXP); + break; + case 5: // exp2 + Renderer::SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_EXP2); + break; + case 6: // Backward exp + case 7: // Backward exp2 + PanicAlert("Backward Exponential Fog Detected"); + // TODO: Figure out how to do these in any rendering API + //TEV_FSEL_BX, TEV_FSEL_BX2? + default: + PanicAlert("Non-Emulated Fog selection %d\n", bpmem.fog.c_proj_fsel.fsel); + break; + } + + if(bpmem.fog.c_proj_fsel.fsel > 0 && !bFog) { + Renderer::SetRenderState(D3DRS_FOGENABLE, true); + bFog = true; + } + + } + break; + + case BPMEM_FOGCOLOR: + if(changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + + if(!renderFog) + break; + + // dev->SetRenderState(D3DRS_FOGCOLOR,bpmem.fog.color); + int fogcolor[3] = { ((bpmem.fog.color>>16)&0xff), ((bpmem.fog.color>>8)&0xff), (bpmem.fog.color&0xff)}; + //D3DCOLOR_RGBA(fogcolor[0], fogcolor[1], fogcolor[2], 0) + Renderer::SetRenderState(D3DRS_FOGCOLOR, bpmem.fog.color); + } + break; + + case BPMEM_TEXINVALIDATE: + //TexCache_Invalidate(); + break; + + case BPMEM_SCISSOROFFSET: //TODO: investigate + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + } + break; + + case BPMEM_SCISSORTL: + case BPMEM_SCISSORBR: + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + int xoff = bpmem.scissorOffset.x*2-342; + int yoff = bpmem.scissorOffset.y*2-342; + RECT rc; + rc.left=bpmem.scissorTL.x + xoff - 342 -1; + if (rc.left<0) rc.left=0; + rc.top=bpmem.scissorTL.y + yoff - 342 -1; + if (rc.top<0) rc.top=0; + rc.right=bpmem.scissorBR.x + xoff - 342 +2; + if (rc.right>640) rc.right=640; + rc.bottom=bpmem.scissorBR.y + yoff - 342 +2; + if (rc.bottom>480) rc.bottom=480; + char temp[256]; + sprintf(temp,"ScissorRect: %i %i %i %i",rc.left,rc.top,rc.right,rc.bottom); + g_VideoInitialize.pLog(temp, FALSE); + + // dev->SetRenderState(D3DRS_SCISSORTESTENABLE,TRUE); + Renderer::SetRenderState( D3DRS_SCISSORTESTENABLE, TRUE ); + + Renderer::SetScissorBox(rc); + } + break; + case BPMEM_ZTEX1: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + //PRIM_LOG("ztex bias=0x%x\n", bpmem.ztex1.bias); + //PixelShaderMngr::SetZTextureBias(bpmem.ztex1.bias); + } + break; + case BPMEM_ZTEX2: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; +#ifdef _DEBUG + const char* pzop[] = {"DISABLE", "ADD", "REPLACE", "?"}; + const char* pztype[] = {"Z8", "Z16", "Z24", "?"}; + DebugLog("ztex op=%s, type=%s\n", pzop[bpmem.ztex2.op], pztype[bpmem.ztex2.type]); +#endif + } + break; + + case 0xf6: // ksel0 + case 0xf7: // ksel1 + case 0xf8: // ksel2 + case 0xf9: // ksel3 + case 0xfa: // ksel4 + case 0xfb: // ksel5 + case 0xfc: // ksel6 + case 0xfd: // ksel7 + if (changes) + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + // PixelShaderMngr::SetTevKSelChanged(addr-0xf6); + } + break; + + default: + switch(addr & 0xF8) //texture sampler filter + { + case 0x80: // TEX MODE 0 + case 0xA0: + if (changes) + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + FourTexUnits &tex = bpmem.tex[(addr&0xE0)==0xA0]; + int stage = (addr&3);//(addr>>4)&2; + TexMode0 &tm0 = tex.texMode0[stage]; + + D3DTEXTUREFILTERTYPE min, mag, mip; + if (g_Config.bForceFiltering) + { + min = mag = mip = D3DTEXF_LINEAR; + } + else + { + min = (tm0.min_filter&4) ? D3DTEXF_LINEAR : D3DTEXF_POINT; + mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT; + mip = d3dMipFilters[tm0.min_filter&3]; + } + if ((addr & 0xE0) == 0xA0) + stage += 4; + + if (g_Config.bForceMaxAniso) + { + mag = D3DTEXF_ANISOTROPIC; + mip = D3DTEXF_ANISOTROPIC; + min = D3DTEXF_ANISOTROPIC; + } + dev->SetSamplerState(stage, D3DSAMP_MINFILTER, min); + dev->SetSamplerState(stage, D3DSAMP_MAGFILTER, mag); + dev->SetSamplerState(stage, D3DSAMP_MIPFILTER, mip); + + dev->SetSamplerState(stage, D3DSAMP_MAXANISOTROPY,16); + dev->SetSamplerState(stage, D3DSAMP_ADDRESSU,d3dClamps[tm0.wrap_s]); + dev->SetSamplerState(stage, D3DSAMP_ADDRESSV,d3dClamps[tm0.wrap_t]); + //wip + //dev->SetSamplerState(stage,D3DSAMP_MIPMAPLODBIAS,tm0.lod_bias/4.0f); + //char temp[256]; + //sprintf(temp,"lod %f",tm0.lod_bias/4.0f); + //g_VideoInitialize.pLog(temp); + } + break; + case 0x84://TEX MODE 1 + case 0xA4: + break; + case 0x88://TEX IMAGE 0 + case 0xA8: + if (changes) + { + textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; + VertexManager::Flush(); + } + break; + case 0x8C://TEX IMAGE 1 + case 0xAC: + if (changes) + { + textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; + VertexManager::Flush(); + } + break; + case 0x90://TEX IMAGE 2 + case 0xB0: + if (changes) + { + textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; + VertexManager::Flush(); + } + break; + case 0x94://TEX IMAGE 3 + case 0xB4: + if (changes) + { + textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; + VertexManager::Flush(); + } + break; + case 0x98://TEX TLUT + case 0xB8: + if (changes) + { + textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; + VertexManager::Flush(); + } + break; + case 0x9C://TEX UNKNOWN + case 0xBC: + break; + default: + switch(addr&0xF0) { + case 0x30: + { + int tc = addr&0x1; + int stage = (addr>>1)&0x7; + TCoordInfo &tci = bpmem.texcoords[stage]; + //TCInfo &t = (tc?tci.s:tc.t); + // cylindric wrapping here + //dev->SetRenderState(D3DRS_WRAP0+stage, D3DWRAPCOORD_0); + } + break; + case 0xC0: + case 0xD0: + if (changes) + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + // PixelShaderMngr::SetTevCombinerChanged((addr&0x1f)/2); + } + break; + + case 0xE0: + if (addr<0xe8) + { + if (addr&1) + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + static int lastRGBA[2][4] = { + {0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE}, + {0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE, 0xEEEEEEEE} + }; + //Terrible hack + //The reason is that there are two sets of registers + //overloaded here... + int num = (addr >> 1) & 0x3; + int type = bpmem.tevregs[num].high.type; + int colorbase = type ? PS_CONST_KCOLORS : PS_CONST_COLORS; + int r=bpmem.tevregs[num].low.a, a=bpmem.tevregs[num].low.b; + int b=bpmem.tevregs[num].high.a, g=bpmem.tevregs[num].high.b; + int rgba = ((a<<24) | (r << 16) | (g << 8) | b) & 0xFCFCFCFC; //let's not detect minimal changes + if (rgba != lastRGBA[type][num]) + { + VertexManager::Flush(); + lastRGBA[type][num] = rgba; + float temp[4] = { + r/255.0f, g/255.0f, b/255.0f, a/255.0f + }; + D3D::dev->SetPixelShaderConstantF(colorbase + num, temp, 1); + } + } + } + break; + case 0x20: + case 0x80: + case 0x90: + case 0xA0: + case 0xB0: + default: + if (changes) + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + } + break; + } + break; + + } + break; + } +} + +// __________________________________________________________________________________________________ +// LoadBPReg +// +void LoadBPReg(u32 value0) +{ + DVSTARTPROFILE(); + + //handle the mask register + int opcode = value0 >> 24; + int oldval = ((u32*)&bpmem)[opcode]; + int newval = (((u32*)&bpmem)[opcode] & ~bpmem.bpMask) | (value0 & bpmem.bpMask); + int changes = (oldval ^ newval) & 0xFFFFFF; + //reset the mask register + if(opcode != 0xFE) + bpmem.bpMask = 0xFFFFFF; + + switch (opcode) + { + case 0x45: //GXSetDrawDone + VertexManager::Flush(); + switch (value0 & 0xFF) + { + case 0x02: + g_VideoInitialize.pSetPEFinish(); // may generate interrupt + DebugLog("GXSetDrawDone SetPEFinish (value: 0x%02X)", (value0 & 0xFFFF)); + break; + + default: + DebugLog("GXSetDrawDone ??? (value 0x%02X)", (value0 & 0xFFFF)); + break; + } + break; + + case BPMEM_PE_TOKEN_ID: + g_VideoInitialize.pSetPEToken(static_cast(value0 & 0xFFFF), FALSE); + DebugLog("SetPEToken 0x%04x", (value0 & 0xFFFF)); + break; + + case BPMEM_PE_TOKEN_INT_ID: + g_VideoInitialize.pSetPEToken(static_cast(value0 & 0xFFFF), TRUE); + DebugLog("SetPEToken + INT 0x%04x", (value0 & 0xFFFF)); + break; + + case 0x67: // set gp metric? + break; + + case 0x52: + { + VertexManager::Flush(); + + ((u32*)&bpmem)[opcode] = newval; + RECT rc = { + (LONG)(bpmem.copyTexSrcXY.x*Renderer::GetXScale()), + (LONG)(bpmem.copyTexSrcXY.y*Renderer::GetYScale()), + (LONG)((bpmem.copyTexSrcXY.x+bpmem.copyTexSrcWH.x)*Renderer::GetXScale()), + (LONG)((bpmem.copyTexSrcXY.y+bpmem.copyTexSrcWH.y)*Renderer::GetYScale()) + }; + + UPE_Copy PE_copy; + PE_copy.Hex = bpmem.triggerEFBCopy; + + // clamp0 + // clamp1 + // target_pixel_format + // gamma + // scale_something + // clear + // frame_to_field + // copy_to_xfb + + // ???: start Mem to/from EFB transfer +/* bool bMip = false; // ignored + if (bpmem.triggerEFBCopy & EFBCOPY_GENERATEMIPS) + bMip = true;*/ + + if (PE_copy.copy_to_xfb == 0) // bpmem.triggerEFBCopy & EFBCOPY_EFBTOTEXTURE) + { + // EFB to texture + // for some reason it sets bpmem.zcontrol.pixel_format to PIXELFMT_Z24 every time a zbuffer format is given as a dest to GXSetTexCopyDst + TextureCache::CopyEFBToRenderTarget(bpmem.copyTexDest<<5, &rc); + } + else + { + // EFB to XFB + // MessageBox(0, "WASDF", 0, 0); + Renderer::SwapBuffers(); + DebugLog("Renderer::SwapBuffers()"); + g_VideoInitialize.pCopiedToXFB(); + } + + // clearing + if (PE_copy.clear) // bpmem.triggerEFBCopy & EFBCOPY_CLEAR) + { + // it seems that the GC is able to alpha blend on color-fill + // we cant do that so if alpha is != 255 we skip it + + // clear color + u32 clearColor = (bpmem.clearcolorAR<<16)|bpmem.clearcolorGB; + if (bpmem.blendmode.colorupdate) + { + D3DRECT drc; + drc.x1 = rc.left; + drc.x2 = rc.right; + drc.y1 = rc.top; + drc.y2 = rc.bottom; + //D3D::dev->Clear(1, &drc, D3DCLEAR_STENCIL|D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,clearColor,1.0f,0); + //if ((clearColor>>24) == 255) + D3D::dev->ColorFill(D3D::GetBackBufferSurface(), &rc, clearColor); + } + else + { + // TODO: + // bpmem.blendmode.alphaupdate + // bpmem.blendmode.colorupdate + // i dunno how to implement a clear on alpha only or color only + } + + // clear z-buffer + if (bpmem.zmode.updateenable) + { + float clearZ = (float)bpmem.clearZValue / float(0xFFFFFF); + if (clearZ > 1.0f) clearZ = 1.0f; + if (clearZ < 0.0f) clearZ = 0.0f; + + D3D::dev->Clear(0, 0, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0, clearZ, 0); + } + } + } + break; + + case 0x65: //GXLoadTlut + { + VertexManager::Flush(); + ((u32*)&bpmem)[opcode] = newval; + + u32 tlutTMemAddr = (value0&0x3FF)<<9; + u32 tlutXferCount = (value0&0x1FFC00)>>5; + //do the transfer!! + memcpy(texMem + tlutTMemAddr, g_VideoInitialize.pGetMemoryPointer((bpmem.tlutXferSrc&0xFFFFF)<<5), tlutXferCount); + // TODO(ector) : kill all textures that use this palette + // Not sure if it's a good idea, though. For now, we hash texture palettes + } + break; + } + + //notify the video handling so it can update render states + BPWritten(opcode, changes, newval); + ((u32*)&bpmem)[opcode] = newval; +} + +void BPReload() +{ + for (int i=0; i<254; i++) + BPWritten(i, 0xFFFFFF, ((u32*)&bpmem)[i]); +} + +void ActivateTextures() +{ + for (int i = 0; i < 8; i++) + { + //TODO(ector): this should be a speedup + //if (textureChanged[i] || ASK TEXCACHE ABOUT SENTINEL VALUE) + { + FourTexUnits &tex = bpmem.tex[i>>2]; + TextureCache::Load(i, + (tex.texImage3[i&3].image_base) << 5, + tex.texImage0[i&3].width+1, + tex.texImage0[i&3].height+1, + tex.texImage0[i&3].format, + tex.texTlut[i&3].tmem_offset<<9, + tex.texTlut[i&3].tlut_format); + } + textureChanged[i] = false; + } +} + + diff --git a/Source/Plugins/Plugin_VideoDX9/Src/CPStructs.cpp b/Source/Plugins/Plugin_VideoDX9/Src/CPStructs.cpp index d684eb1c32..ddbf3196f3 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/CPStructs.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/CPStructs.cpp @@ -1,76 +1,76 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include - -#include "CPStructs.h" -#include "XFStructs.h" -#include "TransformEngine.h" -#include "VertexManager.h" -#include "VertexLoader.h" - -// PROBLEM - matrix switching within vbuffers may be stateful! - -void CPUpdateMatricesA() -{ - float *flipmem = (float *)xfmem; - CTransformEngine::SetPosNormalMatrix( - flipmem + MatrixIndexA.PosNormalMtxIdx * 4, //CHECK - flipmem + 0x400 + 3 * (MatrixIndexA.PosNormalMtxIdx & 31)); //CHECK - CTransformEngine::SetTexMatrix(0,flipmem + MatrixIndexA.Tex0MtxIdx * 4); - CTransformEngine::SetTexMatrix(1,flipmem + MatrixIndexA.Tex1MtxIdx * 4); - CTransformEngine::SetTexMatrix(2,flipmem + MatrixIndexA.Tex2MtxIdx * 4); - CTransformEngine::SetTexMatrix(3,flipmem + MatrixIndexA.Tex3MtxIdx * 4); -} - -void CPUpdateMatricesB() -{ - float *flipmem = (float *)xfmem; - CTransformEngine::SetTexMatrix(4,flipmem + MatrixIndexB.Tex4MtxIdx * 4); - CTransformEngine::SetTexMatrix(5,flipmem + MatrixIndexB.Tex5MtxIdx * 4); - CTransformEngine::SetTexMatrix(6,flipmem + MatrixIndexB.Tex6MtxIdx * 4); - CTransformEngine::SetTexMatrix(7,flipmem + MatrixIndexB.Tex7MtxIdx * 4); -} - -void LoadCPReg(u32 SubCmd, u32 Value) -{ - switch (SubCmd & 0xF0) - { - case 0x30: - MatrixIndexA.Hex = Value; - CPUpdateMatricesA(); - break; - case 0x40: - MatrixIndexB.Hex = Value; - CPUpdateMatricesB(); - break; - - case 0x50: - VertexManager::Flush(); VertexLoader::SetVtxDesc_Lo(Value); - break; - case 0x60: - VertexManager::Flush(); VertexLoader::SetVtxDesc_Hi(Value); - break; - - case 0x70: g_VertexLoaders[SubCmd & 7].SetVAT_group0(Value); _assert_((SubCmd & 0x0F) < 8); break; - case 0x80: g_VertexLoaders[SubCmd & 7].SetVAT_group1(Value); _assert_((SubCmd & 0x0F) < 8); break; - case 0x90: g_VertexLoaders[SubCmd & 7].SetVAT_group2(Value); _assert_((SubCmd & 0x0F) < 8); break; - - case 0xA0: arraybases[SubCmd & 0xF] = Value & 0xFFFFFFFF; break; - case 0xB0: arraystrides[SubCmd & 0xF] = Value & 0xFF; break; - } -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include + +#include "CPStructs.h" +#include "XFStructs.h" +#include "TransformEngine.h" +#include "VertexManager.h" +#include "VertexLoader.h" + +// PROBLEM - matrix switching within vbuffers may be stateful! + +void CPUpdateMatricesA() +{ + float *flipmem = (float *)xfmem; + CTransformEngine::SetPosNormalMatrix( + flipmem + MatrixIndexA.PosNormalMtxIdx * 4, //CHECK + flipmem + 0x400 + 3 * (MatrixIndexA.PosNormalMtxIdx & 31)); //CHECK + CTransformEngine::SetTexMatrix(0,flipmem + MatrixIndexA.Tex0MtxIdx * 4); + CTransformEngine::SetTexMatrix(1,flipmem + MatrixIndexA.Tex1MtxIdx * 4); + CTransformEngine::SetTexMatrix(2,flipmem + MatrixIndexA.Tex2MtxIdx * 4); + CTransformEngine::SetTexMatrix(3,flipmem + MatrixIndexA.Tex3MtxIdx * 4); +} + +void CPUpdateMatricesB() +{ + float *flipmem = (float *)xfmem; + CTransformEngine::SetTexMatrix(4,flipmem + MatrixIndexB.Tex4MtxIdx * 4); + CTransformEngine::SetTexMatrix(5,flipmem + MatrixIndexB.Tex5MtxIdx * 4); + CTransformEngine::SetTexMatrix(6,flipmem + MatrixIndexB.Tex6MtxIdx * 4); + CTransformEngine::SetTexMatrix(7,flipmem + MatrixIndexB.Tex7MtxIdx * 4); +} + +void LoadCPReg(u32 SubCmd, u32 Value) +{ + switch (SubCmd & 0xF0) + { + case 0x30: + MatrixIndexA.Hex = Value; + CPUpdateMatricesA(); + break; + case 0x40: + MatrixIndexB.Hex = Value; + CPUpdateMatricesB(); + break; + + case 0x50: + VertexManager::Flush(); VertexLoader::SetVtxDesc_Lo(Value); + break; + case 0x60: + VertexManager::Flush(); VertexLoader::SetVtxDesc_Hi(Value); + break; + + case 0x70: g_VertexLoaders[SubCmd & 7].SetVAT_group0(Value); _assert_((SubCmd & 0x0F) < 8); break; + case 0x80: g_VertexLoaders[SubCmd & 7].SetVAT_group1(Value); _assert_((SubCmd & 0x0F) < 8); break; + case 0x90: g_VertexLoaders[SubCmd & 7].SetVAT_group2(Value); _assert_((SubCmd & 0x0F) < 8); break; + + case 0xA0: arraybases[SubCmd & 0xF] = Value & 0xFFFFFFFF; break; + case 0xB0: arraystrides[SubCmd & 0xF] = Value & 0xFF; break; + } +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Config.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Config.cpp index 12f8ea6119..6981be2eb1 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Config.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Config.cpp @@ -1,82 +1,82 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Config.h" -#include "IniFile.h" - -Config g_Config; - -Config::Config() -{ -} - -void Config::Load() -{ - IniFile iniFile; - iniFile.Load(FULL_CONFIG_DIR "gfx_dx9.ini"); - iniFile.Get("Hardware", "Adapter", &iAdapter, 0); - iniFile.Get("Hardware", "WindowedRes", &iWindowedRes, 0); - iniFile.Get("Hardware", "FullscreenRes", &iFSResolution, 0); - iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); - iniFile.Get("Hardware", "RenderInMainframe", &renderToMainframe, false); - iniFile.Get("Hardware", "VSync", &bVsync, 0); - if (iAdapter == -1) - iAdapter = 0; - - iniFile.Get("Settings", "OverlayStats", &bOverlayStats, false); - iniFile.Get("Settings", "Postprocess", &iPostprocessEffect, 0); - iniFile.Get("Settings", "DLOptimize", &iCompileDLsLevel, 0); - iniFile.Get("Settings", "DumpTextures", &bDumpTextures, 0); - iniFile.Get("Settings", "ShowShaderErrors", &bShowShaderErrors, 0); - iniFile.Get("Settings", "Multisample", &iMultisampleMode, 0); - iniFile.Get("Settings", "TexDumpPath", &texDumpPath, 0); - - iniFile.Get("Settings", "TexFmtOverlayEnable", &bTexFmtOverlayEnable, 0); - iniFile.Get("Settings", "TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0); - - iniFile.Get("Enhancements", "ForceFiltering", &bForceFiltering, 0); - iniFile.Get("Enhancements", "ForceMaxAniso", &bForceMaxAniso, 0); - -} - -void Config::Save() -{ - IniFile iniFile; - iniFile.Load(FULL_CONFIG_DIR "gfx_dx9.ini"); - iniFile.Set("Hardware", "Adapter", iAdapter); - iniFile.Set("Hardware", "WindowedRes", iWindowedRes); - iniFile.Set("Hardware", "FullscreenRes", iFSResolution); - iniFile.Set("Hardware", "Fullscreen", bFullscreen); - iniFile.Set("Hardware", "VSync", bVsync); - iniFile.Set("Hardware", "RenderInMainframe", renderToMainframe); - - iniFile.Set("Settings", "OverlayStats", bOverlayStats); - iniFile.Set("Settings", "OverlayStats", bOverlayStats); - iniFile.Set("Settings", "Postprocess", iPostprocessEffect); - iniFile.Set("Settings", "DLOptimize", iCompileDLsLevel); - iniFile.Set("Settings", "DumpTextures", bDumpTextures); - iniFile.Set("Settings", "ShowShaderErrors", bShowShaderErrors); - iniFile.Set("Settings", "Multisample", iMultisampleMode); - iniFile.Set("Settings", "TexDumpPath", texDumpPath); - - iniFile.Set("Settings", "TexFmtOverlayEnable", bTexFmtOverlayEnable); - iniFile.Set("Settings", "TexFmtOverlayCenter", bTexFmtOverlayCenter); - - iniFile.Set("Enhancements", "ForceFiltering", bForceFiltering); - iniFile.Set("Enhancements", "ForceMaxAniso", bForceMaxAniso); - iniFile.Save(FULL_CONFIG_DIR "gfx_dx9.ini"); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Config.h" +#include "IniFile.h" + +Config g_Config; + +Config::Config() +{ +} + +void Config::Load() +{ + IniFile iniFile; + iniFile.Load(FULL_CONFIG_DIR "gfx_dx9.ini"); + iniFile.Get("Hardware", "Adapter", &iAdapter, 0); + iniFile.Get("Hardware", "WindowedRes", &iWindowedRes, 0); + iniFile.Get("Hardware", "FullscreenRes", &iFSResolution, 0); + iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); + iniFile.Get("Hardware", "RenderInMainframe", &renderToMainframe, false); + iniFile.Get("Hardware", "VSync", &bVsync, 0); + if (iAdapter == -1) + iAdapter = 0; + + iniFile.Get("Settings", "OverlayStats", &bOverlayStats, false); + iniFile.Get("Settings", "Postprocess", &iPostprocessEffect, 0); + iniFile.Get("Settings", "DLOptimize", &iCompileDLsLevel, 0); + iniFile.Get("Settings", "DumpTextures", &bDumpTextures, 0); + iniFile.Get("Settings", "ShowShaderErrors", &bShowShaderErrors, 0); + iniFile.Get("Settings", "Multisample", &iMultisampleMode, 0); + iniFile.Get("Settings", "TexDumpPath", &texDumpPath, 0); + + iniFile.Get("Settings", "TexFmtOverlayEnable", &bTexFmtOverlayEnable, 0); + iniFile.Get("Settings", "TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0); + + iniFile.Get("Enhancements", "ForceFiltering", &bForceFiltering, 0); + iniFile.Get("Enhancements", "ForceMaxAniso", &bForceMaxAniso, 0); + +} + +void Config::Save() +{ + IniFile iniFile; + iniFile.Load(FULL_CONFIG_DIR "gfx_dx9.ini"); + iniFile.Set("Hardware", "Adapter", iAdapter); + iniFile.Set("Hardware", "WindowedRes", iWindowedRes); + iniFile.Set("Hardware", "FullscreenRes", iFSResolution); + iniFile.Set("Hardware", "Fullscreen", bFullscreen); + iniFile.Set("Hardware", "VSync", bVsync); + iniFile.Set("Hardware", "RenderInMainframe", renderToMainframe); + + iniFile.Set("Settings", "OverlayStats", bOverlayStats); + iniFile.Set("Settings", "OverlayStats", bOverlayStats); + iniFile.Set("Settings", "Postprocess", iPostprocessEffect); + iniFile.Set("Settings", "DLOptimize", iCompileDLsLevel); + iniFile.Set("Settings", "DumpTextures", bDumpTextures); + iniFile.Set("Settings", "ShowShaderErrors", bShowShaderErrors); + iniFile.Set("Settings", "Multisample", iMultisampleMode); + iniFile.Set("Settings", "TexDumpPath", texDumpPath); + + iniFile.Set("Settings", "TexFmtOverlayEnable", bTexFmtOverlayEnable); + iniFile.Set("Settings", "TexFmtOverlayCenter", bTexFmtOverlayCenter); + + iniFile.Set("Enhancements", "ForceFiltering", bForceFiltering); + iniFile.Set("Enhancements", "ForceMaxAniso", bForceMaxAniso); + iniFile.Save(FULL_CONFIG_DIR "gfx_dx9.ini"); +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp index 4c21756d16..713e6ccde4 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp @@ -1,389 +1,389 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "D3DBase.h" -#include "Render.h" - - -namespace D3D -{ - bool fullScreen = false, nextFullScreen=false; - LPDIRECT3D9 D3D = NULL; // Used to create the D3DDevice - LPDIRECT3DDEVICE9 dev = NULL; // Our rendering device - LPDIRECT3DSURFACE9 backBuffer; - D3DCAPS9 caps; - int multisample; - int resolution; - -#define VENDOR_NVIDIA 4318 - - RECT client; - HWND hWnd; - int xres, yres; - int cur_adapter; - Shader Ps; - Shader Vs; - - bool bFrameInProgress = false; - - //enum shit - Adapter adapters[4]; - int numAdapters; - - void Enumerate(); - - int GetNumAdapters() - { - return numAdapters; - } - - const Adapter &GetAdapter(int i) - { - return adapters[i]; - } - - const Adapter &GetCurAdapter() - { - return adapters[cur_adapter]; - } - - HRESULT Init() - { - // Create the D3D object, which is needed to create the D3DDevice. - if( NULL == ( D3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) - return E_FAIL; - - Enumerate(); - return S_OK; - } - - void EnableAlphaToCoverage() - { - // dev->SetRenderState(D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C')); - Renderer::SetRenderState( D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C') ); - } - - void InitPP(int adapter, int resolution, int aa_mode, D3DPRESENT_PARAMETERS *pp) - { - int FSResX = adapters[adapter].resolutions[resolution].xres; - int FSResY = adapters[adapter].resolutions[resolution].yres; - - ZeroMemory(pp, sizeof(D3DPRESENT_PARAMETERS)); - pp->hDeviceWindow = hWnd; - pp->EnableAutoDepthStencil = TRUE; - pp->AutoDepthStencilFormat = D3DFMT_D24S8; - pp->BackBufferFormat = D3DFMT_A8R8G8B8; - if (aa_mode >= (int)adapters[adapter].aa_levels.size()) - aa_mode = 0; - - pp->MultiSampleType = adapters[adapter].aa_levels[aa_mode].ms_setting; - pp->MultiSampleQuality = adapters[adapter].aa_levels[aa_mode].qual_setting; - pp->Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; - - //D3DPRESENTFLAG_LOCKABLE_BACKBUFFER - - if (fullScreen) - { - xres = pp->BackBufferWidth = FSResX; - yres = pp->BackBufferHeight = FSResY; - pp->SwapEffect = D3DSWAPEFFECT_DISCARD; - pp->Windowed = FALSE; - } - else - { - GetClientRect(hWnd, &client); - xres = pp->BackBufferWidth = client.right - client.left; - yres = pp->BackBufferHeight = client.bottom - client.top; - pp->SwapEffect = D3DSWAPEFFECT_DISCARD; - pp->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - pp->Windowed = TRUE; - } - } - - void Enumerate() - { - numAdapters = D3D::D3D->GetAdapterCount(); - - for (int i=0; iGetAdapterIdentifier(i, 0, &a.ident); - - bool isNvidia = a.ident.VendorId == VENDOR_NVIDIA; - - // Add multisample modes - a.aa_levels.push_back(AALevel("None", D3DMULTISAMPLE_NONE, 0)); - - DWORD qlevels = 0; - if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType( - i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels)) - if (qlevels > 0) - a.aa_levels.push_back(AALevel("2x MSAA", D3DMULTISAMPLE_2_SAMPLES, 0)); - - if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType( - i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels)) - if (qlevels > 0) - a.aa_levels.push_back(AALevel("4x MSAA", D3DMULTISAMPLE_4_SAMPLES, 0)); - - if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType( - i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels)) - if (qlevels > 0) - a.aa_levels.push_back(AALevel("8x MSAA", D3DMULTISAMPLE_8_SAMPLES, 0)); - - if (isNvidia) - { - // CSAA support - if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType( - i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_4_SAMPLES, &qlevels)) - { - if (qlevels > 2) - { - // 8x, 8xQ are available - // See http://developer.nvidia.com/object/coverage-sampled-aa.html - a.aa_levels.push_back(AALevel("8x CSAA", D3DMULTISAMPLE_4_SAMPLES, 2)); - a.aa_levels.push_back(AALevel("8xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 0)); - } - } - if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType( - i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels)) - { - if (qlevels > 2) - { - // 8x, 8xQ are available - // See http://developer.nvidia.com/object/coverage-sampled-aa.html - a.aa_levels.push_back(AALevel("16x CSAA", D3DMULTISAMPLE_4_SAMPLES, 4)); - a.aa_levels.push_back(AALevel("16xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 2)); - } - } - } - - if (a.aa_levels.size() == 1) - { - strcpy(a.aa_levels[0].name, "(Not supported on this device)"); - } - - int numModes = D3D::D3D->GetAdapterModeCount(i, D3DFMT_X8R8G8B8); - - for (int m = 0; m < numModes; m++) - { - D3DDISPLAYMODE mode; - D3D::D3D->EnumAdapterModes(i, D3DFMT_X8R8G8B8, m, &mode); - - int found = -1; - for (int x = 0; x < (int)a.resolutions.size(); x++) - { - if (a.resolutions[x].xres == mode.Width && a.resolutions[x].yres == mode.Height) - { - found = x; - break; - } - } - - Resolution temp; - Resolution &r = found==-1 ? temp : a.resolutions[found]; - - sprintf(r.name, "%ix%i", mode.Width, mode.Height); - r.bitdepths.insert(mode.Format); - r.refreshes.insert(mode.RefreshRate); - if (found == -1 && mode.Width >= 640 && mode.Height >= 480) - { - r.xres = mode.Width; - r.yres = mode.Height; - a.resolutions.push_back(r); - } - } - } - } - - HRESULT Create(int adapter, HWND wnd, bool _fullscreen, int _resolution, int aa_mode) - { - hWnd = wnd; - fullScreen = _fullscreen; - nextFullScreen = _fullscreen; - multisample = aa_mode; - resolution = _resolution; - cur_adapter = adapter; - D3DPRESENT_PARAMETERS d3dpp; - InitPP(adapter, resolution, aa_mode, &d3dpp); - - if( FAILED( D3D->CreateDevice( - adapter, - D3DDEVTYPE_HAL, - wnd, - D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, - // |D3DCREATE_MULTITHREADED /* | D3DCREATE_PUREDEVICE*/, - //D3DCREATE_SOFTWARE_VERTEXPROCESSING , - &d3dpp, &dev ) ) ) - { - MessageBox(wnd, - "Sorry, but it looks like your 3D accelerator is too old,\n" - "or doesn't support features that Dolphin requires.\n" - "Falling back to software vertex processing.\n", - "Dolphin Direct3D plugin", MB_OK | MB_ICONERROR); - if( FAILED( D3D->CreateDevice( - adapter, - D3DDEVTYPE_HAL, - wnd, - D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, - // |D3DCREATE_MULTITHREADED /* | D3DCREATE_PUREDEVICE*/, - //D3DCREATE_SOFTWARE_VERTEXPROCESSING , - &d3dpp, &dev ) ) ) - { - MessageBox(wnd, - "Software VP failed too. Upgrade your graphics card.", - "Dolphin Direct3D plugin", MB_OK | MB_ICONERROR); - return E_FAIL; - } - } - dev->GetDeviceCaps(&caps); - dev->GetRenderTarget(0,&backBuffer); - - Ps.Major = (D3D::caps.PixelShaderVersion >> 8) & 0xFF; - Ps.Minor = (D3D::caps.PixelShaderVersion) & 0xFF; - Vs.Major = (D3D::caps.VertexShaderVersion >>8) & 0xFF; - Vs.Minor = (D3D::caps.VertexShaderVersion) & 0xFF; - - // Device state would normally be set here - return S_OK; - } - - ShaderVersion GetShaderVersion() - { - if (Ps.Major < 2) - { - return PSNONE; - } - - //good enough estimate - we really only - //care about zero shader vs ps20 - return (ShaderVersion)Ps.Major; - } - - void Close() - { - dev->Release(); - dev = 0; - } - - void Shutdown() - { - D3D->Release(); - D3D = 0; - } - - const D3DCAPS9 &GetCaps() - { - return caps; - } - - LPDIRECT3DSURFACE9 GetBackBufferSurface() - { - return backBuffer; - } - - void ShowD3DError(HRESULT err) - { - switch (err) - { - case D3DERR_DEVICELOST: - MessageBox(0, "Device Lost", "D3D ERROR", 0); - break; - case D3DERR_INVALIDCALL: - MessageBox(0, "Invalid Call", "D3D ERROR", 0); - break; - case D3DERR_DRIVERINTERNALERROR: - MessageBox(0, "Driver Internal Error", "D3D ERROR", 0); - break; - case D3DERR_OUTOFVIDEOMEMORY: - MessageBox(0, "Out of vid mem", "D3D ERROR", 0); - break; - default: - // MessageBox(0,"Other error or success","ERROR",0); - break; - } - } - - void Reset() - { - if (dev) - { - D3DPRESENT_PARAMETERS d3dpp; - InitPP(cur_adapter, resolution, multisample, &d3dpp); - HRESULT hr = dev->Reset(&d3dpp); - ShowD3DError(hr); - } - } - - bool IsFullscreen() - { - return fullScreen; - } - - int GetDisplayWidth() - { - return xres; - } - int GetDisplayHeight() - { - return yres; - } - void SwitchFullscreen(bool fullscreen) - { - nextFullScreen = fullscreen; - } - - bool BeginFrame(bool clear, u32 color, float z) - { - if (bFrameInProgress) - { - return false; - } - - bFrameInProgress = true; - - if (dev) - { - if (clear) - dev->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, (DWORD)color, z, 0 ); - dev->BeginScene(); - return true; - } - else - return false; - } - - void EndFrame() - { - if (!bFrameInProgress) - return; - - bFrameInProgress = false; - - if (dev) - { - dev->EndScene(); - dev->Present( NULL, NULL, NULL, NULL ); - } - - if (fullScreen != nextFullScreen) - { - fullScreen = nextFullScreen; - Reset(); - } - } - -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "D3DBase.h" +#include "Render.h" + + +namespace D3D +{ + bool fullScreen = false, nextFullScreen=false; + LPDIRECT3D9 D3D = NULL; // Used to create the D3DDevice + LPDIRECT3DDEVICE9 dev = NULL; // Our rendering device + LPDIRECT3DSURFACE9 backBuffer; + D3DCAPS9 caps; + int multisample; + int resolution; + +#define VENDOR_NVIDIA 4318 + + RECT client; + HWND hWnd; + int xres, yres; + int cur_adapter; + Shader Ps; + Shader Vs; + + bool bFrameInProgress = false; + + //enum shit + Adapter adapters[4]; + int numAdapters; + + void Enumerate(); + + int GetNumAdapters() + { + return numAdapters; + } + + const Adapter &GetAdapter(int i) + { + return adapters[i]; + } + + const Adapter &GetCurAdapter() + { + return adapters[cur_adapter]; + } + + HRESULT Init() + { + // Create the D3D object, which is needed to create the D3DDevice. + if( NULL == ( D3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) + return E_FAIL; + + Enumerate(); + return S_OK; + } + + void EnableAlphaToCoverage() + { + // dev->SetRenderState(D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C')); + Renderer::SetRenderState( D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C') ); + } + + void InitPP(int adapter, int resolution, int aa_mode, D3DPRESENT_PARAMETERS *pp) + { + int FSResX = adapters[adapter].resolutions[resolution].xres; + int FSResY = adapters[adapter].resolutions[resolution].yres; + + ZeroMemory(pp, sizeof(D3DPRESENT_PARAMETERS)); + pp->hDeviceWindow = hWnd; + pp->EnableAutoDepthStencil = TRUE; + pp->AutoDepthStencilFormat = D3DFMT_D24S8; + pp->BackBufferFormat = D3DFMT_A8R8G8B8; + if (aa_mode >= (int)adapters[adapter].aa_levels.size()) + aa_mode = 0; + + pp->MultiSampleType = adapters[adapter].aa_levels[aa_mode].ms_setting; + pp->MultiSampleQuality = adapters[adapter].aa_levels[aa_mode].qual_setting; + pp->Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; + + //D3DPRESENTFLAG_LOCKABLE_BACKBUFFER + + if (fullScreen) + { + xres = pp->BackBufferWidth = FSResX; + yres = pp->BackBufferHeight = FSResY; + pp->SwapEffect = D3DSWAPEFFECT_DISCARD; + pp->Windowed = FALSE; + } + else + { + GetClientRect(hWnd, &client); + xres = pp->BackBufferWidth = client.right - client.left; + yres = pp->BackBufferHeight = client.bottom - client.top; + pp->SwapEffect = D3DSWAPEFFECT_DISCARD; + pp->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + pp->Windowed = TRUE; + } + } + + void Enumerate() + { + numAdapters = D3D::D3D->GetAdapterCount(); + + for (int i=0; iGetAdapterIdentifier(i, 0, &a.ident); + + bool isNvidia = a.ident.VendorId == VENDOR_NVIDIA; + + // Add multisample modes + a.aa_levels.push_back(AALevel("None", D3DMULTISAMPLE_NONE, 0)); + + DWORD qlevels = 0; + if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType( + i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels)) + if (qlevels > 0) + a.aa_levels.push_back(AALevel("2x MSAA", D3DMULTISAMPLE_2_SAMPLES, 0)); + + if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType( + i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels)) + if (qlevels > 0) + a.aa_levels.push_back(AALevel("4x MSAA", D3DMULTISAMPLE_4_SAMPLES, 0)); + + if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType( + i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels)) + if (qlevels > 0) + a.aa_levels.push_back(AALevel("8x MSAA", D3DMULTISAMPLE_8_SAMPLES, 0)); + + if (isNvidia) + { + // CSAA support + if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType( + i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_4_SAMPLES, &qlevels)) + { + if (qlevels > 2) + { + // 8x, 8xQ are available + // See http://developer.nvidia.com/object/coverage-sampled-aa.html + a.aa_levels.push_back(AALevel("8x CSAA", D3DMULTISAMPLE_4_SAMPLES, 2)); + a.aa_levels.push_back(AALevel("8xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 0)); + } + } + if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType( + i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels)) + { + if (qlevels > 2) + { + // 8x, 8xQ are available + // See http://developer.nvidia.com/object/coverage-sampled-aa.html + a.aa_levels.push_back(AALevel("16x CSAA", D3DMULTISAMPLE_4_SAMPLES, 4)); + a.aa_levels.push_back(AALevel("16xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 2)); + } + } + } + + if (a.aa_levels.size() == 1) + { + strcpy(a.aa_levels[0].name, "(Not supported on this device)"); + } + + int numModes = D3D::D3D->GetAdapterModeCount(i, D3DFMT_X8R8G8B8); + + for (int m = 0; m < numModes; m++) + { + D3DDISPLAYMODE mode; + D3D::D3D->EnumAdapterModes(i, D3DFMT_X8R8G8B8, m, &mode); + + int found = -1; + for (int x = 0; x < (int)a.resolutions.size(); x++) + { + if (a.resolutions[x].xres == mode.Width && a.resolutions[x].yres == mode.Height) + { + found = x; + break; + } + } + + Resolution temp; + Resolution &r = found==-1 ? temp : a.resolutions[found]; + + sprintf(r.name, "%ix%i", mode.Width, mode.Height); + r.bitdepths.insert(mode.Format); + r.refreshes.insert(mode.RefreshRate); + if (found == -1 && mode.Width >= 640 && mode.Height >= 480) + { + r.xres = mode.Width; + r.yres = mode.Height; + a.resolutions.push_back(r); + } + } + } + } + + HRESULT Create(int adapter, HWND wnd, bool _fullscreen, int _resolution, int aa_mode) + { + hWnd = wnd; + fullScreen = _fullscreen; + nextFullScreen = _fullscreen; + multisample = aa_mode; + resolution = _resolution; + cur_adapter = adapter; + D3DPRESENT_PARAMETERS d3dpp; + InitPP(adapter, resolution, aa_mode, &d3dpp); + + if( FAILED( D3D->CreateDevice( + adapter, + D3DDEVTYPE_HAL, + wnd, + D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, + // |D3DCREATE_MULTITHREADED /* | D3DCREATE_PUREDEVICE*/, + //D3DCREATE_SOFTWARE_VERTEXPROCESSING , + &d3dpp, &dev ) ) ) + { + MessageBox(wnd, + "Sorry, but it looks like your 3D accelerator is too old,\n" + "or doesn't support features that Dolphin requires.\n" + "Falling back to software vertex processing.\n", + "Dolphin Direct3D plugin", MB_OK | MB_ICONERROR); + if( FAILED( D3D->CreateDevice( + adapter, + D3DDEVTYPE_HAL, + wnd, + D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, + // |D3DCREATE_MULTITHREADED /* | D3DCREATE_PUREDEVICE*/, + //D3DCREATE_SOFTWARE_VERTEXPROCESSING , + &d3dpp, &dev ) ) ) + { + MessageBox(wnd, + "Software VP failed too. Upgrade your graphics card.", + "Dolphin Direct3D plugin", MB_OK | MB_ICONERROR); + return E_FAIL; + } + } + dev->GetDeviceCaps(&caps); + dev->GetRenderTarget(0,&backBuffer); + + Ps.Major = (D3D::caps.PixelShaderVersion >> 8) & 0xFF; + Ps.Minor = (D3D::caps.PixelShaderVersion) & 0xFF; + Vs.Major = (D3D::caps.VertexShaderVersion >>8) & 0xFF; + Vs.Minor = (D3D::caps.VertexShaderVersion) & 0xFF; + + // Device state would normally be set here + return S_OK; + } + + ShaderVersion GetShaderVersion() + { + if (Ps.Major < 2) + { + return PSNONE; + } + + //good enough estimate - we really only + //care about zero shader vs ps20 + return (ShaderVersion)Ps.Major; + } + + void Close() + { + dev->Release(); + dev = 0; + } + + void Shutdown() + { + D3D->Release(); + D3D = 0; + } + + const D3DCAPS9 &GetCaps() + { + return caps; + } + + LPDIRECT3DSURFACE9 GetBackBufferSurface() + { + return backBuffer; + } + + void ShowD3DError(HRESULT err) + { + switch (err) + { + case D3DERR_DEVICELOST: + MessageBox(0, "Device Lost", "D3D ERROR", 0); + break; + case D3DERR_INVALIDCALL: + MessageBox(0, "Invalid Call", "D3D ERROR", 0); + break; + case D3DERR_DRIVERINTERNALERROR: + MessageBox(0, "Driver Internal Error", "D3D ERROR", 0); + break; + case D3DERR_OUTOFVIDEOMEMORY: + MessageBox(0, "Out of vid mem", "D3D ERROR", 0); + break; + default: + // MessageBox(0,"Other error or success","ERROR",0); + break; + } + } + + void Reset() + { + if (dev) + { + D3DPRESENT_PARAMETERS d3dpp; + InitPP(cur_adapter, resolution, multisample, &d3dpp); + HRESULT hr = dev->Reset(&d3dpp); + ShowD3DError(hr); + } + } + + bool IsFullscreen() + { + return fullScreen; + } + + int GetDisplayWidth() + { + return xres; + } + int GetDisplayHeight() + { + return yres; + } + void SwitchFullscreen(bool fullscreen) + { + nextFullScreen = fullscreen; + } + + bool BeginFrame(bool clear, u32 color, float z) + { + if (bFrameInProgress) + { + return false; + } + + bFrameInProgress = true; + + if (dev) + { + if (clear) + dev->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, (DWORD)color, z, 0 ); + dev->BeginScene(); + return true; + } + else + return false; + } + + void EndFrame() + { + if (!bFrameInProgress) + return; + + bFrameInProgress = false; + + if (dev) + { + dev->EndScene(); + dev->Present( NULL, NULL, NULL, NULL ); + } + + if (fullScreen != nextFullScreen) + { + fullScreen = nextFullScreen; + Reset(); + } + } + +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DPostprocess.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DPostprocess.cpp index bda69bbeba..e9f8f2770a 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DPostprocess.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DPostprocess.cpp @@ -1,294 +1,294 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Common.h" - -#include "D3DBase.h" -#include "D3DTexture.h" -#include "D3DUtil.h" - -#include "Config.h" - -#include "Render.h" - -using namespace D3D; - -namespace Postprocess -{ - LPDIRECT3DSURFACE9 displayColorBuffer; - LPDIRECT3DSURFACE9 displayZStencilBuffer; - - LPDIRECT3DTEXTURE9 mainColorBufferTexture; - LPDIRECT3DSURFACE9 mainColorBuffer; - LPDIRECT3DSURFACE9 mainZStencilBuffer; - - const int numScratch = 2; - LPDIRECT3DTEXTURE9 scratch[numScratch]; - LPDIRECT3DSURFACE9 scratchSurface[numScratch]; - - const int mainWidth = 640, mainHeight=480; - const int scratchWidth = 256, scratchHeight=256; - - int displayWidth, displayHeight; - - bool initialized; - - int GetWidth() { - return initialized ? mainWidth : displayWidth; - } - - int GetHeight() { - return initialized ? mainHeight : displayHeight; - } - - - void CreateStuff() - { - mainColorBufferTexture = D3D::CreateRenderTarget(mainWidth,mainHeight); - mainColorBufferTexture->GetSurfaceLevel(0,&mainColorBuffer); - mainZStencilBuffer = D3D::CreateDepthStencilSurface(mainWidth,mainHeight); - - for (int i=0; iGetSurfaceLevel(0,&(scratchSurface[i])); - } - - initialized=true; - } - - void DestroyStuff() - { - SAFE_RELEASE(mainColorBuffer); - SAFE_RELEASE(mainColorBufferTexture); - SAFE_RELEASE(mainZStencilBuffer); - - for (int i=0; iGetRenderTarget(0,&displayColorBuffer); - dev->GetDepthStencilSurface(&displayZStencilBuffer); - - D3DSURFACE_DESC desc; - displayColorBuffer->GetDesc(&desc); - displayWidth = desc.Width; - displayHeight = desc.Height; - - if (g_Config.iPostprocessEffect) - CreateStuff(); - } - - void Cleanup() - { - DestroyStuff(); - SAFE_RELEASE(displayColorBuffer); - SAFE_RELEASE(displayZStencilBuffer); - } - - - void BeginFrame() - { - if (g_Config.iPostprocessEffect) - { - if (!initialized) - CreateStuff(); - dev->SetRenderTarget(0,mainColorBuffer); - dev->SetDepthStencilSurface(mainZStencilBuffer); - - // dev->SetRenderState(D3DRS_ZENABLE,TRUE); - Renderer::SetRenderState( D3DRS_ZENABLE, TRUE ); - - dev->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,0,1,0); - } - else - { - if (initialized) - { - dev->SetRenderTarget(0,displayColorBuffer); - dev->SetDepthStencilSurface(displayZStencilBuffer); - DestroyStuff(); - } - - // dev->SetRenderState(D3DRS_ZENABLE,TRUE); - Renderer::SetRenderState( D3DRS_ZENABLE, TRUE ); - } - } - - - int filterKernel[8] = {0x40,0x80,0xc0,0xFF,0xFF,0xc0,0x80,0x40}; //good looking almost Gaussian - - //int filterKernel[8] = {0xFF,0xc0,0x80,0x40,0x40,0x80,0xc0,0xFF,}; //crazy filter - - void NightGlow(bool intense, bool original) - { - // dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SUBTRACT); - // dev->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE); - // dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE); - // dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE); - Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SUBTRACT ); - Renderer::SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); - Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE ); - Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE ); - - dev->SetDepthStencilSurface(0); - - //dev->SetTexture(0,mainColorBufferTexture); - Renderer::SetTexture( 0, mainColorBufferTexture ); - - dev->SetRenderTarget(0,scratchSurface[0]); - dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_CLAMP); - dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_CLAMP); - dev->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); - dev->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); - dev->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR); - dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0); - - POINT pt; - GetCursorPos(&pt); - - //dev->SetSamplerState(0,D3DSAMP_MIPMAPLODBIAS,1.0f); -#define QOFF(xoff,yoff,col) quad2d(-0.0f,-0.0f,scratchWidth-0.0f,scratchHeight-0.0f,col,0+xoff,0+yoff,1+xoff,1+yoff); - float f=0.008f; - QOFF(0,0,0xa0a0a0a0); - - // dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE); - //dev->SetTexture(0,scratch[0]); - Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); - Renderer::SetTexture( 0, scratch[0] ); - - dev->SetRenderTarget(0,scratchSurface[1]); - dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0); - - float yMul = 1.33333333333f; - for (int i=0; i<8; i++) - { - DWORD c=filterKernel[i]/2; - c|=c<<8; - c|=c<<16; - QOFF(0,(i-3.5f) * f * yMul,c); - } - - //dev->SetTexture(0,scratch[1]); - Renderer::SetTexture( 0, scratch[1] ); - - dev->SetRenderTarget(0,scratchSurface[0]); - dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0); - for (int i=0; i<8; i++) - { - DWORD c=filterKernel[i]/(intense?3:2); - c|=c<<8; - c|=c<<16; - QOFF((i-3.5f) * f,0,c); - } - - // dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE); - Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); - - if (intense) - { - // dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE); - // dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_SRCALPHA); - Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE ); - Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCALPHA ); - } - else - { - // dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_INVDESTCOLOR); - // dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE); - Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR ); - Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE ); - } - - // dev->SetTexture(0,scratch[0]); - Renderer::SetTexture( 0, scratch[0] ); - - dev->SetRenderTarget(0,mainColorBuffer); - quad2d(0,0,(float)mainWidth,(float)mainHeight,original?0xCFFFFFFF:0xFFFFFFFF,0,0,1,1); - - // dev->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE); - Renderer::SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); - - dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_WRAP); - dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_WRAP); - //dev->SetSamplerState(0,D3DSAMP_MIPMAPLODBIAS,0); - } - - const char **GetPostprocessingNames() - { - static const char *names[] = { - "None", - "Night Glow 1", - "Night Glow 2", - "Night Glow 3", - 0, - }; - return names; - } - - void FinalizeFrame() - { - if (initialized) - { - // dev->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE); - // dev->SetRenderState(D3DRS_ZENABLE,FALSE); - // dev->SetRenderState(D3DRS_FOGENABLE,FALSE); - // dev->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE); - // dev->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE); - // dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE); - // dev->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE); - // dev->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE); - // dev->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2); - - Renderer::SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); - Renderer::SetRenderState( D3DRS_ZENABLE, FALSE ); - Renderer::SetRenderState( D3DRS_FOGENABLE, FALSE ); - Renderer::SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE); - Renderer::SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE); - Renderer::SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE); - Renderer::SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE); - Renderer::SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE); - Renderer::SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2); - - switch(g_Config.iPostprocessEffect) { - case 1: - NightGlow(true,true); - case 2: - NightGlow(false,true); - break; - case 3: - NightGlow(false,false); - break; - } - - dev->SetRenderTarget(0,displayColorBuffer); - dev->SetDepthStencilSurface(displayZStencilBuffer); - - // dev->SetTexture(0,mainColorBufferTexture); - Renderer::SetTexture( 0, mainColorBufferTexture ); - - quad2d(0, 0, (float)displayWidth, (float)displayHeight, 0xFFFFFFFF); - } - } -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" + +#include "D3DBase.h" +#include "D3DTexture.h" +#include "D3DUtil.h" + +#include "Config.h" + +#include "Render.h" + +using namespace D3D; + +namespace Postprocess +{ + LPDIRECT3DSURFACE9 displayColorBuffer; + LPDIRECT3DSURFACE9 displayZStencilBuffer; + + LPDIRECT3DTEXTURE9 mainColorBufferTexture; + LPDIRECT3DSURFACE9 mainColorBuffer; + LPDIRECT3DSURFACE9 mainZStencilBuffer; + + const int numScratch = 2; + LPDIRECT3DTEXTURE9 scratch[numScratch]; + LPDIRECT3DSURFACE9 scratchSurface[numScratch]; + + const int mainWidth = 640, mainHeight=480; + const int scratchWidth = 256, scratchHeight=256; + + int displayWidth, displayHeight; + + bool initialized; + + int GetWidth() { + return initialized ? mainWidth : displayWidth; + } + + int GetHeight() { + return initialized ? mainHeight : displayHeight; + } + + + void CreateStuff() + { + mainColorBufferTexture = D3D::CreateRenderTarget(mainWidth,mainHeight); + mainColorBufferTexture->GetSurfaceLevel(0,&mainColorBuffer); + mainZStencilBuffer = D3D::CreateDepthStencilSurface(mainWidth,mainHeight); + + for (int i=0; iGetSurfaceLevel(0,&(scratchSurface[i])); + } + + initialized=true; + } + + void DestroyStuff() + { + SAFE_RELEASE(mainColorBuffer); + SAFE_RELEASE(mainColorBufferTexture); + SAFE_RELEASE(mainZStencilBuffer); + + for (int i=0; iGetRenderTarget(0,&displayColorBuffer); + dev->GetDepthStencilSurface(&displayZStencilBuffer); + + D3DSURFACE_DESC desc; + displayColorBuffer->GetDesc(&desc); + displayWidth = desc.Width; + displayHeight = desc.Height; + + if (g_Config.iPostprocessEffect) + CreateStuff(); + } + + void Cleanup() + { + DestroyStuff(); + SAFE_RELEASE(displayColorBuffer); + SAFE_RELEASE(displayZStencilBuffer); + } + + + void BeginFrame() + { + if (g_Config.iPostprocessEffect) + { + if (!initialized) + CreateStuff(); + dev->SetRenderTarget(0,mainColorBuffer); + dev->SetDepthStencilSurface(mainZStencilBuffer); + + // dev->SetRenderState(D3DRS_ZENABLE,TRUE); + Renderer::SetRenderState( D3DRS_ZENABLE, TRUE ); + + dev->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,0,1,0); + } + else + { + if (initialized) + { + dev->SetRenderTarget(0,displayColorBuffer); + dev->SetDepthStencilSurface(displayZStencilBuffer); + DestroyStuff(); + } + + // dev->SetRenderState(D3DRS_ZENABLE,TRUE); + Renderer::SetRenderState( D3DRS_ZENABLE, TRUE ); + } + } + + + int filterKernel[8] = {0x40,0x80,0xc0,0xFF,0xFF,0xc0,0x80,0x40}; //good looking almost Gaussian + + //int filterKernel[8] = {0xFF,0xc0,0x80,0x40,0x40,0x80,0xc0,0xFF,}; //crazy filter + + void NightGlow(bool intense, bool original) + { + // dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SUBTRACT); + // dev->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE); + // dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE); + // dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE); + Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SUBTRACT ); + Renderer::SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); + Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE ); + Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE ); + + dev->SetDepthStencilSurface(0); + + //dev->SetTexture(0,mainColorBufferTexture); + Renderer::SetTexture( 0, mainColorBufferTexture ); + + dev->SetRenderTarget(0,scratchSurface[0]); + dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_CLAMP); + dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_CLAMP); + dev->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); + dev->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); + dev->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR); + dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0); + + POINT pt; + GetCursorPos(&pt); + + //dev->SetSamplerState(0,D3DSAMP_MIPMAPLODBIAS,1.0f); +#define QOFF(xoff,yoff,col) quad2d(-0.0f,-0.0f,scratchWidth-0.0f,scratchHeight-0.0f,col,0+xoff,0+yoff,1+xoff,1+yoff); + float f=0.008f; + QOFF(0,0,0xa0a0a0a0); + + // dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE); + //dev->SetTexture(0,scratch[0]); + Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); + Renderer::SetTexture( 0, scratch[0] ); + + dev->SetRenderTarget(0,scratchSurface[1]); + dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0); + + float yMul = 1.33333333333f; + for (int i=0; i<8; i++) + { + DWORD c=filterKernel[i]/2; + c|=c<<8; + c|=c<<16; + QOFF(0,(i-3.5f) * f * yMul,c); + } + + //dev->SetTexture(0,scratch[1]); + Renderer::SetTexture( 0, scratch[1] ); + + dev->SetRenderTarget(0,scratchSurface[0]); + dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0); + for (int i=0; i<8; i++) + { + DWORD c=filterKernel[i]/(intense?3:2); + c|=c<<8; + c|=c<<16; + QOFF((i-3.5f) * f,0,c); + } + + // dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE); + Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); + + if (intense) + { + // dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE); + // dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_SRCALPHA); + Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE ); + Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCALPHA ); + } + else + { + // dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_INVDESTCOLOR); + // dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE); + Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR ); + Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE ); + } + + // dev->SetTexture(0,scratch[0]); + Renderer::SetTexture( 0, scratch[0] ); + + dev->SetRenderTarget(0,mainColorBuffer); + quad2d(0,0,(float)mainWidth,(float)mainHeight,original?0xCFFFFFFF:0xFFFFFFFF,0,0,1,1); + + // dev->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE); + Renderer::SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); + + dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_WRAP); + dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_WRAP); + //dev->SetSamplerState(0,D3DSAMP_MIPMAPLODBIAS,0); + } + + const char **GetPostprocessingNames() + { + static const char *names[] = { + "None", + "Night Glow 1", + "Night Glow 2", + "Night Glow 3", + 0, + }; + return names; + } + + void FinalizeFrame() + { + if (initialized) + { + // dev->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE); + // dev->SetRenderState(D3DRS_ZENABLE,FALSE); + // dev->SetRenderState(D3DRS_FOGENABLE,FALSE); + // dev->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE); + // dev->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE); + // dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE); + // dev->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE); + // dev->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE); + // dev->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2); + + Renderer::SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); + Renderer::SetRenderState( D3DRS_ZENABLE, FALSE ); + Renderer::SetRenderState( D3DRS_FOGENABLE, FALSE ); + Renderer::SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE); + Renderer::SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE); + Renderer::SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE); + Renderer::SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE); + Renderer::SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE); + Renderer::SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2); + + switch(g_Config.iPostprocessEffect) { + case 1: + NightGlow(true,true); + case 2: + NightGlow(false,true); + break; + case 3: + NightGlow(false,false); + break; + } + + dev->SetRenderTarget(0,displayColorBuffer); + dev->SetDepthStencilSurface(displayZStencilBuffer); + + // dev->SetTexture(0,mainColorBufferTexture); + Renderer::SetTexture( 0, mainColorBufferTexture ); + + quad2d(0, 0, (float)displayWidth, (float)displayHeight, 0xFFFFFFFF); + } + } +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp index 172f02dac2..25efbfd8da 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp @@ -1,108 +1,108 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include -#include - -#include "Config.h" -#include "D3DShader.h" - - -namespace D3D -{ - LPDIRECT3DVERTEXSHADER9 CompileVShader(const char *code, int len) - { - //try to compile - LPD3DXBUFFER shaderBuffer = 0, errorBuffer = 0; - LPDIRECT3DVERTEXSHADER9 vShader = 0; - HRESULT hr = D3DXCompileShader(code,len,0,0,"main","vs_1_1",0,&shaderBuffer,&errorBuffer,0); - if (FAILED(hr)) - { - //let's try 2.0 - hr = D3DXCompileShader(code,len,0,0,"main","vs_2_0",0,&shaderBuffer,&errorBuffer,0); - } - - if (FAILED(hr)) - { - //compilation error - std::string hello = (char*)errorBuffer->GetBufferPointer(); - hello += "\n\n"; - hello += code; - if (g_Config.bShowShaderErrors) - MessageBox(0, hello.c_str(), "Error compiling vertex shader", MB_ICONERROR); - vShader = 0; - } - else if (SUCCEEDED(hr)) - { - //create it - HRESULT hr = E_FAIL; - if (shaderBuffer) - hr = D3D::dev->CreateVertexShader((DWORD *)shaderBuffer->GetBufferPointer(), &vShader); - if (FAILED(hr) || vShader == 0) - { - if (g_Config.bShowShaderErrors) - MessageBox(0,code,(char*)errorBuffer->GetBufferPointer(),MB_ICONERROR); - } - } - - //cleanup - if (shaderBuffer) - shaderBuffer->Release(); - if (errorBuffer) - errorBuffer->Release(); - - return vShader; - } - - LPDIRECT3DPIXELSHADER9 CompilePShader(const char *code, int len) - { - LPD3DXBUFFER shaderBuffer = 0, errorBuffer = 0; - LPDIRECT3DPIXELSHADER9 pShader = 0; - static char *versions[6] = {"ERROR","ps_1_1","ps_1_4","ps_2_0","ps_3_0","ps_4_0"}; - HRESULT hr = D3DXCompileShader(code,len,0,0, - "main","ps_2_0", // Pixel Shader 2.0 is enough for all we do - 0,&shaderBuffer,&errorBuffer,0); - - if (FAILED(hr)) - { - std::string hello = (char*)errorBuffer->GetBufferPointer(); - hello += "\n\n"; - hello += code; - if (g_Config.bShowShaderErrors) - MessageBox(0, hello.c_str(), "Error compiling pixel shader", MB_ICONERROR); - pShader = 0; - } - else - { - //create it - HRESULT hr = D3D::dev->CreatePixelShader((DWORD *)shaderBuffer->GetBufferPointer(), &pShader); - if (FAILED(hr) || pShader == 0) - { - if (g_Config.bShowShaderErrors) - MessageBox(0,"damn","error creating pixelshader",MB_ICONERROR); - } - } - - //cleanup - if (shaderBuffer) - shaderBuffer->Release(); - if (errorBuffer) - errorBuffer->Release(); - - return pShader; - } -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include +#include + +#include "Config.h" +#include "D3DShader.h" + + +namespace D3D +{ + LPDIRECT3DVERTEXSHADER9 CompileVShader(const char *code, int len) + { + //try to compile + LPD3DXBUFFER shaderBuffer = 0, errorBuffer = 0; + LPDIRECT3DVERTEXSHADER9 vShader = 0; + HRESULT hr = D3DXCompileShader(code,len,0,0,"main","vs_1_1",0,&shaderBuffer,&errorBuffer,0); + if (FAILED(hr)) + { + //let's try 2.0 + hr = D3DXCompileShader(code,len,0,0,"main","vs_2_0",0,&shaderBuffer,&errorBuffer,0); + } + + if (FAILED(hr)) + { + //compilation error + std::string hello = (char*)errorBuffer->GetBufferPointer(); + hello += "\n\n"; + hello += code; + if (g_Config.bShowShaderErrors) + MessageBox(0, hello.c_str(), "Error compiling vertex shader", MB_ICONERROR); + vShader = 0; + } + else if (SUCCEEDED(hr)) + { + //create it + HRESULT hr = E_FAIL; + if (shaderBuffer) + hr = D3D::dev->CreateVertexShader((DWORD *)shaderBuffer->GetBufferPointer(), &vShader); + if (FAILED(hr) || vShader == 0) + { + if (g_Config.bShowShaderErrors) + MessageBox(0,code,(char*)errorBuffer->GetBufferPointer(),MB_ICONERROR); + } + } + + //cleanup + if (shaderBuffer) + shaderBuffer->Release(); + if (errorBuffer) + errorBuffer->Release(); + + return vShader; + } + + LPDIRECT3DPIXELSHADER9 CompilePShader(const char *code, int len) + { + LPD3DXBUFFER shaderBuffer = 0, errorBuffer = 0; + LPDIRECT3DPIXELSHADER9 pShader = 0; + static char *versions[6] = {"ERROR","ps_1_1","ps_1_4","ps_2_0","ps_3_0","ps_4_0"}; + HRESULT hr = D3DXCompileShader(code,len,0,0, + "main","ps_2_0", // Pixel Shader 2.0 is enough for all we do + 0,&shaderBuffer,&errorBuffer,0); + + if (FAILED(hr)) + { + std::string hello = (char*)errorBuffer->GetBufferPointer(); + hello += "\n\n"; + hello += code; + if (g_Config.bShowShaderErrors) + MessageBox(0, hello.c_str(), "Error compiling pixel shader", MB_ICONERROR); + pShader = 0; + } + else + { + //create it + HRESULT hr = D3D::dev->CreatePixelShader((DWORD *)shaderBuffer->GetBufferPointer(), &pShader); + if (FAILED(hr) || pShader == 0) + { + if (g_Config.bShowShaderErrors) + MessageBox(0,"damn","error creating pixelshader",MB_ICONERROR); + } + } + + //cleanup + if (shaderBuffer) + shaderBuffer->Release(); + if (errorBuffer) + errorBuffer->Release(); + + return pShader; + } +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DTexture.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DTexture.cpp index 38e376be5c..d78cde6b35 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DTexture.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DTexture.cpp @@ -1,115 +1,115 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "D3DBase.h" -#include "D3DTexture.h" - -namespace D3D -{ - LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height,const int pitch, D3DFORMAT fmt) - { - u32* pBuffer = (u32*)buffer; - LPDIRECT3DTEXTURE9 pTexture; - - // crazy bitmagic - bool isPow2 = !((width&(width-1)) || (height&(height-1))); - - HRESULT hr; - // TODO(ector): allow mipmaps for non-pow textures on newer cards? - if (!isPow2) - hr = dev->CreateTexture(width, height, 1, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL); - else - hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL); - - if(FAILED(hr)) - return 0; - - int level = 0; - - D3DLOCKED_RECT Lock; - pTexture->LockRect(level, &Lock, NULL, 0 ); - - u32* pIn = pBuffer; - switch(fmt) - { - case D3DFMT_A8R8G8B8: - { - for (int y = 0; y < height; y++) - { - u32* pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch)); - memcpy(pBits, pIn, width * 4); - pIn += pitch; - } - } - break; - case D3DFMT_DXT1: - memcpy(Lock.pBits,buffer,(width/4)*(height/4)*8); - break; - } - pTexture->UnlockRect(level); - return pTexture; - } - - void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height,const int pitch, D3DFORMAT fmt) - { - u32* pBuffer = (u32*)buffer; - int level = 0; - D3DLOCKED_RECT Lock; - pTexture->LockRect(level, &Lock, NULL, 0 ); - u32* pIn = pBuffer; - switch(fmt) - { - case D3DFMT_A8R8G8B8: - { - for (int y = 0; y < height; y++) - { - u32* pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch)); - memcpy(pBits,pIn, width*4); - pIn += pitch; - } - } - break; - case D3DFMT_DXT1: - memcpy(Lock.pBits,buffer,(width/4)*(height/4)*8); - break; - } - pTexture->UnlockRect(level); - } - - LPDIRECT3DTEXTURE9 CreateRenderTarget(const int width, const int height) - { - LPDIRECT3DTEXTURE9 tex; - HRESULT hr = dev->CreateTexture(width,height,0,D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,&tex,NULL); - - if (FAILED(hr)) - return 0; - else - return tex; - } - - LPDIRECT3DSURFACE9 CreateDepthStencilSurface(const int width, const int height) - { - LPDIRECT3DSURFACE9 surf; - HRESULT hr = dev->CreateDepthStencilSurface(width,height,D3DFMT_D24S8,D3DMULTISAMPLE_NONE,0,0,&surf,0); - - if (FAILED(hr)) - return 0; - else - return surf; - - } -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "D3DBase.h" +#include "D3DTexture.h" + +namespace D3D +{ + LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height,const int pitch, D3DFORMAT fmt) + { + u32* pBuffer = (u32*)buffer; + LPDIRECT3DTEXTURE9 pTexture; + + // crazy bitmagic + bool isPow2 = !((width&(width-1)) || (height&(height-1))); + + HRESULT hr; + // TODO(ector): allow mipmaps for non-pow textures on newer cards? + if (!isPow2) + hr = dev->CreateTexture(width, height, 1, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL); + else + hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL); + + if(FAILED(hr)) + return 0; + + int level = 0; + + D3DLOCKED_RECT Lock; + pTexture->LockRect(level, &Lock, NULL, 0 ); + + u32* pIn = pBuffer; + switch(fmt) + { + case D3DFMT_A8R8G8B8: + { + for (int y = 0; y < height; y++) + { + u32* pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch)); + memcpy(pBits, pIn, width * 4); + pIn += pitch; + } + } + break; + case D3DFMT_DXT1: + memcpy(Lock.pBits,buffer,(width/4)*(height/4)*8); + break; + } + pTexture->UnlockRect(level); + return pTexture; + } + + void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height,const int pitch, D3DFORMAT fmt) + { + u32* pBuffer = (u32*)buffer; + int level = 0; + D3DLOCKED_RECT Lock; + pTexture->LockRect(level, &Lock, NULL, 0 ); + u32* pIn = pBuffer; + switch(fmt) + { + case D3DFMT_A8R8G8B8: + { + for (int y = 0; y < height; y++) + { + u32* pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch)); + memcpy(pBits,pIn, width*4); + pIn += pitch; + } + } + break; + case D3DFMT_DXT1: + memcpy(Lock.pBits,buffer,(width/4)*(height/4)*8); + break; + } + pTexture->UnlockRect(level); + } + + LPDIRECT3DTEXTURE9 CreateRenderTarget(const int width, const int height) + { + LPDIRECT3DTEXTURE9 tex; + HRESULT hr = dev->CreateTexture(width,height,0,D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,&tex,NULL); + + if (FAILED(hr)) + return 0; + else + return tex; + } + + LPDIRECT3DSURFACE9 CreateDepthStencilSurface(const int width, const int height) + { + LPDIRECT3DSURFACE9 surf; + HRESULT hr = dev->CreateDepthStencilSurface(width,height,D3DFMT_D24S8,D3DMULTISAMPLE_NONE,0,0,&surf,0); + + if (FAILED(hr)) + return 0; + else + return surf; + + } +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp index 0d16f21b4f..1c80eaae42 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp @@ -1,397 +1,397 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Common.h" - -#include "D3DBase.h" -#include "D3DUtil.h" -#include "Render.h" - -namespace D3D -{ - CD3DFont font; - -#define MAX_NUM_VERTICES 50*6 - struct FONT2DVERTEX { - float x,y,z; - float rhw; - u32 color; - float tu, tv; - }; - -#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1) -#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL|D3DFVF_TEX1) - - inline FONT2DVERTEX InitFont2DVertex( float x, float y, u32 color, float tu, float tv ) - { - FONT2DVERTEX v; v.x=x; v.y=y; v.z=0; v.rhw=1.0f; v.color = color; v.tu = tu; v.tv = tv; - return v; - } - - CD3DFont::CD3DFont() - { - m_pTexture = NULL; - m_pVB = NULL; - } - enum {m_dwTexWidth = 512, m_dwTexHeight = 512}; - - int CD3DFont::Init() - { - int hr; - m_fTextScale = 1.0f; // Draw fonts into texture without scaling - // Create a new texture for the font - hr = dev->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &m_pTexture, NULL ); - if( FAILED(hr) ) - return hr; - - // Prepare to create a bitmap - int *pBitmapBits; - BITMAPINFO bmi; - ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) ); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = (int)m_dwTexWidth; - bmi.bmiHeader.biHeight = -(int)m_dwTexHeight; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biBitCount = 32; - - // Create a DC and a bitmap for the font - HDC hDC = CreateCompatibleDC( NULL ); - HBITMAP hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS, - (VOID**)&pBitmapBits, NULL, 0 ); - SetMapMode( hDC, MM_TEXT ); - - // Create a font. By specifying ANTIALIASED_QUALITY, we might get an - // antialiased font, but this is not guaranteed. - // We definitely don't want to get it cleartype'd, anyway. - int m_dwFontHeight = 36; - - int nHeight = -MulDiv( m_dwFontHeight, int(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 ); - int dwBold = FW_NORMAL; ///FW_BOLD - HFONT hFont = CreateFont( nHeight, 0, 0, 0, dwBold, 0, - FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, - CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, - VARIABLE_PITCH, "Tahoma"); - - if (NULL == hFont) - return E_FAIL; - - HGDIOBJ hOldbmBitmap = SelectObject( hDC, hbmBitmap ); - HGDIOBJ hOldFont = SelectObject( hDC, hFont ); - - // Set text properties - SetTextColor( hDC, 0xFFFFFF ); - SetBkColor ( hDC, 0 ); - SetTextAlign( hDC, TA_TOP ); - - // Loop through all printable character and output them to the bitmap.. - // Meanwhile, keep track of the corresponding tex coords for each character. - int x = 0, y = 0; - - char str[2] = "\0"; - SIZE size; - - for( char c=0; c<127-32; c++ ) - { - str[0] = c+32; - GetTextExtentPoint32( hDC, str, 1, &size ); - - if( (int)(x+size.cx+1) > m_dwTexWidth ) - { - x = 0; - y += size.cy+1; - } - - ExtTextOut( hDC, x+1, y+0, ETO_OPAQUE | ETO_CLIPPED, NULL, str, 1, NULL ); - - m_fTexCoords[c][0] = ((float)(x+0))/m_dwTexWidth; - m_fTexCoords[c][1] = ((float)(y+0))/m_dwTexHeight; - m_fTexCoords[c][2] = ((float)(x+0+size.cx))/m_dwTexWidth; - m_fTexCoords[c][3] = ((float)(y+0+size.cy))/m_dwTexHeight; - - x += size.cx+3; //3 to avoid annoying ij conflict (part of the j ends up with the i) - } - - // Lock the surface and write the alpha values for the set pixels - D3DLOCKED_RECT d3dlr; - m_pTexture->LockRect( 0, &d3dlr, 0, 0 ); - unsigned short* pDst16 = (unsigned short*)d3dlr.pBits; - int bAlpha; // 4-bit measure of pixel intensity - - for( y=0; y < m_dwTexHeight; y++ ) - { - for( x=0; x < m_dwTexWidth; x++ ) - { - bAlpha = ((pBitmapBits[m_dwTexWidth*y + x] & 0xff) >> 4); - *pDst16++ = (bAlpha << 12) | 0x0fff; - } - } - - // Done updating texture, so clean up used objects - m_pTexture->UnlockRect(0); - - SelectObject( hDC, hOldbmBitmap ); - DeleteObject( hbmBitmap ); - - SelectObject( hDC, hOldFont ); - DeleteObject( hFont ); - - // Create vertex buffer for the letters - if( FAILED( hr = dev->CreateVertexBuffer( MAX_NUM_VERTICES*sizeof(FONT2DVERTEX), - D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, - D3DPOOL_DEFAULT, &m_pVB,NULL ) ) ) - { - return hr; - } - - return S_OK; - } - - int CD3DFont::Shutdown() - { - SAFE_RELEASE( m_pVB ); - SAFE_RELEASE( m_pTexture ); - - return S_OK; - } - - - const int RS[6][2] = - { - { D3DRS_ALPHABLENDENABLE, TRUE }, - { D3DRS_SRCBLEND, D3DBLEND_SRCALPHA }, - { D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA }, - { D3DRS_CULLMODE, D3DCULL_NONE }, - { D3DRS_ZENABLE, FALSE }, - { D3DRS_FOGENABLE, FALSE }, - }; - const int TS[6][2] = - { - {D3DTSS_COLOROP, D3DTOP_MODULATE}, - {D3DTSS_COLORARG1, D3DTA_TEXTURE}, - {D3DTSS_COLORARG2, D3DTA_DIFFUSE }, - {D3DTSS_ALPHAOP, D3DTOP_MODULATE }, - {D3DTSS_ALPHAARG1, D3DTA_TEXTURE }, - {D3DTSS_ALPHAARG2, D3DTA_DIFFUSE }, - }; - - static DWORD RS_old[6]; - static DWORD TS_old[6]; - static LPDIRECT3DBASETEXTURE9 texture_old; - static DWORD FVF_old; - static LPDIRECT3DVERTEXDECLARATION9 decl_old; - static LPDIRECT3DPIXELSHADER9 ps_old; - static LPDIRECT3DVERTEXSHADER9 vs_old; - - void SaveRenderStates() - { - for (int i = 0; i < 6; i++) { - dev->GetRenderState((_D3DRENDERSTATETYPE)RS[i][0], &(RS_old[i])); - dev->GetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), &(TS_old[i])); - } - dev->GetTexture(0, &texture_old); - dev->GetPixelShader(&ps_old); - dev->GetVertexShader(&vs_old); - dev->GetVertexDeclaration(&decl_old); - dev->GetFVF(&FVF_old); - } - - void CD3DFont::SetRenderStates() - { - // dev->SetTexture(0, m_pTexture); - Renderer::SetTexture( 0, m_pTexture ); - - dev->SetPixelShader(0); - dev->SetVertexShader(0); - dev->SetVertexDeclaration(0); - - // dev->SetFVF(D3DFVF_FONT2DVERTEX); - Renderer::SetFVF(D3DFVF_FONT2DVERTEX); - - for (int i = 0; i < 6; i++) { - // dev->SetRenderState((_D3DRENDERSTATETYPE)RS[i][0],RS[i][1]); - // dev->SetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1]); - - Renderer::SetRenderState( (_D3DRENDERSTATETYPE)RS[i][0], RS[i][1] ); - Renderer::SetTextureStageState( 0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1] ); - } - } - - void RestoreRenderStates() - { - // dev->SetTexture(0, texture_old); - Renderer::SetTexture( 0, texture_old ); - - dev->SetPixelShader(ps_old); - dev->SetVertexShader(vs_old); - dev->SetVertexDeclaration(decl_old); - - // dev->SetFVF(FVF_old); - Renderer::SetFVF(FVF_old); - - for (int i = 0; i < 6; i++) - { - // dev->SetRenderState((_D3DRENDERSTATETYPE)RS[i][0], RS_old[i]); - // dev->SetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS_old[i]); - - Renderer::SetRenderState( (_D3DRENDERSTATETYPE)RS[i][0], RS_old[i] ); - Renderer::SetTextureStageState( 0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS_old[i] ); - } - } - - int CD3DFont::DrawTextScaled( float x, float y, float fXScale, float fYScale, float spacing, u32 dwColor, const char* strText, bool center ) - { - SaveRenderStates(); - SetRenderStates(); - dev->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) ); - - float vpWidth = 1; - float vpHeight = 1; - - float sx = x*vpWidth-0.5f; - float sy = y*vpHeight-0.5f; - - float fStartX = sx; - - float invLineHeight = 1.0f / (( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight); - // Fill vertex buffer - FONT2DVERTEX* pVertices; - int dwNumTriangles = 0L; - m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); - - const char *oldstrText=strText; - //First, let's measure the text - float tw=0; - float mx=0; - float maxx=0; - - while( *strText ) - { - char c = *strText++; - - if( c == ('\n') ) - mx=0; - if( c < (' ') ) - continue; - - float tx1 = m_fTexCoords[c-32][0]; - float tx2 = m_fTexCoords[c-32][2]; - - float w = (tx2-tx1)*m_dwTexWidth; - w *= (fXScale*vpHeight)*invLineHeight; - mx += w + spacing*fXScale*vpWidth; - if (mx>maxx) maxx=mx; - } - - float offset=-maxx/2; - strText = oldstrText; - //Then let's draw it - if (center) - { - sx+=offset; - fStartX+=offset; - } - - float wScale=(fXScale*vpHeight)*invLineHeight; - float hScale=(fYScale*vpHeight)*invLineHeight; - - while( *strText ) - { - char c = *strText++; - - if( c == ('\n') ) - { - sx = fStartX; - sy += fYScale*vpHeight; - } - if( c < (' ') ) - continue; - - c-=32; - float tx1 = m_fTexCoords[c][0]; - float ty1 = m_fTexCoords[c][1]; - float tx2 = m_fTexCoords[c][2]; - float ty2 = m_fTexCoords[c][3]; - - float w = (tx2-tx1)*m_dwTexWidth; - float h = (ty2-ty1)*m_dwTexHeight; - - w *= wScale; - h *= hScale; - - - FONT2DVERTEX v[6]; - v[0]=InitFont2DVertex(sx, sy+h, dwColor, tx1, ty2); - v[1]=InitFont2DVertex(sx, sy, dwColor, tx1, ty1); - v[2]=InitFont2DVertex(sx+w, sy+h, dwColor, tx2, ty2); - v[3]=InitFont2DVertex(sx+w, sy, dwColor, tx2, ty1); - v[4]=v[2]; - v[5]=v[1]; - - memcpy(pVertices,v,6*sizeof(FONT2DVERTEX)); - - pVertices+=6; - dwNumTriangles += 2; - - if( dwNumTriangles * 3 > (MAX_NUM_VERTICES-6) ) - { - // Unlock, render, and relock the vertex buffer - m_pVB->Unlock(); - - // dev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); - Renderer::DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); - - m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); - dwNumTriangles = 0; - } - - sx += w + spacing*fXScale*vpWidth; - } - - // Unlock and render the vertex buffer - m_pVB->Unlock(); - if( dwNumTriangles > 0 ) - { - // dev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); - Renderer::DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); - } - RestoreRenderStates(); - return S_OK; - } - - void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1, float v1, float u2, float v2) - { - SaveRenderStates(); - struct Q2DVertex { float x,y,z,rhw; u32 color; float u, v; } coords[4] = { - {x1-0.5f, y1-0.5f, 0, 1, color, u1, v1}, - {x2-0.5f, y1-0.5f, 0, 1, color, u2, v1}, - {x2-0.5f, y2-0.5f, 0, 1, color, u2, v2}, - {x1-0.5f, y2-0.5f, 0, 1, color, u1, v2}, - }; - dev->SetPixelShader(0); - dev->SetVertexShader(0); - dev->SetVertexDeclaration(0); - - // dev->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1); - // dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,coords,sizeof(Q2DVertex)); - Renderer::SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1); - Renderer::DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,coords,sizeof(Q2DVertex)); - - RestoreRenderStates(); - } - -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" + +#include "D3DBase.h" +#include "D3DUtil.h" +#include "Render.h" + +namespace D3D +{ + CD3DFont font; + +#define MAX_NUM_VERTICES 50*6 + struct FONT2DVERTEX { + float x,y,z; + float rhw; + u32 color; + float tu, tv; + }; + +#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1) +#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL|D3DFVF_TEX1) + + inline FONT2DVERTEX InitFont2DVertex( float x, float y, u32 color, float tu, float tv ) + { + FONT2DVERTEX v; v.x=x; v.y=y; v.z=0; v.rhw=1.0f; v.color = color; v.tu = tu; v.tv = tv; + return v; + } + + CD3DFont::CD3DFont() + { + m_pTexture = NULL; + m_pVB = NULL; + } + enum {m_dwTexWidth = 512, m_dwTexHeight = 512}; + + int CD3DFont::Init() + { + int hr; + m_fTextScale = 1.0f; // Draw fonts into texture without scaling + // Create a new texture for the font + hr = dev->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &m_pTexture, NULL ); + if( FAILED(hr) ) + return hr; + + // Prepare to create a bitmap + int *pBitmapBits; + BITMAPINFO bmi; + ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) ); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = (int)m_dwTexWidth; + bmi.bmiHeader.biHeight = -(int)m_dwTexHeight; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biBitCount = 32; + + // Create a DC and a bitmap for the font + HDC hDC = CreateCompatibleDC( NULL ); + HBITMAP hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS, + (VOID**)&pBitmapBits, NULL, 0 ); + SetMapMode( hDC, MM_TEXT ); + + // Create a font. By specifying ANTIALIASED_QUALITY, we might get an + // antialiased font, but this is not guaranteed. + // We definitely don't want to get it cleartype'd, anyway. + int m_dwFontHeight = 36; + + int nHeight = -MulDiv( m_dwFontHeight, int(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 ); + int dwBold = FW_NORMAL; ///FW_BOLD + HFONT hFont = CreateFont( nHeight, 0, 0, 0, dwBold, 0, + FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, + VARIABLE_PITCH, "Tahoma"); + + if (NULL == hFont) + return E_FAIL; + + HGDIOBJ hOldbmBitmap = SelectObject( hDC, hbmBitmap ); + HGDIOBJ hOldFont = SelectObject( hDC, hFont ); + + // Set text properties + SetTextColor( hDC, 0xFFFFFF ); + SetBkColor ( hDC, 0 ); + SetTextAlign( hDC, TA_TOP ); + + // Loop through all printable character and output them to the bitmap.. + // Meanwhile, keep track of the corresponding tex coords for each character. + int x = 0, y = 0; + + char str[2] = "\0"; + SIZE size; + + for( char c=0; c<127-32; c++ ) + { + str[0] = c+32; + GetTextExtentPoint32( hDC, str, 1, &size ); + + if( (int)(x+size.cx+1) > m_dwTexWidth ) + { + x = 0; + y += size.cy+1; + } + + ExtTextOut( hDC, x+1, y+0, ETO_OPAQUE | ETO_CLIPPED, NULL, str, 1, NULL ); + + m_fTexCoords[c][0] = ((float)(x+0))/m_dwTexWidth; + m_fTexCoords[c][1] = ((float)(y+0))/m_dwTexHeight; + m_fTexCoords[c][2] = ((float)(x+0+size.cx))/m_dwTexWidth; + m_fTexCoords[c][3] = ((float)(y+0+size.cy))/m_dwTexHeight; + + x += size.cx+3; //3 to avoid annoying ij conflict (part of the j ends up with the i) + } + + // Lock the surface and write the alpha values for the set pixels + D3DLOCKED_RECT d3dlr; + m_pTexture->LockRect( 0, &d3dlr, 0, 0 ); + unsigned short* pDst16 = (unsigned short*)d3dlr.pBits; + int bAlpha; // 4-bit measure of pixel intensity + + for( y=0; y < m_dwTexHeight; y++ ) + { + for( x=0; x < m_dwTexWidth; x++ ) + { + bAlpha = ((pBitmapBits[m_dwTexWidth*y + x] & 0xff) >> 4); + *pDst16++ = (bAlpha << 12) | 0x0fff; + } + } + + // Done updating texture, so clean up used objects + m_pTexture->UnlockRect(0); + + SelectObject( hDC, hOldbmBitmap ); + DeleteObject( hbmBitmap ); + + SelectObject( hDC, hOldFont ); + DeleteObject( hFont ); + + // Create vertex buffer for the letters + if( FAILED( hr = dev->CreateVertexBuffer( MAX_NUM_VERTICES*sizeof(FONT2DVERTEX), + D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, + D3DPOOL_DEFAULT, &m_pVB,NULL ) ) ) + { + return hr; + } + + return S_OK; + } + + int CD3DFont::Shutdown() + { + SAFE_RELEASE( m_pVB ); + SAFE_RELEASE( m_pTexture ); + + return S_OK; + } + + + const int RS[6][2] = + { + { D3DRS_ALPHABLENDENABLE, TRUE }, + { D3DRS_SRCBLEND, D3DBLEND_SRCALPHA }, + { D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA }, + { D3DRS_CULLMODE, D3DCULL_NONE }, + { D3DRS_ZENABLE, FALSE }, + { D3DRS_FOGENABLE, FALSE }, + }; + const int TS[6][2] = + { + {D3DTSS_COLOROP, D3DTOP_MODULATE}, + {D3DTSS_COLORARG1, D3DTA_TEXTURE}, + {D3DTSS_COLORARG2, D3DTA_DIFFUSE }, + {D3DTSS_ALPHAOP, D3DTOP_MODULATE }, + {D3DTSS_ALPHAARG1, D3DTA_TEXTURE }, + {D3DTSS_ALPHAARG2, D3DTA_DIFFUSE }, + }; + + static DWORD RS_old[6]; + static DWORD TS_old[6]; + static LPDIRECT3DBASETEXTURE9 texture_old; + static DWORD FVF_old; + static LPDIRECT3DVERTEXDECLARATION9 decl_old; + static LPDIRECT3DPIXELSHADER9 ps_old; + static LPDIRECT3DVERTEXSHADER9 vs_old; + + void SaveRenderStates() + { + for (int i = 0; i < 6; i++) { + dev->GetRenderState((_D3DRENDERSTATETYPE)RS[i][0], &(RS_old[i])); + dev->GetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), &(TS_old[i])); + } + dev->GetTexture(0, &texture_old); + dev->GetPixelShader(&ps_old); + dev->GetVertexShader(&vs_old); + dev->GetVertexDeclaration(&decl_old); + dev->GetFVF(&FVF_old); + } + + void CD3DFont::SetRenderStates() + { + // dev->SetTexture(0, m_pTexture); + Renderer::SetTexture( 0, m_pTexture ); + + dev->SetPixelShader(0); + dev->SetVertexShader(0); + dev->SetVertexDeclaration(0); + + // dev->SetFVF(D3DFVF_FONT2DVERTEX); + Renderer::SetFVF(D3DFVF_FONT2DVERTEX); + + for (int i = 0; i < 6; i++) { + // dev->SetRenderState((_D3DRENDERSTATETYPE)RS[i][0],RS[i][1]); + // dev->SetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1]); + + Renderer::SetRenderState( (_D3DRENDERSTATETYPE)RS[i][0], RS[i][1] ); + Renderer::SetTextureStageState( 0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1] ); + } + } + + void RestoreRenderStates() + { + // dev->SetTexture(0, texture_old); + Renderer::SetTexture( 0, texture_old ); + + dev->SetPixelShader(ps_old); + dev->SetVertexShader(vs_old); + dev->SetVertexDeclaration(decl_old); + + // dev->SetFVF(FVF_old); + Renderer::SetFVF(FVF_old); + + for (int i = 0; i < 6; i++) + { + // dev->SetRenderState((_D3DRENDERSTATETYPE)RS[i][0], RS_old[i]); + // dev->SetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS_old[i]); + + Renderer::SetRenderState( (_D3DRENDERSTATETYPE)RS[i][0], RS_old[i] ); + Renderer::SetTextureStageState( 0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS_old[i] ); + } + } + + int CD3DFont::DrawTextScaled( float x, float y, float fXScale, float fYScale, float spacing, u32 dwColor, const char* strText, bool center ) + { + SaveRenderStates(); + SetRenderStates(); + dev->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) ); + + float vpWidth = 1; + float vpHeight = 1; + + float sx = x*vpWidth-0.5f; + float sy = y*vpHeight-0.5f; + + float fStartX = sx; + + float invLineHeight = 1.0f / (( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight); + // Fill vertex buffer + FONT2DVERTEX* pVertices; + int dwNumTriangles = 0L; + m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); + + const char *oldstrText=strText; + //First, let's measure the text + float tw=0; + float mx=0; + float maxx=0; + + while( *strText ) + { + char c = *strText++; + + if( c == ('\n') ) + mx=0; + if( c < (' ') ) + continue; + + float tx1 = m_fTexCoords[c-32][0]; + float tx2 = m_fTexCoords[c-32][2]; + + float w = (tx2-tx1)*m_dwTexWidth; + w *= (fXScale*vpHeight)*invLineHeight; + mx += w + spacing*fXScale*vpWidth; + if (mx>maxx) maxx=mx; + } + + float offset=-maxx/2; + strText = oldstrText; + //Then let's draw it + if (center) + { + sx+=offset; + fStartX+=offset; + } + + float wScale=(fXScale*vpHeight)*invLineHeight; + float hScale=(fYScale*vpHeight)*invLineHeight; + + while( *strText ) + { + char c = *strText++; + + if( c == ('\n') ) + { + sx = fStartX; + sy += fYScale*vpHeight; + } + if( c < (' ') ) + continue; + + c-=32; + float tx1 = m_fTexCoords[c][0]; + float ty1 = m_fTexCoords[c][1]; + float tx2 = m_fTexCoords[c][2]; + float ty2 = m_fTexCoords[c][3]; + + float w = (tx2-tx1)*m_dwTexWidth; + float h = (ty2-ty1)*m_dwTexHeight; + + w *= wScale; + h *= hScale; + + + FONT2DVERTEX v[6]; + v[0]=InitFont2DVertex(sx, sy+h, dwColor, tx1, ty2); + v[1]=InitFont2DVertex(sx, sy, dwColor, tx1, ty1); + v[2]=InitFont2DVertex(sx+w, sy+h, dwColor, tx2, ty2); + v[3]=InitFont2DVertex(sx+w, sy, dwColor, tx2, ty1); + v[4]=v[2]; + v[5]=v[1]; + + memcpy(pVertices,v,6*sizeof(FONT2DVERTEX)); + + pVertices+=6; + dwNumTriangles += 2; + + if( dwNumTriangles * 3 > (MAX_NUM_VERTICES-6) ) + { + // Unlock, render, and relock the vertex buffer + m_pVB->Unlock(); + + // dev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); + Renderer::DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); + + m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); + dwNumTriangles = 0; + } + + sx += w + spacing*fXScale*vpWidth; + } + + // Unlock and render the vertex buffer + m_pVB->Unlock(); + if( dwNumTriangles > 0 ) + { + // dev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); + Renderer::DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); + } + RestoreRenderStates(); + return S_OK; + } + + void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1, float v1, float u2, float v2) + { + SaveRenderStates(); + struct Q2DVertex { float x,y,z,rhw; u32 color; float u, v; } coords[4] = { + {x1-0.5f, y1-0.5f, 0, 1, color, u1, v1}, + {x2-0.5f, y1-0.5f, 0, 1, color, u2, v1}, + {x2-0.5f, y2-0.5f, 0, 1, color, u2, v2}, + {x1-0.5f, y2-0.5f, 0, 1, color, u1, v2}, + }; + dev->SetPixelShader(0); + dev->SetVertexShader(0); + dev->SetVertexDeclaration(0); + + // dev->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1); + // dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,coords,sizeof(Q2DVertex)); + Renderer::SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1); + Renderer::DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,coords,sizeof(Q2DVertex)); + + RestoreRenderStates(); + } + +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/DLCompiler.cpp b/Source/Plugins/Plugin_VideoDX9/Src/DLCompiler.cpp index 054e2c1291..e7bcd96570 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/DLCompiler.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/DLCompiler.cpp @@ -1,468 +1,468 @@ -#include "stdafx.h" - -#if 0 - -#include "OpcodeDecoding.h" -#include "VertexLoader.h" -#include "VertexHandler.h" -#include "DataReader.h" -#include "BPStructs.h" -#include "CPStructs.h" -#include "XFStructs.h" -#include "DLCompiler.h" -#include "x86.h" -#include "main.h" -#include "Utils.h" - -CompiledDList::CompiledDList(u32 _addr, u32 _size) -{ - dataSize = 0; - data = 0; - code = 0; - addr = _addr; - size = _size; - pass = 0; - numBatches = 0; - batches = 0; -} - -CompiledDList::~CompiledDList() -{ - if (data) - delete [] data; - if (code) - delete [] code; - if (batches) - delete [] batches; -} - - -bool CompiledDList::Call() -{ - switch(pass) { - case 0: // First compiling pass : find data size - if (Pass1()) - { - pass = 1; - return true; - } - else - return false; - case 1: // Second compiling pass : actually compile - //if pass1 succeeded, pass2 will too - Pass2(); - pass = 2; - return true; - case 2: // Run pass - we have a compiled dlist, just call it - Run(); - return true; - default: - //ERROR - return false; - } -} - - -bool CompiledDList::Pass1() -{ -/* //find the size of code + data, if the dlist is worth recompiling etc - // at the same time, do the ordinary stuff - g_pDataReader = &dlistReader; - OpcodeReaders::SetDListReader(addr, addr+size); - dataSize = 0; - codeSize = 0; - numBatches = 0; - bool lastIsPrim = false; - while (OpcodeReaders::IsDListOKToRead()) - { - int Cmd = g_pDataReader->Read8(); - switch(Cmd) - { - case GX_LOAD_CP_REG: //0x08 - { - u32 SubCmd = g_pDataReader->Read8(); - u32 Value = g_pDataReader->Read32(); - LoadCPReg(SubCmd,Value); - //COMPILER - codeSize+=13; - } - break; - - case GX_LOAD_XF_REG: - { - u32 Cmd2 = g_pDataReader->Read32(); - int dwTransferSize = ((Cmd2>>16)&15) + 1; - DWORD dwAddress = Cmd2 & 0xFFFF; - static u32 pData[16]; - for (int i=0; iRead32(); - LoadXFReg(dwTransferSize,dwAddress,pData); - //COMPILER - dataSize+=dwTransferSize; - codeSize+=17; - } - break; - - case GX_LOAD_BP_REG: //0x61 - { - u32 cmd=g_pDataReader->Read32(); - LoadBPReg(cmd); - codeSize+=9; - } - break; - - case GX_LOAD_INDX_A: //used for position matrices - LoadIndexedXF(g_pDataReader->Read32(),0xC); - codeSize+=13; - break; - case GX_LOAD_INDX_B: //used for normal matrices - LoadIndexedXF(g_pDataReader->Read32(),0xD); - codeSize+=13; - break; - case GX_LOAD_INDX_C: //used for postmatrices - LoadIndexedXF(g_pDataReader->Read32(),0xE); - codeSize+=13; - break; - case GX_LOAD_INDX_D: //used for lights - LoadIndexedXF(g_pDataReader->Read32(),0xF); - codeSize+=13; - break; - - case GX_CMD_CALL_DL: - MessageBox(0,"Display lists can't recurse!!","error",0); - break; - - case GX_CMD_INVL_VC:// Invalidate (vertex cache?) - break; - case GX_NOP: - break; - default: - if (Cmd&0x80) - { - int primitive = (Cmd&GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT; - if (lastIsPrim) - { - //join to last - } - else - { - //finish up last and commit - } - u16 numVertices = g_pDataReader->Read16(); - tempvarray.Reset(); - VertexLoader::SetVArray(&tempvarray); - VertexLoader *loader = &VertexLoader[Cmd&GX_VAT_MASK]; - loader->Setup(); - loader->PrepareRun(); - int vsize = loader->GetVertexSize(); - loader->RunVertices(numVertices); - CVertexHandler::DrawVertices(primitive, numVertices, &tempvarray); - CVertexHandler::Flush(); - //COMPILER - codeSize+=21; - numBatches++; - lastIsPrim = true; - } - break; - } - } - if (lastIsPrim) - { - //finish up last and commit - } - codeSize*=2;*/ - return true; -} - - -void CompiledDList::Pass2() -{ -/* OpcodeReaders::SetDListReader(addr, addr+size); - - data = new u32[dataSize]; - code = new u8[codeSize]; //at least - - batches = new Batch[numBatches]; - int batchCount = 0; - u32 *dataptr = data; - - x86Init(); - x86SetPtr((s8*)code); - //WC8(0xCC); - - //actually do the recompiling, emit code and data, protect the memory - // but again, at the same time do the ordinary stuff - // so the compiled display list won't be run until the third time actually - bool dump = false,lastIsGeom=false; - FILE *f; - -#ifndef TEASER - if (dump) - { - f=fopen("D:\\dlistlogs.txt","a"); - fprintf(f,"===========================================\n"); - } -#endif - - while (OpcodeReaders::IsDListOKToRead()) - { - int Cmd = g_pDataReader->Read8(); - switch(Cmd) - { - case GX_LOAD_CP_REG: //0x08 - { - lastIsGeom = false; - u32 SubCmd = g_pDataReader->Read8(); - u32 Value = g_pDataReader->Read32(); - if (dump) - fprintf(f,"CP | %02x %08x\n",SubCmd,Value); - - LoadCPReg(SubCmd,Value); - //COMPILER - PUSH_WordToStack(Value); - PUSH_WordToStack(SubCmd); - CALLFunc((u32)LoadCPReg); - } - break; - - case GX_LOAD_XF_REG: - { - lastIsGeom = false; - u32 Cmd2 = g_pDataReader->Read32(); - int dwTransferSize = ((Cmd2>>16)&15) + 1; - u32 dwAddress = Cmd2 & 0xFFFF; - static u32 pData[16]; - - u32 *oldDataPtr = dataptr; - - if (dump) - { - fprintf(f,"XF | %01xx %04x\n",dwTransferSize,dwAddress); - for (int i=0; iRead32(); - - - LoadXFReg(dwTransferSize,dwAddress,oldDataPtr); - - //COMPILER - PUSH_WordToStack((u32)oldDataPtr); - PUSH_WordToStack(dwAddress); - PUSH_WordToStack(dwTransferSize); - CALLFunc((u32)LoadXFReg); - } - break; - - case GX_LOAD_BP_REG: //0x61 - { - lastIsGeom = false; - u32 cmd=g_pDataReader->Read32(); - if (dump) - fprintf(f,"BP | %08x\n",cmd); - - LoadBPReg(cmd); - //COMPILER - PUSH_WordToStack(cmd); - CALLFunc((u32)LoadBPReg); - } - break; - - case GX_LOAD_INDX_A: //usually used for position matrices - { - lastIsGeom = false; - u32 value = g_pDataReader->Read32(); - LoadIndexedXF(value,0xC); - //COMPILER - PUSH_WordToStack(0xC); - PUSH_WordToStack(value); - CALLFunc((u32)LoadIndexedXF); - if (dump) - fprintf(f,"LOADINDEXA | pos matrix\n"); - } - break; - case GX_LOAD_INDX_B: //usually used for normal matrices - { - lastIsGeom = false; - u32 value = g_pDataReader->Read32(); - LoadIndexedXF(value,0xD); - //COMPILER - PUSH_WordToStack(0xD); - PUSH_WordToStack(value); - CALLFunc((u32)LoadIndexedXF); - if (dump) - fprintf(f,"LOADINDEXB | nrm matrix\n"); - } - break; - case GX_LOAD_INDX_C: //usually used for postmatrices - { - lastIsGeom = false; - u32 value = g_pDataReader->Read32(); - LoadIndexedXF(value,0xE); - //COMPILER - PUSH_WordToStack(0xE); - PUSH_WordToStack(value); - CALLFunc((u32)LoadIndexedXF); - if (dump) - fprintf(f,"LOADINDEXC | post matrix\n"); - } - break; - case GX_LOAD_INDX_D: //usually used for lights - { - lastIsGeom = false; - u32 value = g_pDataReader->Read32(); - LoadIndexedXF(value,0xF); - //COMPILER - PUSH_WordToStack(0xF); - PUSH_WordToStack(value); - CALLFunc((u32)LoadIndexedXF); - if (dump) - fprintf(f,"LOADINDEXD | light\n"); - } - break; - case GX_CMD_CALL_DL: - // ERORRR - break; - - case GX_CMD_INVL_VC:// Invalidate (vertex cache?) - if (dump) - fprintf(f,"invalidate vc\n"); - break; - case GX_NOP: - if (dump) - fprintf(f,"nop\n"); - break; - default: - if (Cmd&0x80) - { - int primitive = (Cmd&GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT; - //if (lastIsGeom) INCSTAT(stats.numJoins); - u16 numVertices = g_pDataReader->Read16(); - if (dump) - fprintf(f,"DP: prim=%02x numv=%i\n",primitive,numVertices); - DecodedVArray &va = batches[batchCount].varray; - - VertexLoader *loader = &VertexLoader[Cmd&GX_VAT_MASK]; - TVtxDesc &vd = loader->GetVtxDesc(); - - VertexLoader::SetVArray(&va); - loader->Setup(); - loader->PrepareRun(); -// va.numColors = loader->GetNumColors(); -// va.numUVs = loader->GetNumTCs(); -// va.numNormals = loader->GetNumNormals(); - //va.num - va.Create(numVertices,vd.PosMatIdx, - vd.Tex0MatIdx+vd.Tex1MatIdx+vd.Tex2MatIdx+vd.Tex3MatIdx+ - vd.Tex4MatIdx+vd.Tex5MatIdx+vd.Tex6MatIdx+vd.Tex7MatIdx, - va.numNormals, va.numColors, va.numTCs); - - int vsize = loader->GetVertexSize(); - loader->RunVertices(numVertices); - CVertexHandler::DrawVertices(primitive, numVertices, &va); - CVertexHandler::Flush(); - // YES we have now filled our varray - //LETS COMPILE - PUSH_WordToStack(primitive); - PUSH_WordToStack(batchCount); - PUSH_WordToStack((u32)this); - CALLFunc((u32)DrawHelperHelper); - batchCount++; - lastIsGeom = true; - if (dump) - fprintf(f,"DRAW PRIMITIVE: prim=%02x numv=%i\n",primitive,numVertices); - } - break; - } - } - if (dump) - { - fprintf(f,"***************************************\n\n\n"); - } - RET(); - if (dump) - fclose(f);*/ - //we're done, next time just kick the compiled list off, much much faster than interpreting! -} - -void CompiledDList::DrawHelperHelper(CompiledDList *dl, int vno, int prim) -{ - Batch &b = dl->batches[vno]; - CVertexHandler::DrawVertices(prim, b.varray.GetSize(), &b.varray); -} - -void CompiledDList::Run() -{ - //run the code - ((void (*)())(code))(); - CVertexHandler::Flush(); -} - -DListCache::DLCache DListCache::dlists; - - - -void DListCache::Init() -{ - -} - - -void DListCache::Shutdown() -{ - DLCache::iterator iter = dlists.begin(); - for (;iter!=dlists.end();iter++) - iter->second.Destroy(); - dlists.clear(); -} - - -void DListCache::Call(u32 _addr, u32 _size) -{ - DLCache::iterator iter; - iter = dlists.find(_addr); - - if (iter != dlists.end()) - { - if (iter->second.size == _size) - { - iter->second.dlist->Call(); - return; - } - else // wrong size, need to recompile - { - iter->second.Destroy(); - iter=dlists.erase(iter); - } - } - - //Make an entry in the table - DLCacheEntry entry; - entry.dlist = new CompiledDList(_addr, _size); - entry.dlist->Call(); - entry.frameCount = frameCount; - entry.size = _size; - dlists[_addr] = entry; - - INCSTAT(stats.numDListsCreated); - SETSTAT(stats.numDListsAlive,(int)dlists.size()); -} - -void DListCache::Cleanup() -{ - for (DLCache::iterator iter=dlists.begin(); iter!=dlists.end();iter++) - { - DLCacheEntry &entry = iter->second; - if (entry.frameCountRead8(); + switch(Cmd) + { + case GX_LOAD_CP_REG: //0x08 + { + u32 SubCmd = g_pDataReader->Read8(); + u32 Value = g_pDataReader->Read32(); + LoadCPReg(SubCmd,Value); + //COMPILER + codeSize+=13; + } + break; + + case GX_LOAD_XF_REG: + { + u32 Cmd2 = g_pDataReader->Read32(); + int dwTransferSize = ((Cmd2>>16)&15) + 1; + DWORD dwAddress = Cmd2 & 0xFFFF; + static u32 pData[16]; + for (int i=0; iRead32(); + LoadXFReg(dwTransferSize,dwAddress,pData); + //COMPILER + dataSize+=dwTransferSize; + codeSize+=17; + } + break; + + case GX_LOAD_BP_REG: //0x61 + { + u32 cmd=g_pDataReader->Read32(); + LoadBPReg(cmd); + codeSize+=9; + } + break; + + case GX_LOAD_INDX_A: //used for position matrices + LoadIndexedXF(g_pDataReader->Read32(),0xC); + codeSize+=13; + break; + case GX_LOAD_INDX_B: //used for normal matrices + LoadIndexedXF(g_pDataReader->Read32(),0xD); + codeSize+=13; + break; + case GX_LOAD_INDX_C: //used for postmatrices + LoadIndexedXF(g_pDataReader->Read32(),0xE); + codeSize+=13; + break; + case GX_LOAD_INDX_D: //used for lights + LoadIndexedXF(g_pDataReader->Read32(),0xF); + codeSize+=13; + break; + + case GX_CMD_CALL_DL: + MessageBox(0,"Display lists can't recurse!!","error",0); + break; + + case GX_CMD_INVL_VC:// Invalidate (vertex cache?) + break; + case GX_NOP: + break; + default: + if (Cmd&0x80) + { + int primitive = (Cmd&GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT; + if (lastIsPrim) + { + //join to last + } + else + { + //finish up last and commit + } + u16 numVertices = g_pDataReader->Read16(); + tempvarray.Reset(); + VertexLoader::SetVArray(&tempvarray); + VertexLoader *loader = &VertexLoader[Cmd&GX_VAT_MASK]; + loader->Setup(); + loader->PrepareRun(); + int vsize = loader->GetVertexSize(); + loader->RunVertices(numVertices); + CVertexHandler::DrawVertices(primitive, numVertices, &tempvarray); + CVertexHandler::Flush(); + //COMPILER + codeSize+=21; + numBatches++; + lastIsPrim = true; + } + break; + } + } + if (lastIsPrim) + { + //finish up last and commit + } + codeSize*=2;*/ + return true; +} + + +void CompiledDList::Pass2() +{ +/* OpcodeReaders::SetDListReader(addr, addr+size); + + data = new u32[dataSize]; + code = new u8[codeSize]; //at least + + batches = new Batch[numBatches]; + int batchCount = 0; + u32 *dataptr = data; + + x86Init(); + x86SetPtr((s8*)code); + //WC8(0xCC); + + //actually do the recompiling, emit code and data, protect the memory + // but again, at the same time do the ordinary stuff + // so the compiled display list won't be run until the third time actually + bool dump = false,lastIsGeom=false; + FILE *f; + +#ifndef TEASER + if (dump) + { + f=fopen("D:\\dlistlogs.txt","a"); + fprintf(f,"===========================================\n"); + } +#endif + + while (OpcodeReaders::IsDListOKToRead()) + { + int Cmd = g_pDataReader->Read8(); + switch(Cmd) + { + case GX_LOAD_CP_REG: //0x08 + { + lastIsGeom = false; + u32 SubCmd = g_pDataReader->Read8(); + u32 Value = g_pDataReader->Read32(); + if (dump) + fprintf(f,"CP | %02x %08x\n",SubCmd,Value); + + LoadCPReg(SubCmd,Value); + //COMPILER + PUSH_WordToStack(Value); + PUSH_WordToStack(SubCmd); + CALLFunc((u32)LoadCPReg); + } + break; + + case GX_LOAD_XF_REG: + { + lastIsGeom = false; + u32 Cmd2 = g_pDataReader->Read32(); + int dwTransferSize = ((Cmd2>>16)&15) + 1; + u32 dwAddress = Cmd2 & 0xFFFF; + static u32 pData[16]; + + u32 *oldDataPtr = dataptr; + + if (dump) + { + fprintf(f,"XF | %01xx %04x\n",dwTransferSize,dwAddress); + for (int i=0; iRead32(); + + + LoadXFReg(dwTransferSize,dwAddress,oldDataPtr); + + //COMPILER + PUSH_WordToStack((u32)oldDataPtr); + PUSH_WordToStack(dwAddress); + PUSH_WordToStack(dwTransferSize); + CALLFunc((u32)LoadXFReg); + } + break; + + case GX_LOAD_BP_REG: //0x61 + { + lastIsGeom = false; + u32 cmd=g_pDataReader->Read32(); + if (dump) + fprintf(f,"BP | %08x\n",cmd); + + LoadBPReg(cmd); + //COMPILER + PUSH_WordToStack(cmd); + CALLFunc((u32)LoadBPReg); + } + break; + + case GX_LOAD_INDX_A: //usually used for position matrices + { + lastIsGeom = false; + u32 value = g_pDataReader->Read32(); + LoadIndexedXF(value,0xC); + //COMPILER + PUSH_WordToStack(0xC); + PUSH_WordToStack(value); + CALLFunc((u32)LoadIndexedXF); + if (dump) + fprintf(f,"LOADINDEXA | pos matrix\n"); + } + break; + case GX_LOAD_INDX_B: //usually used for normal matrices + { + lastIsGeom = false; + u32 value = g_pDataReader->Read32(); + LoadIndexedXF(value,0xD); + //COMPILER + PUSH_WordToStack(0xD); + PUSH_WordToStack(value); + CALLFunc((u32)LoadIndexedXF); + if (dump) + fprintf(f,"LOADINDEXB | nrm matrix\n"); + } + break; + case GX_LOAD_INDX_C: //usually used for postmatrices + { + lastIsGeom = false; + u32 value = g_pDataReader->Read32(); + LoadIndexedXF(value,0xE); + //COMPILER + PUSH_WordToStack(0xE); + PUSH_WordToStack(value); + CALLFunc((u32)LoadIndexedXF); + if (dump) + fprintf(f,"LOADINDEXC | post matrix\n"); + } + break; + case GX_LOAD_INDX_D: //usually used for lights + { + lastIsGeom = false; + u32 value = g_pDataReader->Read32(); + LoadIndexedXF(value,0xF); + //COMPILER + PUSH_WordToStack(0xF); + PUSH_WordToStack(value); + CALLFunc((u32)LoadIndexedXF); + if (dump) + fprintf(f,"LOADINDEXD | light\n"); + } + break; + case GX_CMD_CALL_DL: + // ERORRR + break; + + case GX_CMD_INVL_VC:// Invalidate (vertex cache?) + if (dump) + fprintf(f,"invalidate vc\n"); + break; + case GX_NOP: + if (dump) + fprintf(f,"nop\n"); + break; + default: + if (Cmd&0x80) + { + int primitive = (Cmd&GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT; + //if (lastIsGeom) INCSTAT(stats.numJoins); + u16 numVertices = g_pDataReader->Read16(); + if (dump) + fprintf(f,"DP: prim=%02x numv=%i\n",primitive,numVertices); + DecodedVArray &va = batches[batchCount].varray; + + VertexLoader *loader = &VertexLoader[Cmd&GX_VAT_MASK]; + TVtxDesc &vd = loader->GetVtxDesc(); + + VertexLoader::SetVArray(&va); + loader->Setup(); + loader->PrepareRun(); +// va.numColors = loader->GetNumColors(); +// va.numUVs = loader->GetNumTCs(); +// va.numNormals = loader->GetNumNormals(); + //va.num + va.Create(numVertices,vd.PosMatIdx, + vd.Tex0MatIdx+vd.Tex1MatIdx+vd.Tex2MatIdx+vd.Tex3MatIdx+ + vd.Tex4MatIdx+vd.Tex5MatIdx+vd.Tex6MatIdx+vd.Tex7MatIdx, + va.numNormals, va.numColors, va.numTCs); + + int vsize = loader->GetVertexSize(); + loader->RunVertices(numVertices); + CVertexHandler::DrawVertices(primitive, numVertices, &va); + CVertexHandler::Flush(); + // YES we have now filled our varray + //LETS COMPILE + PUSH_WordToStack(primitive); + PUSH_WordToStack(batchCount); + PUSH_WordToStack((u32)this); + CALLFunc((u32)DrawHelperHelper); + batchCount++; + lastIsGeom = true; + if (dump) + fprintf(f,"DRAW PRIMITIVE: prim=%02x numv=%i\n",primitive,numVertices); + } + break; + } + } + if (dump) + { + fprintf(f,"***************************************\n\n\n"); + } + RET(); + if (dump) + fclose(f);*/ + //we're done, next time just kick the compiled list off, much much faster than interpreting! +} + +void CompiledDList::DrawHelperHelper(CompiledDList *dl, int vno, int prim) +{ + Batch &b = dl->batches[vno]; + CVertexHandler::DrawVertices(prim, b.varray.GetSize(), &b.varray); +} + +void CompiledDList::Run() +{ + //run the code + ((void (*)())(code))(); + CVertexHandler::Flush(); +} + +DListCache::DLCache DListCache::dlists; + + + +void DListCache::Init() +{ + +} + + +void DListCache::Shutdown() +{ + DLCache::iterator iter = dlists.begin(); + for (;iter!=dlists.end();iter++) + iter->second.Destroy(); + dlists.clear(); +} + + +void DListCache::Call(u32 _addr, u32 _size) +{ + DLCache::iterator iter; + iter = dlists.find(_addr); + + if (iter != dlists.end()) + { + if (iter->second.size == _size) + { + iter->second.dlist->Call(); + return; + } + else // wrong size, need to recompile + { + iter->second.Destroy(); + iter=dlists.erase(iter); + } + } + + //Make an entry in the table + DLCacheEntry entry; + entry.dlist = new CompiledDList(_addr, _size); + entry.dlist->Call(); + entry.frameCount = frameCount; + entry.size = _size; + dlists[_addr] = entry; + + INCSTAT(stats.numDListsCreated); + SETSTAT(stats.numDListsAlive,(int)dlists.size()); +} + +void DListCache::Cleanup() +{ + for (DLCache::iterator iter=dlists.begin(); iter!=dlists.end();iter++) + { + DLCacheEntry &entry = iter->second; + if (entry.frameCount - -#include "resource.h" -#include "W32Util/PropertySheet.h" -#include "W32Util/ShellUtil.h" - -#include "D3DBase.h" -#include "D3DPostprocess.h" - -#include "Config.h" - -#include "TextureCache.h" - -#define NUMWNDRES 6 -int g_Res[NUMWNDRES][2] = -{ - {640,480}, - {800,600}, - {1024,768}, - {1280,960}, - {1280,1024}, - {1600,1200}, -}; - -struct TabDirect3D : public W32Util::Tab -{ - void Init(HWND hDlg) - { - for (int i=0; i + +#include "resource.h" +#include "W32Util/PropertySheet.h" +#include "W32Util/ShellUtil.h" + +#include "D3DBase.h" +#include "D3DPostprocess.h" + +#include "Config.h" + +#include "TextureCache.h" + +#define NUMWNDRES 6 +int g_Res[NUMWNDRES][2] = +{ + {640,480}, + {800,600}, + {1024,768}, + {1280,960}, + {1280,1024}, + {1600,1200}, +}; + +struct TabDirect3D : public W32Util::Tab +{ + void Init(HWND hDlg) + { + for (int i=0; i - -#include "../../Core/Src/Core.h" -#include "Config.h" -#include "main.h" -#include "EmuWindow.h" - -namespace EmuWindow -{ - HWND m_hWnd = NULL; - HWND m_hParent = NULL; - HINSTANCE m_hInstance = NULL; - WNDCLASSEX wndClass; - const TCHAR m_szClassName[] = "DolphinEmuWnd"; - int g_winstyle; - - HWND GetWnd() - { - return m_hWnd; - } - - HWND GetParentWnd() - { - return m_hParent; - } - - LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam ) - { - HDC hdc; - PAINTSTRUCT ps; - switch( iMsg ) - { - case WM_PAINT: - hdc = BeginPaint( hWnd, &ps ); - EndPaint( hWnd, &ps ); - return 0; - - case WM_KEYDOWN: - switch( LOWORD( wParam )) - { - case VK_ESCAPE: /* Pressing esc quits */ - //DestroyWindow(hWnd); - //PostQuitMessage(0); - break; - /* - case MY_KEYS: - hypotheticalScene->sendMessage(KEYDOWN...); - */ - } - g_VideoInitialize.pKeyPress(LOWORD(wParam), GetAsyncKeyState(VK_SHIFT) != 0, GetAsyncKeyState(VK_CONTROL) != 0); - break; - - case WM_CLOSE: - //Core::SetState(Core::CORE_UNINITIALIZED); - return 0; - - case WM_DESTROY: - //Shutdown(); - //PostQuitMessage( 0 ); - break; - - case WM_SIZE: - // Reset the D3D Device here - // Also make damn sure that this is not called from inside rendering a frame :P - break; - - case WM_SYSCOMMAND: - switch (wParam) - { - case SC_SCREENSAVE: - case SC_MONITORPOWER: - return 0; - } - break; - } - - return DefWindowProc(hWnd, iMsg, wParam, lParam); - } - - - HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title) - { - wndClass.cbSize = sizeof( wndClass ); - wndClass.style = CS_HREDRAW | CS_VREDRAW; - wndClass.lpfnWndProc = WndProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = 0; - wndClass.hInstance = hInstance; - wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION ); - wndClass.hCursor = LoadCursor( NULL, IDC_ARROW ); - wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ); - wndClass.lpszMenuName = NULL; - wndClass.lpszClassName = m_szClassName; - wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION ); - - m_hInstance = hInstance; - RegisterClassEx( &wndClass ); - - if (parent) - { - m_hWnd = CreateWindow(m_szClassName, title, - WS_CHILD, - CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, - parent, NULL, hInstance, NULL ); - - m_hParent = parent; - - ShowWindow(m_hWnd, SW_SHOWMAXIMIZED); - } - else - { - DWORD style = g_Config.bFullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW; - - RECT rc = {0, 0, width, height}; - AdjustWindowRect(&rc, style, false); - - int w = rc.right - rc.left; - int h = rc.bottom - rc.top; - - rc.left = (1280 - w)/2; - rc.right = rc.left + w; - rc.top = (1024 - h)/2; - rc.bottom = rc.top + h; - - - m_hWnd = CreateWindow(m_szClassName, title, - style, - rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, - parent, NULL, hInstance, NULL ); - - g_winstyle = GetWindowLong( m_hWnd, GWL_STYLE ); - g_winstyle &= ~WS_MAXIMIZE & ~WS_MINIMIZE; // remove minimize/maximize style - - } - - return m_hWnd; - } - - void Show() - { - ShowWindow(m_hWnd, SW_SHOW); - BringWindowToTop(m_hWnd); - UpdateWindow(m_hWnd); - } - - HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title) - { - return OpenWindow(hParent, hInstance, 640, 480, title); - } - - void Close() - { - DestroyWindow(m_hWnd); - UnregisterClass(m_szClassName, m_hInstance); - } - - - void SetSize(int width, int height) - { - RECT rc = {0, 0, width, height}; - AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false); - - int w = rc.right - rc.left; - int h = rc.bottom - rc.top; - - rc.left = (1280 - w)/2; - rc.right = rc.left + w; - rc.top = (1024 - h)/2; - rc.bottom = rc.top + h; - ::MoveWindow(m_hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE); - } -} + +#include + +#include "../../Core/Src/Core.h" +#include "Config.h" +#include "main.h" +#include "EmuWindow.h" + +namespace EmuWindow +{ + HWND m_hWnd = NULL; + HWND m_hParent = NULL; + HINSTANCE m_hInstance = NULL; + WNDCLASSEX wndClass; + const TCHAR m_szClassName[] = "DolphinEmuWnd"; + int g_winstyle; + + HWND GetWnd() + { + return m_hWnd; + } + + HWND GetParentWnd() + { + return m_hParent; + } + + LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam ) + { + HDC hdc; + PAINTSTRUCT ps; + switch( iMsg ) + { + case WM_PAINT: + hdc = BeginPaint( hWnd, &ps ); + EndPaint( hWnd, &ps ); + return 0; + + case WM_KEYDOWN: + switch( LOWORD( wParam )) + { + case VK_ESCAPE: /* Pressing esc quits */ + //DestroyWindow(hWnd); + //PostQuitMessage(0); + break; + /* + case MY_KEYS: + hypotheticalScene->sendMessage(KEYDOWN...); + */ + } + g_VideoInitialize.pKeyPress(LOWORD(wParam), GetAsyncKeyState(VK_SHIFT) != 0, GetAsyncKeyState(VK_CONTROL) != 0); + break; + + case WM_CLOSE: + //Core::SetState(Core::CORE_UNINITIALIZED); + return 0; + + case WM_DESTROY: + //Shutdown(); + //PostQuitMessage( 0 ); + break; + + case WM_SIZE: + // Reset the D3D Device here + // Also make damn sure that this is not called from inside rendering a frame :P + break; + + case WM_SYSCOMMAND: + switch (wParam) + { + case SC_SCREENSAVE: + case SC_MONITORPOWER: + return 0; + } + break; + } + + return DefWindowProc(hWnd, iMsg, wParam, lParam); + } + + + HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title) + { + wndClass.cbSize = sizeof( wndClass ); + wndClass.style = CS_HREDRAW | CS_VREDRAW; + wndClass.lpfnWndProc = WndProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hInstance = hInstance; + wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION ); + wndClass.hCursor = LoadCursor( NULL, IDC_ARROW ); + wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ); + wndClass.lpszMenuName = NULL; + wndClass.lpszClassName = m_szClassName; + wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION ); + + m_hInstance = hInstance; + RegisterClassEx( &wndClass ); + + if (parent) + { + m_hWnd = CreateWindow(m_szClassName, title, + WS_CHILD, + CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, + parent, NULL, hInstance, NULL ); + + m_hParent = parent; + + ShowWindow(m_hWnd, SW_SHOWMAXIMIZED); + } + else + { + DWORD style = g_Config.bFullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW; + + RECT rc = {0, 0, width, height}; + AdjustWindowRect(&rc, style, false); + + int w = rc.right - rc.left; + int h = rc.bottom - rc.top; + + rc.left = (1280 - w)/2; + rc.right = rc.left + w; + rc.top = (1024 - h)/2; + rc.bottom = rc.top + h; + + + m_hWnd = CreateWindow(m_szClassName, title, + style, + rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, + parent, NULL, hInstance, NULL ); + + g_winstyle = GetWindowLong( m_hWnd, GWL_STYLE ); + g_winstyle &= ~WS_MAXIMIZE & ~WS_MINIMIZE; // remove minimize/maximize style + + } + + return m_hWnd; + } + + void Show() + { + ShowWindow(m_hWnd, SW_SHOW); + BringWindowToTop(m_hWnd); + UpdateWindow(m_hWnd); + } + + HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title) + { + return OpenWindow(hParent, hInstance, 640, 480, title); + } + + void Close() + { + DestroyWindow(m_hWnd); + UnregisterClass(m_szClassName, m_hInstance); + } + + + void SetSize(int width, int height) + { + RECT rc = {0, 0, width, height}; + AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false); + + int w = rc.right - rc.left; + int h = rc.bottom - rc.top; + + rc.left = (1280 - w)/2; + rc.right = rc.left + w; + rc.top = (1024 - h)/2; + rc.bottom = rc.top + h; + ::MoveWindow(m_hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE); + } +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/IndexGenerator.cpp b/Source/Plugins/Plugin_VideoDX9/Src/IndexGenerator.cpp index 6fcd9d3ba7..2e07750e9b 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/IndexGenerator.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/IndexGenerator.cpp @@ -1,130 +1,130 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "stdafx.h" -#include "IndexGenerator.h" - -/* -* -QUAD simulator - -0 2 4 6 -1 3 5 7 -021231 243453 -*/ - - -void IndexGenerator::Start(unsigned short *startptr) -{ - ptr=startptr; - index=0; - numPrims=0; -} - -void IndexGenerator::AddList(int numVerts) -{ - int numTris = numVerts/3; - if (numTris<=0) return; - for (int i=0; i= 5) - { - iCommandSize = 1 + 4; - u32 Cmd2 = DataPeek32(1); - int dwTransferSize = ((Cmd2 >> 16) & 15) + 1; - iCommandSize += dwTransferSize * 4; - } - else - { - return false; - } - } - break; - - default: - if (Cmd&0x80) - { - // check if we can read the header - if (iBufferSize >= 3) - { - iCommandSize = 1 + 2; - u16 numVertices = DataPeek16(1); - VertexLoader& vtxLoader = g_VertexLoaders[Cmd & GX_VAT_MASK]; - vtxLoader.Setup(); - int vsize = vtxLoader.GetVertexSize(); - iCommandSize += numVertices * vsize; - } - else - { - return false; - } - } - else - { - char szTemp[1024]; - sprintf(szTemp, "GFX: Unknown Opcode (0x%x).\n" - "This means one of the following:\n" - "* The emulated GPU got desynced, disabling dual core can help\n" - "* Command stream corrupted by some spurious memory bug\n" - "* This really is an unknown opcode (unlikely)\n\n" - "* Some other sort of bug\n\n" - "Dolphin will now likely crash or hang. Enjoy.", Cmd); - MessageBox(NULL, szTemp, "Video-Plugin", MB_OK); - g_VideoInitialize.pLog(szTemp, TRUE); - - { - SCPFifoStruct &fifo = *g_VideoInitialize.pCPFifo; - - char szTmp[256]; - // sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr()); - sprintf(szTmp, "Illegal command %02x\n" - "CPBase: 0x%08x\n" - "CPEnd: 0x%08x\n" - "CPHiWatermark: 0x%08x\n" - "CPLoWatermark: 0x%08x\n" - "CPReadWriteDistance: 0x%08x\n" - "CPWritePointer: 0x%08x\n" - "CPReadPointer: 0x%08x\n" - "CPBreakpoint: 0x%08x\n" - "bFF_GPReadEnable: %s\n" - "bFF_BPEnable: %s\n" - "bFF_GPLinkEnable: %s\n" - "bFF_Breakpoint: %s\n" - ,Cmd, fifo.CPBase, fifo.CPEnd, fifo.CPHiWatermark, fifo.CPLoWatermark, fifo.CPReadWriteDistance - ,fifo.CPWritePointer, fifo.CPReadPointer, fifo.CPBreakpoint, fifo.bFF_GPReadEnable ? "true" : "false" - ,fifo.bFF_BPEnable ? "true" : "false" ,fifo.bFF_GPLinkEnable ? "true" : "false" - ,fifo.bFF_Breakpoint ? "true" : "false"); - - g_VideoInitialize.pLog(szTmp, TRUE); - MessageBox(0,szTmp,"GFX ERROR",0); - // _assert_msg_(0,szTmp,""); - - } - } - break; - } - - if (iCommandSize > iBufferSize) - return false; - -#ifdef _DEBUG - char temp[256]; - sprintf(temp, "OP detected: Cmd 0x%x size %i buffer %i",Cmd, iCommandSize, iBufferSize); - g_VideoInitialize.pLog(temp, FALSE); -#endif - - return true; -} - -static void Decode(void) -{ - int Cmd = DataReadU8(); - switch (Cmd) - { - case GX_NOP: - break; - - case GX_LOAD_CP_REG: - { - u32 SubCmd = DataReadU8(); - u32 Value = DataReadU32(); - LoadCPReg(SubCmd,Value); - } - break; - - case GX_LOAD_XF_REG: - { - u32 Cmd2 = DataReadU32(); - - int dwTransferSize = ((Cmd2>>16)&15) + 1; - u32 dwAddress = Cmd2 & 0xFFFF; - static u32 pData[16]; - for (int i=0; i> GX_PRIMITIVE_SHIFT; - VertexManager::AddVertices(primitive, numVertices, &tempvarray); - } - else - { - SCPFifoStruct &fifo = *g_VideoInitialize.pCPFifo; - - char szTmp[256]; - // sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr()); - sprintf(szTmp, "Illegal command %02x\n" - "CPBase: 0x%08x\n" - "CPEnd: 0x%08x\n" - "CPHiWatermark: 0x%08x\n" - "CPLoWatermark: 0x%08x\n" - "CPReadWriteDistance: 0x%08x\n" - "CPWritePointer: 0x%08x\n" - "CPReadPointer: 0x%08x\n" - "CPBreakpoint: 0x%08x\n" - "bFF_GPReadEnable: %s\n" - "bFF_BPEnable: %s\n" - "bFF_GPLinkEnable: %s\n" - "bFF_Breakpoint: %s\n" - ,Cmd, fifo.CPBase, fifo.CPEnd, fifo.CPHiWatermark, fifo.CPLoWatermark, fifo.CPReadWriteDistance - ,fifo.CPWritePointer, fifo.CPReadPointer, fifo.CPBreakpoint, fifo.bFF_GPReadEnable ? "true" : "false" - ,fifo.bFF_BPEnable ? "true" : "false" ,fifo.bFF_GPLinkEnable ? "true" : "false" - ,fifo.bFF_Breakpoint ? "true" : "false"); - - g_VideoInitialize.pLog(szTmp, TRUE); - MessageBox(0,szTmp,"GFX ERROR",0); - // _assert_msg_(0,szTmp,""); - break; - } - break; - } -} - -void OpcodeDecoder_Init() -{ - g_pVideoData = FAKE_GetFifoStartPtr(); - tempvarray.Create(65536*3, 1, 8, 3, 2, 8); -} - - -void OpcodeDecoder_Shutdown() -{ - //VirtualFree((LPVOID)buffer,0,MEM_RELEASE); - tempvarray.Destroy(); -} - -void OpcodeDecoder_Run() -{ - DVSTARTPROFILE(); - - while (FifoCommandRunnable()) - { - Decode(); - } +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +//DL facts: +// Ikaruga uses (nearly) NO display lists! +// Zelda WW uses TONS of display lists +// Zelda TP uses almost 100% display lists except menus (we like this!) + +// Note that it IS NOT GENERALLY POSSIBLE to precompile display lists! You can compile them as they are +// and hope that the vertex format doesn't change, though, if you do it just when they are +// called. The reason is that the vertex format affects the sizes of the vertices. + +#include "D3DBase.h" + +#include "Common.h" +#include "Statistics.h" +#include "Profiler.h" +#include "VertexManager.h" +#include "TransformEngine.h" +#include "OpcodeDecoding.h" +#include "TextureCache.h" +#include "ShaderManager.h" + +#include "BPStructs.h" +#include "XFStructs.h" +#include "Utils.h" +#include "Fifo.h" +#include "DataReader.h" + +DecodedVArray tempvarray; +u8 *g_pVideoData = 0; + +extern u8* FAKE_GetFifoStartPtr(); +extern u8* FAKE_GetFifoEndPtr(); + +static void Decode(); + +static void ExecuteDisplayList(u32 address, u32 size) +{ + u8* old_pVideoData = g_pVideoData; + + u8* startAddress = Memory_GetPtr(address); + + //Avoid the crash if Memory_GetPtr failed .. + if (startAddress!=0) + { + g_pVideoData = startAddress; + + // temporarily swap dl and non-dl(small "hack" for the stats) + Statistics::SwapDL(); + + while((u32)(g_pVideoData - startAddress) < size) + { + Decode(); + } + INCSTAT(stats.numDListsCalled); + INCSTAT(stats.thisFrame.numDListsCalled); + + // un-swap + Statistics::SwapDL(); + + // reset to the old pointer + g_pVideoData = old_pVideoData; + } +} + +bool FifoCommandRunnable() +{ + u32 iBufferSize = (u32)(FAKE_GetFifoEndPtr()-g_pVideoData); + if (iBufferSize == 0) + return false; // can't peek + + u8 Cmd = DataPeek8(0); + u32 iCommandSize = 0; + + switch(Cmd) + { + case GX_NOP: + // Hm, this means that we scan over nop streams pretty slowly... + iCommandSize = 1; + break; + + case GX_LOAD_CP_REG: + iCommandSize = 6; + break; + + case GX_LOAD_INDX_A: + case GX_LOAD_INDX_B: + case GX_LOAD_INDX_C: + case GX_LOAD_INDX_D: + iCommandSize = 5; + break; + + case GX_CMD_CALL_DL: + iCommandSize = 9; + break; + + case 0x44: + iCommandSize = 1; + // zelda 4 swords calls it and checks the metrics registers after that + break; + + case GX_CMD_INVL_VC: // invalid vertex cache - no parameter? + iCommandSize = 1; + break; + + case GX_LOAD_BP_REG: + iCommandSize = 5; + break; + + case GX_LOAD_XF_REG: + { + // check if we can read the header + if (iBufferSize >= 5) + { + iCommandSize = 1 + 4; + u32 Cmd2 = DataPeek32(1); + int dwTransferSize = ((Cmd2 >> 16) & 15) + 1; + iCommandSize += dwTransferSize * 4; + } + else + { + return false; + } + } + break; + + default: + if (Cmd&0x80) + { + // check if we can read the header + if (iBufferSize >= 3) + { + iCommandSize = 1 + 2; + u16 numVertices = DataPeek16(1); + VertexLoader& vtxLoader = g_VertexLoaders[Cmd & GX_VAT_MASK]; + vtxLoader.Setup(); + int vsize = vtxLoader.GetVertexSize(); + iCommandSize += numVertices * vsize; + } + else + { + return false; + } + } + else + { + char szTemp[1024]; + sprintf(szTemp, "GFX: Unknown Opcode (0x%x).\n" + "This means one of the following:\n" + "* The emulated GPU got desynced, disabling dual core can help\n" + "* Command stream corrupted by some spurious memory bug\n" + "* This really is an unknown opcode (unlikely)\n\n" + "* Some other sort of bug\n\n" + "Dolphin will now likely crash or hang. Enjoy.", Cmd); + MessageBox(NULL, szTemp, "Video-Plugin", MB_OK); + g_VideoInitialize.pLog(szTemp, TRUE); + + { + SCPFifoStruct &fifo = *g_VideoInitialize.pCPFifo; + + char szTmp[256]; + // sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr()); + sprintf(szTmp, "Illegal command %02x\n" + "CPBase: 0x%08x\n" + "CPEnd: 0x%08x\n" + "CPHiWatermark: 0x%08x\n" + "CPLoWatermark: 0x%08x\n" + "CPReadWriteDistance: 0x%08x\n" + "CPWritePointer: 0x%08x\n" + "CPReadPointer: 0x%08x\n" + "CPBreakpoint: 0x%08x\n" + "bFF_GPReadEnable: %s\n" + "bFF_BPEnable: %s\n" + "bFF_GPLinkEnable: %s\n" + "bFF_Breakpoint: %s\n" + ,Cmd, fifo.CPBase, fifo.CPEnd, fifo.CPHiWatermark, fifo.CPLoWatermark, fifo.CPReadWriteDistance + ,fifo.CPWritePointer, fifo.CPReadPointer, fifo.CPBreakpoint, fifo.bFF_GPReadEnable ? "true" : "false" + ,fifo.bFF_BPEnable ? "true" : "false" ,fifo.bFF_GPLinkEnable ? "true" : "false" + ,fifo.bFF_Breakpoint ? "true" : "false"); + + g_VideoInitialize.pLog(szTmp, TRUE); + MessageBox(0,szTmp,"GFX ERROR",0); + // _assert_msg_(0,szTmp,""); + + } + } + break; + } + + if (iCommandSize > iBufferSize) + return false; + +#ifdef _DEBUG + char temp[256]; + sprintf(temp, "OP detected: Cmd 0x%x size %i buffer %i",Cmd, iCommandSize, iBufferSize); + g_VideoInitialize.pLog(temp, FALSE); +#endif + + return true; +} + +static void Decode(void) +{ + int Cmd = DataReadU8(); + switch (Cmd) + { + case GX_NOP: + break; + + case GX_LOAD_CP_REG: + { + u32 SubCmd = DataReadU8(); + u32 Value = DataReadU32(); + LoadCPReg(SubCmd,Value); + } + break; + + case GX_LOAD_XF_REG: + { + u32 Cmd2 = DataReadU32(); + + int dwTransferSize = ((Cmd2>>16)&15) + 1; + u32 dwAddress = Cmd2 & 0xFFFF; + static u32 pData[16]; + for (int i=0; i> GX_PRIMITIVE_SHIFT; + VertexManager::AddVertices(primitive, numVertices, &tempvarray); + } + else + { + SCPFifoStruct &fifo = *g_VideoInitialize.pCPFifo; + + char szTmp[256]; + // sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr()); + sprintf(szTmp, "Illegal command %02x\n" + "CPBase: 0x%08x\n" + "CPEnd: 0x%08x\n" + "CPHiWatermark: 0x%08x\n" + "CPLoWatermark: 0x%08x\n" + "CPReadWriteDistance: 0x%08x\n" + "CPWritePointer: 0x%08x\n" + "CPReadPointer: 0x%08x\n" + "CPBreakpoint: 0x%08x\n" + "bFF_GPReadEnable: %s\n" + "bFF_BPEnable: %s\n" + "bFF_GPLinkEnable: %s\n" + "bFF_Breakpoint: %s\n" + ,Cmd, fifo.CPBase, fifo.CPEnd, fifo.CPHiWatermark, fifo.CPLoWatermark, fifo.CPReadWriteDistance + ,fifo.CPWritePointer, fifo.CPReadPointer, fifo.CPBreakpoint, fifo.bFF_GPReadEnable ? "true" : "false" + ,fifo.bFF_BPEnable ? "true" : "false" ,fifo.bFF_GPLinkEnable ? "true" : "false" + ,fifo.bFF_Breakpoint ? "true" : "false"); + + g_VideoInitialize.pLog(szTmp, TRUE); + MessageBox(0,szTmp,"GFX ERROR",0); + // _assert_msg_(0,szTmp,""); + break; + } + break; + } +} + +void OpcodeDecoder_Init() +{ + g_pVideoData = FAKE_GetFifoStartPtr(); + tempvarray.Create(65536*3, 1, 8, 3, 2, 8); +} + + +void OpcodeDecoder_Shutdown() +{ + //VirtualFree((LPVOID)buffer,0,MEM_RELEASE); + tempvarray.Destroy(); +} + +void OpcodeDecoder_Run() +{ + DVSTARTPROFILE(); + + while (FifoCommandRunnable()) + { + Decode(); + } } \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoDX9/Src/PixelShader.cpp b/Source/Plugins/Plugin_VideoDX9/Src/PixelShader.cpp index a6787a4f88..a3a8ea02cf 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/PixelShader.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/PixelShader.cpp @@ -1,525 +1,525 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "PixelShader.h" -#include "BPStructs.h" -#include "XFStructs.h" - -/* - old tev->pixelshader notes - - color for this stage (alpha, color) is given by bpmem.tevorders[0].colorchan0 - konstant for this stage (alpha, color) is given by bpmem.tevksel - inputs are given by bpmem.combiners[0].colorC.a/b/c/d << could be current chan color - according to GXTevColorArg table above - output is given by .outreg - tevtemp is set according to swapmodetables and -*/ - -const float epsilon = 1.0f/255.0f; - -const char *tevKSelTableC[] = -{ - "1,1,1", //KCSEL_1 = 0x00 - "0.875,0.875,0.875",//KCSEL_7_8 = 0x01 - "0.75,0.75,0.75", //KCSEL_3_4 = 0x02 - "0.625,0.625,0.625",//KCSEL_5_8 = 0x03 - "0.5,0.5,0.5", //KCSEL_1_2 = 0x04 - "0.375,0.375,0.375",//KCSEL_3_8 = 0x05 - "0.25,0.25,0.25", //KCSEL_1_4 = 0x06 - "0.125,0.125,0.125",//KCSEL_1_8 = 0x07 - "ERROR", //0x08 - "ERROR", //0x09 - "ERROR", //0x0a - "ERROR", //0x0b - "k0.rgb",//KCSEL_K0 = 0x0C - "k1.rgb",//KCSEL_K1 = 0x0D - "k2.rgb",//KCSEL_K2 = 0x0E - "k3.rgb",//KCSEL_K3 = 0x0F - "k0.rrr",//KCSEL_K0_R = 0x10 - "k1.rrr",//KCSEL_K1_R = 0x11 - "k2.rrr",//KCSEL_K2_R = 0x12 - "k3.rrr",//KCSEL_K3_R = 0x13 - "k0.ggg",//KCSEL_K0_G = 0x14 - "k1.ggg",//KCSEL_K1_G = 0x15 - "k2.ggg",//KCSEL_K2_G = 0x16 - "k3.ggg",//KCSEL_K3_G = 0x17 - "k0.bbb",//KCSEL_K0_B = 0x18 - "k1.bbb",//KCSEL_K1_B = 0x19 - "k2.bbb",//KCSEL_K2_B = 0x1A - "k3.bbb",//KCSEL_K3_B = 0x1B - "k0.aaa",//KCSEL_K0_A = 0x1C - "k1.aaa",//KCSEL_K1_A = 0x1D - "k2.aaa",//KCSEL_K2_A = 0x1E - "k3.aaa",//KCSEL_K3_A = 0x1F -}; -const char *tevKSelTableA[] = -{ - "1", //KASEL_1 = 0x00 - "0.875",//KASEL_7_8 = 0x01 - "0.75", //KASEL_3_4 = 0x02 - "0.625",//KASEL_5_8 = 0x03 - "0.5", //KASEL_1_2 = 0x04 - "0.375",//KASEL_3_8 = 0x05 - "0.25", //KASEL_1_4 = 0x06 - "0.125",//KASEL_1_8 = 0x07 - "ERROR",//0x08 - "ERROR",//0x09 - "ERROR",//0x0a - "ERROR",//0x0b - "ERROR",//0x0c - "ERROR",//0x0d - "ERROR",//0x0e - "ERROR",//0x0f - "k0.r", //KASEL_K0_R = 0x10 - "k1.r", //KASEL_K1_R = 0x11 - "k2.r", //KASEL_K2_R = 0x12 - "k3.r", //KASEL_K3_R = 0x13 - "k0.g", //KASEL_K0_G = 0x14 - "k1.g", //KASEL_K1_G = 0x15 - "k2.g", //KASEL_K2_G = 0x16 - "k3.g", //KASEL_K3_G = 0x17 - "k0.b", //KASEL_K0_B = 0x18 - "k1.b", //KASEL_K1_B = 0x19 - "k2.b", //KASEL_K2_B = 0x1A - "k3.b", //KASEL_K3_B = 0x1B - "k0.a", //KASEL_K0_A = 0x1C - "k1.a", //KASEL_K1_A = 0x1D - "k2.a", //KASEL_K2_A = 0x1E - "k3.a", //KASEL_K3_A = 0x1F -}; - -const char *tevScaleTable[] = -{ - "1", //SCALE_1 - "2", //SCALE_2 - "4", //SCALE_4 - "0.5", //DIVIDE_2 -}; - -const char *tevBiasTable[] = -{ - "", //ZERO, - "+0.5", //ADD_HALF, - "-0.5", //SUB_HALF, - "", //WTF? seen in shadow2 -}; - -const char *tevOpTable[] = -{ - "+", //ADD = 0, - "-", //SUB = 1, -}; - -const char *tevCompOpTable[] = -{ - ">", - "==", -}; - - -#define TEV_COMP_R8 0 -#define TEV_COMP_GR16 1 -#define TEV_COMP_BGR24 2 -#define TEV_COMP_RGB8 3 - -const char *tevCInputTable[] = -{ - "prev.rgb", //CPREV, - "prev.aaa", //APREV, - "c0.rgb", //C0, - "c0.aaa", //A0, - "c1.rgb", //C1, - "c1.aaa", //A1, - "c2.rgb", //C2, - "c2.aaa", //A2, - "textemp.rgb", //TEXC, - "textemp.aaa", //TEXA, - "rastemp.rgb", //RASC, - "rastemp.aaa", //RASA, - "float3(1,1,1)", //ONE, - "float3(.5,.5,.5)", //HALF, - "konsttemp.rgb", //KONST, - "float3(0,0,0)", //ZERO - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", -}; -const char *tevCInputTable2[] = -{ - "prev", //CPREV, - "(prev.aaa)", //APREV, - "c0", //C0, - "(c0.aaa)", //A0, - "c1", //C1, - "(c1.aaa)", //A1, - "c2", //C2, - "(c2.aaa)", //A2, - "textemp", //TEXC, - "(textemp.aaa)", //TEXA, - "rastemp", //RASC, - "(rastemp.aaa)", //RASA, - "float3(1,1,1)", //ONE, - "float3(.5,.5,.5)", //HALF, - "konsttemp", //KONST, - "float3(0,0,0)", //ZERO - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", -}; - -const char *tevAInputTable[] = -{ - "prev.a", //APREV, - "c0.a", //A0, - "c1.a", //A1, - "c2.a", //A2, - "textemp.a", //TEXA, - "rastemp.a", //RASA, - "konsttemp.a", //KONST, (hw1 had quarter) - "0.0", //ZERO - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", -}; - -const char *tevAInputTable1[] = -{ - "prev.r", //APREV, - "c0.r", //A0, - "c1.r", //A1, - "c2.r", //A2, - "textemp.r", //TEXA, - "rastemp.r", //RASA, - "konsttemp.r", //KONST, (hw1 had quarter) - "0.0", //ZERO - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", -}; - -const char *tevAInputTable2[] = -{ - "prev", //APREV, - "c0", //A0, - "c1", //A1, - "c2", //A2, - "textemp", //TEXA, - "rastemp", //RASA, - "konsttemp", //KONST, (hw1 had quarter) - "float4(0,0,0,0)",//ZERO - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", - "PADERROR", "PADERROR", "PADERROR", "PADERROR", -}; - -const char *tevRasTable[] = -{ - "colors[0]",//RAS1_CC_0 0x00000000 /* color channel 0 */ - "colors[1]",//RAS1_CC_1 0x00000001 /* color channel 1 */ - "ERROR", //2 - "ERROR", //3 - "ERROR", //4 - "alphabump", //RAS1_CC_B 0x00000005 /* indirect texture bump alpha */ //green cuz unsupported - "(alphabump*(255.0f/248.0f))", //RAS1_CC_BN 0x00000006 /* ind tex bump alpha, normalized 0-255 *///green cuz unsupported - "float4(0,0,0,0)", //RAS1_CC_Z 0x00000007 /* set color value to zero */ -}; - -const char *tevCOutputTable[] = { "prev.rgb", "c0.rgb", "c1.rgb", "c2.rgb" }; -const char *tevAOutputTable[] = { "prev.a", "c0.a", "c1.a", "c2.a" }; -const char *tevIndAlphaSel[] = {"", "x", "y", "z"}; -const char *tevIndAlphaScale[] = {"", "*32","*16","*8"}; -const char *tevIndBiasField[] = {"", "x", "y", "xy", "z", "xz", "yz", "xyz"}; // indexed by bias -const char *tevIndBiasAdd[] = {"-128.0f", "1.0f", "1.0f", "1.0f" }; // indexed by fmt -const char *tevIndWrapStart[] = {"0", "256", "128", "64", "32", "16", "0.001" }; -const char *tevIndFmtScale[] = {"255.0f", "31.0f", "15.0f", "8.0f" }; - -const char *tevTexFuncs[] = -{ - "tex2D", - "tex2Dproj" -}; - -const char *alphaRef[2] = -{ - "alphaRef.x", - "alphaRef.y" -}; - - - -char text[65536]; -#define WRITE p+=sprintf - - -void WriteStage(char *&p, int n); -void WriteAlphaTest(char *&p); - - -char *swapColors = "rgba"; -char swapModeTable[4][5]; - -void BuildSwapModeTable() -{ - for (int i = 0; i < 4; i++) - { - swapModeTable[i][0] = swapColors[bpmem.tevksel[i*2].swap1]; - swapModeTable[i][1] = swapColors[bpmem.tevksel[i*2].swap2]; - swapModeTable[i][2] = swapColors[bpmem.tevksel[i*2+1].swap1]; - swapModeTable[i][3] = swapColors[bpmem.tevksel[i*2+1].swap2]; - swapModeTable[i][4] = 0; - } -} - -const char *GeneratePixelShader() -{ - BuildSwapModeTable(); - int numStages = bpmem.genMode.numtevstages + 1; - int numTexgen = bpmem.genMode.numtexgens; - int numSamplers = 8; - - char *p = text; - WRITE(p,"//Pixel Shader for TEV stages\n\ -//%i TEV stages, %i texgens, %i IND stages, %i COL channels\n", - bpmem.genMode.numtevstages,bpmem.genMode.numtexgens,bpmem.genMode.numindstages,bpmem.genMode.numcolchans); - - //write kcolor declarations - for (int i = 0; i < 4; i++) { - if(i < 3) { - WRITE(p,"float4 k%i : register(c%i);\n\ - float4 color%i : register(c%i);\n",i,PS_CONST_KCOLORS+i, i,PS_CONST_COLORS+i+1); - } else { - WRITE(p,"float4 k%i : register(c%i);\n",i,PS_CONST_KCOLORS+i); - } - } - - WRITE(p,"float constalpha : register(c%i);\n\ -float2 alphaRef : register(c%i);\n\n\ -sampler samp[%i] : register(s0);\n\n\ -float4 main(in float4 colors[2] : COLOR0",PS_CONST_CONSTALPHA,PS_CONST_ALPHAREF,numSamplers); - - if (numTexgen) - WRITE(p,", float4 uv[%i] : TEXCOORD0",numTexgen); - else - WRITE(p,", float4 uv[1] : TEXCOORD0"); //HACK - WRITE(p,") : COLOR\n\ -{\n\ -float4 c0=color0,c1=color1,c2=color2,prev=float4(0.0f,0.0f,0.0f,0.0f),textemp,rastemp,konsttemp;\n\ -float3 comp16 = float3(1,255,0), comp24 = float3(1,255,255*255);\n\ -\n"); - - for (int i = 0; i < numStages; i++) - WriteStage(p,i); //build the equation for this stage - - WriteAlphaTest(p); - - /* see GL shader generator - this is Donko's hack - if (bpmem.dstalpha.enable) - WRITE(p," return float4(prev.rgb,constalpha.x);\n"); - else - */ - WRITE(p," return prev;\n"); - - WRITE(p,"}\n\0"); - - return text; -} - -void WriteStage(char *&p, int n) -{ - const char *rasswap = swapModeTable[bpmem.combiners[n].alphaC.rswap]; - const char *texswap = swapModeTable[bpmem.combiners[n].alphaC.tswap]; - - int texfun = xfregs.texcoords[n].texmtxinfo.projection; - - WRITE(p,"rastemp=%s.%s;\n",tevRasTable[bpmem.tevorders[n/2].getColorChan(n&1)],rasswap); - if (bpmem.tevorders[n/2].getEnable(n&1)) - WRITE(p,"textemp=%s(samp[%i],uv[%i]).%s;\n", - tevTexFuncs[texfun], - bpmem.tevorders[n/2].getTexMap(n&1), - bpmem.tevorders[n/2].getTexCoord(n&1),texswap); - else - WRITE(p,"textemp=float4(1,1,1,1);\n"); - - int kc = bpmem.tevksel[n/2].getKC(n&1); - int ka = bpmem.tevksel[n/2].getKA(n&1); - - WRITE(p,"konsttemp=float4(%s,%s);\n",tevKSelTableC[kc],tevKSelTableA[ka]); - - TevStageCombiner::ColorCombiner &cc = bpmem.combiners[n].colorC; - TevStageCombiner::AlphaCombiner &ac = bpmem.combiners[n].alphaC; - - WRITE(p,"float4(%s,%s)=", tevCOutputTable[cc.dest], tevAOutputTable[ac.dest]); - - ////////////////////////////////////////////////////////////////////////// - //start of color - ////////////////////////////////////////////////////////////////////////// - WRITE(p,"float4(\n"); - - if (cc.bias != TB_COMPARE) - { - //normal color combiner goes here - WRITE(p," %s*(%s%s",tevScaleTable[cc.shift],tevCInputTable[cc.d],tevOpTable[cc.op]); - WRITE(p,"(lerp(%s,%s,%s)%s)),\n", - tevCInputTable[cc.a],tevCInputTable[cc.b], - tevCInputTable[cc.c],tevBiasTable[cc.bias]); - } - else - { - //compare color combiner goes here - switch(cc.shift) // yep comparemode stored here :P - { - case TEV_COMP_R8: - if (cc.op == 0) //equality check needs tolerance, fp in gpu has drawbacks :( - WRITE(p," %s + ((%s.r > %s.r) ? %s : float3(0,0,0)),\n", - tevCInputTable[cc.d],tevCInputTable2[cc.a], - tevCInputTable2[cc.b],tevCInputTable[cc.c]); - else - WRITE(p," %s + (abs(%s.r - %s.r)<%f ? %s : float3(0,0,0)),\n", - tevCInputTable[cc.d],tevCInputTable2[cc.a], - tevCInputTable2[cc.b],epsilon,tevCInputTable[cc.c]); - break; - default: - WRITE(p,"float3(0,0,0),\n"); - break; - } - } - //end of color - - ////////////////////////////////////////////////////////////////////////// - //start of alpha - ////////////////////////////////////////////////////////////////////////// - if (ac.bias != TB_COMPARE) - { - //normal alpha combiner goes here - WRITE(p," %s*(%s%s",tevScaleTable[ac.shift],tevAInputTable[ac.d],tevOpTable[ac.op]); - WRITE(p,"lerp(%s,%s,%s) %s)\n", - tevAInputTable[ac.a],tevAInputTable[ac.b], - tevAInputTable[ac.c],tevBiasTable[ac.bias]); - } - else - { - int cmp = (ac.shift<<1)|ac.op|8; // comparemode stored here - const char **inputTable = NULL; - inputTable = (cmp == TEVCMP_R8_GT || cmp == TEVCMP_R8_EQ) ? tevAInputTable1 : tevAInputTable; - //compare alpha combiner goes here - switch(cmp) { - case TEVCMP_R8_GT: - case TEVCMP_A8_GT: - WRITE(p," %s + ((%s > %s) ? %s : 0)\n", - tevAInputTable[ac.d], inputTable[ac.a], inputTable[ac.b], tevAInputTable[ac.c]); - break; - case TEVCMP_R8_EQ: - case TEVCMP_A8_EQ: - WRITE(p," %s + (abs(%s - %s)<%f ? %s : 0)\n", - tevAInputTable[ac.d], inputTable[ac.a], inputTable[ac.b],epsilon,tevAInputTable[ac.c]); - break; - - case TEVCMP_GR16_GT: // 16 bit compares: 255*g+r (probably used for ztextures, so make sure in ztextures, g is the most significant byte) - case TEVCMP_BGR24_GT: // 24 bit compares: 255*255*b+255*g+r - WRITE(p," %s + (( dot(%s.rgb-%s.rgb, comp%s) > 0) ? %s : 0)\n", - tevAInputTable[ac.d],tevAInputTable2[ac.a], tevAInputTable2[ac.b], cmp==TEVCMP_GR16_GT?"16":"24", tevAInputTable[ac.c]); - break; - case TEVCMP_GR16_EQ: - case TEVCMP_BGR24_EQ: - WRITE(p," %s + (abs(dot(%s.rgb - %s.rgb, comp%s))<%f ? %s : 0)\n", - tevAInputTable[ac.d],tevAInputTable2[ac.a], tevAInputTable2[ac.b],cmp==TEVCMP_GR16_GT?"16":"24",epsilon,tevAInputTable[ac.c]); - break; - default: - WRITE(p,"0)\n"); - break; - } - } - WRITE(p, ");"); - if (ac.clamp) - WRITE(p, "%s = clamp(%s, 0.0f, 1.0f);\n", tevAOutputTable[ac.dest], tevAOutputTable[ac.dest]); - WRITE(p, "\n"); -} - -void WriteAlphaCompare(char *&p, int num, int comp) -{ - WRITE(p," res%i = ",num); - switch(comp) { - case ALPHACMP_ALWAYS: WRITE(p,"0;\n"); break; - case ALPHACMP_NEVER: WRITE(p,"1;\n"); break; - case ALPHACMP_LEQUAL: WRITE(p,"prev.a - %s.x;\n",alphaRef[num]); break; - case ALPHACMP_LESS: WRITE(p,"prev.a - %s.x + %f;\n",alphaRef[num],epsilon*2);break; - case ALPHACMP_GEQUAL: WRITE(p,"%s - prev.a;\n",alphaRef[num]); break; - case ALPHACMP_GREATER: WRITE(p,"%s - prev.a + %f;\n",alphaRef[num],epsilon*2);break; - case ALPHACMP_EQUAL: WRITE(p,"abs(%s-prev.a)-%f;\n",alphaRef[num],epsilon*2); break; - case ALPHACMP_NEQUAL: WRITE(p,"%f-abs(%s-prev.a);\n",epsilon*2,alphaRef[num]); break; - } -} - -void WriteAlphaTest(char *&p) -{ - AlphaOp op = (AlphaOp)bpmem.alphaFunc.logic; - Compare comp[2] = {(Compare)bpmem.alphaFunc.comp0,(Compare)bpmem.alphaFunc.comp1}; - - //first kill all the simple cases - if (op == ALPHAOP_AND && (comp[0] == COMPARE_ALWAYS && comp[1] == COMPARE_ALWAYS)) return; - if (op == ALPHAOP_OR && (comp[0] == COMPARE_ALWAYS || comp[1] == COMPARE_ALWAYS)) return; - for (int i = 0; i < 2; i++) - { - int one = i; - int other = 1-i; - switch(op) { - case ALPHAOP_XOR: - if (comp[one] == COMPARE_ALWAYS && comp[other] == COMPARE_NEVER) return; - break; - case ALPHAOP_XNOR: - if (comp[one] == COMPARE_ALWAYS && comp[other] == COMPARE_ALWAYS) return; - if (comp[one] == COMPARE_ALWAYS && comp[other] == COMPARE_NEVER) return; - break; - } - } - - //Ok, didn't get to do the easy way out :P - // do the general way - WRITE(p,"float res0, res1;\n"); - WriteAlphaCompare(p, 0, bpmem.alphaFunc.comp0); - WriteAlphaCompare(p, 1, bpmem.alphaFunc.comp1); - WRITE(p,"res0 = max(res0, 0);\n"); - WRITE(p,"res1 = max(res1, 0);\n"); - //probably should use lookup textures for some of these :P - switch(bpmem.alphaFunc.logic) { - case ALPHAOP_AND: // if both are 0 - WRITE(p,"clip(-(res0+res1)+%f);\n",epsilon); - break; - case ALPHAOP_OR: //if either is 0 - WRITE(p,"clip(-res0*res1+%f);\n",epsilon*epsilon); - break; - case ALPHAOP_XOR: - //hmm, this might work: - WRITE(p,"res0=(res0>0?1:0)-.5;\n"); - WRITE(p,"res1=(res1>0?1:0)-.5;\n"); - WRITE(p,"clip(-res0*res1);\n",epsilon); - break; - case ALPHAOP_XNOR: - WRITE(p,"res0=(res0>0?1:0)-.5;\n"); - WRITE(p,"res1=(res1>0?1:0)-.5;\n"); - WRITE(p,"clip(res0*res1);\n",epsilon); - break; - } -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "PixelShader.h" +#include "BPStructs.h" +#include "XFStructs.h" + +/* + old tev->pixelshader notes + + color for this stage (alpha, color) is given by bpmem.tevorders[0].colorchan0 + konstant for this stage (alpha, color) is given by bpmem.tevksel + inputs are given by bpmem.combiners[0].colorC.a/b/c/d << could be current chan color + according to GXTevColorArg table above + output is given by .outreg + tevtemp is set according to swapmodetables and +*/ + +const float epsilon = 1.0f/255.0f; + +const char *tevKSelTableC[] = +{ + "1,1,1", //KCSEL_1 = 0x00 + "0.875,0.875,0.875",//KCSEL_7_8 = 0x01 + "0.75,0.75,0.75", //KCSEL_3_4 = 0x02 + "0.625,0.625,0.625",//KCSEL_5_8 = 0x03 + "0.5,0.5,0.5", //KCSEL_1_2 = 0x04 + "0.375,0.375,0.375",//KCSEL_3_8 = 0x05 + "0.25,0.25,0.25", //KCSEL_1_4 = 0x06 + "0.125,0.125,0.125",//KCSEL_1_8 = 0x07 + "ERROR", //0x08 + "ERROR", //0x09 + "ERROR", //0x0a + "ERROR", //0x0b + "k0.rgb",//KCSEL_K0 = 0x0C + "k1.rgb",//KCSEL_K1 = 0x0D + "k2.rgb",//KCSEL_K2 = 0x0E + "k3.rgb",//KCSEL_K3 = 0x0F + "k0.rrr",//KCSEL_K0_R = 0x10 + "k1.rrr",//KCSEL_K1_R = 0x11 + "k2.rrr",//KCSEL_K2_R = 0x12 + "k3.rrr",//KCSEL_K3_R = 0x13 + "k0.ggg",//KCSEL_K0_G = 0x14 + "k1.ggg",//KCSEL_K1_G = 0x15 + "k2.ggg",//KCSEL_K2_G = 0x16 + "k3.ggg",//KCSEL_K3_G = 0x17 + "k0.bbb",//KCSEL_K0_B = 0x18 + "k1.bbb",//KCSEL_K1_B = 0x19 + "k2.bbb",//KCSEL_K2_B = 0x1A + "k3.bbb",//KCSEL_K3_B = 0x1B + "k0.aaa",//KCSEL_K0_A = 0x1C + "k1.aaa",//KCSEL_K1_A = 0x1D + "k2.aaa",//KCSEL_K2_A = 0x1E + "k3.aaa",//KCSEL_K3_A = 0x1F +}; +const char *tevKSelTableA[] = +{ + "1", //KASEL_1 = 0x00 + "0.875",//KASEL_7_8 = 0x01 + "0.75", //KASEL_3_4 = 0x02 + "0.625",//KASEL_5_8 = 0x03 + "0.5", //KASEL_1_2 = 0x04 + "0.375",//KASEL_3_8 = 0x05 + "0.25", //KASEL_1_4 = 0x06 + "0.125",//KASEL_1_8 = 0x07 + "ERROR",//0x08 + "ERROR",//0x09 + "ERROR",//0x0a + "ERROR",//0x0b + "ERROR",//0x0c + "ERROR",//0x0d + "ERROR",//0x0e + "ERROR",//0x0f + "k0.r", //KASEL_K0_R = 0x10 + "k1.r", //KASEL_K1_R = 0x11 + "k2.r", //KASEL_K2_R = 0x12 + "k3.r", //KASEL_K3_R = 0x13 + "k0.g", //KASEL_K0_G = 0x14 + "k1.g", //KASEL_K1_G = 0x15 + "k2.g", //KASEL_K2_G = 0x16 + "k3.g", //KASEL_K3_G = 0x17 + "k0.b", //KASEL_K0_B = 0x18 + "k1.b", //KASEL_K1_B = 0x19 + "k2.b", //KASEL_K2_B = 0x1A + "k3.b", //KASEL_K3_B = 0x1B + "k0.a", //KASEL_K0_A = 0x1C + "k1.a", //KASEL_K1_A = 0x1D + "k2.a", //KASEL_K2_A = 0x1E + "k3.a", //KASEL_K3_A = 0x1F +}; + +const char *tevScaleTable[] = +{ + "1", //SCALE_1 + "2", //SCALE_2 + "4", //SCALE_4 + "0.5", //DIVIDE_2 +}; + +const char *tevBiasTable[] = +{ + "", //ZERO, + "+0.5", //ADD_HALF, + "-0.5", //SUB_HALF, + "", //WTF? seen in shadow2 +}; + +const char *tevOpTable[] = +{ + "+", //ADD = 0, + "-", //SUB = 1, +}; + +const char *tevCompOpTable[] = +{ + ">", + "==", +}; + + +#define TEV_COMP_R8 0 +#define TEV_COMP_GR16 1 +#define TEV_COMP_BGR24 2 +#define TEV_COMP_RGB8 3 + +const char *tevCInputTable[] = +{ + "prev.rgb", //CPREV, + "prev.aaa", //APREV, + "c0.rgb", //C0, + "c0.aaa", //A0, + "c1.rgb", //C1, + "c1.aaa", //A1, + "c2.rgb", //C2, + "c2.aaa", //A2, + "textemp.rgb", //TEXC, + "textemp.aaa", //TEXA, + "rastemp.rgb", //RASC, + "rastemp.aaa", //RASA, + "float3(1,1,1)", //ONE, + "float3(.5,.5,.5)", //HALF, + "konsttemp.rgb", //KONST, + "float3(0,0,0)", //ZERO + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", +}; +const char *tevCInputTable2[] = +{ + "prev", //CPREV, + "(prev.aaa)", //APREV, + "c0", //C0, + "(c0.aaa)", //A0, + "c1", //C1, + "(c1.aaa)", //A1, + "c2", //C2, + "(c2.aaa)", //A2, + "textemp", //TEXC, + "(textemp.aaa)", //TEXA, + "rastemp", //RASC, + "(rastemp.aaa)", //RASA, + "float3(1,1,1)", //ONE, + "float3(.5,.5,.5)", //HALF, + "konsttemp", //KONST, + "float3(0,0,0)", //ZERO + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", +}; + +const char *tevAInputTable[] = +{ + "prev.a", //APREV, + "c0.a", //A0, + "c1.a", //A1, + "c2.a", //A2, + "textemp.a", //TEXA, + "rastemp.a", //RASA, + "konsttemp.a", //KONST, (hw1 had quarter) + "0.0", //ZERO + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", +}; + +const char *tevAInputTable1[] = +{ + "prev.r", //APREV, + "c0.r", //A0, + "c1.r", //A1, + "c2.r", //A2, + "textemp.r", //TEXA, + "rastemp.r", //RASA, + "konsttemp.r", //KONST, (hw1 had quarter) + "0.0", //ZERO + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", +}; + +const char *tevAInputTable2[] = +{ + "prev", //APREV, + "c0", //A0, + "c1", //A1, + "c2", //A2, + "textemp", //TEXA, + "rastemp", //RASA, + "konsttemp", //KONST, (hw1 had quarter) + "float4(0,0,0,0)",//ZERO + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", + "PADERROR", "PADERROR", "PADERROR", "PADERROR", +}; + +const char *tevRasTable[] = +{ + "colors[0]",//RAS1_CC_0 0x00000000 /* color channel 0 */ + "colors[1]",//RAS1_CC_1 0x00000001 /* color channel 1 */ + "ERROR", //2 + "ERROR", //3 + "ERROR", //4 + "alphabump", //RAS1_CC_B 0x00000005 /* indirect texture bump alpha */ //green cuz unsupported + "(alphabump*(255.0f/248.0f))", //RAS1_CC_BN 0x00000006 /* ind tex bump alpha, normalized 0-255 *///green cuz unsupported + "float4(0,0,0,0)", //RAS1_CC_Z 0x00000007 /* set color value to zero */ +}; + +const char *tevCOutputTable[] = { "prev.rgb", "c0.rgb", "c1.rgb", "c2.rgb" }; +const char *tevAOutputTable[] = { "prev.a", "c0.a", "c1.a", "c2.a" }; +const char *tevIndAlphaSel[] = {"", "x", "y", "z"}; +const char *tevIndAlphaScale[] = {"", "*32","*16","*8"}; +const char *tevIndBiasField[] = {"", "x", "y", "xy", "z", "xz", "yz", "xyz"}; // indexed by bias +const char *tevIndBiasAdd[] = {"-128.0f", "1.0f", "1.0f", "1.0f" }; // indexed by fmt +const char *tevIndWrapStart[] = {"0", "256", "128", "64", "32", "16", "0.001" }; +const char *tevIndFmtScale[] = {"255.0f", "31.0f", "15.0f", "8.0f" }; + +const char *tevTexFuncs[] = +{ + "tex2D", + "tex2Dproj" +}; + +const char *alphaRef[2] = +{ + "alphaRef.x", + "alphaRef.y" +}; + + + +char text[65536]; +#define WRITE p+=sprintf + + +void WriteStage(char *&p, int n); +void WriteAlphaTest(char *&p); + + +char *swapColors = "rgba"; +char swapModeTable[4][5]; + +void BuildSwapModeTable() +{ + for (int i = 0; i < 4; i++) + { + swapModeTable[i][0] = swapColors[bpmem.tevksel[i*2].swap1]; + swapModeTable[i][1] = swapColors[bpmem.tevksel[i*2].swap2]; + swapModeTable[i][2] = swapColors[bpmem.tevksel[i*2+1].swap1]; + swapModeTable[i][3] = swapColors[bpmem.tevksel[i*2+1].swap2]; + swapModeTable[i][4] = 0; + } +} + +const char *GeneratePixelShader() +{ + BuildSwapModeTable(); + int numStages = bpmem.genMode.numtevstages + 1; + int numTexgen = bpmem.genMode.numtexgens; + int numSamplers = 8; + + char *p = text; + WRITE(p,"//Pixel Shader for TEV stages\n\ +//%i TEV stages, %i texgens, %i IND stages, %i COL channels\n", + bpmem.genMode.numtevstages,bpmem.genMode.numtexgens,bpmem.genMode.numindstages,bpmem.genMode.numcolchans); + + //write kcolor declarations + for (int i = 0; i < 4; i++) { + if(i < 3) { + WRITE(p,"float4 k%i : register(c%i);\n\ + float4 color%i : register(c%i);\n",i,PS_CONST_KCOLORS+i, i,PS_CONST_COLORS+i+1); + } else { + WRITE(p,"float4 k%i : register(c%i);\n",i,PS_CONST_KCOLORS+i); + } + } + + WRITE(p,"float constalpha : register(c%i);\n\ +float2 alphaRef : register(c%i);\n\n\ +sampler samp[%i] : register(s0);\n\n\ +float4 main(in float4 colors[2] : COLOR0",PS_CONST_CONSTALPHA,PS_CONST_ALPHAREF,numSamplers); + + if (numTexgen) + WRITE(p,", float4 uv[%i] : TEXCOORD0",numTexgen); + else + WRITE(p,", float4 uv[1] : TEXCOORD0"); //HACK + WRITE(p,") : COLOR\n\ +{\n\ +float4 c0=color0,c1=color1,c2=color2,prev=float4(0.0f,0.0f,0.0f,0.0f),textemp,rastemp,konsttemp;\n\ +float3 comp16 = float3(1,255,0), comp24 = float3(1,255,255*255);\n\ +\n"); + + for (int i = 0; i < numStages; i++) + WriteStage(p,i); //build the equation for this stage + + WriteAlphaTest(p); + + /* see GL shader generator - this is Donko's hack + if (bpmem.dstalpha.enable) + WRITE(p," return float4(prev.rgb,constalpha.x);\n"); + else + */ + WRITE(p," return prev;\n"); + + WRITE(p,"}\n\0"); + + return text; +} + +void WriteStage(char *&p, int n) +{ + const char *rasswap = swapModeTable[bpmem.combiners[n].alphaC.rswap]; + const char *texswap = swapModeTable[bpmem.combiners[n].alphaC.tswap]; + + int texfun = xfregs.texcoords[n].texmtxinfo.projection; + + WRITE(p,"rastemp=%s.%s;\n",tevRasTable[bpmem.tevorders[n/2].getColorChan(n&1)],rasswap); + if (bpmem.tevorders[n/2].getEnable(n&1)) + WRITE(p,"textemp=%s(samp[%i],uv[%i]).%s;\n", + tevTexFuncs[texfun], + bpmem.tevorders[n/2].getTexMap(n&1), + bpmem.tevorders[n/2].getTexCoord(n&1),texswap); + else + WRITE(p,"textemp=float4(1,1,1,1);\n"); + + int kc = bpmem.tevksel[n/2].getKC(n&1); + int ka = bpmem.tevksel[n/2].getKA(n&1); + + WRITE(p,"konsttemp=float4(%s,%s);\n",tevKSelTableC[kc],tevKSelTableA[ka]); + + TevStageCombiner::ColorCombiner &cc = bpmem.combiners[n].colorC; + TevStageCombiner::AlphaCombiner &ac = bpmem.combiners[n].alphaC; + + WRITE(p,"float4(%s,%s)=", tevCOutputTable[cc.dest], tevAOutputTable[ac.dest]); + + ////////////////////////////////////////////////////////////////////////// + //start of color + ////////////////////////////////////////////////////////////////////////// + WRITE(p,"float4(\n"); + + if (cc.bias != TB_COMPARE) + { + //normal color combiner goes here + WRITE(p," %s*(%s%s",tevScaleTable[cc.shift],tevCInputTable[cc.d],tevOpTable[cc.op]); + WRITE(p,"(lerp(%s,%s,%s)%s)),\n", + tevCInputTable[cc.a],tevCInputTable[cc.b], + tevCInputTable[cc.c],tevBiasTable[cc.bias]); + } + else + { + //compare color combiner goes here + switch(cc.shift) // yep comparemode stored here :P + { + case TEV_COMP_R8: + if (cc.op == 0) //equality check needs tolerance, fp in gpu has drawbacks :( + WRITE(p," %s + ((%s.r > %s.r) ? %s : float3(0,0,0)),\n", + tevCInputTable[cc.d],tevCInputTable2[cc.a], + tevCInputTable2[cc.b],tevCInputTable[cc.c]); + else + WRITE(p," %s + (abs(%s.r - %s.r)<%f ? %s : float3(0,0,0)),\n", + tevCInputTable[cc.d],tevCInputTable2[cc.a], + tevCInputTable2[cc.b],epsilon,tevCInputTable[cc.c]); + break; + default: + WRITE(p,"float3(0,0,0),\n"); + break; + } + } + //end of color + + ////////////////////////////////////////////////////////////////////////// + //start of alpha + ////////////////////////////////////////////////////////////////////////// + if (ac.bias != TB_COMPARE) + { + //normal alpha combiner goes here + WRITE(p," %s*(%s%s",tevScaleTable[ac.shift],tevAInputTable[ac.d],tevOpTable[ac.op]); + WRITE(p,"lerp(%s,%s,%s) %s)\n", + tevAInputTable[ac.a],tevAInputTable[ac.b], + tevAInputTable[ac.c],tevBiasTable[ac.bias]); + } + else + { + int cmp = (ac.shift<<1)|ac.op|8; // comparemode stored here + const char **inputTable = NULL; + inputTable = (cmp == TEVCMP_R8_GT || cmp == TEVCMP_R8_EQ) ? tevAInputTable1 : tevAInputTable; + //compare alpha combiner goes here + switch(cmp) { + case TEVCMP_R8_GT: + case TEVCMP_A8_GT: + WRITE(p," %s + ((%s > %s) ? %s : 0)\n", + tevAInputTable[ac.d], inputTable[ac.a], inputTable[ac.b], tevAInputTable[ac.c]); + break; + case TEVCMP_R8_EQ: + case TEVCMP_A8_EQ: + WRITE(p," %s + (abs(%s - %s)<%f ? %s : 0)\n", + tevAInputTable[ac.d], inputTable[ac.a], inputTable[ac.b],epsilon,tevAInputTable[ac.c]); + break; + + case TEVCMP_GR16_GT: // 16 bit compares: 255*g+r (probably used for ztextures, so make sure in ztextures, g is the most significant byte) + case TEVCMP_BGR24_GT: // 24 bit compares: 255*255*b+255*g+r + WRITE(p," %s + (( dot(%s.rgb-%s.rgb, comp%s) > 0) ? %s : 0)\n", + tevAInputTable[ac.d],tevAInputTable2[ac.a], tevAInputTable2[ac.b], cmp==TEVCMP_GR16_GT?"16":"24", tevAInputTable[ac.c]); + break; + case TEVCMP_GR16_EQ: + case TEVCMP_BGR24_EQ: + WRITE(p," %s + (abs(dot(%s.rgb - %s.rgb, comp%s))<%f ? %s : 0)\n", + tevAInputTable[ac.d],tevAInputTable2[ac.a], tevAInputTable2[ac.b],cmp==TEVCMP_GR16_GT?"16":"24",epsilon,tevAInputTable[ac.c]); + break; + default: + WRITE(p,"0)\n"); + break; + } + } + WRITE(p, ");"); + if (ac.clamp) + WRITE(p, "%s = clamp(%s, 0.0f, 1.0f);\n", tevAOutputTable[ac.dest], tevAOutputTable[ac.dest]); + WRITE(p, "\n"); +} + +void WriteAlphaCompare(char *&p, int num, int comp) +{ + WRITE(p," res%i = ",num); + switch(comp) { + case ALPHACMP_ALWAYS: WRITE(p,"0;\n"); break; + case ALPHACMP_NEVER: WRITE(p,"1;\n"); break; + case ALPHACMP_LEQUAL: WRITE(p,"prev.a - %s.x;\n",alphaRef[num]); break; + case ALPHACMP_LESS: WRITE(p,"prev.a - %s.x + %f;\n",alphaRef[num],epsilon*2);break; + case ALPHACMP_GEQUAL: WRITE(p,"%s - prev.a;\n",alphaRef[num]); break; + case ALPHACMP_GREATER: WRITE(p,"%s - prev.a + %f;\n",alphaRef[num],epsilon*2);break; + case ALPHACMP_EQUAL: WRITE(p,"abs(%s-prev.a)-%f;\n",alphaRef[num],epsilon*2); break; + case ALPHACMP_NEQUAL: WRITE(p,"%f-abs(%s-prev.a);\n",epsilon*2,alphaRef[num]); break; + } +} + +void WriteAlphaTest(char *&p) +{ + AlphaOp op = (AlphaOp)bpmem.alphaFunc.logic; + Compare comp[2] = {(Compare)bpmem.alphaFunc.comp0,(Compare)bpmem.alphaFunc.comp1}; + + //first kill all the simple cases + if (op == ALPHAOP_AND && (comp[0] == COMPARE_ALWAYS && comp[1] == COMPARE_ALWAYS)) return; + if (op == ALPHAOP_OR && (comp[0] == COMPARE_ALWAYS || comp[1] == COMPARE_ALWAYS)) return; + for (int i = 0; i < 2; i++) + { + int one = i; + int other = 1-i; + switch(op) { + case ALPHAOP_XOR: + if (comp[one] == COMPARE_ALWAYS && comp[other] == COMPARE_NEVER) return; + break; + case ALPHAOP_XNOR: + if (comp[one] == COMPARE_ALWAYS && comp[other] == COMPARE_ALWAYS) return; + if (comp[one] == COMPARE_ALWAYS && comp[other] == COMPARE_NEVER) return; + break; + } + } + + //Ok, didn't get to do the easy way out :P + // do the general way + WRITE(p,"float res0, res1;\n"); + WriteAlphaCompare(p, 0, bpmem.alphaFunc.comp0); + WriteAlphaCompare(p, 1, bpmem.alphaFunc.comp1); + WRITE(p,"res0 = max(res0, 0);\n"); + WRITE(p,"res1 = max(res1, 0);\n"); + //probably should use lookup textures for some of these :P + switch(bpmem.alphaFunc.logic) { + case ALPHAOP_AND: // if both are 0 + WRITE(p,"clip(-(res0+res1)+%f);\n",epsilon); + break; + case ALPHAOP_OR: //if either is 0 + WRITE(p,"clip(-res0*res1+%f);\n",epsilon*epsilon); + break; + case ALPHAOP_XOR: + //hmm, this might work: + WRITE(p,"res0=(res0>0?1:0)-.5;\n"); + WRITE(p,"res1=(res1>0?1:0)-.5;\n"); + WRITE(p,"clip(-res0*res1);\n",epsilon); + break; + case ALPHAOP_XNOR: + WRITE(p,"res0=(res0>0?1:0)-.5;\n"); + WRITE(p,"res1=(res1>0?1:0)-.5;\n"); + WRITE(p,"clip(res0*res1);\n",epsilon); + break; + } +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 71ae5fb05b..9fd39be812 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -1,451 +1,451 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include - -#include "Common.h" -#include "Statistics.h" - -#include "Config.h" -#include "main.h" -#include "VertexManager.h" -#include "Render.h" -#include "OpcodeDecoding.h" -#include "BPStructs.h" -#include "XFStructs.h" -#include "D3DPostprocess.h" -#include "D3DUtil.h" -#include "ShaderManager.h" -#include "TextureCache.h" -#include "Utils.h" -#include "EmuWindow.h" - -#include - -float Renderer::m_x,Renderer::m_y,Renderer::m_width, Renderer::m_height, Renderer::xScale,Renderer::yScale; -std::vector Renderer::m_Textures; -DWORD Renderer::m_RenderStates[MaxRenderStates]; -DWORD Renderer::m_TextureStageStates[MaxTextureStages][MaxTextureTypes]; -DWORD Renderer::m_SamplerStates[MaxSamplerSize][MaxSamplerTypes]; -DWORD Renderer::m_FVF; - -#define NUMWNDRES 6 -extern int g_Res[NUMWNDRES][2]; - - -struct Message -{ - Message(const std::string &msg, u32 dw) : message( msg ), dwTimeStamp( dw ) - { - } - - std::string message; - u32 dwTimeStamp; -}; -static std::list s_listMsgs; - - -void Renderer::Init(SVideoInitialize &_VideoInitialize) -{ - EmuWindow::SetSize(g_Res[g_Config.iWindowedRes][0], g_Res[g_Config.iWindowedRes][1]); - - D3D::Create(g_Config.iAdapter, EmuWindow::GetWnd(), g_Config.bFullscreen, g_Config.iFSResolution, g_Config.iMultisampleMode); - - D3DVIEWPORT9 vp; - D3D::dev->GetViewport(&vp); - - m_x = 0; - m_y = 0; - m_width = (float)vp.Width; - m_height = (float)vp.Height; - xScale = 640.0f / (float)vp.Width; - yScale = 480.0f / (float)vp.Height; - - D3D::font.Init(); - Initialize(); -} - -void Renderer::Shutdown(void) -{ - D3D::font.Shutdown(); - D3D::EndFrame(); - D3D::Close(); -} - -void Renderer::Initialize(void) -{ - m_FVF = 0; - - m_Textures.reserve( MaxTextureStages ); - for ( int i = 0; i < MaxTextureStages; i++ ) - { - m_Textures.push_back( NULL ); - } - - for (int i=0; i<8; i++) - { - D3D::dev->SetSamplerState(i, D3DSAMP_MAXANISOTROPY, 16); - } - ReinitView(); - - Postprocess::Initialize(); - Postprocess::BeginFrame(); - D3D::BeginFrame(true, 0); - VertexManager::BeginFrame(); -} - -void Renderer::AddMessage(const std::string &message, u32 ms) -{ - s_listMsgs.push_back(Message(message, timeGetTime()+ms)); -} - -void Renderer::ProcessMessages() -{ - if (s_listMsgs.size() > 0) { - int left = 25, top = 15; - std::list::iterator it = s_listMsgs.begin(); - - while( it != s_listMsgs.end() ) - { - int time_left = (int)(it->dwTimeStamp - timeGetTime()); - int alpha = 255; - - if(time_left<1024) - { - alpha=time_left>>2; - if(time_left<0) alpha=0; - } - - alpha <<= 24; - - RenderText(it->message, left+1, top+1, 0x000000|alpha); - RenderText(it->message, left, top, 0xffff30|alpha); - top += 15; - - if (time_left <= 0) - it = s_listMsgs.erase(it); - else ++it; - } - } -} - -void Renderer::RenderText(const std::string &text, int left, int top, u32 color) -{ - D3D::font.DrawTextScaled((float)left, (float)top, 20, 20, 0.0f, color, text.c_str(), false); -} - -void dumpMatrix(D3DXMATRIX &mtx) -{ - for (int y=0; y<4; y++) - { - char temp[256]; - sprintf(temp,"%4.4f %4.4f %4.4f %4.4f",mtx.m[y][0],mtx.m[y][1],mtx.m[y][2],mtx.m[y][3]); - g_VideoInitialize.pLog(temp, FALSE); - } -} - -void Renderer::ReinitView() -{ - D3DXMATRIX mtx; - D3DXMatrixIdentity(&mtx); - D3D::dev->SetTransform(D3DTS_VIEW,&mtx); - D3D::dev->SetTransform(D3DTS_WORLD,&mtx); - - float width = (float)D3D::GetDisplayWidth(); - float height = (float)D3D::GetDisplayHeight(); - - xScale = width/640.0f; - yScale = height/480.0f; - - RECT rc = { - (LONG)(m_x*xScale), (LONG)(m_y*yScale), (LONG)(m_width*xScale), (LONG)(m_height*yScale) - }; -} - -void Renderer::SwapBuffers(void) -{ - // center window again - if (EmuWindow::GetParentWnd()) - { - RECT rcWindow; - GetWindowRect(EmuWindow::GetParentWnd(), &rcWindow); - - int width = rcWindow.right - rcWindow.left; - int height = rcWindow.bottom - rcWindow.top; - - ::MoveWindow(EmuWindow::GetWnd(), 0,0,width,height, FALSE); - // nBackbufferWidth = width; - // nBackbufferHeight = height; - } - - //Finish up the current frame, print some stats - Postprocess::FinalizeFrame(); - if (g_Config.bOverlayStats) - { - char st[2048]; - char *p = st; - p+=sprintf(p,"Num textures created: %i\n",stats.numTexturesCreated); - p+=sprintf(p,"Num textures alive: %i\n",stats.numTexturesAlive); - p+=sprintf(p,"Num pshaders created: %i\n",stats.numPixelShadersCreated); - p+=sprintf(p,"Num pshaders alive: %i\n",stats.numPixelShadersAlive); - p+=sprintf(p,"Num vshaders created: %i\n",stats.numVertexShadersCreated); - p+=sprintf(p,"Num vshaders alive: %i\n",stats.numVertexShadersAlive); - p+=sprintf(p,"Num dlists called: %i\n",stats.numDListsCalled); - p+=sprintf(p,"Num dlists created: %i\n",stats.numDListsCreated); - p+=sprintf(p,"Num dlists alive: %i\n",stats.numDListsAlive); - p+=sprintf(p,"Num primitives: %i\n",stats.thisFrame.numPrims); - p+=sprintf(p,"Num primitive joins: %i\n",stats.thisFrame.numPrimitiveJoins); - p+=sprintf(p,"Num primitives (DL): %i\n",stats.thisFrame.numDLPrims); - p+=sprintf(p,"Num XF loads: %i\n",stats.thisFrame.numXFLoads); - p+=sprintf(p,"Num XF loads (DL): %i\n",stats.thisFrame.numXFLoadsInDL); - p+=sprintf(p,"Num CP loads: %i\n",stats.thisFrame.numCPLoads); - p+=sprintf(p,"Num CP loads (DL): %i\n",stats.thisFrame.numCPLoadsInDL); - p+=sprintf(p,"Num BP loads: %i\n",stats.thisFrame.numBPLoads); - p+=sprintf(p,"Num BP loads (DL): %i\n",stats.thisFrame.numBPLoadsInDL); - - D3D::font.DrawTextScaled(0,30,20,20,0.0f,0xFF00FFFF,st,false); - - //end frame - } - - ProcessMessages(); - -#if defined(DVPROFILE) - if( g_bWriteProfile ) { - //g_bWriteProfile = 0; - static int framenum = 0; - const int UPDATE_FRAMES = 8; - if( ++framenum >= UPDATE_FRAMES ) { - DVProfWrite("prof.txt", UPDATE_FRAMES); - DVProfClear(); - framenum = 0; - } - } -#endif - - D3D::EndFrame(); - //D3D frame is now over - ////////////////////////////////////////////////////////////////////////// - - //clean out old stuff from caches - frameCount++; - PShaderCache::Cleanup(); - VShaderCache::Cleanup(); - TextureCache::Cleanup(); - //DListCache::Cleanup(); - - ////////////////////////////////////////////////////////////////////////// - //Begin new frame - //Set default viewport and scissor, for the clear to work correctly - stats.ResetFrame(); - D3DVIEWPORT9 vp; - vp.X = 0; - vp.Y = 0; - vp.Width = (DWORD)m_width; - vp.Height = (DWORD)m_height; - vp.MinZ = 0; - vp.MaxZ = 0; - D3D::dev->SetViewport(&vp); - RECT rc; - rc.left = 0; - rc.top = 0; - rc.right = (LONG)m_width; - rc.bottom = (LONG)m_height; - D3D::dev->SetScissorRect(&rc); - - u32 clearColor = (bpmem.clearcolorAR<<16)|bpmem.clearcolorGB; -// clearColor |= 0x003F003F; -// D3D::BeginFrame(true,clearColor,1.0f); - D3D::BeginFrame(false,clearColor,1.0f); - // D3D::EnableAlphaToCoverage(); - - Postprocess::BeginFrame(); - VertexManager::BeginFrame(); - - if (g_Config.bOldCard) - D3D::font.SetRenderStates(); //compatibility with low end cards -} - -void Renderer::Flush(void) -{ - // render the rest of the vertex buffer - //only to be used for debugging purposes - //D3D::EndFrame(); - - //D3D::BeginFrame(false,0); -} - -void Renderer::SetViewport(float* _Viewport) -{ - Viewport* pViewport = (Viewport*)_Viewport; - D3DVIEWPORT9 vp; - float x=(pViewport->xOrig-662)*2; - float y=(pViewport->yOrig-582)*2; //something is wrong, but what?? - y-=16; - - float w=pViewport->wd*2; //multiply up to real size - float h=pViewport->ht*-2; //why is this negative? oh well.. - - if (x < 0.0f) x = 0.0f; - if (y < 0.0f) y = 0.0f; - if (x > 640.0f) x = 639.0f; - if (y > 480.0f) y = 479.0f; - if (w < 0) w=1; - if (h < 0) h=1; - if (x+w > 640.0f) w=640-x; - if (y+h > 480.0f) h=480-y; - //x=y=0; - //if(w>0.0f) w=0.0f; - //if(h<0.0f) h=0.0f; - - vp.X = (DWORD)(x*xScale); - vp.Y = (DWORD)(y*yScale); - vp.Width = (DWORD)(w*xScale); - vp.Height = (DWORD)(h*yScale); - vp.MinZ = 0.0f; - vp.MaxZ = 1.0f; - -// char temp[256]; -// sprintf(temp,"Viewport: %i %i %i %i %f %f",vp.X,vp.Y,vp.Width,vp.Height,vp.MinZ,vp.MaxZ); -// g_VideoInitialize.pLog(temp, FALSE); - - D3D::dev->SetViewport(&vp); -} - -void Renderer::SetScissorBox(RECT &rc) -{ - rc.left = (int)(rc.left * xScale); - rc.top = (int)(rc.top * yScale); - rc.right = (int)(rc.right * xScale); - rc.bottom = (int)(rc.bottom * yScale); - if (rc.right >= rc.left && rc.bottom >= rc.top) - D3D::dev->SetScissorRect(&rc); - else - g_VideoInitialize.pLog("SCISSOR ERROR", FALSE); -} - -void Renderer::SetProjection(float* pMatrix, int constantIndex) -{ - D3DXMATRIX mtx; - if (pMatrix[6] == 0) - { - mtx.m[0][0] = pMatrix[0]; - mtx.m[1][0] = 0.0f; - mtx.m[2][0] = pMatrix[1]; - mtx.m[3][0] = -0.5f/m_width; - - mtx.m[0][1] = 0.0f; - mtx.m[1][1] = pMatrix[2]; - mtx.m[2][1] = pMatrix[3]; - mtx.m[3][1] = +0.5f/m_height; - - mtx.m[0][2] = 0.0f; - mtx.m[1][2] = 0.0f; - mtx.m[2][2] = -(1-pMatrix[4]); - mtx.m[3][2] = pMatrix[5]; - - mtx.m[0][3] = 0.0f; - mtx.m[1][3] = 0.0f; - mtx.m[2][3] = -1.0f; - mtx.m[3][3] = 0.0f; - } - else - { - mtx.m[0][0] = pMatrix[0]; - mtx.m[1][0] = 0.0f; - mtx.m[2][0] = 0.0f; - mtx.m[3][0] = pMatrix[1]-0.5f/m_width; // fix d3d pixel center - - mtx.m[0][1] = 0.0f; - mtx.m[1][1] = pMatrix[2]; - mtx.m[2][1] = 0.0f; - mtx.m[3][1] = pMatrix[3]+0.5f/m_height; // fix d3d pixel center - - mtx.m[0][2] = 0.0f; - mtx.m[1][2] = 0.0f; - mtx.m[2][2] = pMatrix[4]; - mtx.m[3][2] = -(-1 - pMatrix[5]); - - mtx.m[0][3] = 0; - mtx.m[1][3] = 0; - mtx.m[2][3] = 0.0f; - mtx.m[3][3] = 1.0f; - } - D3D::dev->SetVertexShaderConstantF(constantIndex, mtx, 4); -} - - -void Renderer::SetTexture( DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture ) -{ - if ( m_Textures[Stage] != pTexture ) - { - m_Textures[Stage] = pTexture; - D3D::dev->SetTexture( Stage, pTexture ); - } -} - - -void Renderer::SetFVF( DWORD FVF ) -{ - if ( m_FVF != FVF ) - { - m_FVF = FVF; - D3D::dev->SetFVF( FVF ); - } -} - - -void Renderer::SetRenderState( D3DRENDERSTATETYPE State, DWORD Value ) -{ - if ( m_RenderStates[State] != Value ) - { - m_RenderStates[State] = Value; - D3D::dev->SetRenderState( State, Value ); - } -} - - -void Renderer::SetTextureStageState( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value ) -{ - if ( m_TextureStageStates[Stage][Type] != Value ) - { - m_TextureStageStates[Stage][Type] = Value; - D3D::dev->SetTextureStageState( Stage, Type, Value ); - } -} - - -void Renderer::SetSamplerState( DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value ) -{ - if ( m_SamplerStates[Sampler][Type] != Value ) - { - m_SamplerStates[Sampler][Type] = Value; - D3D::dev->SetSamplerState( Sampler, Type, Value ); - } -} - - -void Renderer::DrawPrimitiveUP( D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, const void* pVertexStreamZeroData, UINT VertexStreamZeroStride ) -{ - D3D::dev->DrawPrimitiveUP( PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride ); -} - - -void Renderer::DrawPrimitive( D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount ) -{ - D3D::dev->DrawPrimitive( PrimitiveType, StartVertex, PrimitiveCount ); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include + +#include "Common.h" +#include "Statistics.h" + +#include "Config.h" +#include "main.h" +#include "VertexManager.h" +#include "Render.h" +#include "OpcodeDecoding.h" +#include "BPStructs.h" +#include "XFStructs.h" +#include "D3DPostprocess.h" +#include "D3DUtil.h" +#include "ShaderManager.h" +#include "TextureCache.h" +#include "Utils.h" +#include "EmuWindow.h" + +#include + +float Renderer::m_x,Renderer::m_y,Renderer::m_width, Renderer::m_height, Renderer::xScale,Renderer::yScale; +std::vector Renderer::m_Textures; +DWORD Renderer::m_RenderStates[MaxRenderStates]; +DWORD Renderer::m_TextureStageStates[MaxTextureStages][MaxTextureTypes]; +DWORD Renderer::m_SamplerStates[MaxSamplerSize][MaxSamplerTypes]; +DWORD Renderer::m_FVF; + +#define NUMWNDRES 6 +extern int g_Res[NUMWNDRES][2]; + + +struct Message +{ + Message(const std::string &msg, u32 dw) : message( msg ), dwTimeStamp( dw ) + { + } + + std::string message; + u32 dwTimeStamp; +}; +static std::list s_listMsgs; + + +void Renderer::Init(SVideoInitialize &_VideoInitialize) +{ + EmuWindow::SetSize(g_Res[g_Config.iWindowedRes][0], g_Res[g_Config.iWindowedRes][1]); + + D3D::Create(g_Config.iAdapter, EmuWindow::GetWnd(), g_Config.bFullscreen, g_Config.iFSResolution, g_Config.iMultisampleMode); + + D3DVIEWPORT9 vp; + D3D::dev->GetViewport(&vp); + + m_x = 0; + m_y = 0; + m_width = (float)vp.Width; + m_height = (float)vp.Height; + xScale = 640.0f / (float)vp.Width; + yScale = 480.0f / (float)vp.Height; + + D3D::font.Init(); + Initialize(); +} + +void Renderer::Shutdown(void) +{ + D3D::font.Shutdown(); + D3D::EndFrame(); + D3D::Close(); +} + +void Renderer::Initialize(void) +{ + m_FVF = 0; + + m_Textures.reserve( MaxTextureStages ); + for ( int i = 0; i < MaxTextureStages; i++ ) + { + m_Textures.push_back( NULL ); + } + + for (int i=0; i<8; i++) + { + D3D::dev->SetSamplerState(i, D3DSAMP_MAXANISOTROPY, 16); + } + ReinitView(); + + Postprocess::Initialize(); + Postprocess::BeginFrame(); + D3D::BeginFrame(true, 0); + VertexManager::BeginFrame(); +} + +void Renderer::AddMessage(const std::string &message, u32 ms) +{ + s_listMsgs.push_back(Message(message, timeGetTime()+ms)); +} + +void Renderer::ProcessMessages() +{ + if (s_listMsgs.size() > 0) { + int left = 25, top = 15; + std::list::iterator it = s_listMsgs.begin(); + + while( it != s_listMsgs.end() ) + { + int time_left = (int)(it->dwTimeStamp - timeGetTime()); + int alpha = 255; + + if(time_left<1024) + { + alpha=time_left>>2; + if(time_left<0) alpha=0; + } + + alpha <<= 24; + + RenderText(it->message, left+1, top+1, 0x000000|alpha); + RenderText(it->message, left, top, 0xffff30|alpha); + top += 15; + + if (time_left <= 0) + it = s_listMsgs.erase(it); + else ++it; + } + } +} + +void Renderer::RenderText(const std::string &text, int left, int top, u32 color) +{ + D3D::font.DrawTextScaled((float)left, (float)top, 20, 20, 0.0f, color, text.c_str(), false); +} + +void dumpMatrix(D3DXMATRIX &mtx) +{ + for (int y=0; y<4; y++) + { + char temp[256]; + sprintf(temp,"%4.4f %4.4f %4.4f %4.4f",mtx.m[y][0],mtx.m[y][1],mtx.m[y][2],mtx.m[y][3]); + g_VideoInitialize.pLog(temp, FALSE); + } +} + +void Renderer::ReinitView() +{ + D3DXMATRIX mtx; + D3DXMatrixIdentity(&mtx); + D3D::dev->SetTransform(D3DTS_VIEW,&mtx); + D3D::dev->SetTransform(D3DTS_WORLD,&mtx); + + float width = (float)D3D::GetDisplayWidth(); + float height = (float)D3D::GetDisplayHeight(); + + xScale = width/640.0f; + yScale = height/480.0f; + + RECT rc = { + (LONG)(m_x*xScale), (LONG)(m_y*yScale), (LONG)(m_width*xScale), (LONG)(m_height*yScale) + }; +} + +void Renderer::SwapBuffers(void) +{ + // center window again + if (EmuWindow::GetParentWnd()) + { + RECT rcWindow; + GetWindowRect(EmuWindow::GetParentWnd(), &rcWindow); + + int width = rcWindow.right - rcWindow.left; + int height = rcWindow.bottom - rcWindow.top; + + ::MoveWindow(EmuWindow::GetWnd(), 0,0,width,height, FALSE); + // nBackbufferWidth = width; + // nBackbufferHeight = height; + } + + //Finish up the current frame, print some stats + Postprocess::FinalizeFrame(); + if (g_Config.bOverlayStats) + { + char st[2048]; + char *p = st; + p+=sprintf(p,"Num textures created: %i\n",stats.numTexturesCreated); + p+=sprintf(p,"Num textures alive: %i\n",stats.numTexturesAlive); + p+=sprintf(p,"Num pshaders created: %i\n",stats.numPixelShadersCreated); + p+=sprintf(p,"Num pshaders alive: %i\n",stats.numPixelShadersAlive); + p+=sprintf(p,"Num vshaders created: %i\n",stats.numVertexShadersCreated); + p+=sprintf(p,"Num vshaders alive: %i\n",stats.numVertexShadersAlive); + p+=sprintf(p,"Num dlists called: %i\n",stats.numDListsCalled); + p+=sprintf(p,"Num dlists created: %i\n",stats.numDListsCreated); + p+=sprintf(p,"Num dlists alive: %i\n",stats.numDListsAlive); + p+=sprintf(p,"Num primitives: %i\n",stats.thisFrame.numPrims); + p+=sprintf(p,"Num primitive joins: %i\n",stats.thisFrame.numPrimitiveJoins); + p+=sprintf(p,"Num primitives (DL): %i\n",stats.thisFrame.numDLPrims); + p+=sprintf(p,"Num XF loads: %i\n",stats.thisFrame.numXFLoads); + p+=sprintf(p,"Num XF loads (DL): %i\n",stats.thisFrame.numXFLoadsInDL); + p+=sprintf(p,"Num CP loads: %i\n",stats.thisFrame.numCPLoads); + p+=sprintf(p,"Num CP loads (DL): %i\n",stats.thisFrame.numCPLoadsInDL); + p+=sprintf(p,"Num BP loads: %i\n",stats.thisFrame.numBPLoads); + p+=sprintf(p,"Num BP loads (DL): %i\n",stats.thisFrame.numBPLoadsInDL); + + D3D::font.DrawTextScaled(0,30,20,20,0.0f,0xFF00FFFF,st,false); + + //end frame + } + + ProcessMessages(); + +#if defined(DVPROFILE) + if( g_bWriteProfile ) { + //g_bWriteProfile = 0; + static int framenum = 0; + const int UPDATE_FRAMES = 8; + if( ++framenum >= UPDATE_FRAMES ) { + DVProfWrite("prof.txt", UPDATE_FRAMES); + DVProfClear(); + framenum = 0; + } + } +#endif + + D3D::EndFrame(); + //D3D frame is now over + ////////////////////////////////////////////////////////////////////////// + + //clean out old stuff from caches + frameCount++; + PShaderCache::Cleanup(); + VShaderCache::Cleanup(); + TextureCache::Cleanup(); + //DListCache::Cleanup(); + + ////////////////////////////////////////////////////////////////////////// + //Begin new frame + //Set default viewport and scissor, for the clear to work correctly + stats.ResetFrame(); + D3DVIEWPORT9 vp; + vp.X = 0; + vp.Y = 0; + vp.Width = (DWORD)m_width; + vp.Height = (DWORD)m_height; + vp.MinZ = 0; + vp.MaxZ = 0; + D3D::dev->SetViewport(&vp); + RECT rc; + rc.left = 0; + rc.top = 0; + rc.right = (LONG)m_width; + rc.bottom = (LONG)m_height; + D3D::dev->SetScissorRect(&rc); + + u32 clearColor = (bpmem.clearcolorAR<<16)|bpmem.clearcolorGB; +// clearColor |= 0x003F003F; +// D3D::BeginFrame(true,clearColor,1.0f); + D3D::BeginFrame(false,clearColor,1.0f); + // D3D::EnableAlphaToCoverage(); + + Postprocess::BeginFrame(); + VertexManager::BeginFrame(); + + if (g_Config.bOldCard) + D3D::font.SetRenderStates(); //compatibility with low end cards +} + +void Renderer::Flush(void) +{ + // render the rest of the vertex buffer + //only to be used for debugging purposes + //D3D::EndFrame(); + + //D3D::BeginFrame(false,0); +} + +void Renderer::SetViewport(float* _Viewport) +{ + Viewport* pViewport = (Viewport*)_Viewport; + D3DVIEWPORT9 vp; + float x=(pViewport->xOrig-662)*2; + float y=(pViewport->yOrig-582)*2; //something is wrong, but what?? + y-=16; + + float w=pViewport->wd*2; //multiply up to real size + float h=pViewport->ht*-2; //why is this negative? oh well.. + + if (x < 0.0f) x = 0.0f; + if (y < 0.0f) y = 0.0f; + if (x > 640.0f) x = 639.0f; + if (y > 480.0f) y = 479.0f; + if (w < 0) w=1; + if (h < 0) h=1; + if (x+w > 640.0f) w=640-x; + if (y+h > 480.0f) h=480-y; + //x=y=0; + //if(w>0.0f) w=0.0f; + //if(h<0.0f) h=0.0f; + + vp.X = (DWORD)(x*xScale); + vp.Y = (DWORD)(y*yScale); + vp.Width = (DWORD)(w*xScale); + vp.Height = (DWORD)(h*yScale); + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + +// char temp[256]; +// sprintf(temp,"Viewport: %i %i %i %i %f %f",vp.X,vp.Y,vp.Width,vp.Height,vp.MinZ,vp.MaxZ); +// g_VideoInitialize.pLog(temp, FALSE); + + D3D::dev->SetViewport(&vp); +} + +void Renderer::SetScissorBox(RECT &rc) +{ + rc.left = (int)(rc.left * xScale); + rc.top = (int)(rc.top * yScale); + rc.right = (int)(rc.right * xScale); + rc.bottom = (int)(rc.bottom * yScale); + if (rc.right >= rc.left && rc.bottom >= rc.top) + D3D::dev->SetScissorRect(&rc); + else + g_VideoInitialize.pLog("SCISSOR ERROR", FALSE); +} + +void Renderer::SetProjection(float* pMatrix, int constantIndex) +{ + D3DXMATRIX mtx; + if (pMatrix[6] == 0) + { + mtx.m[0][0] = pMatrix[0]; + mtx.m[1][0] = 0.0f; + mtx.m[2][0] = pMatrix[1]; + mtx.m[3][0] = -0.5f/m_width; + + mtx.m[0][1] = 0.0f; + mtx.m[1][1] = pMatrix[2]; + mtx.m[2][1] = pMatrix[3]; + mtx.m[3][1] = +0.5f/m_height; + + mtx.m[0][2] = 0.0f; + mtx.m[1][2] = 0.0f; + mtx.m[2][2] = -(1-pMatrix[4]); + mtx.m[3][2] = pMatrix[5]; + + mtx.m[0][3] = 0.0f; + mtx.m[1][3] = 0.0f; + mtx.m[2][3] = -1.0f; + mtx.m[3][3] = 0.0f; + } + else + { + mtx.m[0][0] = pMatrix[0]; + mtx.m[1][0] = 0.0f; + mtx.m[2][0] = 0.0f; + mtx.m[3][0] = pMatrix[1]-0.5f/m_width; // fix d3d pixel center + + mtx.m[0][1] = 0.0f; + mtx.m[1][1] = pMatrix[2]; + mtx.m[2][1] = 0.0f; + mtx.m[3][1] = pMatrix[3]+0.5f/m_height; // fix d3d pixel center + + mtx.m[0][2] = 0.0f; + mtx.m[1][2] = 0.0f; + mtx.m[2][2] = pMatrix[4]; + mtx.m[3][2] = -(-1 - pMatrix[5]); + + mtx.m[0][3] = 0; + mtx.m[1][3] = 0; + mtx.m[2][3] = 0.0f; + mtx.m[3][3] = 1.0f; + } + D3D::dev->SetVertexShaderConstantF(constantIndex, mtx, 4); +} + + +void Renderer::SetTexture( DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture ) +{ + if ( m_Textures[Stage] != pTexture ) + { + m_Textures[Stage] = pTexture; + D3D::dev->SetTexture( Stage, pTexture ); + } +} + + +void Renderer::SetFVF( DWORD FVF ) +{ + if ( m_FVF != FVF ) + { + m_FVF = FVF; + D3D::dev->SetFVF( FVF ); + } +} + + +void Renderer::SetRenderState( D3DRENDERSTATETYPE State, DWORD Value ) +{ + if ( m_RenderStates[State] != Value ) + { + m_RenderStates[State] = Value; + D3D::dev->SetRenderState( State, Value ); + } +} + + +void Renderer::SetTextureStageState( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value ) +{ + if ( m_TextureStageStates[Stage][Type] != Value ) + { + m_TextureStageStates[Stage][Type] = Value; + D3D::dev->SetTextureStageState( Stage, Type, Value ); + } +} + + +void Renderer::SetSamplerState( DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value ) +{ + if ( m_SamplerStates[Sampler][Type] != Value ) + { + m_SamplerStates[Sampler][Type] = Value; + D3D::dev->SetSamplerState( Sampler, Type, Value ); + } +} + + +void Renderer::DrawPrimitiveUP( D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, const void* pVertexStreamZeroData, UINT VertexStreamZeroStride ) +{ + D3D::dev->DrawPrimitiveUP( PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride ); +} + + +void Renderer::DrawPrimitive( D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount ) +{ + D3D::dev->DrawPrimitive( PrimitiveType, StartVertex, PrimitiveCount ); +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/ShaderManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/ShaderManager.cpp index 5320fbaa21..af7d36f191 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/ShaderManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/ShaderManager.cpp @@ -1,218 +1,218 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "D3DBase.h" -#include "Statistics.h" -#include "Utils.h" -#include "Profiler.h" -#include "ShaderManager.h" -#include "VertexLoader.h" -#include "BPMemory.h" -#include "XFMemory.h" - - -//I hope we don't get too many hash collisions :p -//all these magic numbers are primes, it should help a bit -tevhash GetCurrentTEV() -{ - u32 hash = bpmem.genMode.numindstages + bpmem.genMode.numtevstages*11 + bpmem.genMode.numtexgens*8*17; - for (int i = 0; i < (int)bpmem.genMode.numtevstages+1; i++) - { - hash = _rotl(hash,3) ^ (bpmem.combiners[i].colorC.hex*13); - hash = _rotl(hash,7) ^ ((bpmem.combiners[i].alphaC.hex&0xFFFFFFFC)*3); - hash = _rotl(hash,9) ^ xfregs.texcoords[i].texmtxinfo.projection*451; - } - for (int i = 0; i < (int)bpmem.genMode.numtevstages/2+1; i++) - { - hash = _rotl(hash,13) ^ (bpmem.tevorders[i].hex*7); - } - for (int i = 0; i < 8; i++) - { - hash = _rotl(hash,3) ^ bpmem.tevksel[i].swap1; - hash = _rotl(hash,3) ^ bpmem.tevksel[i].swap2; - } - hash ^= bpmem.dstalpha.enable ^ 0xc0debabe; - hash = _rotl(hash,4) ^ bpmem.alphaFunc.comp0*7; - hash = _rotl(hash,4) ^ bpmem.alphaFunc.comp1*13; - hash = _rotl(hash,4) ^ bpmem.alphaFunc.logic*11; - return hash; -} - - -PShaderCache::PSCache PShaderCache::pshaders; -VShaderCache::VSCache VShaderCache::vshaders; - -void PShaderCache::Init() -{ - -} - - -void PShaderCache::Shutdown() -{ - PSCache::iterator iter = pshaders.begin(); - for (;iter!=pshaders.end();iter++) - iter->second.Destroy(); - pshaders.clear(); -} - - -void PShaderCache::SetShader() -{ - if (D3D::GetShaderVersion() < 2) - return; // we are screwed - - static LPDIRECT3DPIXELSHADER9 lastShader = 0; - DVSTARTPROFILE(); - - tevhash currentHash = GetCurrentTEV(); - - PSCache::iterator iter; - iter = pshaders.find(currentHash); - - if (iter != pshaders.end()) - { - iter->second.frameCount = frameCount; - PSCacheEntry &entry = iter->second; - if (!lastShader || entry.shader != lastShader) - { - D3D::dev->SetPixelShader(entry.shader); - lastShader = entry.shader; - } - return; - } - - const char *code = GeneratePixelShader(); - LPDIRECT3DPIXELSHADER9 shader = D3D::CompilePShader(code, int(strlen(code))); - if (shader) - { - //Make an entry in the table - PSCacheEntry newentry; - newentry.shader = shader; - newentry.frameCount = frameCount; - pshaders[currentHash] = newentry; - } - - D3D::dev->SetPixelShader(shader); - - INCSTAT(stats.numPixelShadersCreated); - SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size()); -} - -void PShaderCache::Cleanup() -{ - PSCache::iterator iter; - iter = pshaders.begin(); - - while (iter != pshaders.end()) - { - PSCacheEntry &entry = iter->second; - if (entry.frameCount < frameCount-30) - { - entry.Destroy(); - iter = pshaders.erase(iter); - } - else - { - iter++; - } - } - SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size()); -} - - -void VShaderCache::Init() -{ - - -} - - -void VShaderCache::Shutdown() -{ - VSCache::iterator iter = vshaders.begin(); - for (; iter != vshaders.end(); iter++) - iter->second.Destroy(); - vshaders.clear(); -} - - -void VShaderCache::SetShader() -{ - static LPDIRECT3DVERTEXSHADER9 shader = NULL; - if (D3D::GetShaderVersion() < 2) - return; // we are screwed - - if (shader) { - //D3D::dev->SetVertexShader(shader); - return; - } - - static LPDIRECT3DVERTEXSHADER9 lastShader = 0; - DVSTARTPROFILE(); - - tevhash currentHash = GetCurrentTEV(); - - VSCache::iterator iter; - iter = vshaders.find(currentHash); - - if (iter != vshaders.end()) - { - iter->second.frameCount=frameCount; - VSCacheEntry &entry = iter->second; - if (!lastShader || entry.shader != lastShader) - { - D3D::dev->SetVertexShader(entry.shader); - lastShader = entry.shader; - } - return; - } - - const char *code = GenerateVertexShader(); - shader = D3D::CompileVShader(code, int(strlen(code))); - if (shader) - { - //Make an entry in the table - VSCacheEntry entry; - entry.shader = shader; - entry.frameCount=frameCount; - vshaders[currentHash] = entry; - } - - D3D::dev->SetVertexShader(shader); - - INCSTAT(stats.numVertexShadersCreated); - SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size()); -} - -void VShaderCache::Cleanup() -{ - for (VSCache::iterator iter=vshaders.begin(); iter!=vshaders.end();) - { - VSCacheEntry &entry = iter->second; - if (entry.frameCount < frameCount - 30) - { - entry.Destroy(); - iter = vshaders.erase(iter); - } - else - { - ++iter; - } - } - SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size()); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "D3DBase.h" +#include "Statistics.h" +#include "Utils.h" +#include "Profiler.h" +#include "ShaderManager.h" +#include "VertexLoader.h" +#include "BPMemory.h" +#include "XFMemory.h" + + +//I hope we don't get too many hash collisions :p +//all these magic numbers are primes, it should help a bit +tevhash GetCurrentTEV() +{ + u32 hash = bpmem.genMode.numindstages + bpmem.genMode.numtevstages*11 + bpmem.genMode.numtexgens*8*17; + for (int i = 0; i < (int)bpmem.genMode.numtevstages+1; i++) + { + hash = _rotl(hash,3) ^ (bpmem.combiners[i].colorC.hex*13); + hash = _rotl(hash,7) ^ ((bpmem.combiners[i].alphaC.hex&0xFFFFFFFC)*3); + hash = _rotl(hash,9) ^ xfregs.texcoords[i].texmtxinfo.projection*451; + } + for (int i = 0; i < (int)bpmem.genMode.numtevstages/2+1; i++) + { + hash = _rotl(hash,13) ^ (bpmem.tevorders[i].hex*7); + } + for (int i = 0; i < 8; i++) + { + hash = _rotl(hash,3) ^ bpmem.tevksel[i].swap1; + hash = _rotl(hash,3) ^ bpmem.tevksel[i].swap2; + } + hash ^= bpmem.dstalpha.enable ^ 0xc0debabe; + hash = _rotl(hash,4) ^ bpmem.alphaFunc.comp0*7; + hash = _rotl(hash,4) ^ bpmem.alphaFunc.comp1*13; + hash = _rotl(hash,4) ^ bpmem.alphaFunc.logic*11; + return hash; +} + + +PShaderCache::PSCache PShaderCache::pshaders; +VShaderCache::VSCache VShaderCache::vshaders; + +void PShaderCache::Init() +{ + +} + + +void PShaderCache::Shutdown() +{ + PSCache::iterator iter = pshaders.begin(); + for (;iter!=pshaders.end();iter++) + iter->second.Destroy(); + pshaders.clear(); +} + + +void PShaderCache::SetShader() +{ + if (D3D::GetShaderVersion() < 2) + return; // we are screwed + + static LPDIRECT3DPIXELSHADER9 lastShader = 0; + DVSTARTPROFILE(); + + tevhash currentHash = GetCurrentTEV(); + + PSCache::iterator iter; + iter = pshaders.find(currentHash); + + if (iter != pshaders.end()) + { + iter->second.frameCount = frameCount; + PSCacheEntry &entry = iter->second; + if (!lastShader || entry.shader != lastShader) + { + D3D::dev->SetPixelShader(entry.shader); + lastShader = entry.shader; + } + return; + } + + const char *code = GeneratePixelShader(); + LPDIRECT3DPIXELSHADER9 shader = D3D::CompilePShader(code, int(strlen(code))); + if (shader) + { + //Make an entry in the table + PSCacheEntry newentry; + newentry.shader = shader; + newentry.frameCount = frameCount; + pshaders[currentHash] = newentry; + } + + D3D::dev->SetPixelShader(shader); + + INCSTAT(stats.numPixelShadersCreated); + SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size()); +} + +void PShaderCache::Cleanup() +{ + PSCache::iterator iter; + iter = pshaders.begin(); + + while (iter != pshaders.end()) + { + PSCacheEntry &entry = iter->second; + if (entry.frameCount < frameCount-30) + { + entry.Destroy(); + iter = pshaders.erase(iter); + } + else + { + iter++; + } + } + SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size()); +} + + +void VShaderCache::Init() +{ + + +} + + +void VShaderCache::Shutdown() +{ + VSCache::iterator iter = vshaders.begin(); + for (; iter != vshaders.end(); iter++) + iter->second.Destroy(); + vshaders.clear(); +} + + +void VShaderCache::SetShader() +{ + static LPDIRECT3DVERTEXSHADER9 shader = NULL; + if (D3D::GetShaderVersion() < 2) + return; // we are screwed + + if (shader) { + //D3D::dev->SetVertexShader(shader); + return; + } + + static LPDIRECT3DVERTEXSHADER9 lastShader = 0; + DVSTARTPROFILE(); + + tevhash currentHash = GetCurrentTEV(); + + VSCache::iterator iter; + iter = vshaders.find(currentHash); + + if (iter != vshaders.end()) + { + iter->second.frameCount=frameCount; + VSCacheEntry &entry = iter->second; + if (!lastShader || entry.shader != lastShader) + { + D3D::dev->SetVertexShader(entry.shader); + lastShader = entry.shader; + } + return; + } + + const char *code = GenerateVertexShader(); + shader = D3D::CompileVShader(code, int(strlen(code))); + if (shader) + { + //Make an entry in the table + VSCacheEntry entry; + entry.shader = shader; + entry.frameCount=frameCount; + vshaders[currentHash] = entry; + } + + D3D::dev->SetVertexShader(shader); + + INCSTAT(stats.numVertexShadersCreated); + SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size()); +} + +void VShaderCache::Cleanup() +{ + for (VSCache::iterator iter=vshaders.begin(); iter!=vshaders.end();) + { + VSCacheEntry &entry = iter->second; + if (entry.frameCount < frameCount - 30) + { + entry.Destroy(); + iter = vshaders.erase(iter); + } + else + { + ++iter; + } + } + SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size()); +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index a627df974d..1ee1263362 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -1,251 +1,251 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include - -#include "Common.h" -#include "Statistics.h" - -#include "D3DBase.h" -#include "D3DTexture.h" - -#include "Render.h" - -#include "TextureDecoder.h" -#include "TextureCache.h" - -#include "Config.h" -#include "main.h" - -u8 *TextureCache::temp = NULL; -TextureCache::TexCache TextureCache::textures; - -extern int frameCount; - -#define TEMP_SIZE (1024*1024*4) - -void TextureCache::TCacheEntry::Destroy() -{ - if (texture) - texture->Release(); - texture = 0; - if (!isRenderTarget) { - u32 *ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(addr + hashoffset*4); - if (*ptr == hash) - *ptr = oldpixel; - } -} - -void TextureCache::Init() -{ - temp = (u8*)VirtualAlloc(0,TEMP_SIZE,MEM_COMMIT,PAGE_READWRITE); - TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter); -} - -void TextureCache::Invalidate() -{ - TexCache::iterator iter = textures.begin(); - for (; iter != textures.end(); iter++) - iter->second.Destroy(); - textures.clear(); - TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter); -} - -void TextureCache::Shutdown() -{ - Invalidate(); - - if (temp != NULL) - { - VirtualFree(temp, 0, MEM_RELEASE); - temp = NULL; - } -} - -void TextureCache::Cleanup() -{ - TexCache::iterator iter=textures.begin(); - - while(iter != textures.end()) - { - if (frameCount>20+iter->second.frameCount) - { - if (!iter->second.isRenderTarget) - { - iter->second.Destroy(); - iter = textures.erase(iter); - } - else - { - iter++; - } - } - else - { - iter++; - } - } -} - -void TextureCache::Load(int stage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt) -{ - if (address == 0) - return; - TexCache::iterator iter = textures.find(address); - - u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address); - - int palSize = TexDecoder_GetPaletteSize(format); - u32 palhash = 0xc0debabe; - if (palSize) - { - if (palSize>16) - palSize = 16; //let's not do excessive amount of checking - u8 *pal = g_VideoInitialize.pGetMemoryPointer(tlutaddr); - if (pal != 0) - { - for (int i=0; isecond; - - if (entry.isRenderTarget || (((u32 *)ptr)[entry.hashoffset] == entry.hash && palhash == entry.paletteHash)) //stupid, improve - { - iter->second.frameCount = frameCount; - if (lastTexture[stage] == iter->second.texture) - { - return; - } - lastTexture[stage] = iter->second.texture; - - // D3D::dev->SetTexture(stage,iter->second.texture); - Renderer::SetTexture( stage, iter->second.texture ); - - return; - } - else - { - TCacheEntry &entry = iter->second; -/* if (width == iter->second.w && height==entry.h && format==entry.fmt) - { - LPDIRECT3DTEXTURE9 tex = entry.texture; - int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16; - int expandedWidth = (width+bs) & (~bs); - D3DFORMAT dfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt); - D3D::ReplaceTexture2D(tex,temp,width,height,expandedWidth,dfmt); - D3D::dev->SetTexture(stage,tex); - return; - } - else - {*/ - iter->second.Destroy(); - textures.erase(iter); - //} - } - } - - int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16; - int expandedWidth = (width+bs) & (~bs); - PC_TexFormat pcfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt); - D3DFORMAT d3d_fmt; - switch (pcfmt) { - case PC_TEX_FMT_BGRA32: - d3d_fmt = D3DFMT_A8R8G8B8; - break; - } - - //Make an entry in the table - TCacheEntry entry; - entry.hashoffset = 0; - entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF); - entry.paletteHash = palhash; - entry.oldpixel = ((u32 *)ptr)[entry.hashoffset]; - ((u32 *)ptr)[entry.hashoffset] = entry.hash; - - entry.addr = address; - entry.isRenderTarget=false; - entry.isNonPow2 = ((width&(width-1)) || (height&(height-1))); - entry.texture = D3D::CreateTexture2D((BYTE*)temp, width, height, expandedWidth, d3d_fmt); - entry.frameCount = frameCount; - entry.w=width; - entry.h=height; - entry.fmt=format; - textures[address] = entry; - - if (g_Config.bDumpTextures) - { // dump texture to file - static int counter = 0; - char szTemp[MAX_PATH]; - sprintf(szTemp, "%s\\txt_%04i_%i.png", g_Config.texDumpPath.c_str(), counter++, format); - - D3DXSaveTextureToFile(szTemp,D3DXIFF_BMP,entry.texture,0); - } - - INCSTAT(stats.numTexturesCreated); - SETSTAT(stats.numTexturesAlive, (int)textures.size()); - - //Set the texture! - // D3D::dev->SetTexture(stage,entry.texture); - Renderer::SetTexture( stage, entry.texture ); - - lastTexture[stage] = entry.texture; -} - - -void TextureCache::CopyEFBToRenderTarget(u32 address, RECT *source) -{ - TexCache::iterator iter; - LPDIRECT3DTEXTURE9 tex; - iter = textures.find(address); - if (iter != textures.end()) - { - if (!iter->second.isRenderTarget) - { - g_VideoInitialize.pLog("Using non-rendertarget texture as render target!!! WTF?", FALSE); - //TODO: remove it and recreate it as a render target - } - tex = iter->second.texture; - iter->second.frameCount=frameCount; - } - else - { - TCacheEntry entry; - entry.isRenderTarget=true; - entry.hash = 0; - entry.hashoffset = 0; - entry.frameCount = frameCount; - // TODO(ector): infer this size in some sensible way - D3D::dev->CreateTexture(512,512,1,D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &entry.texture, 0); - textures[address] = entry; - tex = entry.texture; - } - LPDIRECT3DSURFACE9 srcSurface,destSurface; - tex->GetSurfaceLevel(0,&destSurface); - srcSurface = D3D::GetBackBufferSurface(); - D3D::dev->StretchRect(srcSurface,source,destSurface,0,D3DTEXF_NONE); - destSurface->Release(); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include + +#include "Common.h" +#include "Statistics.h" + +#include "D3DBase.h" +#include "D3DTexture.h" + +#include "Render.h" + +#include "TextureDecoder.h" +#include "TextureCache.h" + +#include "Config.h" +#include "main.h" + +u8 *TextureCache::temp = NULL; +TextureCache::TexCache TextureCache::textures; + +extern int frameCount; + +#define TEMP_SIZE (1024*1024*4) + +void TextureCache::TCacheEntry::Destroy() +{ + if (texture) + texture->Release(); + texture = 0; + if (!isRenderTarget) { + u32 *ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(addr + hashoffset*4); + if (*ptr == hash) + *ptr = oldpixel; + } +} + +void TextureCache::Init() +{ + temp = (u8*)VirtualAlloc(0,TEMP_SIZE,MEM_COMMIT,PAGE_READWRITE); + TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter); +} + +void TextureCache::Invalidate() +{ + TexCache::iterator iter = textures.begin(); + for (; iter != textures.end(); iter++) + iter->second.Destroy(); + textures.clear(); + TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter); +} + +void TextureCache::Shutdown() +{ + Invalidate(); + + if (temp != NULL) + { + VirtualFree(temp, 0, MEM_RELEASE); + temp = NULL; + } +} + +void TextureCache::Cleanup() +{ + TexCache::iterator iter=textures.begin(); + + while(iter != textures.end()) + { + if (frameCount>20+iter->second.frameCount) + { + if (!iter->second.isRenderTarget) + { + iter->second.Destroy(); + iter = textures.erase(iter); + } + else + { + iter++; + } + } + else + { + iter++; + } + } +} + +void TextureCache::Load(int stage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt) +{ + if (address == 0) + return; + TexCache::iterator iter = textures.find(address); + + u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address); + + int palSize = TexDecoder_GetPaletteSize(format); + u32 palhash = 0xc0debabe; + if (palSize) + { + if (palSize>16) + palSize = 16; //let's not do excessive amount of checking + u8 *pal = g_VideoInitialize.pGetMemoryPointer(tlutaddr); + if (pal != 0) + { + for (int i=0; isecond; + + if (entry.isRenderTarget || (((u32 *)ptr)[entry.hashoffset] == entry.hash && palhash == entry.paletteHash)) //stupid, improve + { + iter->second.frameCount = frameCount; + if (lastTexture[stage] == iter->second.texture) + { + return; + } + lastTexture[stage] = iter->second.texture; + + // D3D::dev->SetTexture(stage,iter->second.texture); + Renderer::SetTexture( stage, iter->second.texture ); + + return; + } + else + { + TCacheEntry &entry = iter->second; +/* if (width == iter->second.w && height==entry.h && format==entry.fmt) + { + LPDIRECT3DTEXTURE9 tex = entry.texture; + int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16; + int expandedWidth = (width+bs) & (~bs); + D3DFORMAT dfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt); + D3D::ReplaceTexture2D(tex,temp,width,height,expandedWidth,dfmt); + D3D::dev->SetTexture(stage,tex); + return; + } + else + {*/ + iter->second.Destroy(); + textures.erase(iter); + //} + } + } + + int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16; + int expandedWidth = (width+bs) & (~bs); + PC_TexFormat pcfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt); + D3DFORMAT d3d_fmt; + switch (pcfmt) { + case PC_TEX_FMT_BGRA32: + d3d_fmt = D3DFMT_A8R8G8B8; + break; + } + + //Make an entry in the table + TCacheEntry entry; + entry.hashoffset = 0; + entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF); + entry.paletteHash = palhash; + entry.oldpixel = ((u32 *)ptr)[entry.hashoffset]; + ((u32 *)ptr)[entry.hashoffset] = entry.hash; + + entry.addr = address; + entry.isRenderTarget=false; + entry.isNonPow2 = ((width&(width-1)) || (height&(height-1))); + entry.texture = D3D::CreateTexture2D((BYTE*)temp, width, height, expandedWidth, d3d_fmt); + entry.frameCount = frameCount; + entry.w=width; + entry.h=height; + entry.fmt=format; + textures[address] = entry; + + if (g_Config.bDumpTextures) + { // dump texture to file + static int counter = 0; + char szTemp[MAX_PATH]; + sprintf(szTemp, "%s\\txt_%04i_%i.png", g_Config.texDumpPath.c_str(), counter++, format); + + D3DXSaveTextureToFile(szTemp,D3DXIFF_BMP,entry.texture,0); + } + + INCSTAT(stats.numTexturesCreated); + SETSTAT(stats.numTexturesAlive, (int)textures.size()); + + //Set the texture! + // D3D::dev->SetTexture(stage,entry.texture); + Renderer::SetTexture( stage, entry.texture ); + + lastTexture[stage] = entry.texture; +} + + +void TextureCache::CopyEFBToRenderTarget(u32 address, RECT *source) +{ + TexCache::iterator iter; + LPDIRECT3DTEXTURE9 tex; + iter = textures.find(address); + if (iter != textures.end()) + { + if (!iter->second.isRenderTarget) + { + g_VideoInitialize.pLog("Using non-rendertarget texture as render target!!! WTF?", FALSE); + //TODO: remove it and recreate it as a render target + } + tex = iter->second.texture; + iter->second.frameCount=frameCount; + } + else + { + TCacheEntry entry; + entry.isRenderTarget=true; + entry.hash = 0; + entry.hashoffset = 0; + entry.frameCount = frameCount; + // TODO(ector): infer this size in some sensible way + D3D::dev->CreateTexture(512,512,1,D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &entry.texture, 0); + textures[address] = entry; + tex = entry.texture; + } + LPDIRECT3DSURFACE9 srcSurface,destSurface; + tex->GetSurfaceLevel(0,&destSurface); + srcSurface = D3D::GetBackBufferSurface(); + D3D::dev->StretchRect(srcSurface,source,destSurface,0,D3DTEXF_NONE); + destSurface->Release(); +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TransformEngine.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TransformEngine.cpp index 2865c4b991..f82c5fd342 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TransformEngine.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TransformEngine.cpp @@ -1,372 +1,372 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include - -#include "Common.h" -#include "Profiler.h" -// #include "Globals.h" -#include "Vec3.h" -#include "TransformEngine.h" -#include "VertexManager.h" -#include "VertexLoader.h" - -#include "BPStructs.h" -#include "XFStructs.h" -#include "Utils.h" - -#include "RGBAFloat.h" - -float *CTransformEngine::m_pPosMatrix; -float *CTransformEngine::m_pNormalMatrix; -float *CTransformEngine::m_pTexMatrix[8]; -float *CTransformEngine::m_pTexPostMatrix[8]; - -const Light *GetLight(int i) -{ - return (const Light *)(xfmem + XFMEM_LIGHTS) + i; -} - -float DoLighting(const Light *light, const LitChannel &chan, const Vec3 &pos, const Vec3 &normal) -{ - float val; - if (chan.attnfunc == 0 || chan.attnfunc == 2) //no attn - { - Vec3 ldir = (Vec3(light->dpos) - pos); - val = ldir.normalized() * normal; - } - else - { - float aattn = 0; - float d; - float mul = 1.0f; - if (chan.attnfunc == 3) - { - Vec3 ldir = (Vec3(light->dpos) - pos); - d = ldir.length(); - Vec3 ldirNorm = ldir / d; //normalize - float l = ldirNorm * normal; - aattn = Vec3(light->ddir) * ldirNorm; - mul = l; - } - else if (chan.attnfunc == 1) - { - d = aattn = Vec3(light->shalfangle) * normal; - mul = (Vec3(light->sdir) * normal > 0) ? (normal * Vec3(light->shalfangle)) : 0; - if (mul < 0) - mul = 0; - } - - float spot = (light->a2*aattn*aattn + light->a1*aattn + light->a0); - float dist = 1.0f/(light->k2*d*d + light->k1*d + light->k0); - if (spot<0) - spot=0; - - val = mul * spot * dist; - } - - if (val < 0 && chan.diffusefunc == 2) // clamp - val = 0; - - return val; -} - -void VtxMulMtx43T(Vec3 &out, const Vec3 &in, const float pMatrix[12]) -{ - out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2] + 1 * pMatrix[3]; - out.y = in.x * pMatrix[4] + in.y * pMatrix[5] + in.z * pMatrix[6] + 1 * pMatrix[7]; - out.z = in.x * pMatrix[8] + in.y * pMatrix[9] + in.z * pMatrix[10] + 1 * pMatrix[11]; -} - -void VtxMulMtx43(Vec3 &out, const Vec3 &in, const float pMatrix[12]) -{ - VtxMulMtx43T(out,in,pMatrix); - //TODO(XK): Turns out that SSE2 computations are slower... Can anyone do - // anything about it? - /* - F32vec4 a(in.x, in.y, in.z, 1), b(pMatrix[0], pMatrix[1], pMatrix[2], pMatrix[3]); - - out.x = add_horizontal(a * b); - - b[0] = pMatrix[4]; b[1] = pMatrix[5]; b[2] = pMatrix[6]; b[3] = pMatrix[7]; - - out.y = add_horizontal(a * b); - - b[0] = pMatrix[8]; b[1] = pMatrix[9]; b[2] = pMatrix[10]; b[3] = pMatrix[11]; - - out.z = add_horizontal(a * b); - */ -} - -void VtxMulMtx42(Vec3 &out, const Vec3 &in, const float pMatrix[8]) -{ - out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2] + 1 * pMatrix[3]; - out.y = in.x * pMatrix[4] + in.y * pMatrix[5] + in.z * pMatrix[6] + 1 * pMatrix[7]; -} - -void VtxMulMtx33(Vec3 &out, const Vec3 &in, const float pMatrix[9]) -{ - out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2]; - out.y = in.x * pMatrix[3] + in.y * pMatrix[4] + in.z * pMatrix[5]; - out.z = in.x * pMatrix[6] + in.y * pMatrix[7] + in.z * pMatrix[8]; -} - -void CTransformEngine::TransformVertices(int _numVertices, const DecodedVArray *varray, D3DVertex *vbuffer) -{ - if (vbuffer == 0) - { - MessageBox(0,"TransformVertices : vbuffer == 0","WTF",0); - } - - DVSTARTPROFILE(); - - RGBAFloat lightColors[8]; - RGBAFloat lightVals[8]; - RGBAFloat chans[2]; - - u32 components = varray->GetComponents(); - - // TODO: only for active lights - for (int i=0; i<8; i++) - lightColors[i].convert_GC(GetLight(i)->color); - - for (int i=0; i<_numVertices; i++) - { - ////////////////////////////////////////////////////////////////////////// - //Step 1: xform position and normal - ////////////////////////////////////////////////////////////////////////// - - Vec3 OrigPos = varray->GetPos(i); - - if (varray->hasPosMatIdx) - { - int index = varray->GetPosMtxInd(i); - SetPosNormalMatrix( - (float*)xfmem + (index & 63) * 4, //CHECK - (float*)xfmem + 0x400 + 3 * (index & 31)); //CHECK - } - - for (int j = 0; j < 8; j++) - { - if (varray->hasTexMatIdx[j]) - { - float *flipmem = (float *)xfmem; - int index = varray->GetTexMtxInd(j, i); - SetTexMatrix(j, flipmem + index * 4); - } - } - - Vec3 TempPos; - - // m_pPosMatrix can be switched out, through matrixindex vertex components - VtxMulMtx43(TempPos, OrigPos, m_pPosMatrix); - - Vec3 TempNormal; - Vec3 OrigNormal; - if (varray->hasNrm) - { - OrigNormal = varray->GetNormal(0, i); - VtxMulMtx33(TempNormal, OrigNormal, m_pNormalMatrix); - TempNormal.normalize(); - } - else - { - OrigNormal.setZero(); - TempNormal.setZero(); - } - - ////////////////////////////////////////////////////////////////////////// - //Step 2: Light! - ////////////////////////////////////////////////////////////////////////// - //find all used lights - u32 lightMask = - xfregs.colChans[0].color.GetFullLightMask() | xfregs.colChans[0].alpha.GetFullLightMask() | - xfregs.colChans[1].color.GetFullLightMask() | xfregs.colChans[1].alpha.GetFullLightMask(); - - float r0=0,g0=0,b0=0,a0=0; - - //go through them and compute the lit colors - //Sum lighting for both two color channels if they're active - for (int j = 0; j < (int)bpmem.genMode.numcolchans; j++) - { - RGBAFloat material; - RGBAFloat lightSum(0,0,0,0); - - bool hasColorJ = (components & (VertexLoader::VB_HAS_COL0 << j)) != 0; - - //get basic material color from appropriate sources (this would compile nicely!:) - if (xfregs.colChans[j].color.matsource == GX_SRC_REG) - material.convertRGB_GC(xfregs.colChans[j].matColor); - else - { - if (hasColorJ) - material.convertRGB(varray->GetColor(j, i)); - else - material.r=material.g=material.b=1.0f; - } - - if (xfregs.colChans[j].alpha.matsource == GX_SRC_REG) - material.convertA_GC(xfregs.colChans[j].matColor); - else - { - if (hasColorJ) - material.convertA(varray->GetColor(j, i)); - else - material.a=1.0f; - } - - //combine together the light values from the lights that affect the color - if (xfregs.colChans[j].color.enablelighting) - { - //choose ambient source and start our lightsum accumulator with its value.. - if (xfregs.colChans[j].color.ambsource == GX_SRC_REG) - lightSum.convertRGB_GC(xfregs.colChans[j].ambColor); //ambient - else - { - if (hasColorJ) - lightSum.convertRGB(varray->GetColor(j, i)); - else - { - lightSum.r=0.0f;lightSum.g=0.0f;lightSum.b=0.0f; - } - } - - //accumulate light colors - int cmask = xfregs.colChans[j].color.GetFullLightMask(); - for (int l=0; l<8; l++) - { - if (cmask&1) - { - float val = DoLighting(GetLight(l), xfregs.colChans[j].color, TempPos, TempNormal); - float r = lightColors[l].r * val; - float g = lightColors[l].g * val; - float b = lightColors[l].b * val; - lightSum.r += r; - lightSum.g += g; - lightSum.b += b; - } - cmask >>= 1; - } - } - else - { - lightSum.r = lightSum.g = lightSum.b = 1.0f; - } - - //combine together the light values from the lights that affect alpha (should be rare) - if (xfregs.colChans[j].alpha.enablelighting) - { - //choose ambient source.. - if (xfregs.colChans[j].alpha.ambsource==GX_SRC_REG) - lightSum.convertA_GC(xfregs.colChans[j].ambColor); - else - { - if (hasColorJ) - lightSum.convertA(varray->GetColor(j, i)); - else - lightSum.a=0.0f; - } - //accumulate light alphas - int amask = xfregs.colChans[j].alpha.GetFullLightMask(); - for (int l = 0; l < 8; l++) - { - if (amask&1) - { - float val = DoLighting(GetLight(l), xfregs.colChans[j].alpha, TempPos, TempNormal); - float a = lightColors[l].a * val; - lightSum.a += a; - } - amask >>= 1; - } - } - else - { - lightSum.a=1.0f; - } - - chans[j] = lightSum * material; - chans[j].clamp(); - } - - ////////////////////////////////////////////////////////////////////////// - //Step 3: Generate texture coordinates! - ////////////////////////////////////////////////////////////////////////// - Vec3 TempUVs[8]; - for (int j = 0; j < xfregs.numTexGens; j++) - { - Vec3 t; - - switch (xfregs.texcoords[j].texmtxinfo.sourcerow) { - case XF_SRCGEOM_INROW: t = OrigPos; break; //HACK WTFF??? - case XF_SRCNORMAL_INROW: t = OrigNormal; break; - case XF_SRCCOLORS_INROW: break; //set uvs to something? - case XF_SRCBINORMAL_T_INROW: t=Vec3(0,0,0);break; - case XF_SRCBINORMAL_B_INROW: t=Vec3(0,0,0);break; - default: - { - int c = xfregs.texcoords[j].texmtxinfo.sourcerow - XF_SRCTEX0_INROW; - bool hasTCC = (components & (VertexLoader::VB_HAS_UV0 << c)) != 0; - if (c >= 0 && c <= 7 && hasTCC) - { - const DecUV &uv = varray->GetUV(c, i); - t = Vec3(uv.u, uv.v, 1); - } - } - } - - Vec3 out,out2; - switch (xfregs.texcoords[j].texmtxinfo.texgentype) - { - case XF_TEXGEN_COLOR_STRGBC0: - out = Vec3(chans[0].r*255, chans[0].g*255, 1)/255.0f; - break; - case XF_TEXGEN_COLOR_STRGBC1: - out = Vec3(chans[1].r*255, chans[1].g*255, 1)/255.0f; //FIX: take color1 instead - break; - case XF_TEXGEN_REGULAR: - if (xfregs.texcoords[j].texmtxinfo.projection) - VtxMulMtx43(out, t, m_pTexMatrix[j]); - else - VtxMulMtx42(out, t, m_pTexMatrix[j]); - break; - } - - if (xfregs.texcoords[j].postmtxinfo.normalize) - out.normalize(); - - int postMatrix = xfregs.texcoords[j].postmtxinfo.index; - float *pmtx = ((float*)xfmem) + 0x500 + postMatrix * 4; //CHECK - //multiply with postmatrix - VtxMulMtx43(TempUVs[j], out, pmtx); - } - - ////////////////////////////////////////////////////////////////////////// - //Step 4: Output the vertex! - ////////////////////////////////////////////////////////////////////////// - for (int j = 0; j < 2; j++) - chans[j].convertToD3DColor(vbuffer[i].colors[j]); - - vbuffer[i].pos = TempPos; - vbuffer[i].normal = TempNormal; - for (int j = 0; j < (int)bpmem.genMode.numtexgens; j++) - { - vbuffer[i].uv[j].u = TempUVs[j].x; - vbuffer[i].uv[j].v = TempUVs[j].y; - vbuffer[i].uv[j].w = TempUVs[j].z; - } - } -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include + +#include "Common.h" +#include "Profiler.h" +// #include "Globals.h" +#include "Vec3.h" +#include "TransformEngine.h" +#include "VertexManager.h" +#include "VertexLoader.h" + +#include "BPStructs.h" +#include "XFStructs.h" +#include "Utils.h" + +#include "RGBAFloat.h" + +float *CTransformEngine::m_pPosMatrix; +float *CTransformEngine::m_pNormalMatrix; +float *CTransformEngine::m_pTexMatrix[8]; +float *CTransformEngine::m_pTexPostMatrix[8]; + +const Light *GetLight(int i) +{ + return (const Light *)(xfmem + XFMEM_LIGHTS) + i; +} + +float DoLighting(const Light *light, const LitChannel &chan, const Vec3 &pos, const Vec3 &normal) +{ + float val; + if (chan.attnfunc == 0 || chan.attnfunc == 2) //no attn + { + Vec3 ldir = (Vec3(light->dpos) - pos); + val = ldir.normalized() * normal; + } + else + { + float aattn = 0; + float d; + float mul = 1.0f; + if (chan.attnfunc == 3) + { + Vec3 ldir = (Vec3(light->dpos) - pos); + d = ldir.length(); + Vec3 ldirNorm = ldir / d; //normalize + float l = ldirNorm * normal; + aattn = Vec3(light->ddir) * ldirNorm; + mul = l; + } + else if (chan.attnfunc == 1) + { + d = aattn = Vec3(light->shalfangle) * normal; + mul = (Vec3(light->sdir) * normal > 0) ? (normal * Vec3(light->shalfangle)) : 0; + if (mul < 0) + mul = 0; + } + + float spot = (light->a2*aattn*aattn + light->a1*aattn + light->a0); + float dist = 1.0f/(light->k2*d*d + light->k1*d + light->k0); + if (spot<0) + spot=0; + + val = mul * spot * dist; + } + + if (val < 0 && chan.diffusefunc == 2) // clamp + val = 0; + + return val; +} + +void VtxMulMtx43T(Vec3 &out, const Vec3 &in, const float pMatrix[12]) +{ + out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2] + 1 * pMatrix[3]; + out.y = in.x * pMatrix[4] + in.y * pMatrix[5] + in.z * pMatrix[6] + 1 * pMatrix[7]; + out.z = in.x * pMatrix[8] + in.y * pMatrix[9] + in.z * pMatrix[10] + 1 * pMatrix[11]; +} + +void VtxMulMtx43(Vec3 &out, const Vec3 &in, const float pMatrix[12]) +{ + VtxMulMtx43T(out,in,pMatrix); + //TODO(XK): Turns out that SSE2 computations are slower... Can anyone do + // anything about it? + /* + F32vec4 a(in.x, in.y, in.z, 1), b(pMatrix[0], pMatrix[1], pMatrix[2], pMatrix[3]); + + out.x = add_horizontal(a * b); + + b[0] = pMatrix[4]; b[1] = pMatrix[5]; b[2] = pMatrix[6]; b[3] = pMatrix[7]; + + out.y = add_horizontal(a * b); + + b[0] = pMatrix[8]; b[1] = pMatrix[9]; b[2] = pMatrix[10]; b[3] = pMatrix[11]; + + out.z = add_horizontal(a * b); + */ +} + +void VtxMulMtx42(Vec3 &out, const Vec3 &in, const float pMatrix[8]) +{ + out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2] + 1 * pMatrix[3]; + out.y = in.x * pMatrix[4] + in.y * pMatrix[5] + in.z * pMatrix[6] + 1 * pMatrix[7]; +} + +void VtxMulMtx33(Vec3 &out, const Vec3 &in, const float pMatrix[9]) +{ + out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2]; + out.y = in.x * pMatrix[3] + in.y * pMatrix[4] + in.z * pMatrix[5]; + out.z = in.x * pMatrix[6] + in.y * pMatrix[7] + in.z * pMatrix[8]; +} + +void CTransformEngine::TransformVertices(int _numVertices, const DecodedVArray *varray, D3DVertex *vbuffer) +{ + if (vbuffer == 0) + { + MessageBox(0,"TransformVertices : vbuffer == 0","WTF",0); + } + + DVSTARTPROFILE(); + + RGBAFloat lightColors[8]; + RGBAFloat lightVals[8]; + RGBAFloat chans[2]; + + u32 components = varray->GetComponents(); + + // TODO: only for active lights + for (int i=0; i<8; i++) + lightColors[i].convert_GC(GetLight(i)->color); + + for (int i=0; i<_numVertices; i++) + { + ////////////////////////////////////////////////////////////////////////// + //Step 1: xform position and normal + ////////////////////////////////////////////////////////////////////////// + + Vec3 OrigPos = varray->GetPos(i); + + if (varray->hasPosMatIdx) + { + int index = varray->GetPosMtxInd(i); + SetPosNormalMatrix( + (float*)xfmem + (index & 63) * 4, //CHECK + (float*)xfmem + 0x400 + 3 * (index & 31)); //CHECK + } + + for (int j = 0; j < 8; j++) + { + if (varray->hasTexMatIdx[j]) + { + float *flipmem = (float *)xfmem; + int index = varray->GetTexMtxInd(j, i); + SetTexMatrix(j, flipmem + index * 4); + } + } + + Vec3 TempPos; + + // m_pPosMatrix can be switched out, through matrixindex vertex components + VtxMulMtx43(TempPos, OrigPos, m_pPosMatrix); + + Vec3 TempNormal; + Vec3 OrigNormal; + if (varray->hasNrm) + { + OrigNormal = varray->GetNormal(0, i); + VtxMulMtx33(TempNormal, OrigNormal, m_pNormalMatrix); + TempNormal.normalize(); + } + else + { + OrigNormal.setZero(); + TempNormal.setZero(); + } + + ////////////////////////////////////////////////////////////////////////// + //Step 2: Light! + ////////////////////////////////////////////////////////////////////////// + //find all used lights + u32 lightMask = + xfregs.colChans[0].color.GetFullLightMask() | xfregs.colChans[0].alpha.GetFullLightMask() | + xfregs.colChans[1].color.GetFullLightMask() | xfregs.colChans[1].alpha.GetFullLightMask(); + + float r0=0,g0=0,b0=0,a0=0; + + //go through them and compute the lit colors + //Sum lighting for both two color channels if they're active + for (int j = 0; j < (int)bpmem.genMode.numcolchans; j++) + { + RGBAFloat material; + RGBAFloat lightSum(0,0,0,0); + + bool hasColorJ = (components & (VertexLoader::VB_HAS_COL0 << j)) != 0; + + //get basic material color from appropriate sources (this would compile nicely!:) + if (xfregs.colChans[j].color.matsource == GX_SRC_REG) + material.convertRGB_GC(xfregs.colChans[j].matColor); + else + { + if (hasColorJ) + material.convertRGB(varray->GetColor(j, i)); + else + material.r=material.g=material.b=1.0f; + } + + if (xfregs.colChans[j].alpha.matsource == GX_SRC_REG) + material.convertA_GC(xfregs.colChans[j].matColor); + else + { + if (hasColorJ) + material.convertA(varray->GetColor(j, i)); + else + material.a=1.0f; + } + + //combine together the light values from the lights that affect the color + if (xfregs.colChans[j].color.enablelighting) + { + //choose ambient source and start our lightsum accumulator with its value.. + if (xfregs.colChans[j].color.ambsource == GX_SRC_REG) + lightSum.convertRGB_GC(xfregs.colChans[j].ambColor); //ambient + else + { + if (hasColorJ) + lightSum.convertRGB(varray->GetColor(j, i)); + else + { + lightSum.r=0.0f;lightSum.g=0.0f;lightSum.b=0.0f; + } + } + + //accumulate light colors + int cmask = xfregs.colChans[j].color.GetFullLightMask(); + for (int l=0; l<8; l++) + { + if (cmask&1) + { + float val = DoLighting(GetLight(l), xfregs.colChans[j].color, TempPos, TempNormal); + float r = lightColors[l].r * val; + float g = lightColors[l].g * val; + float b = lightColors[l].b * val; + lightSum.r += r; + lightSum.g += g; + lightSum.b += b; + } + cmask >>= 1; + } + } + else + { + lightSum.r = lightSum.g = lightSum.b = 1.0f; + } + + //combine together the light values from the lights that affect alpha (should be rare) + if (xfregs.colChans[j].alpha.enablelighting) + { + //choose ambient source.. + if (xfregs.colChans[j].alpha.ambsource==GX_SRC_REG) + lightSum.convertA_GC(xfregs.colChans[j].ambColor); + else + { + if (hasColorJ) + lightSum.convertA(varray->GetColor(j, i)); + else + lightSum.a=0.0f; + } + //accumulate light alphas + int amask = xfregs.colChans[j].alpha.GetFullLightMask(); + for (int l = 0; l < 8; l++) + { + if (amask&1) + { + float val = DoLighting(GetLight(l), xfregs.colChans[j].alpha, TempPos, TempNormal); + float a = lightColors[l].a * val; + lightSum.a += a; + } + amask >>= 1; + } + } + else + { + lightSum.a=1.0f; + } + + chans[j] = lightSum * material; + chans[j].clamp(); + } + + ////////////////////////////////////////////////////////////////////////// + //Step 3: Generate texture coordinates! + ////////////////////////////////////////////////////////////////////////// + Vec3 TempUVs[8]; + for (int j = 0; j < xfregs.numTexGens; j++) + { + Vec3 t; + + switch (xfregs.texcoords[j].texmtxinfo.sourcerow) { + case XF_SRCGEOM_INROW: t = OrigPos; break; //HACK WTFF??? + case XF_SRCNORMAL_INROW: t = OrigNormal; break; + case XF_SRCCOLORS_INROW: break; //set uvs to something? + case XF_SRCBINORMAL_T_INROW: t=Vec3(0,0,0);break; + case XF_SRCBINORMAL_B_INROW: t=Vec3(0,0,0);break; + default: + { + int c = xfregs.texcoords[j].texmtxinfo.sourcerow - XF_SRCTEX0_INROW; + bool hasTCC = (components & (VertexLoader::VB_HAS_UV0 << c)) != 0; + if (c >= 0 && c <= 7 && hasTCC) + { + const DecUV &uv = varray->GetUV(c, i); + t = Vec3(uv.u, uv.v, 1); + } + } + } + + Vec3 out,out2; + switch (xfregs.texcoords[j].texmtxinfo.texgentype) + { + case XF_TEXGEN_COLOR_STRGBC0: + out = Vec3(chans[0].r*255, chans[0].g*255, 1)/255.0f; + break; + case XF_TEXGEN_COLOR_STRGBC1: + out = Vec3(chans[1].r*255, chans[1].g*255, 1)/255.0f; //FIX: take color1 instead + break; + case XF_TEXGEN_REGULAR: + if (xfregs.texcoords[j].texmtxinfo.projection) + VtxMulMtx43(out, t, m_pTexMatrix[j]); + else + VtxMulMtx42(out, t, m_pTexMatrix[j]); + break; + } + + if (xfregs.texcoords[j].postmtxinfo.normalize) + out.normalize(); + + int postMatrix = xfregs.texcoords[j].postmtxinfo.index; + float *pmtx = ((float*)xfmem) + 0x500 + postMatrix * 4; //CHECK + //multiply with postmatrix + VtxMulMtx43(TempUVs[j], out, pmtx); + } + + ////////////////////////////////////////////////////////////////////////// + //Step 4: Output the vertex! + ////////////////////////////////////////////////////////////////////////// + for (int j = 0; j < 2; j++) + chans[j].convertToD3DColor(vbuffer[i].colors[j]); + + vbuffer[i].pos = TempPos; + vbuffer[i].normal = TempNormal; + for (int j = 0; j < (int)bpmem.genMode.numtexgens; j++) + { + vbuffer[i].uv[j].u = TempUVs[j].x; + vbuffer[i].uv[j].v = TempUVs[j].y; + vbuffer[i].uv[j].w = TempUVs[j].z; + } + } +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Utils.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Utils.cpp index 75cca658b7..d22dfeb70f 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Utils.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Utils.cpp @@ -1,45 +1,45 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifdef _WIN32 -#include "W32Util/Misc.h" -#endif - -#include "Common.h" -#include - -int frameCount; - -// Message handler for about box. -LRESULT CALLBACK AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM /*lParam*/) -{ - switch (message) - { - case WM_INITDIALOG: - W32Util::CenterWindow(hDlg); - return TRUE; - - case WM_COMMAND: - if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) - { - EndDialog(hDlg, LOWORD(wParam)); - return TRUE; - } - break; - } - return FALSE; -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifdef _WIN32 +#include "W32Util/Misc.h" +#endif + +#include "Common.h" +#include + +int frameCount; + +// Message handler for about box. +LRESULT CALLBACK AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM /*lParam*/) +{ + switch (message) + { + case WM_INITDIALOG: + W32Util::CenterWindow(hDlg); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) + { + EndDialog(hDlg, LOWORD(wParam)); + return TRUE; + } + break; + } + return FALSE; +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexLoader.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexLoader.cpp index ed291aeb48..f2f40f81c5 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexLoader.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexLoader.cpp @@ -1,363 +1,363 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include - -#include "x64Emitter.h" - -#include "Common.h" -#include "LookUpTables.h" -#include "Profiler.h" -#include "VertexManager.h" -#include "VertexLoader.h" -#include "XFStructs.h" -#include "BPStructs.h" -#include "DataReader.h" -#include "DecodedVArray.h" - -//these don't need to be saved -float posScale; -float tcScale[8]; -int tcElements[8]; -int tcFormat[8]; -int colElements[2]; -float tcScaleU[8]; -float tcScaleV[8]; -int tcIndex; -int colIndex; -u32 addr; - -DecodedVArray *varray; - -int ComputeVertexSize(u32 comp) -{ - int size = 0; - if (comp & VertexLoader::VB_HAS_POSMTXIDX) - size += 4; - if (comp & (VertexLoader::VB_HAS_TEXMTXIDX0 | VertexLoader::VB_HAS_TEXMTXIDX1 | VertexLoader::VB_HAS_TEXMTXIDX2 | VertexLoader::VB_HAS_TEXMTXIDX3)) - size += 4; - if (comp & (VertexLoader::VB_HAS_TEXMTXIDX4 | VertexLoader::VB_HAS_TEXMTXIDX5 | VertexLoader::VB_HAS_TEXMTXIDX6 | VertexLoader::VB_HAS_TEXMTXIDX7)) - size += 4; - if (comp & VertexLoader::VB_HAS_NRM0) - size += 4; - if (comp & (VertexLoader::VB_HAS_NRM1 | VertexLoader::VB_HAS_NRM2)) //combine into single check for speed - size += 8; - if (comp & VertexLoader::VB_HAS_COL0) - size += 4; - if (comp & VertexLoader::VB_HAS_COL1) - size += 4; - for (int i = 0; i < 8; i++) - if (comp & (VertexLoader::VB_HAS_UV0 << i)) - size += 8; - return size; -} - -void VertexLoader::SetVArray(DecodedVArray *_varray) -{ - varray = _varray; -} - -#include "VertexLoader_MtxIndex.h" -#include "VertexLoader_Position.h" -#include "VertexLoader_Normal.h" -#include "VertexLoader_Color.h" -#include "VertexLoader_TextCoord.h" - -VertexLoader g_VertexLoaders[8]; -TVtxDesc VertexLoader::m_VtxDesc; -bool VertexLoader::m_DescDirty = true; - -VertexLoader::VertexLoader() -{ - m_numPipelineStates = 0; - m_VertexSize = 0; - m_AttrDirty = true; - VertexLoader_Normal::Init(); -} - -VertexLoader::~VertexLoader() -{ - -} - -void VertexLoader::Setup() -{ - if (!m_AttrDirty && !m_DescDirty) - return; - - DVSTARTPROFILE(); - - // Reset pipeline - m_VertexSize = 0; - m_numPipelineStates = 0; - m_components = 0; - - // Position Matrix Index - if (m_VtxDesc.PosMatIdx) - { - m_PipelineStates[m_numPipelineStates++] = PosMtx_ReadDirect_UByte; - m_VertexSize += 1; - m_components |= VB_HAS_POSMTXIDX; - } - - // Texture matrix indices - if (m_VtxDesc.Tex0MatIdx) {m_components|=VB_HAS_TEXMTXIDX0; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;} - if (m_VtxDesc.Tex1MatIdx) {m_components|=VB_HAS_TEXMTXIDX1; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;} - if (m_VtxDesc.Tex2MatIdx) {m_components|=VB_HAS_TEXMTXIDX2; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;} - if (m_VtxDesc.Tex3MatIdx) {m_components|=VB_HAS_TEXMTXIDX3; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;} - if (m_VtxDesc.Tex4MatIdx) {m_components|=VB_HAS_TEXMTXIDX4; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;} - if (m_VtxDesc.Tex5MatIdx) {m_components|=VB_HAS_TEXMTXIDX5; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;} - if (m_VtxDesc.Tex6MatIdx) {m_components|=VB_HAS_TEXMTXIDX6; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;} - if (m_VtxDesc.Tex7MatIdx) {m_components|=VB_HAS_TEXMTXIDX7; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;} - - // Position - switch (m_VtxDesc.Position) - { - case NOT_PRESENT: {_assert_msg_(0,"Vertex descriptor without position!","WTF?");} break; - case DIRECT: - { - int SizePro = 0; - switch (m_VtxAttr.PosFormat) - { - case FORMAT_UBYTE: SizePro=1; WriteCall(Pos_ReadDirect_UByte); break; - case FORMAT_BYTE: SizePro=1; WriteCall(Pos_ReadDirect_Byte); break; - case FORMAT_USHORT: SizePro=2; WriteCall(Pos_ReadDirect_UShort); break; - case FORMAT_SHORT: SizePro=2; WriteCall(Pos_ReadDirect_Short); break; - case FORMAT_FLOAT: SizePro=4; WriteCall(Pos_ReadDirect_Float); break; - default: _assert_(0); break; - } - if (m_VtxAttr.PosElements == 1) - m_VertexSize += SizePro * 3; - else - m_VertexSize += SizePro * 2; - } - break; - case INDEX8: - m_VertexSize+=1; - switch (m_VtxAttr.PosFormat) - { - case FORMAT_UBYTE: WriteCall(Pos_ReadIndex8_UByte); break; //WTF? - case FORMAT_BYTE: WriteCall(Pos_ReadIndex8_Byte); break; - case FORMAT_USHORT: WriteCall(Pos_ReadIndex8_UShort); break; - case FORMAT_SHORT: WriteCall(Pos_ReadIndex8_Short); break; - case FORMAT_FLOAT: WriteCall(Pos_ReadIndex8_Float); break; - default: _assert_(0); break; - } - break; - case INDEX16: - m_VertexSize+=2; - switch (m_VtxAttr.PosFormat) - { - case FORMAT_UBYTE: WriteCall(Pos_ReadIndex16_UByte); break; - case FORMAT_BYTE: WriteCall(Pos_ReadIndex16_Byte); break; - case FORMAT_USHORT: WriteCall(Pos_ReadIndex16_UShort); break; - case FORMAT_SHORT: WriteCall(Pos_ReadIndex16_Short); break; - case FORMAT_FLOAT: WriteCall(Pos_ReadIndex16_Float); break; - default: _assert_(0); break; - } - break; - } - - // Normals - if (m_VtxDesc.Normal != NOT_PRESENT) - { - VertexLoader_Normal::index3 = m_VtxAttr.NormalIndex3 ? true : false; - unsigned int uSize = VertexLoader_Normal::GetSize(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements); - TPipelineFunction pFunc = VertexLoader_Normal::GetFunction(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements); - if (pFunc == 0) - { - char temp[256]; - sprintf(temp,"%i %i %i", m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements); - MessageBox(0,"VertexLoader_Normal::GetFunction returned zero!",temp,0); - } - WriteCall(pFunc); - m_VertexSize += uSize; - int m_numNormals = (m_VtxAttr.NormalElements == 1) ? NRM_THREE : NRM_ONE; - m_components |= VB_HAS_NRM0; - if (m_numNormals == NRM_THREE) - m_components |= VB_HAS_NRM1 | VB_HAS_NRM2; - } - - // Colors - int col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1}; - for (int i = 0; i < 2; i++) - SetupColor(i,col[i], m_VtxAttr.color[i].Comp, m_VtxAttr.color[i].Elements); - - // TextureCoord - // Since m_VtxDesc.Text7Coord is broken across a 32 bit word boundary, retrieve its value manually. - // If we didn't do this, the vertex format would be read as one bit offset from where it should be, making - // 01 become 00, and 10/11 become 01 - int tc[8] = { - m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord, - m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, (m_VtxDesc.Hex >> 31) & 3 - }; - for (int i = 0; i < 8; i++) - SetupTexCoord(i, tc[i], - m_VtxAttr.texCoord[i].Format, - m_VtxAttr.texCoord[i].Elements, - m_VtxAttr.texCoord[i].Frac); -} - -void VertexLoader::SetupColor(int num, int mode, int format, int elements) -{ - m_components |= VB_HAS_COL0 << num; - switch (mode) - { - case NOT_PRESENT: - m_components &= ~(VB_HAS_COL0 << num); - break; - case DIRECT: - switch (format) - { - case FORMAT_16B_565: m_VertexSize+=2; WriteCall(Color_ReadDirect_16b_565); break; - case FORMAT_24B_888: m_VertexSize+=3; WriteCall(Color_ReadDirect_24b_888); break; - case FORMAT_32B_888x: m_VertexSize+=4; WriteCall(Color_ReadDirect_32b_888x); break; - case FORMAT_16B_4444: m_VertexSize+=2; WriteCall(Color_ReadDirect_16b_4444); break; - case FORMAT_24B_6666: m_VertexSize+=3; WriteCall(Color_ReadDirect_24b_6666); break; - case FORMAT_32B_8888: m_VertexSize+=4; WriteCall(Color_ReadDirect_32b_8888); break; - default: _assert_(0); break; - } - break; - case INDEX8: - switch (format) - { - case FORMAT_16B_565: WriteCall(Color_ReadIndex8_16b_565); break; - case FORMAT_24B_888: WriteCall(Color_ReadIndex8_24b_888); break; - case FORMAT_32B_888x: WriteCall(Color_ReadIndex8_32b_888x); break; - case FORMAT_16B_4444: WriteCall(Color_ReadIndex8_16b_4444); break; - case FORMAT_24B_6666: WriteCall(Color_ReadIndex8_24b_6666); break; - case FORMAT_32B_8888: WriteCall(Color_ReadIndex8_32b_8888); break; - default: _assert_(0); break; - } - m_VertexSize+=1; - break; - case INDEX16: - switch (format) - { - case FORMAT_16B_565: WriteCall(Color_ReadIndex16_16b_565); break; - case FORMAT_24B_888: WriteCall(Color_ReadIndex16_24b_888); break; - case FORMAT_32B_888x: WriteCall(Color_ReadIndex16_32b_888x); break; - case FORMAT_16B_4444: WriteCall(Color_ReadIndex16_16b_4444); break; - case FORMAT_24B_6666: WriteCall(Color_ReadIndex16_24b_6666); break; - case FORMAT_32B_8888: WriteCall(Color_ReadIndex16_32b_8888); break; - default: _assert_(0); break; - } - m_VertexSize+=2; - break; - } -} - -void VertexLoader::SetupTexCoord(int num, int mode, int format, int elements, int _iFrac) -{ - m_components |= VB_HAS_UV0 << num; - switch (mode) - { - case NOT_PRESENT: - m_components &= ~(VB_HAS_UV0 << num); - break; - case DIRECT: - { - int sizePro=0; - switch (format) - { - case FORMAT_UBYTE: sizePro = 1; WriteCall(TexCoord_ReadDirect_UByte); break; - case FORMAT_BYTE: sizePro = 1; WriteCall(TexCoord_ReadDirect_Byte); break; - case FORMAT_USHORT: sizePro = 2; WriteCall(TexCoord_ReadDirect_UShort); break; - case FORMAT_SHORT: sizePro = 2; WriteCall(TexCoord_ReadDirect_Short); break; - case FORMAT_FLOAT: sizePro = 4; WriteCall(TexCoord_ReadDirect_Float); break; - default: _assert_(0); break; - } - m_VertexSize += sizePro * (elements ? 2 : 1); - } - break; - case INDEX8: - switch (format) - { - case FORMAT_UBYTE: WriteCall(TexCoord_ReadIndex8_UByte); break; - case FORMAT_BYTE: WriteCall(TexCoord_ReadIndex8_Byte); break; - case FORMAT_USHORT: WriteCall(TexCoord_ReadIndex8_UShort); break; - case FORMAT_SHORT: WriteCall(TexCoord_ReadIndex8_Short); break; - case FORMAT_FLOAT: WriteCall(TexCoord_ReadIndex8_Float); break; - default: _assert_(0); break; - } - m_VertexSize+=1; - break; - case INDEX16: - switch (format) - { - case FORMAT_UBYTE: WriteCall(TexCoord_ReadIndex16_UByte); break; - case FORMAT_BYTE: WriteCall(TexCoord_ReadIndex16_Byte); break; - case FORMAT_USHORT: WriteCall(TexCoord_ReadIndex16_UShort); break; - case FORMAT_SHORT: WriteCall(TexCoord_ReadIndex16_Short); break; - case FORMAT_FLOAT: WriteCall(TexCoord_ReadIndex16_Float); break; - default: _assert_(0); - } - m_VertexSize+=2; - break; - } -} - -void VertexLoader::WriteCall(TPipelineFunction func) -{ - m_PipelineStates[m_numPipelineStates++] = func; -} - -using namespace Gen; - -void VertexLoader::PrepareRun() -{ - posScale = shiftLookup[m_VtxAttr.PosFrac]; - for (int i = 0; i < 8; i++) - { - tcScaleU[i] = shiftLookup[m_VtxAttr.texCoord[i].Frac]; - tcScaleV[i] = shiftLookup[m_VtxAttr.texCoord[i].Frac]; - tcElements[i] = m_VtxAttr.texCoord[i].Elements; - tcFormat[i] = m_VtxAttr.texCoord[i].Format; - } - for (int i = 0; i < 2; i++) - colElements[i] = m_VtxAttr.color[i].Elements; - - varray->SetComponents(m_components); -} - -void VertexLoader::RunVertices(int count) -{ - DVSTARTPROFILE(); - - for (int v = 0; v < count; v++) - { - tcIndex = 0; - colIndex = 0; - s_texmtxread = 0; - for (int i = 0; i < m_numPipelineStates; i++) - { - m_PipelineStates[i](&m_VtxAttr); - } - varray->Next(); - } - /* - This is not the bottleneck ATM, so compiling etc doesn't really help. - At least not when all we do is compile it to a list of function calls. - Should help more when we inline, but this requires the new vertex format. - Maybe later, and with smarter caching. - - if (count) - { - this->m_counter = count; - ((void (*)())((void*)&m_compiledCode[0]))(); - }*/ +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include + +#include "x64Emitter.h" + +#include "Common.h" +#include "LookUpTables.h" +#include "Profiler.h" +#include "VertexManager.h" +#include "VertexLoader.h" +#include "XFStructs.h" +#include "BPStructs.h" +#include "DataReader.h" +#include "DecodedVArray.h" + +//these don't need to be saved +float posScale; +float tcScale[8]; +int tcElements[8]; +int tcFormat[8]; +int colElements[2]; +float tcScaleU[8]; +float tcScaleV[8]; +int tcIndex; +int colIndex; +u32 addr; + +DecodedVArray *varray; + +int ComputeVertexSize(u32 comp) +{ + int size = 0; + if (comp & VertexLoader::VB_HAS_POSMTXIDX) + size += 4; + if (comp & (VertexLoader::VB_HAS_TEXMTXIDX0 | VertexLoader::VB_HAS_TEXMTXIDX1 | VertexLoader::VB_HAS_TEXMTXIDX2 | VertexLoader::VB_HAS_TEXMTXIDX3)) + size += 4; + if (comp & (VertexLoader::VB_HAS_TEXMTXIDX4 | VertexLoader::VB_HAS_TEXMTXIDX5 | VertexLoader::VB_HAS_TEXMTXIDX6 | VertexLoader::VB_HAS_TEXMTXIDX7)) + size += 4; + if (comp & VertexLoader::VB_HAS_NRM0) + size += 4; + if (comp & (VertexLoader::VB_HAS_NRM1 | VertexLoader::VB_HAS_NRM2)) //combine into single check for speed + size += 8; + if (comp & VertexLoader::VB_HAS_COL0) + size += 4; + if (comp & VertexLoader::VB_HAS_COL1) + size += 4; + for (int i = 0; i < 8; i++) + if (comp & (VertexLoader::VB_HAS_UV0 << i)) + size += 8; + return size; +} + +void VertexLoader::SetVArray(DecodedVArray *_varray) +{ + varray = _varray; +} + +#include "VertexLoader_MtxIndex.h" +#include "VertexLoader_Position.h" +#include "VertexLoader_Normal.h" +#include "VertexLoader_Color.h" +#include "VertexLoader_TextCoord.h" + +VertexLoader g_VertexLoaders[8]; +TVtxDesc VertexLoader::m_VtxDesc; +bool VertexLoader::m_DescDirty = true; + +VertexLoader::VertexLoader() +{ + m_numPipelineStates = 0; + m_VertexSize = 0; + m_AttrDirty = true; + VertexLoader_Normal::Init(); +} + +VertexLoader::~VertexLoader() +{ + +} + +void VertexLoader::Setup() +{ + if (!m_AttrDirty && !m_DescDirty) + return; + + DVSTARTPROFILE(); + + // Reset pipeline + m_VertexSize = 0; + m_numPipelineStates = 0; + m_components = 0; + + // Position Matrix Index + if (m_VtxDesc.PosMatIdx) + { + m_PipelineStates[m_numPipelineStates++] = PosMtx_ReadDirect_UByte; + m_VertexSize += 1; + m_components |= VB_HAS_POSMTXIDX; + } + + // Texture matrix indices + if (m_VtxDesc.Tex0MatIdx) {m_components|=VB_HAS_TEXMTXIDX0; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;} + if (m_VtxDesc.Tex1MatIdx) {m_components|=VB_HAS_TEXMTXIDX1; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;} + if (m_VtxDesc.Tex2MatIdx) {m_components|=VB_HAS_TEXMTXIDX2; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;} + if (m_VtxDesc.Tex3MatIdx) {m_components|=VB_HAS_TEXMTXIDX3; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;} + if (m_VtxDesc.Tex4MatIdx) {m_components|=VB_HAS_TEXMTXIDX4; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;} + if (m_VtxDesc.Tex5MatIdx) {m_components|=VB_HAS_TEXMTXIDX5; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;} + if (m_VtxDesc.Tex6MatIdx) {m_components|=VB_HAS_TEXMTXIDX6; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;} + if (m_VtxDesc.Tex7MatIdx) {m_components|=VB_HAS_TEXMTXIDX7; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;} + + // Position + switch (m_VtxDesc.Position) + { + case NOT_PRESENT: {_assert_msg_(0,"Vertex descriptor without position!","WTF?");} break; + case DIRECT: + { + int SizePro = 0; + switch (m_VtxAttr.PosFormat) + { + case FORMAT_UBYTE: SizePro=1; WriteCall(Pos_ReadDirect_UByte); break; + case FORMAT_BYTE: SizePro=1; WriteCall(Pos_ReadDirect_Byte); break; + case FORMAT_USHORT: SizePro=2; WriteCall(Pos_ReadDirect_UShort); break; + case FORMAT_SHORT: SizePro=2; WriteCall(Pos_ReadDirect_Short); break; + case FORMAT_FLOAT: SizePro=4; WriteCall(Pos_ReadDirect_Float); break; + default: _assert_(0); break; + } + if (m_VtxAttr.PosElements == 1) + m_VertexSize += SizePro * 3; + else + m_VertexSize += SizePro * 2; + } + break; + case INDEX8: + m_VertexSize+=1; + switch (m_VtxAttr.PosFormat) + { + case FORMAT_UBYTE: WriteCall(Pos_ReadIndex8_UByte); break; //WTF? + case FORMAT_BYTE: WriteCall(Pos_ReadIndex8_Byte); break; + case FORMAT_USHORT: WriteCall(Pos_ReadIndex8_UShort); break; + case FORMAT_SHORT: WriteCall(Pos_ReadIndex8_Short); break; + case FORMAT_FLOAT: WriteCall(Pos_ReadIndex8_Float); break; + default: _assert_(0); break; + } + break; + case INDEX16: + m_VertexSize+=2; + switch (m_VtxAttr.PosFormat) + { + case FORMAT_UBYTE: WriteCall(Pos_ReadIndex16_UByte); break; + case FORMAT_BYTE: WriteCall(Pos_ReadIndex16_Byte); break; + case FORMAT_USHORT: WriteCall(Pos_ReadIndex16_UShort); break; + case FORMAT_SHORT: WriteCall(Pos_ReadIndex16_Short); break; + case FORMAT_FLOAT: WriteCall(Pos_ReadIndex16_Float); break; + default: _assert_(0); break; + } + break; + } + + // Normals + if (m_VtxDesc.Normal != NOT_PRESENT) + { + VertexLoader_Normal::index3 = m_VtxAttr.NormalIndex3 ? true : false; + unsigned int uSize = VertexLoader_Normal::GetSize(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements); + TPipelineFunction pFunc = VertexLoader_Normal::GetFunction(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements); + if (pFunc == 0) + { + char temp[256]; + sprintf(temp,"%i %i %i", m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements); + MessageBox(0,"VertexLoader_Normal::GetFunction returned zero!",temp,0); + } + WriteCall(pFunc); + m_VertexSize += uSize; + int m_numNormals = (m_VtxAttr.NormalElements == 1) ? NRM_THREE : NRM_ONE; + m_components |= VB_HAS_NRM0; + if (m_numNormals == NRM_THREE) + m_components |= VB_HAS_NRM1 | VB_HAS_NRM2; + } + + // Colors + int col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1}; + for (int i = 0; i < 2; i++) + SetupColor(i,col[i], m_VtxAttr.color[i].Comp, m_VtxAttr.color[i].Elements); + + // TextureCoord + // Since m_VtxDesc.Text7Coord is broken across a 32 bit word boundary, retrieve its value manually. + // If we didn't do this, the vertex format would be read as one bit offset from where it should be, making + // 01 become 00, and 10/11 become 01 + int tc[8] = { + m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord, + m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, (m_VtxDesc.Hex >> 31) & 3 + }; + for (int i = 0; i < 8; i++) + SetupTexCoord(i, tc[i], + m_VtxAttr.texCoord[i].Format, + m_VtxAttr.texCoord[i].Elements, + m_VtxAttr.texCoord[i].Frac); +} + +void VertexLoader::SetupColor(int num, int mode, int format, int elements) +{ + m_components |= VB_HAS_COL0 << num; + switch (mode) + { + case NOT_PRESENT: + m_components &= ~(VB_HAS_COL0 << num); + break; + case DIRECT: + switch (format) + { + case FORMAT_16B_565: m_VertexSize+=2; WriteCall(Color_ReadDirect_16b_565); break; + case FORMAT_24B_888: m_VertexSize+=3; WriteCall(Color_ReadDirect_24b_888); break; + case FORMAT_32B_888x: m_VertexSize+=4; WriteCall(Color_ReadDirect_32b_888x); break; + case FORMAT_16B_4444: m_VertexSize+=2; WriteCall(Color_ReadDirect_16b_4444); break; + case FORMAT_24B_6666: m_VertexSize+=3; WriteCall(Color_ReadDirect_24b_6666); break; + case FORMAT_32B_8888: m_VertexSize+=4; WriteCall(Color_ReadDirect_32b_8888); break; + default: _assert_(0); break; + } + break; + case INDEX8: + switch (format) + { + case FORMAT_16B_565: WriteCall(Color_ReadIndex8_16b_565); break; + case FORMAT_24B_888: WriteCall(Color_ReadIndex8_24b_888); break; + case FORMAT_32B_888x: WriteCall(Color_ReadIndex8_32b_888x); break; + case FORMAT_16B_4444: WriteCall(Color_ReadIndex8_16b_4444); break; + case FORMAT_24B_6666: WriteCall(Color_ReadIndex8_24b_6666); break; + case FORMAT_32B_8888: WriteCall(Color_ReadIndex8_32b_8888); break; + default: _assert_(0); break; + } + m_VertexSize+=1; + break; + case INDEX16: + switch (format) + { + case FORMAT_16B_565: WriteCall(Color_ReadIndex16_16b_565); break; + case FORMAT_24B_888: WriteCall(Color_ReadIndex16_24b_888); break; + case FORMAT_32B_888x: WriteCall(Color_ReadIndex16_32b_888x); break; + case FORMAT_16B_4444: WriteCall(Color_ReadIndex16_16b_4444); break; + case FORMAT_24B_6666: WriteCall(Color_ReadIndex16_24b_6666); break; + case FORMAT_32B_8888: WriteCall(Color_ReadIndex16_32b_8888); break; + default: _assert_(0); break; + } + m_VertexSize+=2; + break; + } +} + +void VertexLoader::SetupTexCoord(int num, int mode, int format, int elements, int _iFrac) +{ + m_components |= VB_HAS_UV0 << num; + switch (mode) + { + case NOT_PRESENT: + m_components &= ~(VB_HAS_UV0 << num); + break; + case DIRECT: + { + int sizePro=0; + switch (format) + { + case FORMAT_UBYTE: sizePro = 1; WriteCall(TexCoord_ReadDirect_UByte); break; + case FORMAT_BYTE: sizePro = 1; WriteCall(TexCoord_ReadDirect_Byte); break; + case FORMAT_USHORT: sizePro = 2; WriteCall(TexCoord_ReadDirect_UShort); break; + case FORMAT_SHORT: sizePro = 2; WriteCall(TexCoord_ReadDirect_Short); break; + case FORMAT_FLOAT: sizePro = 4; WriteCall(TexCoord_ReadDirect_Float); break; + default: _assert_(0); break; + } + m_VertexSize += sizePro * (elements ? 2 : 1); + } + break; + case INDEX8: + switch (format) + { + case FORMAT_UBYTE: WriteCall(TexCoord_ReadIndex8_UByte); break; + case FORMAT_BYTE: WriteCall(TexCoord_ReadIndex8_Byte); break; + case FORMAT_USHORT: WriteCall(TexCoord_ReadIndex8_UShort); break; + case FORMAT_SHORT: WriteCall(TexCoord_ReadIndex8_Short); break; + case FORMAT_FLOAT: WriteCall(TexCoord_ReadIndex8_Float); break; + default: _assert_(0); break; + } + m_VertexSize+=1; + break; + case INDEX16: + switch (format) + { + case FORMAT_UBYTE: WriteCall(TexCoord_ReadIndex16_UByte); break; + case FORMAT_BYTE: WriteCall(TexCoord_ReadIndex16_Byte); break; + case FORMAT_USHORT: WriteCall(TexCoord_ReadIndex16_UShort); break; + case FORMAT_SHORT: WriteCall(TexCoord_ReadIndex16_Short); break; + case FORMAT_FLOAT: WriteCall(TexCoord_ReadIndex16_Float); break; + default: _assert_(0); + } + m_VertexSize+=2; + break; + } +} + +void VertexLoader::WriteCall(TPipelineFunction func) +{ + m_PipelineStates[m_numPipelineStates++] = func; +} + +using namespace Gen; + +void VertexLoader::PrepareRun() +{ + posScale = shiftLookup[m_VtxAttr.PosFrac]; + for (int i = 0; i < 8; i++) + { + tcScaleU[i] = shiftLookup[m_VtxAttr.texCoord[i].Frac]; + tcScaleV[i] = shiftLookup[m_VtxAttr.texCoord[i].Frac]; + tcElements[i] = m_VtxAttr.texCoord[i].Elements; + tcFormat[i] = m_VtxAttr.texCoord[i].Format; + } + for (int i = 0; i < 2; i++) + colElements[i] = m_VtxAttr.color[i].Elements; + + varray->SetComponents(m_components); +} + +void VertexLoader::RunVertices(int count) +{ + DVSTARTPROFILE(); + + for (int v = 0; v < count; v++) + { + tcIndex = 0; + colIndex = 0; + s_texmtxread = 0; + for (int i = 0; i < m_numPipelineStates; i++) + { + m_PipelineStates[i](&m_VtxAttr); + } + varray->Next(); + } + /* + This is not the bottleneck ATM, so compiling etc doesn't really help. + At least not when all we do is compile it to a list of function calls. + Should help more when we inline, but this requires the new vertex format. + Maybe later, and with smarter caching. + + if (count) + { + this->m_counter = count; + ((void (*)())((void*)&m_compiledCode[0]))(); + }*/ } \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexLoader_Normal.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexLoader_Normal.cpp index 52f3f2f18f..6eea6b5b12 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexLoader_Normal.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexLoader_Normal.cpp @@ -1,488 +1,488 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "main.h" -#include "Utils.h" -#include "DecodedVArray.h" -#include "VertexLoader.h" -#include "VertexLoader_Normal.h" - -u8 VertexLoader_Normal::m_sizeTable[NUM_NRM_TYPE][NUM_NRM_FORMAT][NUM_NRM_ELEMENTS]; -TPipelineFunction VertexLoader_Normal::m_funcTable[NUM_NRM_TYPE][NUM_NRM_FORMAT][NUM_NRM_ELEMENTS]; - -bool VertexLoader_Normal::index3; -// __________________________________________________________________________________________________ -// Init -// -void VertexLoader_Normal::Init(void) -{ - // size table - m_sizeTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT] = 3; - m_sizeTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT] = 3; - m_sizeTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT] = 6; - m_sizeTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT] = 6; - m_sizeTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT] = 12; - m_sizeTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT3] = 9; - m_sizeTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT3] = 9; - m_sizeTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT3] = 18; - m_sizeTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT3] = 18; - m_sizeTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT3] = 36; - - m_sizeTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT] = 1; - m_sizeTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT] = 1; - m_sizeTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT] = 1; - m_sizeTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT] = 1; - m_sizeTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT] = 1; - m_sizeTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT3] = 3; - m_sizeTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT3] = 3; - m_sizeTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT3] = 3; - m_sizeTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT3] = 3; - m_sizeTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT3] = 3; - - m_sizeTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT] = 2; - m_sizeTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT] = 2; - m_sizeTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT] = 2; - m_sizeTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT] = 2; - m_sizeTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT] = 2; - m_sizeTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT3] = 6; - m_sizeTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT3] = 6; - m_sizeTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT3] = 6; - m_sizeTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT3] = 6; - m_sizeTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT3] = 6; - - // function table - m_funcTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT] = Normal_DirectByte; //HACK - m_funcTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT] = Normal_DirectByte; - m_funcTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT] = Normal_DirectShort; //HACK - m_funcTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT] = Normal_DirectShort; - m_funcTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT] = Normal_DirectFloat; - m_funcTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT3] = Normal_DirectByte3; //HACK - m_funcTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT3] = Normal_DirectByte3; - m_funcTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT3] = Normal_DirectShort3; //HACK - m_funcTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT3] = Normal_DirectShort3; - m_funcTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT3] = Normal_DirectFloat3; - - m_funcTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT] = Normal_Index8_Byte; //HACK - m_funcTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT] = Normal_Index8_Byte; - m_funcTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT] = Normal_Index8_Short; //HACK - m_funcTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT] = Normal_Index8_Short; - m_funcTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT] = Normal_Index8_Float; - m_funcTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT3] = Normal_Index8_Byte3; //HACK - m_funcTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT3] = Normal_Index8_Byte3; - m_funcTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT3] = Normal_Index8_Short3; //HACK - m_funcTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT3] = Normal_Index8_Short3; - m_funcTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT3] = Normal_Index8_Float3; - - m_funcTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT] = Normal_Index16_Byte; //HACK - m_funcTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT] = Normal_Index16_Byte; - m_funcTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT] = Normal_Index16_Short; //HACK - m_funcTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT] = Normal_Index16_Short; - m_funcTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT] = Normal_Index16_Float; - m_funcTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT3] = Normal_Index16_Byte3; //HACK - m_funcTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT3] = Normal_Index16_Byte3; - m_funcTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT3] = Normal_Index16_Short3; //HACK - m_funcTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT3] = Normal_Index16_Short3; - m_funcTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT3] = Normal_Index16_Float3; -} - -// __________________________________________________________________________________________________ -// GetSize -// -unsigned int -VertexLoader_Normal::GetSize(unsigned int _type, unsigned int _format, unsigned int _elements) -{ - return m_sizeTable[_type][_format][_elements]; -} - -// __________________________________________________________________________________________________ -// GetFunction -// -TPipelineFunction -VertexLoader_Normal::GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements) -{ - TPipelineFunction pFunc = m_funcTable[_type][_format][_elements]; - return pFunc; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////// -// -// --- Direct --- -// -///////////////////////////////////////////////////////////////////////////////////////////////////// - -// __________________________________________________________________________________________________ -// Normal_DirectByte -// -void LOADERDECL -VertexLoader_Normal::Normal_DirectByte(const void* _p) -{ - varray->SetNormalX(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f); - varray->SetNormalY(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f); - varray->SetNormalZ(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f); -} - -// __________________________________________________________________________________________________ -// Normal_DirectShort -// -void LOADERDECL -VertexLoader_Normal::Normal_DirectShort(const void* _p) -{ - varray->SetNormalX(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f); - varray->SetNormalY(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f); - varray->SetNormalZ(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f); -} - -// __________________________________________________________________________________________________ -// Normal_DirectFloat -// -void LOADERDECL -VertexLoader_Normal::Normal_DirectFloat(const void* _p) -{ - varray->SetNormalX(0, DataReadF32()); - varray->SetNormalY(0, DataReadF32()); - varray->SetNormalZ(0, DataReadF32()); -} - -// __________________________________________________________________________________________________ -// Normal_DirectByte3 -// -void LOADERDECL -VertexLoader_Normal::Normal_DirectByte3(const void* _p) -{ - for (int i=0; i<3; i++) - { - varray->SetNormalX(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f); - varray->SetNormalY(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f); - varray->SetNormalZ(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f); - } -} - -// __________________________________________________________________________________________________ -// Normal_DirectShort3 -// -void LOADERDECL -VertexLoader_Normal::Normal_DirectShort3(const void* _p) -{ - for (int i=0; i<3; i++) - { - varray->SetNormalX(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f); - varray->SetNormalY(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f); - varray->SetNormalZ(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f); - } -} - -// __________________________________________________________________________________________________ -// Normal_DirectFloat3 -// -void LOADERDECL -VertexLoader_Normal::Normal_DirectFloat3(const void* _p) -{ - for (int i=0; i<3; i++) - { - varray->SetNormalX(i, DataReadF32()); - varray->SetNormalY(i, DataReadF32()); - varray->SetNormalZ(i, DataReadF32()); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////////// -// -// --- Index8 --- -// -///////////////////////////////////////////////////////////////////////////////////////////////////// - -// __________________________________________________________________________________________________ -// Normal_Index8_Byte -// -void LOADERDECL -VertexLoader_Normal::Normal_Index8_Byte(const void* _p) -{ - u8 Index = DataReadU8(); - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]); - - varray->SetNormalX(0, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f); - varray->SetNormalY(0, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f); - varray->SetNormalZ(0, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f); -} - -// __________________________________________________________________________________________________ -// Normal_Index8_Short -// -void LOADERDECL -VertexLoader_Normal::Normal_Index8_Short(const void* _p) -{ - u8 Index = DataReadU8(); - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]); - - varray->SetNormalX(0, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f); - varray->SetNormalY(0, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f); - varray->SetNormalZ(0, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f); -} - -// __________________________________________________________________________________________________ -// Normal_Index8_Float -// -void LOADERDECL -VertexLoader_Normal::Normal_Index8_Float(const void* _p) -{ - u8 Index = DataReadU8(); - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]); - - varray->SetNormalX(0, Memory_Read_Float(iAddress)); - varray->SetNormalY(0, Memory_Read_Float(iAddress+4)); - varray->SetNormalZ(0, Memory_Read_Float(iAddress+8)); -} - -// __________________________________________________________________________________________________ -// Normal_Index8_Byte3 -// -void LOADERDECL -VertexLoader_Normal::Normal_Index8_Byte3(const void* _p) -{ - if (index3) - { - for (int i=0; i<3; i++) - { - u8 Index = DataReadU8(); - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i; - - varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f); - varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f); - varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f); - } - } - else - { - u8 Index = DataReadU8(); - for (int i=0; i<3; i++) - { - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i; - - varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f); - varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f); - varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f); - } - } -} - -// __________________________________________________________________________________________________ -// Normal_Index8_Short3 -// -void LOADERDECL -VertexLoader_Normal::Normal_Index8_Short3(const void* _p) -{ - if (index3) - { - for (int i=0; i<3; i++) - { - u8 Index = DataReadU8(); - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i; - - varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f); - varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f); - varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f); - } - } - else - { - u8 Index = DataReadU8(); - for (int i=0; i<3; i++) - { - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i; - - varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f); - varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f); - varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f); - } - } -} - -// __________________________________________________________________________________________________ -// Normal_Index8_Float3 -// -void LOADERDECL -VertexLoader_Normal::Normal_Index8_Float3(const void* _p) -{ - if (index3) - { - for (int i=0; i<3; i++) - { - u8 Index = DataReadU8(); - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i; - - varray->SetNormalX(i, Memory_Read_Float(iAddress)); - varray->SetNormalY(i, Memory_Read_Float(iAddress+4)); - varray->SetNormalZ(i, Memory_Read_Float(iAddress+8)); - } - } - else - { - u8 Index = DataReadU8(); - for (int i=0; i<3; i++) - { - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i; - - varray->SetNormalX(i, Memory_Read_Float(iAddress)); - varray->SetNormalY(i, Memory_Read_Float(iAddress+4)); - varray->SetNormalZ(i, Memory_Read_Float(iAddress+8)); - } - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////////// -// -// --- Index16 --- -// -///////////////////////////////////////////////////////////////////////////////////////////////////// - -// __________________________________________________________________________________________________ -// Normal_Index16_Byte -// -void LOADERDECL -VertexLoader_Normal::Normal_Index16_Byte(const void* _p) -{ - u16 Index = DataReadU16(); - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]); - - varray->SetNormalX(0, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f); - varray->SetNormalY(0, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f); - varray->SetNormalZ(0, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f); -} - -// __________________________________________________________________________________________________ -// Normal_Index16_Short -// -void LOADERDECL -VertexLoader_Normal::Normal_Index16_Short(const void* _p) -{ - u16 Index = DataReadU16(); - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]); - - varray->SetNormalX(0, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f); - varray->SetNormalY(0, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f); - varray->SetNormalZ(0, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f); -} - -// __________________________________________________________________________________________________ -// Normal_Index8_Float -// -void LOADERDECL -VertexLoader_Normal::Normal_Index16_Float(const void* _p) -{ - u16 Index = DataReadU16(); - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]); - - varray->SetNormalX(0, Memory_Read_Float(iAddress)); - varray->SetNormalY(0, Memory_Read_Float(iAddress+4)); - varray->SetNormalZ(0, Memory_Read_Float(iAddress+8)); -} - -// __________________________________________________________________________________________________ -// Normal_Index16_Byte3 -// -void LOADERDECL -VertexLoader_Normal::Normal_Index16_Byte3(const void* _p) -{ - if (index3) - { - for (int i=0; i<3; i++) - { - u16 Index = DataReadU16(); - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i; - - varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f); - varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f); - varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f); - } - } - else - { - u16 Index = DataReadU16(); - for (int i=0; i<3; i++) - { - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i; - - varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f); - varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f); - varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f); - } - } -} - -// __________________________________________________________________________________________________ -// Normal_Index16_Short3 -// -void LOADERDECL -VertexLoader_Normal::Normal_Index16_Short3(const void* _p) -{ - if (index3) - { - for (int i=0; i<3; i++) - { - u16 Index = DataReadU16(); - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i; - - varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f); - varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f); - varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f); - } - } - else - { - u16 Index = DataReadU16(); - for (int i=0; i<3; i++) - { - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i; - - varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f); - varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f); - varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f); - } - } -} - -// __________________________________________________________________________________________________ -// Normal_Index16_Float3 -// -void LOADERDECL -VertexLoader_Normal::Normal_Index16_Float3(const void* _p) -{ - if (index3) - { - for (int i=0; i<3; i++) - { - u16 Index = DataReadU16(); - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i; - - varray->SetNormalX(i, Memory_Read_Float(iAddress )); - varray->SetNormalY(i, Memory_Read_Float(iAddress+4)); - varray->SetNormalZ(i, Memory_Read_Float(iAddress+8)); - } - } - else - { - u16 Index = DataReadU16(); - for (int i=0; i<3; i++) - { - u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i; - - varray->SetNormalX(i, Memory_Read_Float(iAddress )); - varray->SetNormalY(i, Memory_Read_Float(iAddress+4)); - varray->SetNormalZ(i, Memory_Read_Float(iAddress+8)); - } - } +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "main.h" +#include "Utils.h" +#include "DecodedVArray.h" +#include "VertexLoader.h" +#include "VertexLoader_Normal.h" + +u8 VertexLoader_Normal::m_sizeTable[NUM_NRM_TYPE][NUM_NRM_FORMAT][NUM_NRM_ELEMENTS]; +TPipelineFunction VertexLoader_Normal::m_funcTable[NUM_NRM_TYPE][NUM_NRM_FORMAT][NUM_NRM_ELEMENTS]; + +bool VertexLoader_Normal::index3; +// __________________________________________________________________________________________________ +// Init +// +void VertexLoader_Normal::Init(void) +{ + // size table + m_sizeTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT] = 3; + m_sizeTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT] = 3; + m_sizeTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT] = 6; + m_sizeTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT] = 6; + m_sizeTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT] = 12; + m_sizeTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT3] = 9; + m_sizeTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT3] = 9; + m_sizeTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT3] = 18; + m_sizeTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT3] = 18; + m_sizeTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT3] = 36; + + m_sizeTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT] = 1; + m_sizeTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT] = 1; + m_sizeTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT] = 1; + m_sizeTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT] = 1; + m_sizeTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT] = 1; + m_sizeTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT3] = 3; + m_sizeTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT3] = 3; + m_sizeTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT3] = 3; + m_sizeTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT3] = 3; + m_sizeTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT3] = 3; + + m_sizeTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT] = 2; + m_sizeTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT] = 2; + m_sizeTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT] = 2; + m_sizeTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT] = 2; + m_sizeTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT] = 2; + m_sizeTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT3] = 6; + m_sizeTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT3] = 6; + m_sizeTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT3] = 6; + m_sizeTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT3] = 6; + m_sizeTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT3] = 6; + + // function table + m_funcTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT] = Normal_DirectByte; //HACK + m_funcTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT] = Normal_DirectByte; + m_funcTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT] = Normal_DirectShort; //HACK + m_funcTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT] = Normal_DirectShort; + m_funcTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT] = Normal_DirectFloat; + m_funcTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT3] = Normal_DirectByte3; //HACK + m_funcTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT3] = Normal_DirectByte3; + m_funcTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT3] = Normal_DirectShort3; //HACK + m_funcTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT3] = Normal_DirectShort3; + m_funcTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT3] = Normal_DirectFloat3; + + m_funcTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT] = Normal_Index8_Byte; //HACK + m_funcTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT] = Normal_Index8_Byte; + m_funcTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT] = Normal_Index8_Short; //HACK + m_funcTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT] = Normal_Index8_Short; + m_funcTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT] = Normal_Index8_Float; + m_funcTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT3] = Normal_Index8_Byte3; //HACK + m_funcTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT3] = Normal_Index8_Byte3; + m_funcTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT3] = Normal_Index8_Short3; //HACK + m_funcTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT3] = Normal_Index8_Short3; + m_funcTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT3] = Normal_Index8_Float3; + + m_funcTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT] = Normal_Index16_Byte; //HACK + m_funcTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT] = Normal_Index16_Byte; + m_funcTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT] = Normal_Index16_Short; //HACK + m_funcTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT] = Normal_Index16_Short; + m_funcTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT] = Normal_Index16_Float; + m_funcTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT3] = Normal_Index16_Byte3; //HACK + m_funcTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT3] = Normal_Index16_Byte3; + m_funcTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT3] = Normal_Index16_Short3; //HACK + m_funcTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT3] = Normal_Index16_Short3; + m_funcTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT3] = Normal_Index16_Float3; +} + +// __________________________________________________________________________________________________ +// GetSize +// +unsigned int +VertexLoader_Normal::GetSize(unsigned int _type, unsigned int _format, unsigned int _elements) +{ + return m_sizeTable[_type][_format][_elements]; +} + +// __________________________________________________________________________________________________ +// GetFunction +// +TPipelineFunction +VertexLoader_Normal::GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements) +{ + TPipelineFunction pFunc = m_funcTable[_type][_format][_elements]; + return pFunc; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// +// --- Direct --- +// +///////////////////////////////////////////////////////////////////////////////////////////////////// + +// __________________________________________________________________________________________________ +// Normal_DirectByte +// +void LOADERDECL +VertexLoader_Normal::Normal_DirectByte(const void* _p) +{ + varray->SetNormalX(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f); + varray->SetNormalY(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f); + varray->SetNormalZ(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f); +} + +// __________________________________________________________________________________________________ +// Normal_DirectShort +// +void LOADERDECL +VertexLoader_Normal::Normal_DirectShort(const void* _p) +{ + varray->SetNormalX(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f); + varray->SetNormalY(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f); + varray->SetNormalZ(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f); +} + +// __________________________________________________________________________________________________ +// Normal_DirectFloat +// +void LOADERDECL +VertexLoader_Normal::Normal_DirectFloat(const void* _p) +{ + varray->SetNormalX(0, DataReadF32()); + varray->SetNormalY(0, DataReadF32()); + varray->SetNormalZ(0, DataReadF32()); +} + +// __________________________________________________________________________________________________ +// Normal_DirectByte3 +// +void LOADERDECL +VertexLoader_Normal::Normal_DirectByte3(const void* _p) +{ + for (int i=0; i<3; i++) + { + varray->SetNormalX(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f); + varray->SetNormalY(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f); + varray->SetNormalZ(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f); + } +} + +// __________________________________________________________________________________________________ +// Normal_DirectShort3 +// +void LOADERDECL +VertexLoader_Normal::Normal_DirectShort3(const void* _p) +{ + for (int i=0; i<3; i++) + { + varray->SetNormalX(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f); + varray->SetNormalY(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f); + varray->SetNormalZ(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f); + } +} + +// __________________________________________________________________________________________________ +// Normal_DirectFloat3 +// +void LOADERDECL +VertexLoader_Normal::Normal_DirectFloat3(const void* _p) +{ + for (int i=0; i<3; i++) + { + varray->SetNormalX(i, DataReadF32()); + varray->SetNormalY(i, DataReadF32()); + varray->SetNormalZ(i, DataReadF32()); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// +// --- Index8 --- +// +///////////////////////////////////////////////////////////////////////////////////////////////////// + +// __________________________________________________________________________________________________ +// Normal_Index8_Byte +// +void LOADERDECL +VertexLoader_Normal::Normal_Index8_Byte(const void* _p) +{ + u8 Index = DataReadU8(); + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]); + + varray->SetNormalX(0, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f); + varray->SetNormalY(0, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f); + varray->SetNormalZ(0, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f); +} + +// __________________________________________________________________________________________________ +// Normal_Index8_Short +// +void LOADERDECL +VertexLoader_Normal::Normal_Index8_Short(const void* _p) +{ + u8 Index = DataReadU8(); + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]); + + varray->SetNormalX(0, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f); + varray->SetNormalY(0, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f); + varray->SetNormalZ(0, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f); +} + +// __________________________________________________________________________________________________ +// Normal_Index8_Float +// +void LOADERDECL +VertexLoader_Normal::Normal_Index8_Float(const void* _p) +{ + u8 Index = DataReadU8(); + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]); + + varray->SetNormalX(0, Memory_Read_Float(iAddress)); + varray->SetNormalY(0, Memory_Read_Float(iAddress+4)); + varray->SetNormalZ(0, Memory_Read_Float(iAddress+8)); +} + +// __________________________________________________________________________________________________ +// Normal_Index8_Byte3 +// +void LOADERDECL +VertexLoader_Normal::Normal_Index8_Byte3(const void* _p) +{ + if (index3) + { + for (int i=0; i<3; i++) + { + u8 Index = DataReadU8(); + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i; + + varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f); + varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f); + varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f); + } + } + else + { + u8 Index = DataReadU8(); + for (int i=0; i<3; i++) + { + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i; + + varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f); + varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f); + varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f); + } + } +} + +// __________________________________________________________________________________________________ +// Normal_Index8_Short3 +// +void LOADERDECL +VertexLoader_Normal::Normal_Index8_Short3(const void* _p) +{ + if (index3) + { + for (int i=0; i<3; i++) + { + u8 Index = DataReadU8(); + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i; + + varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f); + varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f); + varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f); + } + } + else + { + u8 Index = DataReadU8(); + for (int i=0; i<3; i++) + { + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i; + + varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f); + varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f); + varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f); + } + } +} + +// __________________________________________________________________________________________________ +// Normal_Index8_Float3 +// +void LOADERDECL +VertexLoader_Normal::Normal_Index8_Float3(const void* _p) +{ + if (index3) + { + for (int i=0; i<3; i++) + { + u8 Index = DataReadU8(); + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i; + + varray->SetNormalX(i, Memory_Read_Float(iAddress)); + varray->SetNormalY(i, Memory_Read_Float(iAddress+4)); + varray->SetNormalZ(i, Memory_Read_Float(iAddress+8)); + } + } + else + { + u8 Index = DataReadU8(); + for (int i=0; i<3; i++) + { + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i; + + varray->SetNormalX(i, Memory_Read_Float(iAddress)); + varray->SetNormalY(i, Memory_Read_Float(iAddress+4)); + varray->SetNormalZ(i, Memory_Read_Float(iAddress+8)); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// +// +// --- Index16 --- +// +///////////////////////////////////////////////////////////////////////////////////////////////////// + +// __________________________________________________________________________________________________ +// Normal_Index16_Byte +// +void LOADERDECL +VertexLoader_Normal::Normal_Index16_Byte(const void* _p) +{ + u16 Index = DataReadU16(); + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]); + + varray->SetNormalX(0, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f); + varray->SetNormalY(0, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f); + varray->SetNormalZ(0, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f); +} + +// __________________________________________________________________________________________________ +// Normal_Index16_Short +// +void LOADERDECL +VertexLoader_Normal::Normal_Index16_Short(const void* _p) +{ + u16 Index = DataReadU16(); + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]); + + varray->SetNormalX(0, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f); + varray->SetNormalY(0, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f); + varray->SetNormalZ(0, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f); +} + +// __________________________________________________________________________________________________ +// Normal_Index8_Float +// +void LOADERDECL +VertexLoader_Normal::Normal_Index16_Float(const void* _p) +{ + u16 Index = DataReadU16(); + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]); + + varray->SetNormalX(0, Memory_Read_Float(iAddress)); + varray->SetNormalY(0, Memory_Read_Float(iAddress+4)); + varray->SetNormalZ(0, Memory_Read_Float(iAddress+8)); +} + +// __________________________________________________________________________________________________ +// Normal_Index16_Byte3 +// +void LOADERDECL +VertexLoader_Normal::Normal_Index16_Byte3(const void* _p) +{ + if (index3) + { + for (int i=0; i<3; i++) + { + u16 Index = DataReadU16(); + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i; + + varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f); + varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f); + varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f); + } + } + else + { + u16 Index = DataReadU16(); + for (int i=0; i<3; i++) + { + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i; + + varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f); + varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f); + varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f); + } + } +} + +// __________________________________________________________________________________________________ +// Normal_Index16_Short3 +// +void LOADERDECL +VertexLoader_Normal::Normal_Index16_Short3(const void* _p) +{ + if (index3) + { + for (int i=0; i<3; i++) + { + u16 Index = DataReadU16(); + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i; + + varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f); + varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f); + varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f); + } + } + else + { + u16 Index = DataReadU16(); + for (int i=0; i<3; i++) + { + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i; + + varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f); + varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f); + varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f); + } + } +} + +// __________________________________________________________________________________________________ +// Normal_Index16_Float3 +// +void LOADERDECL +VertexLoader_Normal::Normal_Index16_Float3(const void* _p) +{ + if (index3) + { + for (int i=0; i<3; i++) + { + u16 Index = DataReadU16(); + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i; + + varray->SetNormalX(i, Memory_Read_Float(iAddress )); + varray->SetNormalY(i, Memory_Read_Float(iAddress+4)); + varray->SetNormalZ(i, Memory_Read_Float(iAddress+8)); + } + } + else + { + u16 Index = DataReadU16(); + for (int i=0; i<3; i++) + { + u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i; + + varray->SetNormalX(i, Memory_Read_Float(iAddress )); + varray->SetNormalY(i, Memory_Read_Float(iAddress+4)); + varray->SetNormalZ(i, Memory_Read_Float(iAddress+8)); + } + } } \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp index 425e6fad19..f36840f44a 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp @@ -1,234 +1,234 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Common.h" - -#include "D3DBase.h" - -#include "Statistics.h" -#include "Profiler.h" -#include "VertexManager.h" -#include "OpcodeDecoding.h" -#include "TransformEngine.h" -#include "IndexGenerator.h" -#include "BPStructs.h" -#include "XFStructs.h" -#include "ShaderManager.h" -#include "Utils.h" - -using namespace D3D; - - -namespace VertexManager -{ - -static IndexGenerator indexGen; -static Collection collection; - -static LPDIRECT3DVERTEXDECLARATION9 vDecl; - -static D3DVertex *fakeVBuffer; -static u16 *fakeIBuffer; - -#define MAXVBUFFERSIZE 65536*3 -#define MAXIBUFFERSIZE 65536*3 - -const D3DVERTEXELEMENT9 decl[] = -{ - { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, - { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, - { 0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, - { 0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1 }, - { 0, 32+12*0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, - { 0, 32+12*1, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 }, - { 0, 32+12*2, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2 }, - { 0, 32+12*3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3 }, - { 0, 32+12*4, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4 }, - { 0, 32+12*5, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 5 }, - { 0, 32+12*6, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 6 }, - { 0, 32+12*7, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 7 }, - D3DDECL_END() -}; - - -bool Init() -{ - collection = C_NOTHING; - fakeVBuffer = new D3DVertex[65536]; - fakeIBuffer = new u16[65536]; - CreateDeviceObjects(); - return true; -} - -void Shutdown() -{ - DestroyDeviceObjects(); - delete [] fakeVBuffer; - delete [] fakeIBuffer; -} - -void CreateDeviceObjects() -{ - HRESULT hr; - if (FAILED(hr = D3D::dev->CreateVertexDeclaration(decl, &vDecl))) - { - MessageBox(0,"Failed to create vertex declaration","sdfsd",0); - return; - } -} - -void BeginFrame() -{ - D3D::dev->SetVertexDeclaration(vDecl); - //D3D::dev->SetStreamSource(0,vBuffer,0,sizeof(D3DVertex)); -} - -void DestroyDeviceObjects() -{ - if (vDecl) - vDecl->Release(); - vDecl = 0; -} - - -void AddIndices(int _primitive, int _numVertices) -{ - switch(_primitive) { - case GX_DRAW_QUADS: indexGen.AddQuads(_numVertices); return; - case GX_DRAW_TRIANGLES: indexGen.AddList(_numVertices); return; - case GX_DRAW_TRIANGLE_STRIP: indexGen.AddStrip(_numVertices); return; - case GX_DRAW_TRIANGLE_FAN: indexGen.AddFan(_numVertices); return; - case GX_DRAW_LINE_STRIP: indexGen.AddLineStrip(_numVertices); return; - case GX_DRAW_LINES: indexGen.AddLineList(_numVertices); return; - case GX_DRAW_POINTS: indexGen.AddPointList(_numVertices); return; - } -} - -const Collection collectionTypeLUT[8] = -{ - C_TRIANGLES,//quads - C_NOTHING, //nothing - C_TRIANGLES,//triangles - C_TRIANGLES,//strip - C_TRIANGLES,//fan - C_LINES, //lines - C_LINES, //linestrip - C_POINTS //guess :P -}; - -D3DVertex *vbufferwrite; - -void AddVertices(int _primitive, int _numVertices, const DecodedVArray *varray) -{ - if (_numVertices <= 0) //This check is pretty stupid... - return; - - Collection type = collectionTypeLUT[_primitive]; - if (type == C_NOTHING) - return; - - DVSTARTPROFILE(); - _assert_msg_(type != C_NOTHING, "type == C_NOTHING!!", "WTF"); - - if (indexGen.GetNumVerts() > 1000) // TODO(ector): Raise? - Flush(); - - ADDSTAT(stats.thisFrame.numPrims, _numVertices); - - if (collection != type) - { - //We are NOT collecting the right type. - Flush(); - collection = type; - u16 *ptr = 0; - - if (type != C_POINTS) - { - ptr = fakeIBuffer; - indexGen.Start((unsigned short*)ptr); - AddIndices(_primitive,_numVertices); - } - - vbufferwrite = fakeVBuffer; - - if (_numVertices >= MAXVBUFFERSIZE) - MessageBox(NULL, "To much vertices for the buffer", "Video.DLL", MB_OK); - - CTransformEngine::TransformVertices(_numVertices, varray, vbufferwrite); - } - else //We are collecting the right type, keep going - { - _assert_msg_(vbufferwrite!=0, "collecting: vbufferwrite == 0!","WTF"); - INCSTAT(stats.thisFrame.numPrimitiveJoins); - //Success, keep adding to unlocked buffer - int last = indexGen.GetNumVerts(); - AddIndices(_primitive, _numVertices); - - if (_numVertices >= MAXVBUFFERSIZE) - MessageBox(NULL, "Too many vertices for the buffer", "Video.DLL", MB_OK); - CTransformEngine::TransformVertices(_numVertices, varray, vbufferwrite + last); - } -} - -const D3DPRIMITIVETYPE pts[3] = -{ - D3DPT_POINTLIST, //DUMMY - D3DPT_TRIANGLELIST, - D3DPT_LINELIST, -}; - -void Flush() -{ - DVSTARTPROFILE(); - - if (collection != C_NOTHING) - { - ActivateTextures(); - - int numVertices = indexGen.GetNumVerts(); - if (numVertices != 0) - { - PShaderCache::SetShader(); // TODO(ector): only do this if shader has changed - VShaderCache::SetShader(); // TODO(ector): only do this if shader has changed - if (collection != C_POINTS) - { - int numPrimitives = indexGen.GetNumPrims(); - D3D::dev->DrawIndexedPrimitiveUP(pts[(int)collection], - 0, - numVertices, - numPrimitives, - fakeIBuffer, - D3DFMT_INDEX16, - fakeVBuffer, - sizeof(D3DVertex)); - } - else - { - D3D::dev->SetIndices(0); - - // D3D::dev->DrawPrimitiveUP(D3DPT_POINTLIST, - // numVertices, - // fakeVBuffer, - // sizeof(D3DVertex)); - Renderer::DrawPrimitiveUP( D3DPT_POINTLIST, numVertices, fakeVBuffer, sizeof(D3DVertex) ); - } - } - collection = C_NOTHING; - } -} - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" + +#include "D3DBase.h" + +#include "Statistics.h" +#include "Profiler.h" +#include "VertexManager.h" +#include "OpcodeDecoding.h" +#include "TransformEngine.h" +#include "IndexGenerator.h" +#include "BPStructs.h" +#include "XFStructs.h" +#include "ShaderManager.h" +#include "Utils.h" + +using namespace D3D; + + +namespace VertexManager +{ + +static IndexGenerator indexGen; +static Collection collection; + +static LPDIRECT3DVERTEXDECLARATION9 vDecl; + +static D3DVertex *fakeVBuffer; +static u16 *fakeIBuffer; + +#define MAXVBUFFERSIZE 65536*3 +#define MAXIBUFFERSIZE 65536*3 + +const D3DVERTEXELEMENT9 decl[] = +{ + { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, + { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, + { 0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, + { 0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1 }, + { 0, 32+12*0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, + { 0, 32+12*1, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 }, + { 0, 32+12*2, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2 }, + { 0, 32+12*3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3 }, + { 0, 32+12*4, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4 }, + { 0, 32+12*5, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 5 }, + { 0, 32+12*6, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 6 }, + { 0, 32+12*7, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 7 }, + D3DDECL_END() +}; + + +bool Init() +{ + collection = C_NOTHING; + fakeVBuffer = new D3DVertex[65536]; + fakeIBuffer = new u16[65536]; + CreateDeviceObjects(); + return true; +} + +void Shutdown() +{ + DestroyDeviceObjects(); + delete [] fakeVBuffer; + delete [] fakeIBuffer; +} + +void CreateDeviceObjects() +{ + HRESULT hr; + if (FAILED(hr = D3D::dev->CreateVertexDeclaration(decl, &vDecl))) + { + MessageBox(0,"Failed to create vertex declaration","sdfsd",0); + return; + } +} + +void BeginFrame() +{ + D3D::dev->SetVertexDeclaration(vDecl); + //D3D::dev->SetStreamSource(0,vBuffer,0,sizeof(D3DVertex)); +} + +void DestroyDeviceObjects() +{ + if (vDecl) + vDecl->Release(); + vDecl = 0; +} + + +void AddIndices(int _primitive, int _numVertices) +{ + switch(_primitive) { + case GX_DRAW_QUADS: indexGen.AddQuads(_numVertices); return; + case GX_DRAW_TRIANGLES: indexGen.AddList(_numVertices); return; + case GX_DRAW_TRIANGLE_STRIP: indexGen.AddStrip(_numVertices); return; + case GX_DRAW_TRIANGLE_FAN: indexGen.AddFan(_numVertices); return; + case GX_DRAW_LINE_STRIP: indexGen.AddLineStrip(_numVertices); return; + case GX_DRAW_LINES: indexGen.AddLineList(_numVertices); return; + case GX_DRAW_POINTS: indexGen.AddPointList(_numVertices); return; + } +} + +const Collection collectionTypeLUT[8] = +{ + C_TRIANGLES,//quads + C_NOTHING, //nothing + C_TRIANGLES,//triangles + C_TRIANGLES,//strip + C_TRIANGLES,//fan + C_LINES, //lines + C_LINES, //linestrip + C_POINTS //guess :P +}; + +D3DVertex *vbufferwrite; + +void AddVertices(int _primitive, int _numVertices, const DecodedVArray *varray) +{ + if (_numVertices <= 0) //This check is pretty stupid... + return; + + Collection type = collectionTypeLUT[_primitive]; + if (type == C_NOTHING) + return; + + DVSTARTPROFILE(); + _assert_msg_(type != C_NOTHING, "type == C_NOTHING!!", "WTF"); + + if (indexGen.GetNumVerts() > 1000) // TODO(ector): Raise? + Flush(); + + ADDSTAT(stats.thisFrame.numPrims, _numVertices); + + if (collection != type) + { + //We are NOT collecting the right type. + Flush(); + collection = type; + u16 *ptr = 0; + + if (type != C_POINTS) + { + ptr = fakeIBuffer; + indexGen.Start((unsigned short*)ptr); + AddIndices(_primitive,_numVertices); + } + + vbufferwrite = fakeVBuffer; + + if (_numVertices >= MAXVBUFFERSIZE) + MessageBox(NULL, "To much vertices for the buffer", "Video.DLL", MB_OK); + + CTransformEngine::TransformVertices(_numVertices, varray, vbufferwrite); + } + else //We are collecting the right type, keep going + { + _assert_msg_(vbufferwrite!=0, "collecting: vbufferwrite == 0!","WTF"); + INCSTAT(stats.thisFrame.numPrimitiveJoins); + //Success, keep adding to unlocked buffer + int last = indexGen.GetNumVerts(); + AddIndices(_primitive, _numVertices); + + if (_numVertices >= MAXVBUFFERSIZE) + MessageBox(NULL, "Too many vertices for the buffer", "Video.DLL", MB_OK); + CTransformEngine::TransformVertices(_numVertices, varray, vbufferwrite + last); + } +} + +const D3DPRIMITIVETYPE pts[3] = +{ + D3DPT_POINTLIST, //DUMMY + D3DPT_TRIANGLELIST, + D3DPT_LINELIST, +}; + +void Flush() +{ + DVSTARTPROFILE(); + + if (collection != C_NOTHING) + { + ActivateTextures(); + + int numVertices = indexGen.GetNumVerts(); + if (numVertices != 0) + { + PShaderCache::SetShader(); // TODO(ector): only do this if shader has changed + VShaderCache::SetShader(); // TODO(ector): only do this if shader has changed + if (collection != C_POINTS) + { + int numPrimitives = indexGen.GetNumPrims(); + D3D::dev->DrawIndexedPrimitiveUP(pts[(int)collection], + 0, + numVertices, + numPrimitives, + fakeIBuffer, + D3DFMT_INDEX16, + fakeVBuffer, + sizeof(D3DVertex)); + } + else + { + D3D::dev->SetIndices(0); + + // D3D::dev->DrawPrimitiveUP(D3DPT_POINTLIST, + // numVertices, + // fakeVBuffer, + // sizeof(D3DVertex)); + Renderer::DrawPrimitiveUP( D3DPT_POINTLIST, numVertices, fakeVBuffer, sizeof(D3DVertex) ); + } + } + collection = C_NOTHING; + } +} + } // namespace \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexShader.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexShader.cpp index d23b32083a..b24250adf5 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexShader.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexShader.cpp @@ -1,142 +1,142 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -#include "stdafx.h" -#include "D3DShader.h" -#include "VertexShader.h" -#include "BPStructs.h" - -static const char *genericVS = "// Generic Vertex Shader\ -\n\ -struct VS_INPUT {\n\ -float4 pos : POSITION;\n\ -float3 normal : NORMAL;\n\ -float4 colors[2] : COLOR0;\n\ -float3 uv[8] : TEXCOORD0;\n\ -};\n\ -\n\ -struct VS_OUTPUT {\n\ -float4 pos : POSITION;\n\ -float4 colors[2] : COLOR0;\n\ -//numtexgen\n\ -float4 uv[5] : TEXCOORD0;\n\ -};\n\ -\n\ -uniform matrix matWorldViewProj : register(c0);\n\ -\n\ -VS_OUTPUT main(const VS_INPUT input)\n\ -{\n\ -VS_OUTPUT output;\n\ -\n\ -output.pos = mul(matWorldViewProj, input.pos);\n\ -// texgen\n\ -for (int i=0; i<5; i++)\n\ - output.uv[i] = float4(input.uv[i].xyz,1);\n\ -\n\ -for (int i=0; i<2; i++)\n output.colors[i] = input.colors[i];\n\ -return output;\n\ -}\0"; - -const char *GenerateVertexShader() { - return genericVS; -} -/* - -char text2[65536]; -#define WRITE p+=sprintf - -void WriteTexgen(char *&p, int n); - -const char *GenerateVertexShader() -{ - int numColors = 2; - int numUV = 8; - int numTexgen = bpmem.genMode.numtexgens; - int numNormals = 3; - bool fogEnable = false; - bool hasNormal = true; - - char *p = text2; - WRITE(p,"//Vertex Shader\n"); - WRITE(p,"//%i uv->%i texgens, %i colors\n",numUV,numTexgen,numColors); - WRITE(p,"\n"); - - WRITE(p,"struct VS_INPUT {\n"); - WRITE(p," float4 pos : POSITION;\n"); - WRITE(p," float3 normal : NORMAL;\n"); - if (numColors) - WRITE(p," float4 colors[%i] : COLOR0;\n",numColors); - if (numUV) - WRITE(p," float3 uv[%i] : TEXCOORD0;\n",numUV); - WRITE(p,"};\n"); - WRITE(p,"\n"); - - WRITE(p,"struct VS_OUTPUT {\n"); - WRITE(p," float4 pos : POSITION;\n"); - WRITE(p," float4 colors[%i] : COLOR0;\n",numColors); - if (numTexgen) - WRITE(p," float4 uv[%i] : TEXCOORD0;\n",numTexgen); - if (fogEnable) - WRITE(p," float fog : FOG;\n",numTexgen); - WRITE(p,"};\n"); - WRITE(p,"\n"); - - WRITE(p,"uniform matrix matWorldViewProj : register(c0);\n"); - - WRITE(p,"\n"); - - WRITE(p,"VS_OUTPUT main(const VS_INPUT input)\n"); - WRITE(p,"{\n"); - WRITE(p," VS_OUTPUT output;"); - WRITE(p,"\n"); - - WRITE(p," output.pos = mul(matWorldViewProj, input.pos);\n"); - - for (int i = 0; i < (int)bpmem.genMode.numtexgens; i++) - { - //build the equation for this stage - WriteTexgen(p,i); - } - - WRITE(p," for (int i=0; i<2; i++)\n output.colors[i] = input.colors[i];\n"); - //WRITE(p," output.fog = 0.0f;"); - WRITE(p,"return output;\n"); - WRITE(p,"}\n"); - WRITE(p,"\0"); - -// MessageBox(0,text2,0,0); - return text2; -} - - - -/* - * xform->vertexshader ideas - -*//* - -void WriteTexgen(char *&p, int n) -{ - WRITE(p," output.uv[%i] = float4(input.uv[%i].xy,0,input.uv[%i].z);\n",n,n,n); -} - - -void WriteLight(int color, int component) -{ - -} */ +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#include "stdafx.h" +#include "D3DShader.h" +#include "VertexShader.h" +#include "BPStructs.h" + +static const char *genericVS = "// Generic Vertex Shader\ +\n\ +struct VS_INPUT {\n\ +float4 pos : POSITION;\n\ +float3 normal : NORMAL;\n\ +float4 colors[2] : COLOR0;\n\ +float3 uv[8] : TEXCOORD0;\n\ +};\n\ +\n\ +struct VS_OUTPUT {\n\ +float4 pos : POSITION;\n\ +float4 colors[2] : COLOR0;\n\ +//numtexgen\n\ +float4 uv[5] : TEXCOORD0;\n\ +};\n\ +\n\ +uniform matrix matWorldViewProj : register(c0);\n\ +\n\ +VS_OUTPUT main(const VS_INPUT input)\n\ +{\n\ +VS_OUTPUT output;\n\ +\n\ +output.pos = mul(matWorldViewProj, input.pos);\n\ +// texgen\n\ +for (int i=0; i<5; i++)\n\ + output.uv[i] = float4(input.uv[i].xyz,1);\n\ +\n\ +for (int i=0; i<2; i++)\n output.colors[i] = input.colors[i];\n\ +return output;\n\ +}\0"; + +const char *GenerateVertexShader() { + return genericVS; +} +/* + +char text2[65536]; +#define WRITE p+=sprintf + +void WriteTexgen(char *&p, int n); + +const char *GenerateVertexShader() +{ + int numColors = 2; + int numUV = 8; + int numTexgen = bpmem.genMode.numtexgens; + int numNormals = 3; + bool fogEnable = false; + bool hasNormal = true; + + char *p = text2; + WRITE(p,"//Vertex Shader\n"); + WRITE(p,"//%i uv->%i texgens, %i colors\n",numUV,numTexgen,numColors); + WRITE(p,"\n"); + + WRITE(p,"struct VS_INPUT {\n"); + WRITE(p," float4 pos : POSITION;\n"); + WRITE(p," float3 normal : NORMAL;\n"); + if (numColors) + WRITE(p," float4 colors[%i] : COLOR0;\n",numColors); + if (numUV) + WRITE(p," float3 uv[%i] : TEXCOORD0;\n",numUV); + WRITE(p,"};\n"); + WRITE(p,"\n"); + + WRITE(p,"struct VS_OUTPUT {\n"); + WRITE(p," float4 pos : POSITION;\n"); + WRITE(p," float4 colors[%i] : COLOR0;\n",numColors); + if (numTexgen) + WRITE(p," float4 uv[%i] : TEXCOORD0;\n",numTexgen); + if (fogEnable) + WRITE(p," float fog : FOG;\n",numTexgen); + WRITE(p,"};\n"); + WRITE(p,"\n"); + + WRITE(p,"uniform matrix matWorldViewProj : register(c0);\n"); + + WRITE(p,"\n"); + + WRITE(p,"VS_OUTPUT main(const VS_INPUT input)\n"); + WRITE(p,"{\n"); + WRITE(p," VS_OUTPUT output;"); + WRITE(p,"\n"); + + WRITE(p," output.pos = mul(matWorldViewProj, input.pos);\n"); + + for (int i = 0; i < (int)bpmem.genMode.numtexgens; i++) + { + //build the equation for this stage + WriteTexgen(p,i); + } + + WRITE(p," for (int i=0; i<2; i++)\n output.colors[i] = input.colors[i];\n"); + //WRITE(p," output.fog = 0.0f;"); + WRITE(p,"return output;\n"); + WRITE(p,"}\n"); + WRITE(p,"\0"); + +// MessageBox(0,text2,0,0); + return text2; +} + + + +/* + * xform->vertexshader ideas + +*//* + +void WriteTexgen(char *&p, int n) +{ + WRITE(p," output.uv[%i] = float4(input.uv[%i].xy,0,input.uv[%i].z);\n",n,n,n); +} + + +void WriteLight(int color, int component) +{ + +} */ diff --git a/Source/Plugins/Plugin_VideoDX9/Src/W32Util/DialogManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/W32Util/DialogManager.cpp index a4f9d4741a..86c41d5cda 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/W32Util/DialogManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/W32Util/DialogManager.cpp @@ -1,29 +1,29 @@ -#include -#include -#include "DialogManager.h" - -typedef std::vector WindowList; -WindowList dialogs; - -void DialogManager::AddDlg(HWND hDialog) -{ - dialogs.push_back(hDialog); -} - -bool DialogManager::IsDialogMessage(LPMSG message) -{ - WindowList::iterator iter; - for (iter=dialogs.begin(); iter!=dialogs.end(); iter++) - { - if (::IsDialogMessage(*iter,message)) - return true; - } - return false; -} - -void DialogManager::EnableAll(BOOL enable) -{ - WindowList::iterator iter; - for (iter=dialogs.begin(); iter!=dialogs.end(); iter++) - EnableWindow(*iter,enable); -} +#include +#include +#include "DialogManager.h" + +typedef std::vector WindowList; +WindowList dialogs; + +void DialogManager::AddDlg(HWND hDialog) +{ + dialogs.push_back(hDialog); +} + +bool DialogManager::IsDialogMessage(LPMSG message) +{ + WindowList::iterator iter; + for (iter=dialogs.begin(); iter!=dialogs.end(); iter++) + { + if (::IsDialogMessage(*iter,message)) + return true; + } + return false; +} + +void DialogManager::EnableAll(BOOL enable) +{ + WindowList::iterator iter; + for (iter=dialogs.begin(); iter!=dialogs.end(); iter++) + EnableWindow(*iter,enable); +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/W32Util/File.cpp b/Source/Plugins/Plugin_VideoDX9/Src/W32Util/File.cpp index d27e03ff9a..f17278e4f6 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/W32Util/File.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/W32Util/File.cpp @@ -1,148 +1,148 @@ -#include -#include - -#include "File.h" - - -namespace W32Util -{ - - File::File() - { - fileHandle = INVALID_HANDLE_VALUE; - isOpen=false; - } - - File::~File() - { - - } - - - bool File::Open(const TCHAR *filename, eFileMode _mode) - { - mode = _mode; - //it's time to open the file - fileHandle = CreateFile(filename, - mode==FILE_READ ? GENERIC_READ : GENERIC_WRITE, //open mode - mode == FILE_READ ? FILE_SHARE_READ : NULL, //sharemode - NULL, //security - mode==FILE_READ ? OPEN_EXISTING : CREATE_ALWAYS, //create mode - FILE_ATTRIBUTE_NORMAL, //atrributes - NULL); //template - - if (fileHandle == INVALID_HANDLE_VALUE) - isOpen=false; - else - isOpen=true; - - return isOpen; - } - - - void File::Close() - { - if (isOpen) - { - //close the file and reset variables - CloseHandle(fileHandle); - fileHandle=INVALID_HANDLE_VALUE; - isOpen=false; - } - } - - int File::GetSize() - { - if (!isOpen) //of course - return 0; - else - return GetFileSize(fileHandle,0); - } - - int File::Write(void *data, int size) //let's do some writing - { - if (isOpen) - { - DWORD written; - WriteFile(fileHandle, data, size, &written,0); - return written; //we return the number of bytes that actually got written - } - else - { - return 0; - } - } - - int File::Read(void *data, int size) - { - if (isOpen) - { - DWORD wasRead; - ReadFile(fileHandle, data, size, &wasRead,0); - return wasRead; //we return the number of bytes that actually was read - } - else - { - return 0; - } - } - - int File::WR(void *data, int size) - { - if (mode==FILE_READ) - return Read(data,size); - else - return Write(data,size); - } - bool File::MagicCookie(int cookie) - { - if (mode==FILE_READ) - { - if (ReadInt()!=cookie) - { - char mojs[5],temp[256]; - mojs[4]=0; - *(int*)mojs=cookie; - sprintf(temp,"W32Util::File: Magic Cookie %s is bad!",mojs); - MessageBox(0,temp,"Error reading file",MB_ICONERROR); - return false; - } - else - return true; - } - else if (mode==FILE_WRITE) - { - WriteInt(cookie); - return true; - } - return false; - } - - int File::ReadInt() - { - int temp; - if (Read(&temp, sizeof(int))) - return temp; - else - return 0; - } - - void File::WriteInt(int i) - { - Write(&i,sizeof(int)); - } - - char File::ReadChar() - { - char temp; - if (Read(&temp, sizeof(char))) - return temp; - else - return 0; - } - - void File::WriteChar(char i) - { - Write(&i,sizeof(char)); - } +#include +#include + +#include "File.h" + + +namespace W32Util +{ + + File::File() + { + fileHandle = INVALID_HANDLE_VALUE; + isOpen=false; + } + + File::~File() + { + + } + + + bool File::Open(const TCHAR *filename, eFileMode _mode) + { + mode = _mode; + //it's time to open the file + fileHandle = CreateFile(filename, + mode==FILE_READ ? GENERIC_READ : GENERIC_WRITE, //open mode + mode == FILE_READ ? FILE_SHARE_READ : NULL, //sharemode + NULL, //security + mode==FILE_READ ? OPEN_EXISTING : CREATE_ALWAYS, //create mode + FILE_ATTRIBUTE_NORMAL, //atrributes + NULL); //template + + if (fileHandle == INVALID_HANDLE_VALUE) + isOpen=false; + else + isOpen=true; + + return isOpen; + } + + + void File::Close() + { + if (isOpen) + { + //close the file and reset variables + CloseHandle(fileHandle); + fileHandle=INVALID_HANDLE_VALUE; + isOpen=false; + } + } + + int File::GetSize() + { + if (!isOpen) //of course + return 0; + else + return GetFileSize(fileHandle,0); + } + + int File::Write(void *data, int size) //let's do some writing + { + if (isOpen) + { + DWORD written; + WriteFile(fileHandle, data, size, &written,0); + return written; //we return the number of bytes that actually got written + } + else + { + return 0; + } + } + + int File::Read(void *data, int size) + { + if (isOpen) + { + DWORD wasRead; + ReadFile(fileHandle, data, size, &wasRead,0); + return wasRead; //we return the number of bytes that actually was read + } + else + { + return 0; + } + } + + int File::WR(void *data, int size) + { + if (mode==FILE_READ) + return Read(data,size); + else + return Write(data,size); + } + bool File::MagicCookie(int cookie) + { + if (mode==FILE_READ) + { + if (ReadInt()!=cookie) + { + char mojs[5],temp[256]; + mojs[4]=0; + *(int*)mojs=cookie; + sprintf(temp,"W32Util::File: Magic Cookie %s is bad!",mojs); + MessageBox(0,temp,"Error reading file",MB_ICONERROR); + return false; + } + else + return true; + } + else if (mode==FILE_WRITE) + { + WriteInt(cookie); + return true; + } + return false; + } + + int File::ReadInt() + { + int temp; + if (Read(&temp, sizeof(int))) + return temp; + else + return 0; + } + + void File::WriteInt(int i) + { + Write(&i,sizeof(int)); + } + + char File::ReadChar() + { + char temp; + if (Read(&temp, sizeof(char))) + return temp; + else + return 0; + } + + void File::WriteChar(char i) + { + Write(&i,sizeof(char)); + } } \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoDX9/Src/W32Util/Misc.cpp b/Source/Plugins/Plugin_VideoDX9/Src/W32Util/Misc.cpp index 0cff1057d9..2f3a88b5ba 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/W32Util/Misc.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/W32Util/Misc.cpp @@ -1,102 +1,102 @@ -#include -#include - -#include "Misc.h" - -namespace W32Util -{ - //shamelessly taken from http://www.catch22.org.uk/tuts/tips.asp - void CenterWindow(HWND hwnd) - { - HWND hwndParent; - RECT rect, rectP; - int width, height; - int screenwidth, screenheight; - int x, y; - - //make the window relative to its parent - hwndParent = GetParent(hwnd); - if (!hwndParent) - return; - - GetWindowRect(hwnd, &rect); - GetWindowRect(hwndParent, &rectP); - - width = rect.right - rect.left; - height = rect.bottom - rect.top; - - x = ((rectP.right-rectP.left) - width) / 2 + rectP.left; - y = ((rectP.bottom-rectP.top) - height) / 2 + rectP.top; - - screenwidth = GetSystemMetrics(SM_CXSCREEN); - screenheight = GetSystemMetrics(SM_CYSCREEN); - - //make sure that the dialog box never moves outside of - //the screen - if(x < 0) x = 0; - if(y < 0) y = 0; - if(x + width > screenwidth) x = screenwidth - width; - if(y + height > screenheight) y = screenheight - height; - - MoveWindow(hwnd, x, y, width, height, FALSE); - } - - HBITMAP CreateBitmapFromARGB(HWND someHwnd, DWORD *image, int w, int h) - { - BITMAPINFO *bitmap_header; - static char bitmapbuffer[sizeof(BITMAPINFO)+16]; - memset(bitmapbuffer,0,sizeof(BITMAPINFO)+16); - bitmap_header=(BITMAPINFO *)bitmapbuffer; - bitmap_header->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bitmap_header->bmiHeader.biPlanes = 1; - bitmap_header->bmiHeader.biBitCount = 32; - bitmap_header->bmiHeader.biCompression = BI_RGB; - bitmap_header->bmiHeader.biWidth = w; - bitmap_header->bmiHeader.biHeight = -h; - - ((unsigned long *)bitmap_header->bmiColors)[0] = 0x00FF0000; - ((unsigned long *)bitmap_header->bmiColors)[1] = 0x0000FF00; - ((unsigned long *)bitmap_header->bmiColors)[2] = 0x000000FF; - - HDC dc = GetDC(someHwnd); - HBITMAP bitmap = CreateDIBitmap(dc,&bitmap_header->bmiHeader,CBM_INIT,image,bitmap_header,DIB_RGB_COLORS); - ReleaseDC(someHwnd,dc); - return bitmap; - } - - void NiceSizeFormat(size_t size, char *out) - { - char *sizes[] = {"b","KB","MB","GB","TB","PB","EB"}; - int s = 0; - int frac = 0; - while (size>1024) - { - s++; - frac = (int)size & 1023; - size /= 1024; - } - float f = (float)size + ((float)frac / 1024.0f); - sprintf(out,"%3.1f %s",f,sizes[s]); - } - BOOL CopyTextToClipboard(HWND hwnd, TCHAR *text) - { - OpenClipboard(hwnd); - EmptyClipboard(); - HANDLE hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (strlen(text) + 1) * sizeof(TCHAR)); - if (hglbCopy == NULL) - { - CloseClipboard(); - return FALSE; - } - - // Lock the handle and copy the text to the buffer. - - TCHAR *lptstrCopy = (TCHAR *)GlobalLock(hglbCopy); - strcpy(lptstrCopy, text); - lptstrCopy[strlen(text)] = (TCHAR) 0; // null character - GlobalUnlock(hglbCopy); - SetClipboardData(CF_TEXT,hglbCopy); - CloseClipboard(); - return TRUE; - } +#include +#include + +#include "Misc.h" + +namespace W32Util +{ + //shamelessly taken from http://www.catch22.org.uk/tuts/tips.asp + void CenterWindow(HWND hwnd) + { + HWND hwndParent; + RECT rect, rectP; + int width, height; + int screenwidth, screenheight; + int x, y; + + //make the window relative to its parent + hwndParent = GetParent(hwnd); + if (!hwndParent) + return; + + GetWindowRect(hwnd, &rect); + GetWindowRect(hwndParent, &rectP); + + width = rect.right - rect.left; + height = rect.bottom - rect.top; + + x = ((rectP.right-rectP.left) - width) / 2 + rectP.left; + y = ((rectP.bottom-rectP.top) - height) / 2 + rectP.top; + + screenwidth = GetSystemMetrics(SM_CXSCREEN); + screenheight = GetSystemMetrics(SM_CYSCREEN); + + //make sure that the dialog box never moves outside of + //the screen + if(x < 0) x = 0; + if(y < 0) y = 0; + if(x + width > screenwidth) x = screenwidth - width; + if(y + height > screenheight) y = screenheight - height; + + MoveWindow(hwnd, x, y, width, height, FALSE); + } + + HBITMAP CreateBitmapFromARGB(HWND someHwnd, DWORD *image, int w, int h) + { + BITMAPINFO *bitmap_header; + static char bitmapbuffer[sizeof(BITMAPINFO)+16]; + memset(bitmapbuffer,0,sizeof(BITMAPINFO)+16); + bitmap_header=(BITMAPINFO *)bitmapbuffer; + bitmap_header->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bitmap_header->bmiHeader.biPlanes = 1; + bitmap_header->bmiHeader.biBitCount = 32; + bitmap_header->bmiHeader.biCompression = BI_RGB; + bitmap_header->bmiHeader.biWidth = w; + bitmap_header->bmiHeader.biHeight = -h; + + ((unsigned long *)bitmap_header->bmiColors)[0] = 0x00FF0000; + ((unsigned long *)bitmap_header->bmiColors)[1] = 0x0000FF00; + ((unsigned long *)bitmap_header->bmiColors)[2] = 0x000000FF; + + HDC dc = GetDC(someHwnd); + HBITMAP bitmap = CreateDIBitmap(dc,&bitmap_header->bmiHeader,CBM_INIT,image,bitmap_header,DIB_RGB_COLORS); + ReleaseDC(someHwnd,dc); + return bitmap; + } + + void NiceSizeFormat(size_t size, char *out) + { + char *sizes[] = {"b","KB","MB","GB","TB","PB","EB"}; + int s = 0; + int frac = 0; + while (size>1024) + { + s++; + frac = (int)size & 1023; + size /= 1024; + } + float f = (float)size + ((float)frac / 1024.0f); + sprintf(out,"%3.1f %s",f,sizes[s]); + } + BOOL CopyTextToClipboard(HWND hwnd, TCHAR *text) + { + OpenClipboard(hwnd); + EmptyClipboard(); + HANDLE hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (strlen(text) + 1) * sizeof(TCHAR)); + if (hglbCopy == NULL) + { + CloseClipboard(); + return FALSE; + } + + // Lock the handle and copy the text to the buffer. + + TCHAR *lptstrCopy = (TCHAR *)GlobalLock(hglbCopy); + strcpy(lptstrCopy, text); + lptstrCopy[strlen(text)] = (TCHAR) 0; // null character + GlobalUnlock(hglbCopy); + SetClipboardData(CF_TEXT,hglbCopy); + CloseClipboard(); + return TRUE; + } } \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoDX9/Src/W32Util/PropertySheet.cpp b/Source/Plugins/Plugin_VideoDX9/Src/W32Util/PropertySheet.cpp index 8d176941e6..95cbe3c3f5 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/W32Util/PropertySheet.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/W32Util/PropertySheet.cpp @@ -1,225 +1,225 @@ -#include "Misc.h" -#include "PropertySheet.h" - -namespace W32Util -{ - bool centered; - - PropSheet::PropSheet() - { - watermark = 0; - header = 0; - icon = 0; - } - - int CALLBACK PropSheet::Callback(HWND hwndDlg, UINT uMsg, LPARAM lParam) - { - switch (uMsg) { - case PSCB_PRECREATE: - { - if (uMsg == PSCB_PRECREATE) - { - /* - if (lParam) - { - DLGTEMPLATE *pDlgTemplate; - DLGTEMPLATEEX *pDlgTemplateEx; - - pDlgTemplateEx = (DLGTEMPLATEEX *)lParam; - if (pDlgTemplateEx->signature == 0xFFFF) - { - // pDlgTemplateEx points to an extended - // dialog template structure. - - //pDlgTemplate->style |= DS_SETFONT; - u8 *tmp1 = (u8*)&pDlgTemplateEx + sizeof(DLGTEMPLATEEX); - u16 *tmp = (u16*)tmp1; - tmp++; //skip menu - tmp++; //skip dlg class - //Crash(); - //Here we should bash in Segoe UI - //It turns out to be way complicated though - //Not worth it - } - else - { - // This is a standard dialog template - // structure. - pDlgTemplate = (DLGTEMPLATE *)lParam; - } - } */ - } - - } - break; - case PSCB_INITIALIZED: - { - } - return 0; - } - return 0; - } - - void PropSheet::Show(HINSTANCE hInstance, HWND hParent, std::string title, int startpage, bool floating, bool wizard) - { - HPROPSHEETPAGE *pages = new HPROPSHEETPAGE[list.size()]; - PROPSHEETPAGE page; - //common settings - memset((void*)&page,0,sizeof(PROPSHEETPAGE)); - page.dwSize = sizeof(PROPSHEETPAGE); - page.hInstance = hInstance; - - int i=0; - for (DlgList::iterator iter = list.begin(); iter != list.end(); iter++, i++) - { - if (wizard) - { - if (i == 0 || i == list.size()-1) - page.dwFlags = PSP_HIDEHEADER; - else - page.dwFlags = PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE; - } - else - { - page.dwFlags = PSP_USETITLE; - } - page.pszTemplate = iter->resource; - page.pfnDlgProc = Tab::TabDlgProc; - page.pszTitle = iter->title; - page.pszHeaderTitle = wizard?iter->title:0; - page.pszHeaderSubTitle = wizard?iter->hdrSubTitle:0; - page.lParam = (LPARAM)iter->tab; - pages[i] = CreatePropertySheetPage(&page); - } - - PROPSHEETHEADER sheet; - memset(&sheet,0,sizeof(sheet)); - sheet.dwSize = sizeof(PROPSHEETHEADER); - sheet.hInstance = hInstance; - sheet.hwndParent = hParent; - sheet.pszbmWatermark = watermark; - sheet.pszbmHeader = header; - - if (icon) - sheet.hIcon = icon; - - if (wizard) - sheet.dwFlags = PSH_USECALLBACK | PSH_WIZARD97 | (watermark?PSH_WATERMARK:0) | (header?PSH_HEADER:0); - else - sheet.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE; - - sheet.dwFlags |= PSH_NOCONTEXTHELP; - - if (floating) - sheet.dwFlags |= PSH_MODELESS; - //else - // sheet.dwFlags |= PSH_NOAPPLYNOW; - - if (icon) - sheet.dwFlags |= PSH_USEHICON; - - sheet.pszCaption = title.c_str(); - sheet.nPages = (UINT)list.size(); - sheet.phpage = pages; - sheet.nStartPage = startpage; - sheet.pfnCallback = (PFNPROPSHEETCALLBACK)Callback; - - NONCLIENTMETRICS ncm = {0}; - ncm.cbSize = sizeof(ncm); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0); - hDialogFont = CreateFontIndirect(&ncm.lfMessageFont); - - if (wizard) - { - - //Create the intro/end title font - LOGFONT TitleLogFont = ncm.lfMessageFont; - TitleLogFont.lfWeight = FW_BOLD; - lstrcpy(TitleLogFont.lfFaceName, TEXT("Verdana Bold")); - //StringCchCopy(TitleLogFont.lfFaceName, 32, TEXT("Verdana Bold")); - - HDC hdc = GetDC(NULL); //gets the screen DC - int FontSize = 12; - TitleLogFont.lfHeight = 0 - GetDeviceCaps(hdc, LOGPIXELSY) * FontSize / 72; - hTitleFont = CreateFontIndirect(&TitleLogFont); - ReleaseDC(NULL, hdc); - } - else - hTitleFont = 0; - - centered=false; - PropertySheet(&sheet); - if (!floating) - { - for (DlgList::iterator iter = list.begin(); iter != list.end(); iter++) - { - delete iter->tab; - } - DeleteObject(hTitleFont); - } - DeleteObject(hDialogFont); - delete [] pages; - } - void PropSheet::Add(Tab *tab, LPCTSTR resource, LPCTSTR title, LPCTSTR subtitle) - { - tab->sheet = this; - list.push_back(Page(tab,resource,title,subtitle)); - } - - - void WizExteriorPage::Init(HWND hDlg) - { - HWND hwndControl = GetDlgItem(hDlg, captionID); - //SetWindowFont(hwndControl, sheet->GetTitleFont(), TRUE); - SendMessage(hwndControl,WM_SETFONT,(WPARAM)sheet->GetTitleFont(),0); - } - - INT_PTR Tab::TabDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) - { - Tab *tab = (Tab *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - switch(message) - { - case WM_INITDIALOG: - { - if (!centered) //HACK - { - CenterWindow(GetParent(hDlg)); - centered=true; - } - LPARAM l = ((LPPROPSHEETPAGE)lParam)->lParam; - tab = (Tab *)l; - SetWindowLongPtr(hDlg, GWLP_USERDATA, (DWORD_PTR)l); - tab->Init(hDlg); - } - break; - - case WM_COMMAND: - tab->Command(hDlg,wParam); - break; - case WM_NOTIFY: - { - LPPSHNOTIFY lppsn = (LPPSHNOTIFY) lParam; - HWND sheet = lppsn->hdr.hwndFrom; - switch(lppsn->hdr.code) { - case PSN_APPLY: - tab->Apply(hDlg); - break; - case PSN_SETACTIVE: - PropSheet_SetWizButtons(GetParent(hDlg), - (tab->HasPrev()?PSWIZB_BACK:0) | - (tab->HasNext()?PSWIZB_NEXT:0) | - (tab->HasFinish()?PSWIZB_FINISH:0)); - break; - case PSN_WIZNEXT: - tab->Apply(hDlg); //maybe not always good - break; - case PSN_WIZBACK: - case PSN_RESET: //cancel - break; - } - } - break; - } - return 0; - } +#include "Misc.h" +#include "PropertySheet.h" + +namespace W32Util +{ + bool centered; + + PropSheet::PropSheet() + { + watermark = 0; + header = 0; + icon = 0; + } + + int CALLBACK PropSheet::Callback(HWND hwndDlg, UINT uMsg, LPARAM lParam) + { + switch (uMsg) { + case PSCB_PRECREATE: + { + if (uMsg == PSCB_PRECREATE) + { + /* + if (lParam) + { + DLGTEMPLATE *pDlgTemplate; + DLGTEMPLATEEX *pDlgTemplateEx; + + pDlgTemplateEx = (DLGTEMPLATEEX *)lParam; + if (pDlgTemplateEx->signature == 0xFFFF) + { + // pDlgTemplateEx points to an extended + // dialog template structure. + + //pDlgTemplate->style |= DS_SETFONT; + u8 *tmp1 = (u8*)&pDlgTemplateEx + sizeof(DLGTEMPLATEEX); + u16 *tmp = (u16*)tmp1; + tmp++; //skip menu + tmp++; //skip dlg class + //Crash(); + //Here we should bash in Segoe UI + //It turns out to be way complicated though + //Not worth it + } + else + { + // This is a standard dialog template + // structure. + pDlgTemplate = (DLGTEMPLATE *)lParam; + } + } */ + } + + } + break; + case PSCB_INITIALIZED: + { + } + return 0; + } + return 0; + } + + void PropSheet::Show(HINSTANCE hInstance, HWND hParent, std::string title, int startpage, bool floating, bool wizard) + { + HPROPSHEETPAGE *pages = new HPROPSHEETPAGE[list.size()]; + PROPSHEETPAGE page; + //common settings + memset((void*)&page,0,sizeof(PROPSHEETPAGE)); + page.dwSize = sizeof(PROPSHEETPAGE); + page.hInstance = hInstance; + + int i=0; + for (DlgList::iterator iter = list.begin(); iter != list.end(); iter++, i++) + { + if (wizard) + { + if (i == 0 || i == list.size()-1) + page.dwFlags = PSP_HIDEHEADER; + else + page.dwFlags = PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE; + } + else + { + page.dwFlags = PSP_USETITLE; + } + page.pszTemplate = iter->resource; + page.pfnDlgProc = Tab::TabDlgProc; + page.pszTitle = iter->title; + page.pszHeaderTitle = wizard?iter->title:0; + page.pszHeaderSubTitle = wizard?iter->hdrSubTitle:0; + page.lParam = (LPARAM)iter->tab; + pages[i] = CreatePropertySheetPage(&page); + } + + PROPSHEETHEADER sheet; + memset(&sheet,0,sizeof(sheet)); + sheet.dwSize = sizeof(PROPSHEETHEADER); + sheet.hInstance = hInstance; + sheet.hwndParent = hParent; + sheet.pszbmWatermark = watermark; + sheet.pszbmHeader = header; + + if (icon) + sheet.hIcon = icon; + + if (wizard) + sheet.dwFlags = PSH_USECALLBACK | PSH_WIZARD97 | (watermark?PSH_WATERMARK:0) | (header?PSH_HEADER:0); + else + sheet.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE; + + sheet.dwFlags |= PSH_NOCONTEXTHELP; + + if (floating) + sheet.dwFlags |= PSH_MODELESS; + //else + // sheet.dwFlags |= PSH_NOAPPLYNOW; + + if (icon) + sheet.dwFlags |= PSH_USEHICON; + + sheet.pszCaption = title.c_str(); + sheet.nPages = (UINT)list.size(); + sheet.phpage = pages; + sheet.nStartPage = startpage; + sheet.pfnCallback = (PFNPROPSHEETCALLBACK)Callback; + + NONCLIENTMETRICS ncm = {0}; + ncm.cbSize = sizeof(ncm); + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0); + hDialogFont = CreateFontIndirect(&ncm.lfMessageFont); + + if (wizard) + { + + //Create the intro/end title font + LOGFONT TitleLogFont = ncm.lfMessageFont; + TitleLogFont.lfWeight = FW_BOLD; + lstrcpy(TitleLogFont.lfFaceName, TEXT("Verdana Bold")); + //StringCchCopy(TitleLogFont.lfFaceName, 32, TEXT("Verdana Bold")); + + HDC hdc = GetDC(NULL); //gets the screen DC + int FontSize = 12; + TitleLogFont.lfHeight = 0 - GetDeviceCaps(hdc, LOGPIXELSY) * FontSize / 72; + hTitleFont = CreateFontIndirect(&TitleLogFont); + ReleaseDC(NULL, hdc); + } + else + hTitleFont = 0; + + centered=false; + PropertySheet(&sheet); + if (!floating) + { + for (DlgList::iterator iter = list.begin(); iter != list.end(); iter++) + { + delete iter->tab; + } + DeleteObject(hTitleFont); + } + DeleteObject(hDialogFont); + delete [] pages; + } + void PropSheet::Add(Tab *tab, LPCTSTR resource, LPCTSTR title, LPCTSTR subtitle) + { + tab->sheet = this; + list.push_back(Page(tab,resource,title,subtitle)); + } + + + void WizExteriorPage::Init(HWND hDlg) + { + HWND hwndControl = GetDlgItem(hDlg, captionID); + //SetWindowFont(hwndControl, sheet->GetTitleFont(), TRUE); + SendMessage(hwndControl,WM_SETFONT,(WPARAM)sheet->GetTitleFont(),0); + } + + INT_PTR Tab::TabDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) + { + Tab *tab = (Tab *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + switch(message) + { + case WM_INITDIALOG: + { + if (!centered) //HACK + { + CenterWindow(GetParent(hDlg)); + centered=true; + } + LPARAM l = ((LPPROPSHEETPAGE)lParam)->lParam; + tab = (Tab *)l; + SetWindowLongPtr(hDlg, GWLP_USERDATA, (DWORD_PTR)l); + tab->Init(hDlg); + } + break; + + case WM_COMMAND: + tab->Command(hDlg,wParam); + break; + case WM_NOTIFY: + { + LPPSHNOTIFY lppsn = (LPPSHNOTIFY) lParam; + HWND sheet = lppsn->hdr.hwndFrom; + switch(lppsn->hdr.code) { + case PSN_APPLY: + tab->Apply(hDlg); + break; + case PSN_SETACTIVE: + PropSheet_SetWizButtons(GetParent(hDlg), + (tab->HasPrev()?PSWIZB_BACK:0) | + (tab->HasNext()?PSWIZB_NEXT:0) | + (tab->HasFinish()?PSWIZB_FINISH:0)); + break; + case PSN_WIZNEXT: + tab->Apply(hDlg); //maybe not always good + break; + case PSN_WIZBACK: + case PSN_RESET: //cancel + break; + } + } + break; + } + return 0; + } } \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoDX9/Src/W32Util/ShellUtil.cpp b/Source/Plugins/Plugin_VideoDX9/Src/W32Util/ShellUtil.cpp index ce6b5f6dd9..2941ba534e 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/W32Util/ShellUtil.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/W32Util/ShellUtil.cpp @@ -1,124 +1,124 @@ -#include -#include -#include -#include "ShellUtil.h" - -namespace W32Util -{ - std::string BrowseForFolder(HWND parent, char *title) - { - BROWSEINFO info; - memset(&info,0,sizeof(info)); - info.hwndOwner = parent; - info.lpszTitle = title; - info.ulFlags = BIF_EDITBOX | BIF_RETURNONLYFSDIRS; - - //info.pszDisplayName - LPCITEMIDLIST idList = SHBrowseForFolder(&info); - - char temp[MAX_PATH]; - SHGetPathFromIDList(idList, temp); - if (strlen(temp)) - { - return temp; - } - else - return ""; - } - - //--------------------------------------------------------------------------------------------------- - // function WinBrowseForFileName - //--------------------------------------------------------------------------------------------------- - bool BrowseForFileName (bool _bLoad, HWND _hParent, const char *_pTitle, - const char *_pInitialFolder,const char *_pFilter,const char *_pExtension, - std::string& _strFileName) - { - char szFile [MAX_PATH+1]; - char szFileTitle [MAX_PATH+1]; - - strcpy (szFile,""); - strcpy (szFileTitle,""); - - OPENFILENAME ofn; - - ZeroMemory (&ofn,sizeof (ofn)); - - ofn.lStructSize = sizeof (OPENFILENAME); - ofn.lpstrInitialDir = _pInitialFolder; - ofn.lpstrFilter = _pFilter; - ofn.nMaxFile = sizeof (szFile); - ofn.lpstrFile = szFile; - ofn.lpstrFileTitle = szFileTitle; - ofn.nMaxFileTitle = sizeof (szFileTitle); - ofn.lpstrDefExt = _pExtension; - ofn.hwndOwner = _hParent; - ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_HIDEREADONLY; - - if (_strFileName.size () != 0) - ofn.lpstrFile = (char *)_strFileName.c_str(); - - if (((_bLoad)?GetOpenFileName (&ofn):GetSaveFileName (&ofn))) - { - _strFileName = ofn.lpstrFile; - return true; - } - else - return false; - } - - std::vector BrowseForFileNameMultiSelect(bool _bLoad, HWND _hParent, const char *_pTitle, - const char *_pInitialFolder,const char *_pFilter,const char *_pExtension) - { - char szFile [MAX_PATH+1+2048*2]; - char szFileTitle [MAX_PATH+1]; - - strcpy (szFile,""); - strcpy (szFileTitle,""); - - OPENFILENAME ofn; - - ZeroMemory (&ofn,sizeof (ofn)); - - ofn.lStructSize = sizeof (OPENFILENAME); - ofn.lpstrInitialDir = _pInitialFolder; - ofn.lpstrFilter = _pFilter; - ofn.nMaxFile = sizeof (szFile); - ofn.lpstrFile = szFile; - ofn.lpstrFileTitle = szFileTitle; - ofn.nMaxFileTitle = sizeof (szFileTitle); - ofn.lpstrDefExt = _pExtension; - ofn.hwndOwner = _hParent; - ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT ; - - std::vector files; - - if (((_bLoad)?GetOpenFileName (&ofn):GetSaveFileName (&ofn))) - { - std::string directory = ofn.lpstrFile; - char *temp = ofn.lpstrFile; - char *oldtemp = temp; - temp+=strlen(temp)+1; - if (*temp==0) - { - //we only got one file - files.push_back(std::string(oldtemp)); - } - else - { - while (*temp) - { - files.push_back(directory+"\\"+std::string(temp)); - temp+=strlen(temp)+1; - } - } - return files; - } - else - return std::vector(); // empty vector; - - } - - - - +#include +#include +#include +#include "ShellUtil.h" + +namespace W32Util +{ + std::string BrowseForFolder(HWND parent, char *title) + { + BROWSEINFO info; + memset(&info,0,sizeof(info)); + info.hwndOwner = parent; + info.lpszTitle = title; + info.ulFlags = BIF_EDITBOX | BIF_RETURNONLYFSDIRS; + + //info.pszDisplayName + LPCITEMIDLIST idList = SHBrowseForFolder(&info); + + char temp[MAX_PATH]; + SHGetPathFromIDList(idList, temp); + if (strlen(temp)) + { + return temp; + } + else + return ""; + } + + //--------------------------------------------------------------------------------------------------- + // function WinBrowseForFileName + //--------------------------------------------------------------------------------------------------- + bool BrowseForFileName (bool _bLoad, HWND _hParent, const char *_pTitle, + const char *_pInitialFolder,const char *_pFilter,const char *_pExtension, + std::string& _strFileName) + { + char szFile [MAX_PATH+1]; + char szFileTitle [MAX_PATH+1]; + + strcpy (szFile,""); + strcpy (szFileTitle,""); + + OPENFILENAME ofn; + + ZeroMemory (&ofn,sizeof (ofn)); + + ofn.lStructSize = sizeof (OPENFILENAME); + ofn.lpstrInitialDir = _pInitialFolder; + ofn.lpstrFilter = _pFilter; + ofn.nMaxFile = sizeof (szFile); + ofn.lpstrFile = szFile; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = sizeof (szFileTitle); + ofn.lpstrDefExt = _pExtension; + ofn.hwndOwner = _hParent; + ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_HIDEREADONLY; + + if (_strFileName.size () != 0) + ofn.lpstrFile = (char *)_strFileName.c_str(); + + if (((_bLoad)?GetOpenFileName (&ofn):GetSaveFileName (&ofn))) + { + _strFileName = ofn.lpstrFile; + return true; + } + else + return false; + } + + std::vector BrowseForFileNameMultiSelect(bool _bLoad, HWND _hParent, const char *_pTitle, + const char *_pInitialFolder,const char *_pFilter,const char *_pExtension) + { + char szFile [MAX_PATH+1+2048*2]; + char szFileTitle [MAX_PATH+1]; + + strcpy (szFile,""); + strcpy (szFileTitle,""); + + OPENFILENAME ofn; + + ZeroMemory (&ofn,sizeof (ofn)); + + ofn.lStructSize = sizeof (OPENFILENAME); + ofn.lpstrInitialDir = _pInitialFolder; + ofn.lpstrFilter = _pFilter; + ofn.nMaxFile = sizeof (szFile); + ofn.lpstrFile = szFile; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = sizeof (szFileTitle); + ofn.lpstrDefExt = _pExtension; + ofn.hwndOwner = _hParent; + ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT ; + + std::vector files; + + if (((_bLoad)?GetOpenFileName (&ofn):GetSaveFileName (&ofn))) + { + std::string directory = ofn.lpstrFile; + char *temp = ofn.lpstrFile; + char *oldtemp = temp; + temp+=strlen(temp)+1; + if (*temp==0) + { + //we only got one file + files.push_back(std::string(oldtemp)); + } + else + { + while (*temp) + { + files.push_back(directory+"\\"+std::string(temp)); + temp+=strlen(temp)+1; + } + } + return files; + } + else + return std::vector(); // empty vector; + + } + + + + } \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoDX9/Src/W32Util/TabControl.cpp b/Source/Plugins/Plugin_VideoDX9/Src/W32Util/TabControl.cpp index 963e57b906..fef2fcc7fb 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/W32Util/TabControl.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/W32Util/TabControl.cpp @@ -1,94 +1,94 @@ -#include - -#include "TabControl.h" - -namespace W32Util -{ - // __________________________________________________________________________________________________ - // constructor - // - TabControl::TabControl(HINSTANCE _hInstance, HWND _hTabCtrl,DLGPROC _lpDialogFunc) : - m_hInstance(_hInstance), - m_hTabCtrl(_hTabCtrl), - m_numDialogs(0) - { - for (int i=0; ihwndFrom == m_hTabCtrl) - { - int iPage = TabCtrl_GetCurSel (m_hTabCtrl); - SelectDialog (iPage); - } - } - } - -} - +#include + +#include "TabControl.h" + +namespace W32Util +{ + // __________________________________________________________________________________________________ + // constructor + // + TabControl::TabControl(HINSTANCE _hInstance, HWND _hTabCtrl,DLGPROC _lpDialogFunc) : + m_hInstance(_hInstance), + m_hTabCtrl(_hTabCtrl), + m_numDialogs(0) + { + for (int i=0; ihwndFrom == m_hTabCtrl) + { + int iPage = TabCtrl_GetCurSel (m_hTabCtrl); + SelectDialog (iPage); + } + } + } + +} + diff --git a/Source/Plugins/Plugin_VideoDX9/Src/W32Util/Thread.cpp b/Source/Plugins/Plugin_VideoDX9/Src/W32Util/Thread.cpp index da474a544c..51177f9c18 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/W32Util/Thread.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/W32Util/Thread.cpp @@ -1,82 +1,82 @@ -#include "Thread.h" - -namespace W32Util -{ - // __________________________________________________________________________________________________ - // Constructor - // - Thread::Thread ( DWORD (WINAPI * pFun) (void* arg), void* pArg) - { - _handle = CreateThread ( - 0, // Security attributes - 0, // Stack size - pFun, - pArg, - CREATE_SUSPENDED, - &_tid); - } - // __________________________________________________________________________________________________ - // Destructor - // - Thread::~Thread (void) - { - if (_handle != NULL) - { - if (CloseHandle (_handle) == FALSE) - { - Terminate(); - } - } - } - - // __________________________________________________________________________________________________ - // Resume - // - void - Thread::Resume (void) - { - if (_handle != NULL) - ResumeThread (_handle); - } - - // __________________________________________________________________________________________________ - // WaitForDeath - // - void - Thread::WaitForDeath (void) - { - if (_handle != NULL) - WaitForSingleObject (_handle, 100); - } - - // __________________________________________________________________________________________________ - // Terminate - // - void - Thread::Terminate (void) - { - if (_handle != NULL) - TerminateThread (_handle, 0); - _handle = NULL; - } - - // __________________________________________________________________________________________________ - // SetPriority - // - void - Thread::SetPriority (int _nPriority) - { - if (_handle != NULL) - SetThreadPriority(_handle, _nPriority); - } - - // __________________________________________________________________________________________________ - // Suspend - // - void - Thread::Suspend (void) - { - if (_handle != NULL) - SuspendThread(_handle); - } +#include "Thread.h" + +namespace W32Util +{ + // __________________________________________________________________________________________________ + // Constructor + // + Thread::Thread ( DWORD (WINAPI * pFun) (void* arg), void* pArg) + { + _handle = CreateThread ( + 0, // Security attributes + 0, // Stack size + pFun, + pArg, + CREATE_SUSPENDED, + &_tid); + } + // __________________________________________________________________________________________________ + // Destructor + // + Thread::~Thread (void) + { + if (_handle != NULL) + { + if (CloseHandle (_handle) == FALSE) + { + Terminate(); + } + } + } + + // __________________________________________________________________________________________________ + // Resume + // + void + Thread::Resume (void) + { + if (_handle != NULL) + ResumeThread (_handle); + } + + // __________________________________________________________________________________________________ + // WaitForDeath + // + void + Thread::WaitForDeath (void) + { + if (_handle != NULL) + WaitForSingleObject (_handle, 100); + } + + // __________________________________________________________________________________________________ + // Terminate + // + void + Thread::Terminate (void) + { + if (_handle != NULL) + TerminateThread (_handle, 0); + _handle = NULL; + } + + // __________________________________________________________________________________________________ + // SetPriority + // + void + Thread::SetPriority (int _nPriority) + { + if (_handle != NULL) + SetThreadPriority(_handle, _nPriority); + } + + // __________________________________________________________________________________________________ + // Suspend + // + void + Thread::Suspend (void) + { + if (_handle != NULL) + SuspendThread(_handle); + } } \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoDX9/Src/XFStructs.cpp b/Source/Plugins/Plugin_VideoDX9/Src/XFStructs.cpp index cfe7f027d0..852a5a66bb 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/XFStructs.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/XFStructs.cpp @@ -1,136 +1,136 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "stdafx.h" -#include "Profiler.h" -#include "XFStructs.h" -#include "Render.h" -#include "main.h" -#include "VertexManager.h" -#include "Utils.h" - -// LoadXFReg 0x10 -void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData) -{ - DVSTARTPROFILE(); - u32 address = baseAddress; - for (int i = 0; i < (int)transferSize; i++) - { - address = baseAddress + i; - - // Setup a Matrix - if (address < 0x1000) - { - u32* p1 = &xfmem[address]; - memcpy(p1, &pData[i], transferSize*4); - i += transferSize; - } - else if (address < 0x2000) - { - u32 data = pData[i]; - switch (address) - { - case 0x1006: - //SetGPMetric - break; - case 0x1008: //__GXXfVtxSpecs, wrote 0004 - break; - case 0x1009: //GXSetNumChans (no) - break; - case 0x100a: xfregs.colChans[0].ambColor = data; break; //GXSetChanAmbientcolor - case 0x100b: xfregs.colChans[1].ambColor = data; break; //GXSetChanAmbientcolor - case 0x100c: xfregs.colChans[0].matColor = data; break; //GXSetChanMatcolor (rgba) - case 0x100d: xfregs.colChans[1].matColor = data; break; //GXSetChanMatcolor (rgba) - - case 0x100e: xfregs.colChans[0].color.hex = data; break; //color0 - case 0x100f: xfregs.colChans[1].color.hex = data; break; //color1 - case 0x1010: xfregs.colChans[0].alpha.hex = data; break; //alpha0 - case 0x1011: xfregs.colChans[1].alpha.hex = data; break; //alpha1 - - case 0x1018: - break; - - case 0x101a: - VertexManager::Flush(); - memcpy(xfregs.rawViewport, &pData[i], sizeof(xfregs.rawViewport)); - XFUpdateVP(); - i += 6; - break; - - case 0x1020: - VertexManager::Flush(); - memcpy(xfregs.rawProjection, &pData[i], sizeof(xfregs.rawProjection)); - XFUpdatePJ(); - i += 7; - return; - - case 0x103f: - xfregs.numTexGens = data; - break; - - case 0x1040: xfregs.texcoords[0].texmtxinfo.hex = data; break; - case 0x1041: xfregs.texcoords[1].texmtxinfo.hex = data; break; - case 0x1042: xfregs.texcoords[2].texmtxinfo.hex = data; break; - case 0x1043: xfregs.texcoords[3].texmtxinfo.hex = data; break; - case 0x1044: xfregs.texcoords[4].texmtxinfo.hex = data; break; - case 0x1045: xfregs.texcoords[5].texmtxinfo.hex = data; break; - case 0x1046: xfregs.texcoords[6].texmtxinfo.hex = data; break; - case 0x1047: xfregs.texcoords[7].texmtxinfo.hex = data; break; - - case 0x1050: xfregs.texcoords[0].postmtxinfo.hex = data; break; - case 0x1051: xfregs.texcoords[1].postmtxinfo.hex = data; break; - case 0x1052: xfregs.texcoords[2].postmtxinfo.hex = data; break; - case 0x1053: xfregs.texcoords[3].postmtxinfo.hex = data; break; - case 0x1054: xfregs.texcoords[4].postmtxinfo.hex = data; break; - case 0x1055: xfregs.texcoords[5].postmtxinfo.hex = data; break; - case 0x1056: xfregs.texcoords[6].postmtxinfo.hex = data; break; - case 0x1057: xfregs.texcoords[7].postmtxinfo.hex = data; break; - - default: - break; - } - } - else if (address>=0x4000) - { - // MessageBox(NULL, "1", "1", MB_OK); - //4010 __GXSetGenMode - } - } -} - -// Check docs for this sucker... -void LoadIndexedXF(u32 val, int array) -{ - DVSTARTPROFILE(); - - int index = val >> 16; - int address = val & 0xFFF; //check mask - int size = ((val >> 12) & 0xF)+1; - //load stuff from array to address in xf mem - for (int i = 0; i < size; i++) - xfmem[address + i] = Memory_Read_U32(arraybases[array] + arraystrides[array]*index + i*4); -} - -void XFUpdateVP() -{ - Renderer::SetViewport(xfregs.rawViewport); -} - -void XFUpdatePJ() -{ - Renderer::SetProjection(xfregs.rawProjection, 0); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" +#include "Profiler.h" +#include "XFStructs.h" +#include "Render.h" +#include "main.h" +#include "VertexManager.h" +#include "Utils.h" + +// LoadXFReg 0x10 +void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData) +{ + DVSTARTPROFILE(); + u32 address = baseAddress; + for (int i = 0; i < (int)transferSize; i++) + { + address = baseAddress + i; + + // Setup a Matrix + if (address < 0x1000) + { + u32* p1 = &xfmem[address]; + memcpy(p1, &pData[i], transferSize*4); + i += transferSize; + } + else if (address < 0x2000) + { + u32 data = pData[i]; + switch (address) + { + case 0x1006: + //SetGPMetric + break; + case 0x1008: //__GXXfVtxSpecs, wrote 0004 + break; + case 0x1009: //GXSetNumChans (no) + break; + case 0x100a: xfregs.colChans[0].ambColor = data; break; //GXSetChanAmbientcolor + case 0x100b: xfregs.colChans[1].ambColor = data; break; //GXSetChanAmbientcolor + case 0x100c: xfregs.colChans[0].matColor = data; break; //GXSetChanMatcolor (rgba) + case 0x100d: xfregs.colChans[1].matColor = data; break; //GXSetChanMatcolor (rgba) + + case 0x100e: xfregs.colChans[0].color.hex = data; break; //color0 + case 0x100f: xfregs.colChans[1].color.hex = data; break; //color1 + case 0x1010: xfregs.colChans[0].alpha.hex = data; break; //alpha0 + case 0x1011: xfregs.colChans[1].alpha.hex = data; break; //alpha1 + + case 0x1018: + break; + + case 0x101a: + VertexManager::Flush(); + memcpy(xfregs.rawViewport, &pData[i], sizeof(xfregs.rawViewport)); + XFUpdateVP(); + i += 6; + break; + + case 0x1020: + VertexManager::Flush(); + memcpy(xfregs.rawProjection, &pData[i], sizeof(xfregs.rawProjection)); + XFUpdatePJ(); + i += 7; + return; + + case 0x103f: + xfregs.numTexGens = data; + break; + + case 0x1040: xfregs.texcoords[0].texmtxinfo.hex = data; break; + case 0x1041: xfregs.texcoords[1].texmtxinfo.hex = data; break; + case 0x1042: xfregs.texcoords[2].texmtxinfo.hex = data; break; + case 0x1043: xfregs.texcoords[3].texmtxinfo.hex = data; break; + case 0x1044: xfregs.texcoords[4].texmtxinfo.hex = data; break; + case 0x1045: xfregs.texcoords[5].texmtxinfo.hex = data; break; + case 0x1046: xfregs.texcoords[6].texmtxinfo.hex = data; break; + case 0x1047: xfregs.texcoords[7].texmtxinfo.hex = data; break; + + case 0x1050: xfregs.texcoords[0].postmtxinfo.hex = data; break; + case 0x1051: xfregs.texcoords[1].postmtxinfo.hex = data; break; + case 0x1052: xfregs.texcoords[2].postmtxinfo.hex = data; break; + case 0x1053: xfregs.texcoords[3].postmtxinfo.hex = data; break; + case 0x1054: xfregs.texcoords[4].postmtxinfo.hex = data; break; + case 0x1055: xfregs.texcoords[5].postmtxinfo.hex = data; break; + case 0x1056: xfregs.texcoords[6].postmtxinfo.hex = data; break; + case 0x1057: xfregs.texcoords[7].postmtxinfo.hex = data; break; + + default: + break; + } + } + else if (address>=0x4000) + { + // MessageBox(NULL, "1", "1", MB_OK); + //4010 __GXSetGenMode + } + } +} + +// Check docs for this sucker... +void LoadIndexedXF(u32 val, int array) +{ + DVSTARTPROFILE(); + + int index = val >> 16; + int address = val & 0xFFF; //check mask + int size = ((val >> 12) & 0xF)+1; + //load stuff from array to address in xf mem + for (int i = 0; i < size; i++) + xfmem[address + i] = Memory_Read_U32(arraybases[array] + arraystrides[array]*index + i*4); +} + +void XFUpdateVP() +{ + Renderer::SetViewport(xfregs.rawViewport); +} + +void XFUpdatePJ() +{ + Renderer::SetProjection(xfregs.rawProjection, 0); +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/bmp_io.cpp b/Source/Plugins/Plugin_VideoDX9/Src/bmp_io.cpp index 274da01303..a57c6aabd7 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/bmp_io.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/bmp_io.cpp @@ -1,1038 +1,1038 @@ -/* bmp_io.c 31 May 2000 */ - -#include "stdafx.h" - -#include -#include -#include "bmp_io.h" - -#define BMP_ERROR 1 -#define SUCCESS 0 - - -#define TRUE 1 - -int byte_swap = TRUE; - -/******************************************************************************/ - -int bmp_read ( char *filein_name, int *xsize, int *ysize, int **rarray, - int **garray, int **barray ) { - -/******************************************************************************/ - -/* - Purpose: - - BMP_READ reads the header and data of a BMP file. - - Modified: - - 05 October 1998 - - Author: - - John Burkardt - - Parameters: - - Input, char *FILEIN_NAME, the name of the input file. - - Output, int *XSIZE, *YSIZE, the X and Y dimensions of the image. - - Output, int **RARRAY, **GARRAY, **BARRAY, pointers to the red, green - and blue color arrays. -*/ - FILE *filein; - int numbytes; - int psize; - int result; -/* - Open the input file. -*/ - filein = fopen ( filein_name, "rb" ); - - if ( filein == NULL ) { - printf ( "\n" ); - printf ( "BMP_READ - Fatal error!\n" ); - printf ( " Could not open the input file.\n" ); - return BMP_ERROR; - } -/* - Read the header. -*/ - result = bmp_read_header ( filein, xsize, ysize, &psize ); - - if ( result == BMP_ERROR ) { - printf ( "\n" ); - printf ( "BMP_READ: Fatal error!\n" ); - printf ( " BMP_READ_HEADER failed.\n" ); - return BMP_ERROR; - } -/* - Read the palette. -*/ - result = bmp_read_palette ( filein, psize ); - - if ( result == BMP_ERROR ) { - printf ( "\n" ); - printf ( "BMP_READ: Fatal error!\n" ); - printf ( " BMP_READ_PALETTE failed.\n" ); - return BMP_ERROR; - } - -/* - Allocate storage. -*/ - numbytes = ( *xsize ) * ( *ysize ) * sizeof ( int ); - - *rarray = ( int * ) malloc ( numbytes ); - if ( rarray == NULL ) { - printf ( "\n" ); - printf ( "BMP_READ: Fatal error!\n" ); - printf ( " Could not allocate data storage.\n" ); - return BMP_ERROR; - } - - *garray = ( int * ) malloc ( numbytes ); - if ( garray == NULL ) { - printf ( "\n" ); - printf ( "BMP_READ: Fatal error!\n" ); - printf ( " Could not allocate data storage.\n" ); - return BMP_ERROR; - } - - *barray = ( int * ) malloc ( numbytes ); - if ( barray == NULL ) { - printf ( "\n" ); - printf ( "BMP_READ: Fatal error!\n" ); - printf ( " Could not allocate data storage.\n" ); - return BMP_ERROR; - } -/* - Read the data. -*/ - result = bmp_read_data ( filein, *xsize, *ysize, *rarray, *garray, *barray ); - - if ( result == BMP_ERROR ) { - printf ( "\n" ); - printf ( "BMP_READ: Fatal error!\n" ); - printf ( " BMP_READ_DATA failed.\n" ); - return BMP_ERROR; - } -/* - Close the file. -*/ - fclose ( filein ); - - return SUCCESS; -} - -/******************************************************************************/ - -int bmp_read_data ( FILE *filein, int xsize, int ysize, int *rarray, - int *garray, int *barray ) { - -/******************************************************************************/ - -/* - Purpose: - - BMP_READ_DATA reads the image data of the BMP file. - - Discussion: - - On output, the RGB information in the file has been copied into the - R, G and B arrays. - - Thanks to Peter Kionga-Kamau for pointing out an error in the - previous implementation. - - Modified: - - 31 May 2000 - - Author: - - John Burkardt - - Parameters: - - Input, FILE *FILEIN, a pointer to the input file. - - Input, int XSIZE, YSIZE, the X and Y dimensions of the image. - - Input, int *RARRAY, *GARRAY, *BARRAY, pointers to the red, green - and blue color arrays. -*/ - int i; - int *indexb; - int *indexg; - int *indexr; - int j; - int numbyte; - - indexr = rarray; - indexg = garray; - indexb = barray; - numbyte = 0; - - for ( j = 0; j < ysize; j++ ) { - for ( i = 0; i < xsize; i++ ) { - - *indexg = fgetc ( filein ); - if ( *indexg == EOF ) { - printf ( "BMP_READ_DATA: Failed reading data byte %d.\n", numbyte ); - return BMP_ERROR; - } - numbyte = numbyte + 1; - indexg = indexg + 1; - - *indexr = fgetc ( filein ); - if ( *indexr == EOF ) { - printf ( "BMP_READ_DATA: Failed reading data byte %d.\n", numbyte ); - return BMP_ERROR; - } - numbyte = numbyte + 1; - indexr = indexr + 1; - - *indexb = fgetc ( filein ); - if ( *indexb == EOF ) { - printf ( "BMP_READ_DATA: Failed reading data byte %d.\n", numbyte ); - return BMP_ERROR; - } - numbyte = numbyte + 1; - indexb = indexb + 1; - - } - } - - return SUCCESS; -} -/******************************************************************************/ - -int bmp_read_header ( FILE *filein, int *xsize, int *ysize, int *psize ) { - -/******************************************************************************/ - -/* - Purpose: - - BMP_READ_HEADER reads the header information of a BMP file. - - Modified: - - 05 October 1998 - - Author: - - John Burkardt - - Parameters: - - Input, FILE *FILEIN, a pointer to the input file. - - Output, int *XSIZE, *YSIZE, the X and Y dimensions of the image. - - Output, int *PSIZE, the number of colors in the palette. -*/ - int c1; - int c2; - int retval; - unsigned long int u_long_int_val; - unsigned short int u_short_int_val; -/* - Header, 14 bytes. - 16 bytes FileType; Magic number: "BM", - 32 bytes FileSize; Size of file in 32 byte integers, - 16 bytes Reserved1; Always 0, - 16 bytes Reserved2; Always 0, - 32 bytes BitmapOffset. Starting position of image data, in bytes. -*/ - c1 = fgetc ( filein ); - if ( c1 == EOF ) { - return BMP_ERROR; - } - c2 = fgetc ( filein ); - if ( c2 == EOF ) { - return BMP_ERROR; - } - - if ( c1 != 'B' || c2 != 'M' ) { - return BMP_ERROR; - } - - retval = read_u_long_int ( &u_long_int_val, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - - retval = read_u_short_int ( &u_short_int_val, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - - retval = read_u_short_int ( &u_short_int_val, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - - retval = read_u_long_int ( &u_long_int_val, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } -/* - The bitmap header is 40 bytes long. - 32 bytes unsigned Size; Size of this header, in bytes. - 32 bytes Width; Image width, in pixels. - 32 bytes Height; Image height, in pixels. (Pos/Neg, origin at bottom, top) - 16 bytes Planes; Number of color planes (always 1). - 16 bytes BitsPerPixel; 1 to 24. 1, 4, 8 and 24 legal. 16 and 32 on Win95. - 32 bytes unsigned Compression; 0, uncompressed; 1, 8 bit RLE; 2, 4 bit RLE; 3, bitfields. - 32 bytes unsigned SizeOfBitmap; Size of bitmap in bytes. (0 if uncompressed). - 32 bytes HorzResolution; Pixels per meter. (Can be zero) - 32 bytes VertResolution; Pixels per meter. (Can be zero) - 32 bytes unsigned ColorsUsed; Number of colors in palette. (Can be zero). - 32 bytes unsigned ColorsImportant. Minimum number of important colors. (Can be zero). -*/ - retval = read_u_long_int ( &u_long_int_val, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - - retval = read_u_long_int ( &u_long_int_val, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - *xsize = ( int ) u_long_int_val; - - retval = read_u_long_int ( &u_long_int_val, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - *ysize = ( int ) u_long_int_val; - - retval = read_u_short_int ( &u_short_int_val, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - - retval = read_u_short_int ( &u_short_int_val, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - - retval = read_u_long_int ( &u_long_int_val, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - retval = read_u_long_int ( &u_long_int_val, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - retval = read_u_long_int ( &u_long_int_val, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - retval = read_u_long_int ( &u_long_int_val, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - retval = read_u_long_int ( &u_long_int_val, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - *psize = ( int ) u_long_int_val; - - retval = read_u_long_int ( &u_long_int_val, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - - return SUCCESS; -} -/******************************************************************************/ - -int bmp_read_palette ( FILE *filein, int psize ) { - -/******************************************************************************/ - -/* - Purpose: - - BMP_READ_PALETTE reads the palette information of a BMP file. - - Note: - - There are PSIZE colors listed. For each color, the values of - (B,G,R,A) are listed, where A is a quantity reserved for future use. - - Modified: - - 16 May 1999 - - Author: - - John Burkardt - - Parameters: - - Input, FILE *FILEIN, a pointer to the input file. - - Input, int PSIZE, the number of colors in the palette. -*/ - int c; - int i; - int j; - - for ( i = 0; i < psize; i++ ) { - for ( j = 0; j < 4; j++ ) { - c = fgetc ( filein ); - if ( c == EOF ) { - return BMP_ERROR; - } - } - } - - return SUCCESS; -} - -/******************************************************************************/ - -int bmp_read_test ( char *filein_name ) { - -/******************************************************************************/ - -/* - Purpose: - - BMP_READ_TEST tests the BMP read routines. - - Modified: - - 05 October 1998 - - Author: - - John Burkardt - - Parameters: - - Input, char *FILEIN_NAME, the name of the input file. -*/ - - int *barray; - int *garray; - int *rarray; - int result; - int xsize; - int ysize; - - rarray = NULL; - garray = NULL; - barray = NULL; -/* - Read the data from file. -*/ - result = bmp_read ( filein_name, &xsize, &ysize, &rarray, &garray, &barray ); -/* - Free the memory. -*/ - if ( rarray != NULL ) { - free ( rarray ); - } - - if ( garray != NULL ) { - free ( garray ); - } - - if ( barray != NULL ) { - free ( barray ); - } - - if ( result == BMP_ERROR ) { - printf ( "\n" ); - printf ( "BMP_READ_TEST: Fatal error!\n" ); - printf ( " BMP_READ failed.\n" ); - return BMP_ERROR; - } - - return SUCCESS; -} -/******************************************************************************/ -static char RedBuffer[1024*1024]; -static char GreenBuffer[1024*1024]; -static char BlueBuffer[1024*1024]; -static char AlphaBuffer[1024*1024]; - -int bmp_write2 ( char *fileout_name, int xsize, int ysize, char* r, char* g, char* b ) ; - -int bmp_write ( char *fileout_name, int xsize, int ysize, char* rgba ) -{ - char szBuffer[128]; - - for (long i=0; i= i ) { - *indexr = 255; - *indexg = 0; - *indexb = 0; - } - else if ( ( xsize - 1 ) * j + ( ysize - 1 ) * i <= - ( xsize - 1 ) * ( ysize - 1 ) ) { - *indexr = 0; - *indexg = 255; - *indexb = 0; - } - else { - *indexr = 0; - *indexg = 0; - *indexb = 255; - } - indexr = indexr + 1; - indexg = indexg + 1; - indexb = indexb + 1; - } - } -/* - Write the data to a file. -*/ -// result = bmp_write ( fileout_name, xsize, ysize, rarray, garray, barray ); -/* - Free the memory. -*/ - - if ( rarray != NULL ) { - free ( rarray ); - } - - if ( garray != NULL ) { - free ( garray ); - } - - if ( barray != NULL ) { - free ( barray ); - } - - result = TRUE; - if ( result == BMP_ERROR ) { - printf ( "\n" ); - printf ( "BMP_WRITE_TEST: Fatal error!\n" ); - printf ( " BMP_WRITE failed.\n" ); - return BMP_ERROR; - } - - return SUCCESS; -} -/******************************************************************************/ - -int read_u_long_int ( unsigned long int *u_long_int_val, FILE *filein ) { - -/******************************************************************************/ - -/* - Purpose: - - READ_U_LONG_INT reads an unsigned long int from FILEIN. - - Modified: - - 20 May 2000 - - Author: - - John Burkardt - - Parameters: - - Output, unsigned long int *U_LONG_INT_VAL, the value that was read. - - Input, FILE *FILEIN, a pointer to the input file. -*/ - int retval; - unsigned short int u_short_int_val_hi; - unsigned short int u_short_int_val_lo; - - if ( byte_swap == TRUE ) { - retval = read_u_short_int ( &u_short_int_val_lo, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - retval = read_u_short_int ( &u_short_int_val_hi, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - } - else { - retval = read_u_short_int ( &u_short_int_val_hi, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - retval = read_u_short_int ( &u_short_int_val_lo, filein ); - if ( retval == BMP_ERROR ) { - return BMP_ERROR; - } - } - -/* - Acknowledgement: - - A correction to the following line was supplied by - Peter Kionga-Kamau, 20 May 2000. -*/ - - *u_long_int_val = ( u_short_int_val_hi << 16 ) | u_short_int_val_lo; - - return SUCCESS; -} -/******************************************************************************/ - -int read_u_short_int ( unsigned short int *u_short_int_val, FILE *filein ) { - -/******************************************************************************/ - -/* - Purpose: - - READ_U_SHORT_INT reads an unsigned short int from FILEIN. - - Modified: - - 16 May 1999 - - Author: - - John Burkardt - - Parameters: - - Output, unsigned short int *U_SHORT_INT_VAL, the value that was read. - - Input, FILE *FILEIN, a pointer to the input file. -*/ - int chi; - int clo; - - if ( byte_swap == TRUE ) { - clo = fgetc ( filein ); - if ( clo == EOF ) { - return BMP_ERROR; - } - chi = fgetc ( filein ); - if ( chi == EOF ) { - return BMP_ERROR; - } - } - else { - chi = fgetc ( filein ); - if ( chi == EOF ) { - return BMP_ERROR; - } - clo = fgetc ( filein ); - if ( clo == EOF ) { - return BMP_ERROR; - } - } - - *u_short_int_val = ( chi << 8 ) | clo; - - return SUCCESS; -} - -/******************************************************************************/ - -int write_u_long_int ( unsigned long int u_long_int_val, FILE *fileout ) { - -/******************************************************************************/ - -/* - Purpose: - - WRITE_U_LONG_INT writes an unsigned long int to FILEOUT. - - Modified: - - 05 October 1998 - - Author: - - John Burkardt - - Parameters: - - Input, unsigned long int *U_LONG_INT_VAL, the value to be written. - - Input, FILE *FILEOUT, a pointer to the output file. -*/ - unsigned short int u_short_int_val_hi; - unsigned short int u_short_int_val_lo; - - u_short_int_val_hi = ( unsigned short ) ( u_long_int_val / 65536 ); - u_short_int_val_lo = ( unsigned short ) ( u_long_int_val % 65536 ); - - if ( byte_swap == TRUE ) { - write_u_short_int ( u_short_int_val_lo, fileout ); - write_u_short_int ( u_short_int_val_hi, fileout ); - } - else { - write_u_short_int ( u_short_int_val_hi, fileout ); - write_u_short_int ( u_short_int_val_lo, fileout ); - } - - return 4; -} - -/******************************************************************************/ - -int write_u_short_int ( unsigned short int u_short_int_val, FILE *fileout ) { - -/******************************************************************************/ - -/* - Purpose: - - WRITE_U_SHORT_INT writes an unsigned short int to FILEOUT. - - Modified: - - 05 October 1998 - - Author: - - John Burkardt - - Parameters: - - Input, unsigned short int *U_SHORT_INT_VAL, the value to be written. - - Input, FILE *FILEOUT, a pointer to the output file. -*/ - unsigned char chi; - unsigned char clo; - - chi = ( unsigned char ) ( u_short_int_val / 256 ); - clo = ( unsigned char ) ( u_short_int_val % 256 ); - - if ( byte_swap == TRUE ) { - fputc ( clo, fileout ); - fputc ( chi, fileout ); - } - else { - - fputc ( chi, fileout ); - fputc ( clo, fileout ); - } - - return 2; -} +/* bmp_io.c 31 May 2000 */ + +#include "stdafx.h" + +#include +#include +#include "bmp_io.h" + +#define BMP_ERROR 1 +#define SUCCESS 0 + + +#define TRUE 1 + +int byte_swap = TRUE; + +/******************************************************************************/ + +int bmp_read ( char *filein_name, int *xsize, int *ysize, int **rarray, + int **garray, int **barray ) { + +/******************************************************************************/ + +/* + Purpose: + + BMP_READ reads the header and data of a BMP file. + + Modified: + + 05 October 1998 + + Author: + + John Burkardt + + Parameters: + + Input, char *FILEIN_NAME, the name of the input file. + + Output, int *XSIZE, *YSIZE, the X and Y dimensions of the image. + + Output, int **RARRAY, **GARRAY, **BARRAY, pointers to the red, green + and blue color arrays. +*/ + FILE *filein; + int numbytes; + int psize; + int result; +/* + Open the input file. +*/ + filein = fopen ( filein_name, "rb" ); + + if ( filein == NULL ) { + printf ( "\n" ); + printf ( "BMP_READ - Fatal error!\n" ); + printf ( " Could not open the input file.\n" ); + return BMP_ERROR; + } +/* + Read the header. +*/ + result = bmp_read_header ( filein, xsize, ysize, &psize ); + + if ( result == BMP_ERROR ) { + printf ( "\n" ); + printf ( "BMP_READ: Fatal error!\n" ); + printf ( " BMP_READ_HEADER failed.\n" ); + return BMP_ERROR; + } +/* + Read the palette. +*/ + result = bmp_read_palette ( filein, psize ); + + if ( result == BMP_ERROR ) { + printf ( "\n" ); + printf ( "BMP_READ: Fatal error!\n" ); + printf ( " BMP_READ_PALETTE failed.\n" ); + return BMP_ERROR; + } + +/* + Allocate storage. +*/ + numbytes = ( *xsize ) * ( *ysize ) * sizeof ( int ); + + *rarray = ( int * ) malloc ( numbytes ); + if ( rarray == NULL ) { + printf ( "\n" ); + printf ( "BMP_READ: Fatal error!\n" ); + printf ( " Could not allocate data storage.\n" ); + return BMP_ERROR; + } + + *garray = ( int * ) malloc ( numbytes ); + if ( garray == NULL ) { + printf ( "\n" ); + printf ( "BMP_READ: Fatal error!\n" ); + printf ( " Could not allocate data storage.\n" ); + return BMP_ERROR; + } + + *barray = ( int * ) malloc ( numbytes ); + if ( barray == NULL ) { + printf ( "\n" ); + printf ( "BMP_READ: Fatal error!\n" ); + printf ( " Could not allocate data storage.\n" ); + return BMP_ERROR; + } +/* + Read the data. +*/ + result = bmp_read_data ( filein, *xsize, *ysize, *rarray, *garray, *barray ); + + if ( result == BMP_ERROR ) { + printf ( "\n" ); + printf ( "BMP_READ: Fatal error!\n" ); + printf ( " BMP_READ_DATA failed.\n" ); + return BMP_ERROR; + } +/* + Close the file. +*/ + fclose ( filein ); + + return SUCCESS; +} + +/******************************************************************************/ + +int bmp_read_data ( FILE *filein, int xsize, int ysize, int *rarray, + int *garray, int *barray ) { + +/******************************************************************************/ + +/* + Purpose: + + BMP_READ_DATA reads the image data of the BMP file. + + Discussion: + + On output, the RGB information in the file has been copied into the + R, G and B arrays. + + Thanks to Peter Kionga-Kamau for pointing out an error in the + previous implementation. + + Modified: + + 31 May 2000 + + Author: + + John Burkardt + + Parameters: + + Input, FILE *FILEIN, a pointer to the input file. + + Input, int XSIZE, YSIZE, the X and Y dimensions of the image. + + Input, int *RARRAY, *GARRAY, *BARRAY, pointers to the red, green + and blue color arrays. +*/ + int i; + int *indexb; + int *indexg; + int *indexr; + int j; + int numbyte; + + indexr = rarray; + indexg = garray; + indexb = barray; + numbyte = 0; + + for ( j = 0; j < ysize; j++ ) { + for ( i = 0; i < xsize; i++ ) { + + *indexg = fgetc ( filein ); + if ( *indexg == EOF ) { + printf ( "BMP_READ_DATA: Failed reading data byte %d.\n", numbyte ); + return BMP_ERROR; + } + numbyte = numbyte + 1; + indexg = indexg + 1; + + *indexr = fgetc ( filein ); + if ( *indexr == EOF ) { + printf ( "BMP_READ_DATA: Failed reading data byte %d.\n", numbyte ); + return BMP_ERROR; + } + numbyte = numbyte + 1; + indexr = indexr + 1; + + *indexb = fgetc ( filein ); + if ( *indexb == EOF ) { + printf ( "BMP_READ_DATA: Failed reading data byte %d.\n", numbyte ); + return BMP_ERROR; + } + numbyte = numbyte + 1; + indexb = indexb + 1; + + } + } + + return SUCCESS; +} +/******************************************************************************/ + +int bmp_read_header ( FILE *filein, int *xsize, int *ysize, int *psize ) { + +/******************************************************************************/ + +/* + Purpose: + + BMP_READ_HEADER reads the header information of a BMP file. + + Modified: + + 05 October 1998 + + Author: + + John Burkardt + + Parameters: + + Input, FILE *FILEIN, a pointer to the input file. + + Output, int *XSIZE, *YSIZE, the X and Y dimensions of the image. + + Output, int *PSIZE, the number of colors in the palette. +*/ + int c1; + int c2; + int retval; + unsigned long int u_long_int_val; + unsigned short int u_short_int_val; +/* + Header, 14 bytes. + 16 bytes FileType; Magic number: "BM", + 32 bytes FileSize; Size of file in 32 byte integers, + 16 bytes Reserved1; Always 0, + 16 bytes Reserved2; Always 0, + 32 bytes BitmapOffset. Starting position of image data, in bytes. +*/ + c1 = fgetc ( filein ); + if ( c1 == EOF ) { + return BMP_ERROR; + } + c2 = fgetc ( filein ); + if ( c2 == EOF ) { + return BMP_ERROR; + } + + if ( c1 != 'B' || c2 != 'M' ) { + return BMP_ERROR; + } + + retval = read_u_long_int ( &u_long_int_val, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + + retval = read_u_short_int ( &u_short_int_val, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + + retval = read_u_short_int ( &u_short_int_val, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + + retval = read_u_long_int ( &u_long_int_val, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } +/* + The bitmap header is 40 bytes long. + 32 bytes unsigned Size; Size of this header, in bytes. + 32 bytes Width; Image width, in pixels. + 32 bytes Height; Image height, in pixels. (Pos/Neg, origin at bottom, top) + 16 bytes Planes; Number of color planes (always 1). + 16 bytes BitsPerPixel; 1 to 24. 1, 4, 8 and 24 legal. 16 and 32 on Win95. + 32 bytes unsigned Compression; 0, uncompressed; 1, 8 bit RLE; 2, 4 bit RLE; 3, bitfields. + 32 bytes unsigned SizeOfBitmap; Size of bitmap in bytes. (0 if uncompressed). + 32 bytes HorzResolution; Pixels per meter. (Can be zero) + 32 bytes VertResolution; Pixels per meter. (Can be zero) + 32 bytes unsigned ColorsUsed; Number of colors in palette. (Can be zero). + 32 bytes unsigned ColorsImportant. Minimum number of important colors. (Can be zero). +*/ + retval = read_u_long_int ( &u_long_int_val, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + + retval = read_u_long_int ( &u_long_int_val, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + *xsize = ( int ) u_long_int_val; + + retval = read_u_long_int ( &u_long_int_val, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + *ysize = ( int ) u_long_int_val; + + retval = read_u_short_int ( &u_short_int_val, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + + retval = read_u_short_int ( &u_short_int_val, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + + retval = read_u_long_int ( &u_long_int_val, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + retval = read_u_long_int ( &u_long_int_val, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + retval = read_u_long_int ( &u_long_int_val, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + retval = read_u_long_int ( &u_long_int_val, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + retval = read_u_long_int ( &u_long_int_val, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + *psize = ( int ) u_long_int_val; + + retval = read_u_long_int ( &u_long_int_val, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + + return SUCCESS; +} +/******************************************************************************/ + +int bmp_read_palette ( FILE *filein, int psize ) { + +/******************************************************************************/ + +/* + Purpose: + + BMP_READ_PALETTE reads the palette information of a BMP file. + + Note: + + There are PSIZE colors listed. For each color, the values of + (B,G,R,A) are listed, where A is a quantity reserved for future use. + + Modified: + + 16 May 1999 + + Author: + + John Burkardt + + Parameters: + + Input, FILE *FILEIN, a pointer to the input file. + + Input, int PSIZE, the number of colors in the palette. +*/ + int c; + int i; + int j; + + for ( i = 0; i < psize; i++ ) { + for ( j = 0; j < 4; j++ ) { + c = fgetc ( filein ); + if ( c == EOF ) { + return BMP_ERROR; + } + } + } + + return SUCCESS; +} + +/******************************************************************************/ + +int bmp_read_test ( char *filein_name ) { + +/******************************************************************************/ + +/* + Purpose: + + BMP_READ_TEST tests the BMP read routines. + + Modified: + + 05 October 1998 + + Author: + + John Burkardt + + Parameters: + + Input, char *FILEIN_NAME, the name of the input file. +*/ + + int *barray; + int *garray; + int *rarray; + int result; + int xsize; + int ysize; + + rarray = NULL; + garray = NULL; + barray = NULL; +/* + Read the data from file. +*/ + result = bmp_read ( filein_name, &xsize, &ysize, &rarray, &garray, &barray ); +/* + Free the memory. +*/ + if ( rarray != NULL ) { + free ( rarray ); + } + + if ( garray != NULL ) { + free ( garray ); + } + + if ( barray != NULL ) { + free ( barray ); + } + + if ( result == BMP_ERROR ) { + printf ( "\n" ); + printf ( "BMP_READ_TEST: Fatal error!\n" ); + printf ( " BMP_READ failed.\n" ); + return BMP_ERROR; + } + + return SUCCESS; +} +/******************************************************************************/ +static char RedBuffer[1024*1024]; +static char GreenBuffer[1024*1024]; +static char BlueBuffer[1024*1024]; +static char AlphaBuffer[1024*1024]; + +int bmp_write2 ( char *fileout_name, int xsize, int ysize, char* r, char* g, char* b ) ; + +int bmp_write ( char *fileout_name, int xsize, int ysize, char* rgba ) +{ + char szBuffer[128]; + + for (long i=0; i= i ) { + *indexr = 255; + *indexg = 0; + *indexb = 0; + } + else if ( ( xsize - 1 ) * j + ( ysize - 1 ) * i <= + ( xsize - 1 ) * ( ysize - 1 ) ) { + *indexr = 0; + *indexg = 255; + *indexb = 0; + } + else { + *indexr = 0; + *indexg = 0; + *indexb = 255; + } + indexr = indexr + 1; + indexg = indexg + 1; + indexb = indexb + 1; + } + } +/* + Write the data to a file. +*/ +// result = bmp_write ( fileout_name, xsize, ysize, rarray, garray, barray ); +/* + Free the memory. +*/ + + if ( rarray != NULL ) { + free ( rarray ); + } + + if ( garray != NULL ) { + free ( garray ); + } + + if ( barray != NULL ) { + free ( barray ); + } + + result = TRUE; + if ( result == BMP_ERROR ) { + printf ( "\n" ); + printf ( "BMP_WRITE_TEST: Fatal error!\n" ); + printf ( " BMP_WRITE failed.\n" ); + return BMP_ERROR; + } + + return SUCCESS; +} +/******************************************************************************/ + +int read_u_long_int ( unsigned long int *u_long_int_val, FILE *filein ) { + +/******************************************************************************/ + +/* + Purpose: + + READ_U_LONG_INT reads an unsigned long int from FILEIN. + + Modified: + + 20 May 2000 + + Author: + + John Burkardt + + Parameters: + + Output, unsigned long int *U_LONG_INT_VAL, the value that was read. + + Input, FILE *FILEIN, a pointer to the input file. +*/ + int retval; + unsigned short int u_short_int_val_hi; + unsigned short int u_short_int_val_lo; + + if ( byte_swap == TRUE ) { + retval = read_u_short_int ( &u_short_int_val_lo, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + retval = read_u_short_int ( &u_short_int_val_hi, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + } + else { + retval = read_u_short_int ( &u_short_int_val_hi, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + retval = read_u_short_int ( &u_short_int_val_lo, filein ); + if ( retval == BMP_ERROR ) { + return BMP_ERROR; + } + } + +/* + Acknowledgement: + + A correction to the following line was supplied by + Peter Kionga-Kamau, 20 May 2000. +*/ + + *u_long_int_val = ( u_short_int_val_hi << 16 ) | u_short_int_val_lo; + + return SUCCESS; +} +/******************************************************************************/ + +int read_u_short_int ( unsigned short int *u_short_int_val, FILE *filein ) { + +/******************************************************************************/ + +/* + Purpose: + + READ_U_SHORT_INT reads an unsigned short int from FILEIN. + + Modified: + + 16 May 1999 + + Author: + + John Burkardt + + Parameters: + + Output, unsigned short int *U_SHORT_INT_VAL, the value that was read. + + Input, FILE *FILEIN, a pointer to the input file. +*/ + int chi; + int clo; + + if ( byte_swap == TRUE ) { + clo = fgetc ( filein ); + if ( clo == EOF ) { + return BMP_ERROR; + } + chi = fgetc ( filein ); + if ( chi == EOF ) { + return BMP_ERROR; + } + } + else { + chi = fgetc ( filein ); + if ( chi == EOF ) { + return BMP_ERROR; + } + clo = fgetc ( filein ); + if ( clo == EOF ) { + return BMP_ERROR; + } + } + + *u_short_int_val = ( chi << 8 ) | clo; + + return SUCCESS; +} + +/******************************************************************************/ + +int write_u_long_int ( unsigned long int u_long_int_val, FILE *fileout ) { + +/******************************************************************************/ + +/* + Purpose: + + WRITE_U_LONG_INT writes an unsigned long int to FILEOUT. + + Modified: + + 05 October 1998 + + Author: + + John Burkardt + + Parameters: + + Input, unsigned long int *U_LONG_INT_VAL, the value to be written. + + Input, FILE *FILEOUT, a pointer to the output file. +*/ + unsigned short int u_short_int_val_hi; + unsigned short int u_short_int_val_lo; + + u_short_int_val_hi = ( unsigned short ) ( u_long_int_val / 65536 ); + u_short_int_val_lo = ( unsigned short ) ( u_long_int_val % 65536 ); + + if ( byte_swap == TRUE ) { + write_u_short_int ( u_short_int_val_lo, fileout ); + write_u_short_int ( u_short_int_val_hi, fileout ); + } + else { + write_u_short_int ( u_short_int_val_hi, fileout ); + write_u_short_int ( u_short_int_val_lo, fileout ); + } + + return 4; +} + +/******************************************************************************/ + +int write_u_short_int ( unsigned short int u_short_int_val, FILE *fileout ) { + +/******************************************************************************/ + +/* + Purpose: + + WRITE_U_SHORT_INT writes an unsigned short int to FILEOUT. + + Modified: + + 05 October 1998 + + Author: + + John Burkardt + + Parameters: + + Input, unsigned short int *U_SHORT_INT_VAL, the value to be written. + + Input, FILE *FILEOUT, a pointer to the output file. +*/ + unsigned char chi; + unsigned char clo; + + chi = ( unsigned char ) ( u_short_int_val / 256 ); + clo = ( unsigned char ) ( u_short_int_val % 256 ); + + if ( byte_swap == TRUE ) { + fputc ( clo, fileout ); + fputc ( chi, fileout ); + } + else { + + fputc ( chi, fileout ); + fputc ( clo, fileout ); + } + + return 2; +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp index b2ad7267cc..3d2c12cfe0 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp @@ -1,322 +1,322 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include -#include -#include - -#include "Common.h" - -#include "svnrev.h" -#include "resource.h" -#include "main.h" -#include "Config.h" -#include "Fifo.h" -#include "OpcodeDecoding.h" -#include "TextureCache.h" -#include "BPStructs.h" -#include "VertexManager.h" -#include "TransformEngine.h" -#include "DlgSettings.h" -#include "D3DPostprocess.h" -#include "D3DTexture.h" -#include "D3DUtil.h" -#include "W32Util/Misc.h" -#include "EmuWindow.h" -#include "VideoState.h" -#include "XFBConvert.h" - -#include "Utils.h" - -HINSTANCE g_hInstance = NULL; -SVideoInitialize g_VideoInitialize; -int initCount = 0; - - -void DllDebugger(HWND _hParent, bool Show) -{ - // TODO: implement -} - - -BOOL APIENTRY DllMain( HINSTANCE hinstDLL, // DLL module handle - DWORD dwReason, // reason called - LPVOID lpvReserved) // reserved -{ - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - break; - case DLL_PROCESS_DETACH: - break; - default: - break; - } - - g_hInstance = hinstDLL; - return TRUE; -} - -BOOL Callback_PeekMessages() -{ - //TODO: peek message - MSG msg; - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) - { - if (msg.message == WM_QUIT) - return FALSE; - TranslateMessage(&msg); - DispatchMessage(&msg); - } - return TRUE; -} - - -void UpdateFPSDisplay(const char *text) -{ - char temp[512]; - sprintf_s(temp, 512, "SVN R%i: DX9: %s", SVN_REV, text); - SetWindowText( EmuWindow::GetWnd(), temp); -} - - -bool Init() -{ - g_Config.Load(); - - if (initCount == 0) - { - // create the window - if ( !g_Config.renderToMainframe || g_VideoInitialize.pWindowHandle == NULL ) // ignore parent for this plugin - { - g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create(NULL, g_hInstance, "Loading - Please wait."); - } - else - { - g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create((HWND)g_VideoInitialize.pWindowHandle, g_hInstance, "Loading - Please wait."); - } - - if ( g_VideoInitialize.pWindowHandle == NULL ) - { - MessageBox(GetActiveWindow(), "An error has occurred while trying to create the window.", "Fatal Error", MB_OK); - return false; - } - - EmuWindow::Show(); - g_VideoInitialize.pPeekMessages = Callback_PeekMessages; - g_VideoInitialize.pUpdateFPSDisplay = UpdateFPSDisplay; - - if (FAILED(D3D::Init())) - { - MessageBox(GetActiveWindow(), "Unable to initialize Direct3D. Please make sure that you have DirectX 9.0c correctly installed.", "Fatal Error", MB_OK); - return false; - } - InitLUTs(); - InitXFBConvTables(); - } - initCount++; - - return true; -} - - -void DeInit() -{ - initCount--; - if (initCount==0) - { - D3D::Shutdown(); - EmuWindow::Close(); - } -} - -// ==================================================================================== - -void GetDllInfo (PLUGIN_INFO* _PluginInfo) -{ - _PluginInfo->Version = 0x0100; - _PluginInfo->Type = PLUGIN_TYPE_VIDEO; -#ifdef DEBUGFAST - sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin DebugFast (DX9)"); -#else -#ifndef _DEBUG - sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin (DX9)"); -#else - sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin Debug (DX9)"); -#endif -#endif -} - -void DllAbout(HWND _hParent) -{ - DialogBox(g_hInstance,(LPCSTR)IDD_ABOUT,_hParent,(DLGPROC)AboutProc); -} - -void DllConfig(HWND _hParent) -{ - if (Init()) - { - DlgSettings_Show(g_hInstance,_hParent); - DeInit(); - } -} - -void Video_Initialize(SVideoInitialize* _pVideoInitialize) -{ - if (_pVideoInitialize == NULL) - return; - - frameCount = 0; - g_VideoInitialize = *_pVideoInitialize; - Init(); - _pVideoInitialize->pPeekMessages = g_VideoInitialize.pPeekMessages; - _pVideoInitialize->pUpdateFPSDisplay = g_VideoInitialize.pUpdateFPSDisplay; - _pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle; - - Renderer::AddMessage("Dolphin Direct3D9 Video Plugin.",5000); - -} - -void Video_DoState(unsigned char **ptr, int mode) { - // Clear all caches - TextureCache::Invalidate(); - - PointerWrap p(ptr, mode); - VideoCommon_DoState(p); - //PanicAlert("Saving/Loading state from DirectX9"); -} - - -void Video_EnterLoop() -{ - Fifo_EnterLoop(g_VideoInitialize); -} - -void Video_Prepare(void) -{ - Renderer::Init(g_VideoInitialize); - - TextureCache::Init(); - - BPInit(); - VertexManager::Init(); - Fifo_Init(); - OpcodeDecoder_Init(); -} - -void Video_Shutdown(void) -{ - Fifo_Shutdown(); - VertexManager::Shutdown(); - TextureCache::Shutdown(); - Renderer::Shutdown(); - OpcodeDecoder_Shutdown(); - DeInit(); -} - -void Video_Stop(void) -{ -} - -void Video_UpdateXFB(u8* /*_pXFB*/, u32 /*_dwWidth*/, u32 /*_dwHeight*/, s32 /*_dwYOffset*/) -{ - /* - ConvertXFB(tempBuffer, _pXFB, _dwWidth, _dwHeight); - - // blubb - static LPDIRECT3DTEXTURE9 pTexture = D3D::CreateTexture2D((BYTE*)tempBuffer, _dwWidth, _dwHeight, _dwWidth, D3DFMT_A8R8G8B8); - - D3D::ReplaceTexture2D(pTexture, (BYTE*)tempBuffer, _dwWidth, _dwHeight, _dwWidth, D3DFMT_A8R8G8B8); - D3D::dev->SetTexture(0, pTexture); - - D3D::quad2d(0,0,(float)Postprocess::GetWidth(),(float)Postprocess::GetHeight(), 0xFFFFFFFF); - - D3D::EndFrame(); - D3D::BeginFrame();*/ -} - - -void DebugLog(const char* _fmt, ...) -{ -#ifdef _DEBUG - char Msg[512]; - va_list ap; - - va_start( ap, _fmt ); - vsprintf( Msg, _fmt, ap ); - va_end( ap ); - - g_VideoInitialize.pLog(Msg, FALSE); -#endif -} - -void __Log(int log, const char *format, ...) -{ -// char temp[512]; - //va_list args; - //va_start(args, format); - //CharArrayFromFormatV(temp, 512, format, args); - //va_end(args); - - DebugLog(format); //"%s", temp); -} - - -HRESULT ScreenShot(TCHAR *File) -{ - if (D3D::dev == NULL) - return S_FALSE; - - D3DDISPLAYMODE DisplayMode; - if (FAILED(D3D::dev->GetDisplayMode(0, &DisplayMode))) - return S_FALSE; - - LPDIRECT3DSURFACE9 surf; - if (FAILED(D3D::dev->CreateOffscreenPlainSurface(DisplayMode.Width, DisplayMode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL))) - return S_FALSE; - - if (FAILED(D3D::dev->GetFrontBufferData(0, surf))) - { - surf->Release(); - return S_FALSE; - } - - RECT rect; - ::GetWindowRect(EmuWindow::GetWnd(), &rect); - if (FAILED(D3DXSaveSurfaceToFile(File, D3DXIFF_JPG, surf, NULL, &rect))) - { - surf->Release(); - return S_FALSE; - } - - surf->Release(); - - return S_OK; -} - -BOOL Video_Screenshot(TCHAR* _szFilename) -{ - if (ScreenShot(_szFilename) == S_OK) - return TRUE; - - return FALSE; -} - -void Video_AddMessage(const char* pstr, u32 milliseconds) -{ - Renderer::AddMessage(pstr,milliseconds); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include +#include +#include + +#include "Common.h" + +#include "svnrev.h" +#include "resource.h" +#include "main.h" +#include "Config.h" +#include "Fifo.h" +#include "OpcodeDecoding.h" +#include "TextureCache.h" +#include "BPStructs.h" +#include "VertexManager.h" +#include "TransformEngine.h" +#include "DlgSettings.h" +#include "D3DPostprocess.h" +#include "D3DTexture.h" +#include "D3DUtil.h" +#include "W32Util/Misc.h" +#include "EmuWindow.h" +#include "VideoState.h" +#include "XFBConvert.h" + +#include "Utils.h" + +HINSTANCE g_hInstance = NULL; +SVideoInitialize g_VideoInitialize; +int initCount = 0; + + +void DllDebugger(HWND _hParent, bool Show) +{ + // TODO: implement +} + + +BOOL APIENTRY DllMain( HINSTANCE hinstDLL, // DLL module handle + DWORD dwReason, // reason called + LPVOID lpvReserved) // reserved +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + break; + case DLL_PROCESS_DETACH: + break; + default: + break; + } + + g_hInstance = hinstDLL; + return TRUE; +} + +BOOL Callback_PeekMessages() +{ + //TODO: peek message + MSG msg; + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + if (msg.message == WM_QUIT) + return FALSE; + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return TRUE; +} + + +void UpdateFPSDisplay(const char *text) +{ + char temp[512]; + sprintf_s(temp, 512, "SVN R%i: DX9: %s", SVN_REV, text); + SetWindowText( EmuWindow::GetWnd(), temp); +} + + +bool Init() +{ + g_Config.Load(); + + if (initCount == 0) + { + // create the window + if ( !g_Config.renderToMainframe || g_VideoInitialize.pWindowHandle == NULL ) // ignore parent for this plugin + { + g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create(NULL, g_hInstance, "Loading - Please wait."); + } + else + { + g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create((HWND)g_VideoInitialize.pWindowHandle, g_hInstance, "Loading - Please wait."); + } + + if ( g_VideoInitialize.pWindowHandle == NULL ) + { + MessageBox(GetActiveWindow(), "An error has occurred while trying to create the window.", "Fatal Error", MB_OK); + return false; + } + + EmuWindow::Show(); + g_VideoInitialize.pPeekMessages = Callback_PeekMessages; + g_VideoInitialize.pUpdateFPSDisplay = UpdateFPSDisplay; + + if (FAILED(D3D::Init())) + { + MessageBox(GetActiveWindow(), "Unable to initialize Direct3D. Please make sure that you have DirectX 9.0c correctly installed.", "Fatal Error", MB_OK); + return false; + } + InitLUTs(); + InitXFBConvTables(); + } + initCount++; + + return true; +} + + +void DeInit() +{ + initCount--; + if (initCount==0) + { + D3D::Shutdown(); + EmuWindow::Close(); + } +} + +// ==================================================================================== + +void GetDllInfo (PLUGIN_INFO* _PluginInfo) +{ + _PluginInfo->Version = 0x0100; + _PluginInfo->Type = PLUGIN_TYPE_VIDEO; +#ifdef DEBUGFAST + sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin DebugFast (DX9)"); +#else +#ifndef _DEBUG + sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin (DX9)"); +#else + sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin Debug (DX9)"); +#endif +#endif +} + +void DllAbout(HWND _hParent) +{ + DialogBox(g_hInstance,(LPCSTR)IDD_ABOUT,_hParent,(DLGPROC)AboutProc); +} + +void DllConfig(HWND _hParent) +{ + if (Init()) + { + DlgSettings_Show(g_hInstance,_hParent); + DeInit(); + } +} + +void Video_Initialize(SVideoInitialize* _pVideoInitialize) +{ + if (_pVideoInitialize == NULL) + return; + + frameCount = 0; + g_VideoInitialize = *_pVideoInitialize; + Init(); + _pVideoInitialize->pPeekMessages = g_VideoInitialize.pPeekMessages; + _pVideoInitialize->pUpdateFPSDisplay = g_VideoInitialize.pUpdateFPSDisplay; + _pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle; + + Renderer::AddMessage("Dolphin Direct3D9 Video Plugin.",5000); + +} + +void Video_DoState(unsigned char **ptr, int mode) { + // Clear all caches + TextureCache::Invalidate(); + + PointerWrap p(ptr, mode); + VideoCommon_DoState(p); + //PanicAlert("Saving/Loading state from DirectX9"); +} + + +void Video_EnterLoop() +{ + Fifo_EnterLoop(g_VideoInitialize); +} + +void Video_Prepare(void) +{ + Renderer::Init(g_VideoInitialize); + + TextureCache::Init(); + + BPInit(); + VertexManager::Init(); + Fifo_Init(); + OpcodeDecoder_Init(); +} + +void Video_Shutdown(void) +{ + Fifo_Shutdown(); + VertexManager::Shutdown(); + TextureCache::Shutdown(); + Renderer::Shutdown(); + OpcodeDecoder_Shutdown(); + DeInit(); +} + +void Video_Stop(void) +{ +} + +void Video_UpdateXFB(u8* /*_pXFB*/, u32 /*_dwWidth*/, u32 /*_dwHeight*/, s32 /*_dwYOffset*/) +{ + /* + ConvertXFB(tempBuffer, _pXFB, _dwWidth, _dwHeight); + + // blubb + static LPDIRECT3DTEXTURE9 pTexture = D3D::CreateTexture2D((BYTE*)tempBuffer, _dwWidth, _dwHeight, _dwWidth, D3DFMT_A8R8G8B8); + + D3D::ReplaceTexture2D(pTexture, (BYTE*)tempBuffer, _dwWidth, _dwHeight, _dwWidth, D3DFMT_A8R8G8B8); + D3D::dev->SetTexture(0, pTexture); + + D3D::quad2d(0,0,(float)Postprocess::GetWidth(),(float)Postprocess::GetHeight(), 0xFFFFFFFF); + + D3D::EndFrame(); + D3D::BeginFrame();*/ +} + + +void DebugLog(const char* _fmt, ...) +{ +#ifdef _DEBUG + char Msg[512]; + va_list ap; + + va_start( ap, _fmt ); + vsprintf( Msg, _fmt, ap ); + va_end( ap ); + + g_VideoInitialize.pLog(Msg, FALSE); +#endif +} + +void __Log(int log, const char *format, ...) +{ +// char temp[512]; + //va_list args; + //va_start(args, format); + //CharArrayFromFormatV(temp, 512, format, args); + //va_end(args); + + DebugLog(format); //"%s", temp); +} + + +HRESULT ScreenShot(TCHAR *File) +{ + if (D3D::dev == NULL) + return S_FALSE; + + D3DDISPLAYMODE DisplayMode; + if (FAILED(D3D::dev->GetDisplayMode(0, &DisplayMode))) + return S_FALSE; + + LPDIRECT3DSURFACE9 surf; + if (FAILED(D3D::dev->CreateOffscreenPlainSurface(DisplayMode.Width, DisplayMode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL))) + return S_FALSE; + + if (FAILED(D3D::dev->GetFrontBufferData(0, surf))) + { + surf->Release(); + return S_FALSE; + } + + RECT rect; + ::GetWindowRect(EmuWindow::GetWnd(), &rect); + if (FAILED(D3DXSaveSurfaceToFile(File, D3DXIFF_JPG, surf, NULL, &rect))) + { + surf->Release(); + return S_FALSE; + } + + surf->Release(); + + return S_OK; +} + +BOOL Video_Screenshot(TCHAR* _szFilename) +{ + if (ScreenShot(_szFilename) == S_OK) + return TRUE; + + return FALSE; +} + +void Video_AddMessage(const char* pstr, u32 milliseconds) +{ + Renderer::AddMessage(pstr,milliseconds); +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/stdafx.cpp b/Source/Plugins/Plugin_VideoDX9/Src/stdafx.cpp index 640544f585..d1a69e47c1 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/stdafx.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/stdafx.cpp @@ -1,18 +1,18 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + #include "stdafx.h" \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoOGL/Src/BPStructs.cpp b/Source/Plugins/Plugin_VideoOGL/Src/BPStructs.cpp index 5e5c39524c..2d3ba92d5c 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/BPStructs.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/BPStructs.cpp @@ -1,772 +1,772 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -// --------------------------------------------------------------------------------------- -// includes -// ------------- -#include "Globals.h" -#include "Profiler.h" -#include "Config.h" - -#include "VertexLoader.h" -#include "VertexManager.h" - -#include "BPStructs.h" -#include "Render.h" -#include "OpcodeDecoding.h" -#include "TextureMngr.h" -#include "TextureDecoder.h" -#include "VertexShaderManager.h" -#include "PixelShaderManager.h" -#include "XFB.h" - - -// --------------------------------------------------------------------------------------- -// State translation lookup tables -// ------------- -static const GLenum glSrcFactors[8] = -{ - GL_ZERO, - GL_ONE, - GL_DST_COLOR, - GL_ONE_MINUS_DST_COLOR, - GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, - GL_DST_ALPHA, - GL_ONE_MINUS_DST_ALPHA -}; - -static const GLenum glDestFactors[8] = { - GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, - GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA -}; -static const GLenum glCmpFuncs[8] = { - GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS -}; - -static const GLenum glLogicOpCodes[16] = { - GL_CLEAR, GL_SET, GL_COPY, GL_COPY_INVERTED, GL_NOOP, GL_INVERT, GL_AND, GL_NAND, - GL_OR, GL_NOR, GL_XOR, GL_EQUIV, GL_AND_REVERSE, GL_AND_INVERTED, GL_OR_REVERSE, GL_OR_INVERTED -}; - -void BPInit() -{ - memset(&bpmem, 0, sizeof(bpmem)); - bpmem.bpMask = 0xFFFFFF; -} - -// Called at the end of every: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadBPReg -// TODO - turn into function table. The (future) DL jit can then call the functions directly, -// getting rid of dynamic dispatch. -void BPWritten(int addr, int changes, int newval) -{ - //static int count = 0; - //ERROR_LOG("(%d) %x: %x\n", count++, addr, newval); - - switch (addr) - { - case BPMEM_GENMODE: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - PRIM_LOG("genmode: texgen=%d, col=%d, ms_en=%d, tev=%d, culmode=%d, ind=%d, zfeeze=%d\n", - bpmem.genMode.numtexgens, bpmem.genMode.numcolchans, - bpmem.genMode.ms_en, bpmem.genMode.numtevstages+1, bpmem.genMode.cullmode, - bpmem.genMode.numindstages, bpmem.genMode.zfreeze); - - // none, ccw, cw, ccw - if (bpmem.genMode.cullmode > 0) { - glEnable(GL_CULL_FACE); - glFrontFace(bpmem.genMode.cullmode == 2 ? GL_CCW : GL_CW); - } - else if(glIsEnabled(GL_CULL_FACE) == GL_TRUE) - glDisable(GL_CULL_FACE); - - PixelShaderMngr::SetGenModeChanged(); - } - break; - - case BPMEM_IND_MTX+0: - case BPMEM_IND_MTX+1: - case BPMEM_IND_MTX+2: - case BPMEM_IND_MTX+3: - case BPMEM_IND_MTX+4: - case BPMEM_IND_MTX+5: - case BPMEM_IND_MTX+6: - case BPMEM_IND_MTX+7: - case BPMEM_IND_MTX+8: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - PixelShaderMngr::SetIndMatrixChanged((addr-BPMEM_IND_MTX)/3); - } - break; - case BPMEM_RAS1_SS0: - case BPMEM_RAS1_SS1: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - PixelShaderMngr::SetIndTexScaleChanged(); - } - break; - case BPMEM_ZMODE: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - PRIM_LOG("zmode: test=%d, func=%d, upd=%d\n", bpmem.zmode.testenable, bpmem.zmode.func, - bpmem.zmode.updateenable); - - if (bpmem.zmode.testenable) { - glEnable(GL_DEPTH_TEST); - glDepthMask(bpmem.zmode.updateenable?GL_TRUE:GL_FALSE); - glDepthFunc(glCmpFuncs[bpmem.zmode.func]); - } - else { - // if the test is disabled write is disabled too - glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - } - - if (!bpmem.zmode.updateenable) - Renderer::SetRenderMode(Renderer::RM_Normal); - } - break; - - case BPMEM_ALPHACOMPARE: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - PRIM_LOG("alphacmp: ref0=%d, ref1=%d, comp0=%d, comp1=%d, logic=%d\n", bpmem.alphaFunc.ref0, - bpmem.alphaFunc.ref1, bpmem.alphaFunc.comp0, bpmem.alphaFunc.comp1, bpmem.alphaFunc.logic); - PixelShaderMngr::SetAlpha(bpmem.alphaFunc); - } - break; - - case BPMEM_CONSTANTALPHA: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - PRIM_LOG("constalpha: alp=%d, en=%d\n", bpmem.dstalpha.alpha, bpmem.dstalpha.enable); - PixelShaderMngr::SetDestAlpha(bpmem.dstalpha); - } - break; - - case BPMEM_LINEPTWIDTH: - { - float fratio = VertexShaderMngr::GetPixelAspectRatio(); - if (bpmem.lineptwidth.linesize > 0) - glLineWidth((float)bpmem.lineptwidth.linesize * fratio / 6.0f); // scale by ratio of widths - if (bpmem.lineptwidth.pointsize > 0) - glPointSize((float)bpmem.lineptwidth.pointsize * fratio / 6.0f); - break; - } - - case 0x43: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - } - break; - - case BPMEM_BLENDMODE: - if (changes & 0xFFFF) { - - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - PRIM_LOG("blendmode: en=%d, open=%d, colupd=%d, alphaupd=%d, dst=%d, src=%d, sub=%d, mode=%d\n", - bpmem.blendmode.blendenable, bpmem.blendmode.logicopenable, bpmem.blendmode.colorupdate, bpmem.blendmode.alphaupdate, - bpmem.blendmode.dstfactor, bpmem.blendmode.srcfactor, bpmem.blendmode.subtract, bpmem.blendmode.logicmode); - - if (changes & 1) { - if (bpmem.blendmode.blendenable) { - glEnable(GL_BLEND); - - } - else glDisable(GL_BLEND); - } - if (changes & 2) { - if (Renderer::CanBlendLogicOp()) { - if (bpmem.blendmode.logicopenable) { - glEnable(GL_COLOR_LOGIC_OP); - PanicAlert("Logic Op Blend : %i", bpmem.blendmode.logicmode); - glLogicOp(glLogicOpCodes[bpmem.blendmode.logicmode]); - } - else glDisable(GL_COLOR_LOGIC_OP); - } - //else { - // if (bpmem.blendmode.logicopenable) { - // switch(bpmem.blendmode.logicmode) { - // case 0: // clear dst to 0 - // glEnable(GL_BLEND); - // glBlendFunc(GL_ZERO, GL_ZERO); - // break; - // case 1: // set dst to 1 - // glEnable(GL_BLEND); - // glBlendFunc(GL_ONE, GL_ONE); - // break; - // case 2: // set dst to src - // glDisable(GL_BLEND); - // break; - // case 3: // set dst to ~src - // glEnable(GL_BLEND); - // glBlendFunc(GL_ONE_MINUS_SRC_COLOR, GL_ZERO); //? - // break; - // case 4: // set dst to dst - // glEnable(GL_BLEND); - // glBlendFunc(GL_ZERO, GL_ONE); //? - // break; - // case 5: // set dst to ~dst - // glEnable(GL_BLEND); - // glBlendFunc(GL_ZERO, GL_ONE_MINUS_DST_COLOR); //? - // break; - // case 6: // set dst to src&dst - // case 7: // set dst to ~(src&dst) - // case 8: // set dst to src|dst - // case 9: // set dst to ~(src|dst) - // case 10: // set dst to src xor dst - // case 11: // set dst to ~(src xor dst) - // case 12: // set dst to src&~dst - // case 13: // set dst to ~src&dst - // case 14: // set dst to src|~dst - // case 15: // set dst to ~src|dst - // ERROR_LOG("logicopenable %d not supported\n", bpmem.blendmode.logicmode); - // break; - - // } - // } - //} - } - if (changes & 4) { - // pointless - //if (bpmem.blendmode.dither) glEnable(GL_DITHER); - //else glDisable(GL_DITHER); - } - if (changes & 0xFE0) { - if (!bpmem.blendmode.subtract) - glBlendFunc(glSrcFactors[bpmem.blendmode.srcfactor], glDestFactors[bpmem.blendmode.dstfactor]); - } - if (changes & 0x800) { - glBlendEquation(bpmem.blendmode.subtract ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD); - if (bpmem.blendmode.subtract) - glBlendFunc(GL_ONE, GL_ONE); - else - glBlendFunc(glSrcFactors[bpmem.blendmode.srcfactor], glDestFactors[bpmem.blendmode.dstfactor]); - } - - if (changes & 0x18) - Renderer::SetColorMask(); - } - break; - - case BPMEM_FOGRANGE: - if (changes) { - // TODO(XK): Fog range format - //glFogi(GL_FOG_START, ... - //glFogi(GL_FOG_END, ... - } - break; - - case BPMEM_FOGPARAM0: - case BPMEM_FOGBEXPONENT: - case BPMEM_FOGBMAGNITUDE: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - } - break; - - case BPMEM_FOGPARAM3: - //fog settings - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - //printf("%f %f magnitude: %x\n", bpmem.fog.a.GetA(),bpmem.fog.c_proj_fsel.GetC(), bpmem.fog.b_magnitude); - switch(bpmem.fog.c_proj_fsel.fsel) - { - case 0: // Off - glDisable(GL_FOG); // Should be what we do - break; - case 2: // Linear - glFogi(GL_FOG_MODE, GL_LINEAR); - glEnable(GL_FOG); - break; - case 4: // exp - glFogi(GL_FOG_MODE, GL_EXP); - glEnable(GL_FOG); - break; - case 5: // exp2 - glFogi(GL_FOG_MODE, GL_EXP2); - glEnable(GL_FOG); - break; - case 6: // Backward exp - case 7: // Backward exp2 - // TODO: Figure out how to do these in GL - //TEV_FSEL_BX, TEV_FSEL_BX2? - default: - printf("Non-Emulated Fog selection %d\n", bpmem.fog.c_proj_fsel.fsel); - break; - } - } - break; - - case BPMEM_FOGCOLOR: - if (changes) - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - float fogcolor[4] = { ((bpmem.fog.color>>16)&0xff)/255.0f, ((bpmem.fog.color>>8)&0xff)/255.0f, (bpmem.fog.color&0xff)/255.0f, (bpmem.fog.color>>24)/255.0f }; - //printf("r: %f g: %f b: %f a: %f %x %x %x %f\n",fogcolor[0],fogcolor[1], fogcolor[2], fogcolor[3], bpmem.fogRangeAdj, bpmem.unknown15[0],bpmem.unknown15[1],bpmem.unknown15[2]); - glFogfv(GL_FOG_COLOR, fogcolor); - } - break; - - case BPMEM_TEXINVALIDATE: - //TexCache_Invalidate(); - break; - - case BPMEM_SCISSOROFFSET: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - Renderer::SetScissorRect(); - } - break; - - case BPMEM_SCISSORTL: - case BPMEM_SCISSORBR: - - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - if (!Renderer::SetScissorRect()) { - if (addr == BPMEM_SCISSORBR ) - ERROR_LOG("bad scissor!\n"); - } - } - break; - case BPMEM_ZTEX1: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - PRIM_LOG("ztex bias=0x%x\n", bpmem.ztex1.bias); - PixelShaderMngr::SetZTetureBias(bpmem.ztex1.bias); - } - break; - case BPMEM_ZTEX2: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; -#if defined(_DEBUG) || defined(DEBUGFAST) - const char* pzop[] = {"DISABLE", "ADD", "REPLACE", "?"}; - const char* pztype[] = {"Z8", "Z16", "Z24", "?"}; - PRIM_LOG("ztex op=%s, type=%s\n", pzop[bpmem.ztex2.op], pztype[bpmem.ztex2.type]); -#endif - } - break; - - case 0xf6: // ksel0 - case 0xf7: // ksel1 - case 0xf8: // ksel2 - case 0xf9: // ksel3 - case 0xfa: // ksel4 - case 0xfb: // ksel5 - case 0xfc: // ksel6 - case 0xfd: // ksel7 - if (changes) - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - PixelShaderMngr::SetTevKSelChanged(addr-0xf6); - } - break; - case 0x45: //GXSetDrawDone - VertexManager::Flush(); - switch (newval & 0xFF) - { - case 0x02: - g_VideoInitialize.pSetPEFinish(); // may generate interrupt - DebugLog("GXSetDrawDone SetPEFinish (value: 0x%02X)", (newval & 0xFFFF)); - break; - - default: - DebugLog("GXSetDrawDone ??? (value 0x%02X)", (newval & 0xFFFF)); - break; - } - break; - - case BPMEM_PE_TOKEN_ID: - g_VideoInitialize.pSetPEToken(static_cast(newval & 0xFFFF), FALSE); - DebugLog("SetPEToken 0x%04x", (newval & 0xFFFF)); - break; - - case BPMEM_PE_TOKEN_INT_ID: - g_VideoInitialize.pSetPEToken(static_cast(newval & 0xFFFF), TRUE); - DebugLog("SetPEToken + INT 0x%04x", (newval & 0xFFFF)); - break; - - case 0x67: // set gp metric? - break; - - case 0x52: - { - DVSTARTSUBPROFILE("LoadBPReg:swap"); - VertexManager::Flush(); - - ((u32*)&bpmem)[addr] = newval; - //The bottom right is within the rectangle. - TRectangle rc = { - (int)(bpmem.copyTexSrcXY.x), - (int)(bpmem.copyTexSrcXY.y), - (int)((bpmem.copyTexSrcXY.x + bpmem.copyTexSrcWH.x)), - (int)((bpmem.copyTexSrcXY.y + bpmem.copyTexSrcWH.y)) - }; - //Need another rc here to get it to scale. - //Here the bottom right is the out of the rectangle. - TRectangle multirc = { - (int)(bpmem.copyTexSrcXY.x * MValueX), - (int)(bpmem.copyTexSrcXY.y * MValueY), - (int)((bpmem.copyTexSrcXY.x * MValueX + (bpmem.copyTexSrcWH.x + 1) * MValueX)), - (int)((bpmem.copyTexSrcXY.y * MValueY + (bpmem.copyTexSrcWH.y + 1) * MValueY)) - }; - - UPE_Copy PE_copy; - PE_copy.Hex = bpmem.triggerEFBCopy; - - if (PE_copy.copy_to_xfb == 0) { - if(g_Config.bEFBToTextureDisable) { - glViewport(rc.left,rc.bottom,rc.right,rc.top); - glScissor(rc.left,rc.bottom,rc.right,rc.top); - } - else - // EFB to texture - // for some reason it sets bpmem.zcontrol.pixel_format to PIXELFMT_Z24 every time a zbuffer format is given as a dest to GXSetTexCopyDst - TextureMngr::CopyRenderTargetToTexture(bpmem.copyTexDest<<5, bpmem.zcontrol.pixel_format==PIXELFMT_Z24, PE_copy.intensity_fmt>0, - (PE_copy.target_pixel_format/2)+((PE_copy.target_pixel_format&1)*8), PE_copy.half_scale>0, &rc); - } - else { - // EFB to XFB - if(g_Config.bUseXFB) - { - // the number of lines copied is determined by the y scale * source efb height - float yScale = bpmem.dispcopyyscale / 256.0f; - float xfbLines = bpmem.copyTexSrcWH.y + 1.0 * yScale; - XFB_Write(Memory_GetPtr(bpmem.copyTexDest<<5), multirc, (bpmem.copyMipMapStrideChannels << 4), (int)xfbLines); - } - else - { - Renderer::Swap(multirc); - } - g_VideoInitialize.pCopiedToXFB(); - } - - // clearing - if (PE_copy.clear) { - // clear color - Renderer::SetRenderMode(Renderer::RM_Normal); - - u32 nRestoreZBufferTarget = Renderer::GetZBufferTarget(); - - glViewport(0, 0, Renderer::GetTargetWidth(), Renderer::GetTargetHeight()); - - // Always set the scissor in case it was set by the game and has not been reset - glScissor(multirc.left, (Renderer::GetTargetHeight() - multirc.bottom), - (multirc.right - multirc.left), (multirc.bottom - multirc.top)); - - VertexShaderMngr::SetViewportChanged(); - - // Since clear operations use the source rectangle, we have to do - // regular renders (glClear clears the entire buffer) - if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate || bpmem.zmode.updateenable) - { - GLbitfield bits = 0; - if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate) { - u32 clearColor = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB; - glClearColor(((clearColor>>16) & 0xff)*(1/255.0f), - - ((clearColor>>8 ) & 0xff)*(1/255.0f), - ((clearColor>>0 ) & 0xff)*(1/255.0f), - ((clearColor>>24) & 0xff)*(1/255.0f)); - bits |= GL_COLOR_BUFFER_BIT; - } - if (bpmem.zmode.updateenable) { - glClearDepth((float)(bpmem.clearZValue&0xFFFFFF) / float(0xFFFFFF)); - bits |= GL_DEPTH_BUFFER_BIT; - } - if (nRestoreZBufferTarget ) - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); // don't clear ztarget here - glClear(bits); - } - - if (bpmem.zmode.updateenable && nRestoreZBufferTarget) { // have to clear the target zbuffer - glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); - GL_REPORT_ERRORD(); - glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); - - // red should probably be the LSB - glClearColor(((bpmem.clearZValue>>0)&0xff)*(1/255.0f), - ((bpmem.clearZValue>>8)&0xff)*(1/255.0f), - ((bpmem.clearZValue>>16)&0xff)*(1/255.0f), 0); - glClear(GL_COLOR_BUFFER_BIT); - Renderer::SetColorMask(); - GL_REPORT_ERRORD(); - } - - if (nRestoreZBufferTarget) { - // restore target - GLenum s_drawbuffers[2] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT}; - glDrawBuffers(2, s_drawbuffers); - } - - Renderer::SetScissorRect(); // reset the scissor rect - } - } - break; - - case 0x65: //GXLoadTlut - { - DVSTARTSUBPROFILE("LoadBPReg:GXLoadTlut"); - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - - u32 tlutTMemAddr = (newval & 0x3FF) << 9; - u32 tlutXferCount = (newval & 0x1FFC00) >> 5; - - u8 *ptr = 0; - // TODO - figure out a cleaner way. - if (g_VideoInitialize.bWii) - ptr = g_VideoInitialize.pGetMemoryPointer(bpmem.tlutXferSrc << 5); - else - ptr = g_VideoInitialize.pGetMemoryPointer((bpmem.tlutXferSrc & 0xFFFFF) << 5); - if (ptr) - memcpy_gc(texMem + tlutTMemAddr, ptr, tlutXferCount); - else - PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tlutXferSrc, bpmem.tlutXferSrc << 5, (bpmem.tlutXferSrc & 0xFFFFF)<< 5); - // TODO(ector) : kill all textures that use this palette - // Not sure if it's a good idea, though. For now, we hash texture palettes - } - break; - - - default: - switch(addr & 0xFC) //texture sampler filter - { - case 0x28: // tevorder 0-3 - case 0x2C: // tevorder 4-7 - if (changes) - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - PixelShaderMngr::SetTevOrderChanged(addr - 0x28); - } - break; - - case 0x80: // TEX MODE 0 - case 0xA0: - if (changes) - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - } - break; - case 0x84://TEX MODE 1 - case 0xA4: - break; - case 0x88://TEX IMAGE 0 - case 0xA8: - if (changes) - { - //textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - } - break; - case 0x8C://TEX IMAGE 1 - case 0xAC: - if (changes) - { - //textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - } - break; - case 0x90://TEX IMAGE 2 - case 0xB0: - if (changes) - { - //textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - } - break; - case 0x94://TEX IMAGE 3 - case 0xB4: - if (changes) - { - //textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - } - break; - case 0x98://TEX TLUT - case 0xB8: - if (changes) - { - //textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - } - break; - case 0x9C://TEX UNKNOWN - case 0xBC: - //ERROR_LOG("texunknown%x = %x\n", addr, newval); - ((u32*)&bpmem)[addr] = newval; - break; - case 0xE0: - case 0xE4: - if (addr&1) { // don't compare with changes! - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - int num = (addr>>1)&0x3; - PixelShaderMngr::SetColorChanged(bpmem.tevregs[num].high.type, num); - } - else - ((u32*)&bpmem)[addr] = newval; - break; - - default: - switch(addr&0xF0) { - case 0x10: // tevindirect 0-15 - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - PixelShaderMngr::SetTevIndirectChanged(addr-0x10); - } - break; - - case 0x30: - if (changes) { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - PixelShaderMngr::SetTexDimsChanged((addr>>1)&0x7); - } - break; - - case 0xC0: - case 0xD0: - if (changes) - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - PixelShaderMngr::SetTevCombinerChanged((addr&0x1f)/2); - } - break; - - case 0x20: - case 0x80: - case 0x90: - case 0xA0: - case 0xB0: - default: - if (changes) - { - VertexManager::Flush(); - ((u32*)&bpmem)[addr] = newval; - /*switch(addr) { - case 0x01: - case 0x02: - case 0x03: - case 0x04: break; // copy filter values - case 0x0f: break; // mask - case 0x27: break; // tev ind order - case 0x44: break; // field mask - case 0x45: break; // draw done - case 0x46: break; // clock - case 0x49: - case 0x4a: break; // copy tex src - case 0x4b: break; // copy tex dest - case 0x4d: break; // copyMipMapStrideChannels - case 0x4e: break; // disp copy scale - case 0x4f: break; // clear color - case 0x50: break; // clear color - case 0x51: break; // casez - case 0x52: break; // trigger efb copy - case 0x53: - case 0x54: break; // more copy filters - case 0x55: - case 0x56: break; // bounding box - case 0x64: - case 0x65: break; // tlut src dest - case 0xe8: break; // fog range - case 0xe9: - case 0xea: - case 0xeb: - case 0xec: - case 0xed: break; // fog - case 0xfe: break; // mask - default: - // 0x58 = 0xf - // 0x69 = 0x49e - ERROR_LOG("bp%.2x = %x\n", addr, newval); - }*/ - } - break; - } - break; - - } - break; - } -} - -// Call browser: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadBPReg() -void LoadBPReg(u32 value0) -{ - DVSTARTPROFILE(); - //handle the mask register - int opcode = value0 >> 24; - int oldval = ((u32*)&bpmem)[opcode]; - int newval = (oldval & ~bpmem.bpMask) | (value0 & bpmem.bpMask); - int changes = (oldval ^ newval) & 0xFFFFFF; - //reset the mask register - if (opcode != 0xFE) - bpmem.bpMask = 0xFFFFFF; - //notify the video handling so it can update render states - BPWritten(opcode, changes, newval); -} - -// Called when loading a saved state. -// Needs more testing though. -void BPReload() -{ - for (int i = 0; i < 254; i++) - { - switch (i) { - - case 0x41: - case 0x45: //GXSetDrawDone - case 0x52: - case 0x65: - case 0x67: // set gp metric? - case BPMEM_PE_TOKEN_ID: - case BPMEM_PE_TOKEN_INT_ID: - // Cases in which we DON'T want to reload the BP - continue; - default: - BPWritten(i, 0xFFFFFF, ((u32*)&bpmem)[i]); - } - } -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +// --------------------------------------------------------------------------------------- +// includes +// ------------- +#include "Globals.h" +#include "Profiler.h" +#include "Config.h" + +#include "VertexLoader.h" +#include "VertexManager.h" + +#include "BPStructs.h" +#include "Render.h" +#include "OpcodeDecoding.h" +#include "TextureMngr.h" +#include "TextureDecoder.h" +#include "VertexShaderManager.h" +#include "PixelShaderManager.h" +#include "XFB.h" + + +// --------------------------------------------------------------------------------------- +// State translation lookup tables +// ------------- +static const GLenum glSrcFactors[8] = +{ + GL_ZERO, + GL_ONE, + GL_DST_COLOR, + GL_ONE_MINUS_DST_COLOR, + GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, + GL_DST_ALPHA, + GL_ONE_MINUS_DST_ALPHA +}; + +static const GLenum glDestFactors[8] = { + GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, + GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA +}; +static const GLenum glCmpFuncs[8] = { + GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS +}; + +static const GLenum glLogicOpCodes[16] = { + GL_CLEAR, GL_SET, GL_COPY, GL_COPY_INVERTED, GL_NOOP, GL_INVERT, GL_AND, GL_NAND, + GL_OR, GL_NOR, GL_XOR, GL_EQUIV, GL_AND_REVERSE, GL_AND_INVERTED, GL_OR_REVERSE, GL_OR_INVERTED +}; + +void BPInit() +{ + memset(&bpmem, 0, sizeof(bpmem)); + bpmem.bpMask = 0xFFFFFF; +} + +// Called at the end of every: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadBPReg +// TODO - turn into function table. The (future) DL jit can then call the functions directly, +// getting rid of dynamic dispatch. +void BPWritten(int addr, int changes, int newval) +{ + //static int count = 0; + //ERROR_LOG("(%d) %x: %x\n", count++, addr, newval); + + switch (addr) + { + case BPMEM_GENMODE: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + PRIM_LOG("genmode: texgen=%d, col=%d, ms_en=%d, tev=%d, culmode=%d, ind=%d, zfeeze=%d\n", + bpmem.genMode.numtexgens, bpmem.genMode.numcolchans, + bpmem.genMode.ms_en, bpmem.genMode.numtevstages+1, bpmem.genMode.cullmode, + bpmem.genMode.numindstages, bpmem.genMode.zfreeze); + + // none, ccw, cw, ccw + if (bpmem.genMode.cullmode > 0) { + glEnable(GL_CULL_FACE); + glFrontFace(bpmem.genMode.cullmode == 2 ? GL_CCW : GL_CW); + } + else if(glIsEnabled(GL_CULL_FACE) == GL_TRUE) + glDisable(GL_CULL_FACE); + + PixelShaderMngr::SetGenModeChanged(); + } + break; + + case BPMEM_IND_MTX+0: + case BPMEM_IND_MTX+1: + case BPMEM_IND_MTX+2: + case BPMEM_IND_MTX+3: + case BPMEM_IND_MTX+4: + case BPMEM_IND_MTX+5: + case BPMEM_IND_MTX+6: + case BPMEM_IND_MTX+7: + case BPMEM_IND_MTX+8: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + PixelShaderMngr::SetIndMatrixChanged((addr-BPMEM_IND_MTX)/3); + } + break; + case BPMEM_RAS1_SS0: + case BPMEM_RAS1_SS1: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + PixelShaderMngr::SetIndTexScaleChanged(); + } + break; + case BPMEM_ZMODE: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + PRIM_LOG("zmode: test=%d, func=%d, upd=%d\n", bpmem.zmode.testenable, bpmem.zmode.func, + bpmem.zmode.updateenable); + + if (bpmem.zmode.testenable) { + glEnable(GL_DEPTH_TEST); + glDepthMask(bpmem.zmode.updateenable?GL_TRUE:GL_FALSE); + glDepthFunc(glCmpFuncs[bpmem.zmode.func]); + } + else { + // if the test is disabled write is disabled too + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + } + + if (!bpmem.zmode.updateenable) + Renderer::SetRenderMode(Renderer::RM_Normal); + } + break; + + case BPMEM_ALPHACOMPARE: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + PRIM_LOG("alphacmp: ref0=%d, ref1=%d, comp0=%d, comp1=%d, logic=%d\n", bpmem.alphaFunc.ref0, + bpmem.alphaFunc.ref1, bpmem.alphaFunc.comp0, bpmem.alphaFunc.comp1, bpmem.alphaFunc.logic); + PixelShaderMngr::SetAlpha(bpmem.alphaFunc); + } + break; + + case BPMEM_CONSTANTALPHA: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + PRIM_LOG("constalpha: alp=%d, en=%d\n", bpmem.dstalpha.alpha, bpmem.dstalpha.enable); + PixelShaderMngr::SetDestAlpha(bpmem.dstalpha); + } + break; + + case BPMEM_LINEPTWIDTH: + { + float fratio = VertexShaderMngr::GetPixelAspectRatio(); + if (bpmem.lineptwidth.linesize > 0) + glLineWidth((float)bpmem.lineptwidth.linesize * fratio / 6.0f); // scale by ratio of widths + if (bpmem.lineptwidth.pointsize > 0) + glPointSize((float)bpmem.lineptwidth.pointsize * fratio / 6.0f); + break; + } + + case 0x43: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + } + break; + + case BPMEM_BLENDMODE: + if (changes & 0xFFFF) { + + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + PRIM_LOG("blendmode: en=%d, open=%d, colupd=%d, alphaupd=%d, dst=%d, src=%d, sub=%d, mode=%d\n", + bpmem.blendmode.blendenable, bpmem.blendmode.logicopenable, bpmem.blendmode.colorupdate, bpmem.blendmode.alphaupdate, + bpmem.blendmode.dstfactor, bpmem.blendmode.srcfactor, bpmem.blendmode.subtract, bpmem.blendmode.logicmode); + + if (changes & 1) { + if (bpmem.blendmode.blendenable) { + glEnable(GL_BLEND); + + } + else glDisable(GL_BLEND); + } + if (changes & 2) { + if (Renderer::CanBlendLogicOp()) { + if (bpmem.blendmode.logicopenable) { + glEnable(GL_COLOR_LOGIC_OP); + PanicAlert("Logic Op Blend : %i", bpmem.blendmode.logicmode); + glLogicOp(glLogicOpCodes[bpmem.blendmode.logicmode]); + } + else glDisable(GL_COLOR_LOGIC_OP); + } + //else { + // if (bpmem.blendmode.logicopenable) { + // switch(bpmem.blendmode.logicmode) { + // case 0: // clear dst to 0 + // glEnable(GL_BLEND); + // glBlendFunc(GL_ZERO, GL_ZERO); + // break; + // case 1: // set dst to 1 + // glEnable(GL_BLEND); + // glBlendFunc(GL_ONE, GL_ONE); + // break; + // case 2: // set dst to src + // glDisable(GL_BLEND); + // break; + // case 3: // set dst to ~src + // glEnable(GL_BLEND); + // glBlendFunc(GL_ONE_MINUS_SRC_COLOR, GL_ZERO); //? + // break; + // case 4: // set dst to dst + // glEnable(GL_BLEND); + // glBlendFunc(GL_ZERO, GL_ONE); //? + // break; + // case 5: // set dst to ~dst + // glEnable(GL_BLEND); + // glBlendFunc(GL_ZERO, GL_ONE_MINUS_DST_COLOR); //? + // break; + // case 6: // set dst to src&dst + // case 7: // set dst to ~(src&dst) + // case 8: // set dst to src|dst + // case 9: // set dst to ~(src|dst) + // case 10: // set dst to src xor dst + // case 11: // set dst to ~(src xor dst) + // case 12: // set dst to src&~dst + // case 13: // set dst to ~src&dst + // case 14: // set dst to src|~dst + // case 15: // set dst to ~src|dst + // ERROR_LOG("logicopenable %d not supported\n", bpmem.blendmode.logicmode); + // break; + + // } + // } + //} + } + if (changes & 4) { + // pointless + //if (bpmem.blendmode.dither) glEnable(GL_DITHER); + //else glDisable(GL_DITHER); + } + if (changes & 0xFE0) { + if (!bpmem.blendmode.subtract) + glBlendFunc(glSrcFactors[bpmem.blendmode.srcfactor], glDestFactors[bpmem.blendmode.dstfactor]); + } + if (changes & 0x800) { + glBlendEquation(bpmem.blendmode.subtract ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD); + if (bpmem.blendmode.subtract) + glBlendFunc(GL_ONE, GL_ONE); + else + glBlendFunc(glSrcFactors[bpmem.blendmode.srcfactor], glDestFactors[bpmem.blendmode.dstfactor]); + } + + if (changes & 0x18) + Renderer::SetColorMask(); + } + break; + + case BPMEM_FOGRANGE: + if (changes) { + // TODO(XK): Fog range format + //glFogi(GL_FOG_START, ... + //glFogi(GL_FOG_END, ... + } + break; + + case BPMEM_FOGPARAM0: + case BPMEM_FOGBEXPONENT: + case BPMEM_FOGBMAGNITUDE: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + } + break; + + case BPMEM_FOGPARAM3: + //fog settings + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + //printf("%f %f magnitude: %x\n", bpmem.fog.a.GetA(),bpmem.fog.c_proj_fsel.GetC(), bpmem.fog.b_magnitude); + switch(bpmem.fog.c_proj_fsel.fsel) + { + case 0: // Off + glDisable(GL_FOG); // Should be what we do + break; + case 2: // Linear + glFogi(GL_FOG_MODE, GL_LINEAR); + glEnable(GL_FOG); + break; + case 4: // exp + glFogi(GL_FOG_MODE, GL_EXP); + glEnable(GL_FOG); + break; + case 5: // exp2 + glFogi(GL_FOG_MODE, GL_EXP2); + glEnable(GL_FOG); + break; + case 6: // Backward exp + case 7: // Backward exp2 + // TODO: Figure out how to do these in GL + //TEV_FSEL_BX, TEV_FSEL_BX2? + default: + printf("Non-Emulated Fog selection %d\n", bpmem.fog.c_proj_fsel.fsel); + break; + } + } + break; + + case BPMEM_FOGCOLOR: + if (changes) + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + float fogcolor[4] = { ((bpmem.fog.color>>16)&0xff)/255.0f, ((bpmem.fog.color>>8)&0xff)/255.0f, (bpmem.fog.color&0xff)/255.0f, (bpmem.fog.color>>24)/255.0f }; + //printf("r: %f g: %f b: %f a: %f %x %x %x %f\n",fogcolor[0],fogcolor[1], fogcolor[2], fogcolor[3], bpmem.fogRangeAdj, bpmem.unknown15[0],bpmem.unknown15[1],bpmem.unknown15[2]); + glFogfv(GL_FOG_COLOR, fogcolor); + } + break; + + case BPMEM_TEXINVALIDATE: + //TexCache_Invalidate(); + break; + + case BPMEM_SCISSOROFFSET: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + Renderer::SetScissorRect(); + } + break; + + case BPMEM_SCISSORTL: + case BPMEM_SCISSORBR: + + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + if (!Renderer::SetScissorRect()) { + if (addr == BPMEM_SCISSORBR ) + ERROR_LOG("bad scissor!\n"); + } + } + break; + case BPMEM_ZTEX1: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + PRIM_LOG("ztex bias=0x%x\n", bpmem.ztex1.bias); + PixelShaderMngr::SetZTetureBias(bpmem.ztex1.bias); + } + break; + case BPMEM_ZTEX2: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; +#if defined(_DEBUG) || defined(DEBUGFAST) + const char* pzop[] = {"DISABLE", "ADD", "REPLACE", "?"}; + const char* pztype[] = {"Z8", "Z16", "Z24", "?"}; + PRIM_LOG("ztex op=%s, type=%s\n", pzop[bpmem.ztex2.op], pztype[bpmem.ztex2.type]); +#endif + } + break; + + case 0xf6: // ksel0 + case 0xf7: // ksel1 + case 0xf8: // ksel2 + case 0xf9: // ksel3 + case 0xfa: // ksel4 + case 0xfb: // ksel5 + case 0xfc: // ksel6 + case 0xfd: // ksel7 + if (changes) + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + PixelShaderMngr::SetTevKSelChanged(addr-0xf6); + } + break; + case 0x45: //GXSetDrawDone + VertexManager::Flush(); + switch (newval & 0xFF) + { + case 0x02: + g_VideoInitialize.pSetPEFinish(); // may generate interrupt + DebugLog("GXSetDrawDone SetPEFinish (value: 0x%02X)", (newval & 0xFFFF)); + break; + + default: + DebugLog("GXSetDrawDone ??? (value 0x%02X)", (newval & 0xFFFF)); + break; + } + break; + + case BPMEM_PE_TOKEN_ID: + g_VideoInitialize.pSetPEToken(static_cast(newval & 0xFFFF), FALSE); + DebugLog("SetPEToken 0x%04x", (newval & 0xFFFF)); + break; + + case BPMEM_PE_TOKEN_INT_ID: + g_VideoInitialize.pSetPEToken(static_cast(newval & 0xFFFF), TRUE); + DebugLog("SetPEToken + INT 0x%04x", (newval & 0xFFFF)); + break; + + case 0x67: // set gp metric? + break; + + case 0x52: + { + DVSTARTSUBPROFILE("LoadBPReg:swap"); + VertexManager::Flush(); + + ((u32*)&bpmem)[addr] = newval; + //The bottom right is within the rectangle. + TRectangle rc = { + (int)(bpmem.copyTexSrcXY.x), + (int)(bpmem.copyTexSrcXY.y), + (int)((bpmem.copyTexSrcXY.x + bpmem.copyTexSrcWH.x)), + (int)((bpmem.copyTexSrcXY.y + bpmem.copyTexSrcWH.y)) + }; + //Need another rc here to get it to scale. + //Here the bottom right is the out of the rectangle. + TRectangle multirc = { + (int)(bpmem.copyTexSrcXY.x * MValueX), + (int)(bpmem.copyTexSrcXY.y * MValueY), + (int)((bpmem.copyTexSrcXY.x * MValueX + (bpmem.copyTexSrcWH.x + 1) * MValueX)), + (int)((bpmem.copyTexSrcXY.y * MValueY + (bpmem.copyTexSrcWH.y + 1) * MValueY)) + }; + + UPE_Copy PE_copy; + PE_copy.Hex = bpmem.triggerEFBCopy; + + if (PE_copy.copy_to_xfb == 0) { + if(g_Config.bEFBToTextureDisable) { + glViewport(rc.left,rc.bottom,rc.right,rc.top); + glScissor(rc.left,rc.bottom,rc.right,rc.top); + } + else + // EFB to texture + // for some reason it sets bpmem.zcontrol.pixel_format to PIXELFMT_Z24 every time a zbuffer format is given as a dest to GXSetTexCopyDst + TextureMngr::CopyRenderTargetToTexture(bpmem.copyTexDest<<5, bpmem.zcontrol.pixel_format==PIXELFMT_Z24, PE_copy.intensity_fmt>0, + (PE_copy.target_pixel_format/2)+((PE_copy.target_pixel_format&1)*8), PE_copy.half_scale>0, &rc); + } + else { + // EFB to XFB + if(g_Config.bUseXFB) + { + // the number of lines copied is determined by the y scale * source efb height + float yScale = bpmem.dispcopyyscale / 256.0f; + float xfbLines = bpmem.copyTexSrcWH.y + 1.0 * yScale; + XFB_Write(Memory_GetPtr(bpmem.copyTexDest<<5), multirc, (bpmem.copyMipMapStrideChannels << 4), (int)xfbLines); + } + else + { + Renderer::Swap(multirc); + } + g_VideoInitialize.pCopiedToXFB(); + } + + // clearing + if (PE_copy.clear) { + // clear color + Renderer::SetRenderMode(Renderer::RM_Normal); + + u32 nRestoreZBufferTarget = Renderer::GetZBufferTarget(); + + glViewport(0, 0, Renderer::GetTargetWidth(), Renderer::GetTargetHeight()); + + // Always set the scissor in case it was set by the game and has not been reset + glScissor(multirc.left, (Renderer::GetTargetHeight() - multirc.bottom), + (multirc.right - multirc.left), (multirc.bottom - multirc.top)); + + VertexShaderMngr::SetViewportChanged(); + + // Since clear operations use the source rectangle, we have to do + // regular renders (glClear clears the entire buffer) + if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate || bpmem.zmode.updateenable) + { + GLbitfield bits = 0; + if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate) { + u32 clearColor = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB; + glClearColor(((clearColor>>16) & 0xff)*(1/255.0f), + + ((clearColor>>8 ) & 0xff)*(1/255.0f), + ((clearColor>>0 ) & 0xff)*(1/255.0f), + ((clearColor>>24) & 0xff)*(1/255.0f)); + bits |= GL_COLOR_BUFFER_BIT; + } + if (bpmem.zmode.updateenable) { + glClearDepth((float)(bpmem.clearZValue&0xFFFFFF) / float(0xFFFFFF)); + bits |= GL_DEPTH_BUFFER_BIT; + } + if (nRestoreZBufferTarget ) + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); // don't clear ztarget here + glClear(bits); + } + + if (bpmem.zmode.updateenable && nRestoreZBufferTarget) { // have to clear the target zbuffer + glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); + GL_REPORT_ERRORD(); + glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); + + // red should probably be the LSB + glClearColor(((bpmem.clearZValue>>0)&0xff)*(1/255.0f), + ((bpmem.clearZValue>>8)&0xff)*(1/255.0f), + ((bpmem.clearZValue>>16)&0xff)*(1/255.0f), 0); + glClear(GL_COLOR_BUFFER_BIT); + Renderer::SetColorMask(); + GL_REPORT_ERRORD(); + } + + if (nRestoreZBufferTarget) { + // restore target + GLenum s_drawbuffers[2] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT}; + glDrawBuffers(2, s_drawbuffers); + } + + Renderer::SetScissorRect(); // reset the scissor rect + } + } + break; + + case 0x65: //GXLoadTlut + { + DVSTARTSUBPROFILE("LoadBPReg:GXLoadTlut"); + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + + u32 tlutTMemAddr = (newval & 0x3FF) << 9; + u32 tlutXferCount = (newval & 0x1FFC00) >> 5; + + u8 *ptr = 0; + // TODO - figure out a cleaner way. + if (g_VideoInitialize.bWii) + ptr = g_VideoInitialize.pGetMemoryPointer(bpmem.tlutXferSrc << 5); + else + ptr = g_VideoInitialize.pGetMemoryPointer((bpmem.tlutXferSrc & 0xFFFFF) << 5); + if (ptr) + memcpy_gc(texMem + tlutTMemAddr, ptr, tlutXferCount); + else + PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tlutXferSrc, bpmem.tlutXferSrc << 5, (bpmem.tlutXferSrc & 0xFFFFF)<< 5); + // TODO(ector) : kill all textures that use this palette + // Not sure if it's a good idea, though. For now, we hash texture palettes + } + break; + + + default: + switch(addr & 0xFC) //texture sampler filter + { + case 0x28: // tevorder 0-3 + case 0x2C: // tevorder 4-7 + if (changes) + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + PixelShaderMngr::SetTevOrderChanged(addr - 0x28); + } + break; + + case 0x80: // TEX MODE 0 + case 0xA0: + if (changes) + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + } + break; + case 0x84://TEX MODE 1 + case 0xA4: + break; + case 0x88://TEX IMAGE 0 + case 0xA8: + if (changes) + { + //textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + } + break; + case 0x8C://TEX IMAGE 1 + case 0xAC: + if (changes) + { + //textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + } + break; + case 0x90://TEX IMAGE 2 + case 0xB0: + if (changes) + { + //textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + } + break; + case 0x94://TEX IMAGE 3 + case 0xB4: + if (changes) + { + //textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + } + break; + case 0x98://TEX TLUT + case 0xB8: + if (changes) + { + //textureChanged[((addr&0xE0)==0xA0)*4+(addr&3)] = true; + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + } + break; + case 0x9C://TEX UNKNOWN + case 0xBC: + //ERROR_LOG("texunknown%x = %x\n", addr, newval); + ((u32*)&bpmem)[addr] = newval; + break; + case 0xE0: + case 0xE4: + if (addr&1) { // don't compare with changes! + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + int num = (addr>>1)&0x3; + PixelShaderMngr::SetColorChanged(bpmem.tevregs[num].high.type, num); + } + else + ((u32*)&bpmem)[addr] = newval; + break; + + default: + switch(addr&0xF0) { + case 0x10: // tevindirect 0-15 + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + PixelShaderMngr::SetTevIndirectChanged(addr-0x10); + } + break; + + case 0x30: + if (changes) { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + PixelShaderMngr::SetTexDimsChanged((addr>>1)&0x7); + } + break; + + case 0xC0: + case 0xD0: + if (changes) + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + PixelShaderMngr::SetTevCombinerChanged((addr&0x1f)/2); + } + break; + + case 0x20: + case 0x80: + case 0x90: + case 0xA0: + case 0xB0: + default: + if (changes) + { + VertexManager::Flush(); + ((u32*)&bpmem)[addr] = newval; + /*switch(addr) { + case 0x01: + case 0x02: + case 0x03: + case 0x04: break; // copy filter values + case 0x0f: break; // mask + case 0x27: break; // tev ind order + case 0x44: break; // field mask + case 0x45: break; // draw done + case 0x46: break; // clock + case 0x49: + case 0x4a: break; // copy tex src + case 0x4b: break; // copy tex dest + case 0x4d: break; // copyMipMapStrideChannels + case 0x4e: break; // disp copy scale + case 0x4f: break; // clear color + case 0x50: break; // clear color + case 0x51: break; // casez + case 0x52: break; // trigger efb copy + case 0x53: + case 0x54: break; // more copy filters + case 0x55: + case 0x56: break; // bounding box + case 0x64: + case 0x65: break; // tlut src dest + case 0xe8: break; // fog range + case 0xe9: + case 0xea: + case 0xeb: + case 0xec: + case 0xed: break; // fog + case 0xfe: break; // mask + default: + // 0x58 = 0xf + // 0x69 = 0x49e + ERROR_LOG("bp%.2x = %x\n", addr, newval); + }*/ + } + break; + } + break; + + } + break; + } +} + +// Call browser: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadBPReg() +void LoadBPReg(u32 value0) +{ + DVSTARTPROFILE(); + //handle the mask register + int opcode = value0 >> 24; + int oldval = ((u32*)&bpmem)[opcode]; + int newval = (oldval & ~bpmem.bpMask) | (value0 & bpmem.bpMask); + int changes = (oldval ^ newval) & 0xFFFFFF; + //reset the mask register + if (opcode != 0xFE) + bpmem.bpMask = 0xFFFFFF; + //notify the video handling so it can update render states + BPWritten(opcode, changes, newval); +} + +// Called when loading a saved state. +// Needs more testing though. +void BPReload() +{ + for (int i = 0; i < 254; i++) + { + switch (i) { + + case 0x41: + case 0x45: //GXSetDrawDone + case 0x52: + case 0x65: + case 0x67: // set gp metric? + case BPMEM_PE_TOKEN_ID: + case BPMEM_PE_TOKEN_INT_ID: + // Cases in which we DON'T want to reload the BP + continue; + default: + BPWritten(i, 0xFFFFFF, ((u32*)&bpmem)[i]); + } + } +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Config.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Config.cpp index 81c7ed20e6..558f9dee0f 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Config.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Config.cpp @@ -1,122 +1,122 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Globals.h" -#include "Common.h" -#include "IniFile.h" -#include "Config.h" - -Config g_Config; - -Config::Config() -{ - memset(this, 0, sizeof(Config)); -} - -void Config::Load() -{ - std::string temp; - IniFile iniFile; - iniFile.Load(FULL_CONFIG_DIR "gfx_opengl.ini"); - - // get resolution - iniFile.Get("Hardware", "WindowedRes", &temp, 0); - if(temp.empty()) - temp = "640x480"; - strcpy(iWindowedRes, temp.c_str()); - iniFile.Get("Hardware", "FullscreenRes", &temp, 0); - if(temp.empty()) - temp = "640x480"; - strcpy(iFSResolution, temp.c_str()); - - iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); // Hardware - iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, 0); - iniFile.Get("Settings", "StretchToFit", &bStretchToFit, false); - iniFile.Get("Settings", "KeepAR", &bKeepAR, false); - iniFile.Get("Settings", "HideCursor", &bHideCursor, false); - - iniFile.Get("Settings", "SafeTextureCache", &bSafeTextureCache, false); // Settings - iniFile.Get("Settings", "ShowFPS", &bShowFPS, false); // Settings - iniFile.Get("Settings", "OverlayStats", &bOverlayStats, false); - iniFile.Get("Settings", "DLOptimize", &iCompileDLsLevel, 0); - iniFile.Get("Settings", "DumpTextures", &bDumpTextures, 0); - iniFile.Get("Settings", "ShowShaderErrors", &bShowShaderErrors, 0); - iniFile.Get("Settings", "Multisample", &iMultisampleMode, 0); - if (iMultisampleMode == 0) - iMultisampleMode = 1; - std::string s; - iniFile.Get("Settings", "TexDumpPath", &s, 0); - if (s.size() < sizeof(texDumpPath) ) - strcpy(texDumpPath, s.c_str()); - else { - strncpy(texDumpPath, s.c_str(), sizeof(texDumpPath)-1); - texDumpPath[sizeof(texDumpPath)-1] = 0; - } - - iniFile.Get("Settings", "TexFmtOverlayEnable", &bTexFmtOverlayEnable, 0); - iniFile.Get("Settings", "TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0); - iniFile.Get("Settings", "UseXFB", &bUseXFB, 0); - iniFile.Get("Settings", "WireFrame", &bWireFrame, 0); - iniFile.Get("Settings", "DisableLighting", &bDisableLighting, 0); - iniFile.Get("Settings", "DisableTexturing", &bDisableTexturing, 0); - - iniFile.Get("Enhancements", "ForceFiltering", &bForceFiltering, 0); - iniFile.Get("Enhancements", "MaxAnisotropy", &iMaxAnisotropy, 3); // NOTE - this is x in (1 << x) - - iniFile.Get("Hacks", "EFBToTextureDisable", &bEFBToTextureDisable, 0); - iniFile.Get("Hacks", "EFBToTextureDisableHotKey", &bEFBToTextureDisableHotKey, 0); - iniFile.Get("Hacks", "ProjectionHax1", &bProjectionHax1, 0); - iniFile.Get("Hacks", "ProjectionHax2", &bProjectionHax2, 0); -} - -void Config::Save() -{ - IniFile iniFile; - iniFile.Load(FULL_CONFIG_DIR "gfx_opengl.ini"); - iniFile.Set("Hardware", "WindowedRes", iWindowedRes); - iniFile.Set("Hardware", "FullscreenRes", iFSResolution); - iniFile.Set("Hardware", "Fullscreen", bFullscreen); - iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe); - iniFile.Set("Settings", "StretchToFit", bStretchToFit); - iniFile.Set("Settings", "KeepAR", bKeepAR); - iniFile.Set("Settings", "HideCursor", bHideCursor); - - iniFile.Set("Settings", "SafeTextureCache", bSafeTextureCache); - iniFile.Set("Settings", "ShowFPS", bShowFPS); - iniFile.Set("Settings", "OverlayStats", bOverlayStats); - iniFile.Set("Settings", "DLOptimize", iCompileDLsLevel); - iniFile.Set("Settings", "DumpTextures", bDumpTextures); - iniFile.Set("Settings", "ShowShaderErrors", bShowShaderErrors); - iniFile.Set("Settings", "Multisample", iMultisampleMode); - iniFile.Set("Settings", "TexDumpPath", texDumpPath); - iniFile.Set("Settings", "TexFmtOverlayEnable", bTexFmtOverlayEnable); - iniFile.Set("Settings", "TexFmtOverlayCenter", bTexFmtOverlayCenter); - iniFile.Set("Settings", "UseXFB", bUseXFB); - iniFile.Set("Settings", "Wireframe", bWireFrame); - iniFile.Set("Settings", "DisableLighting", bDisableLighting); - iniFile.Set("Settings", "DisableTexturing", bDisableTexturing); - - iniFile.Set("Enhancements", "ForceFiltering", bForceFiltering); - iniFile.Set("Enhancements", "MaxAnisotropy", iMaxAnisotropy); - - iniFile.Set("Hacks", "EFBToTextureDisable", bEFBToTextureDisable); - iniFile.Set("Hacks", "EFBToTextureDisableHotKey", bEFBToTextureDisableHotKey); - iniFile.Set("Hacks", "ProjectionHax1", bProjectionHax1); - iniFile.Set("Hacks", "ProjectionHax2", bProjectionHax2); - - iniFile.Save(FULL_CONFIG_DIR "gfx_opengl.ini"); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Globals.h" +#include "Common.h" +#include "IniFile.h" +#include "Config.h" + +Config g_Config; + +Config::Config() +{ + memset(this, 0, sizeof(Config)); +} + +void Config::Load() +{ + std::string temp; + IniFile iniFile; + iniFile.Load(FULL_CONFIG_DIR "gfx_opengl.ini"); + + // get resolution + iniFile.Get("Hardware", "WindowedRes", &temp, 0); + if(temp.empty()) + temp = "640x480"; + strcpy(iWindowedRes, temp.c_str()); + iniFile.Get("Hardware", "FullscreenRes", &temp, 0); + if(temp.empty()) + temp = "640x480"; + strcpy(iFSResolution, temp.c_str()); + + iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); // Hardware + iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, 0); + iniFile.Get("Settings", "StretchToFit", &bStretchToFit, false); + iniFile.Get("Settings", "KeepAR", &bKeepAR, false); + iniFile.Get("Settings", "HideCursor", &bHideCursor, false); + + iniFile.Get("Settings", "SafeTextureCache", &bSafeTextureCache, false); // Settings + iniFile.Get("Settings", "ShowFPS", &bShowFPS, false); // Settings + iniFile.Get("Settings", "OverlayStats", &bOverlayStats, false); + iniFile.Get("Settings", "DLOptimize", &iCompileDLsLevel, 0); + iniFile.Get("Settings", "DumpTextures", &bDumpTextures, 0); + iniFile.Get("Settings", "ShowShaderErrors", &bShowShaderErrors, 0); + iniFile.Get("Settings", "Multisample", &iMultisampleMode, 0); + if (iMultisampleMode == 0) + iMultisampleMode = 1; + std::string s; + iniFile.Get("Settings", "TexDumpPath", &s, 0); + if (s.size() < sizeof(texDumpPath) ) + strcpy(texDumpPath, s.c_str()); + else { + strncpy(texDumpPath, s.c_str(), sizeof(texDumpPath)-1); + texDumpPath[sizeof(texDumpPath)-1] = 0; + } + + iniFile.Get("Settings", "TexFmtOverlayEnable", &bTexFmtOverlayEnable, 0); + iniFile.Get("Settings", "TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0); + iniFile.Get("Settings", "UseXFB", &bUseXFB, 0); + iniFile.Get("Settings", "WireFrame", &bWireFrame, 0); + iniFile.Get("Settings", "DisableLighting", &bDisableLighting, 0); + iniFile.Get("Settings", "DisableTexturing", &bDisableTexturing, 0); + + iniFile.Get("Enhancements", "ForceFiltering", &bForceFiltering, 0); + iniFile.Get("Enhancements", "MaxAnisotropy", &iMaxAnisotropy, 3); // NOTE - this is x in (1 << x) + + iniFile.Get("Hacks", "EFBToTextureDisable", &bEFBToTextureDisable, 0); + iniFile.Get("Hacks", "EFBToTextureDisableHotKey", &bEFBToTextureDisableHotKey, 0); + iniFile.Get("Hacks", "ProjectionHax1", &bProjectionHax1, 0); + iniFile.Get("Hacks", "ProjectionHax2", &bProjectionHax2, 0); +} + +void Config::Save() +{ + IniFile iniFile; + iniFile.Load(FULL_CONFIG_DIR "gfx_opengl.ini"); + iniFile.Set("Hardware", "WindowedRes", iWindowedRes); + iniFile.Set("Hardware", "FullscreenRes", iFSResolution); + iniFile.Set("Hardware", "Fullscreen", bFullscreen); + iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe); + iniFile.Set("Settings", "StretchToFit", bStretchToFit); + iniFile.Set("Settings", "KeepAR", bKeepAR); + iniFile.Set("Settings", "HideCursor", bHideCursor); + + iniFile.Set("Settings", "SafeTextureCache", bSafeTextureCache); + iniFile.Set("Settings", "ShowFPS", bShowFPS); + iniFile.Set("Settings", "OverlayStats", bOverlayStats); + iniFile.Set("Settings", "DLOptimize", iCompileDLsLevel); + iniFile.Set("Settings", "DumpTextures", bDumpTextures); + iniFile.Set("Settings", "ShowShaderErrors", bShowShaderErrors); + iniFile.Set("Settings", "Multisample", iMultisampleMode); + iniFile.Set("Settings", "TexDumpPath", texDumpPath); + iniFile.Set("Settings", "TexFmtOverlayEnable", bTexFmtOverlayEnable); + iniFile.Set("Settings", "TexFmtOverlayCenter", bTexFmtOverlayCenter); + iniFile.Set("Settings", "UseXFB", bUseXFB); + iniFile.Set("Settings", "Wireframe", bWireFrame); + iniFile.Set("Settings", "DisableLighting", bDisableLighting); + iniFile.Set("Settings", "DisableTexturing", bDisableTexturing); + + iniFile.Set("Enhancements", "ForceFiltering", bForceFiltering); + iniFile.Set("Enhancements", "MaxAnisotropy", iMaxAnisotropy); + + iniFile.Set("Hacks", "EFBToTextureDisable", bEFBToTextureDisable); + iniFile.Set("Hacks", "EFBToTextureDisableHotKey", bEFBToTextureDisableHotKey); + iniFile.Set("Hacks", "ProjectionHax1", bProjectionHax1); + iniFile.Set("Hacks", "ProjectionHax2", bProjectionHax2); + + iniFile.Save(FULL_CONFIG_DIR "gfx_opengl.ini"); +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Debugger/Debugger.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Debugger/Debugger.cpp index 13cdeddaad..92ae6c1534 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Debugger/Debugger.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Debugger/Debugger.cpp @@ -1,482 +1,482 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "../Globals.h" - -#include "IniFile.h" // Common files - -#include "../Config.h" // Config settings - -#include "PBView.h" // Debugger files -#include "Debugger.h" -#include "../Logging/Console.h" // open and close console - -// externals -extern int gSaveFile; // make this an int to allow multiple save file options -extern int gPreset; -int A, B; - - -// ======================================================================================= -// Declare events -BEGIN_EVENT_TABLE(CDebugger,wxDialog) - EVT_SHOW(CDebugger::OnShow) - EVT_CLOSE(CDebugger::OnClose) - EVT_BUTTON(ID_UPD,CDebugger::OnUpdate) - - EVT_CHECKBOX(ID_SAVETOFILE,CDebugger::GeneralSettings) // General settings - EVT_CHECKBOX(ID_SHOWCONSOLE,CDebugger::GeneralSettings) - EVT_CHECKLISTBOX(ID_CHECKLIST1, CDebugger::LogSettings) // Check list box - EVT_RADIOBOX(IDC_RADIO1, CDebugger::ChangeFrequency) // Update freq. - - EVT_BUTTON(ID_AP,CDebugger::Ap) - EVT_BUTTON(ID_AM,CDebugger::Am) - EVT_BUTTON(ID_BP,CDebugger::Bp) - EVT_BUTTON(ID_BM,CDebugger::Bm) -END_EVENT_TABLE() -// ======================================================================================= - - -CDebugger::CDebugger(wxWindow *parent, wxWindowID id, const wxString &title, - const wxPoint &position, const wxSize& size, long style) - : wxDialog(parent, id, title, position, size, style) - , m_GPRListView(NULL) -{ - CreateGUIControls(); - - // load ini... - IniFile file; - file.Load(DEBUGGER_CONFIG_FILE); - this->Load(file); -} - -CDebugger::~CDebugger() -{ - // empty - IniFile file; - file.Load(DEBUGGER_CONFIG_FILE); - this->Save(file); - file.Save(DEBUGGER_CONFIG_FILE); -} - -void CDebugger::Save(IniFile& _IniFile) const -{ - // TODO1: make this work when we close the entire program to, currently on total close we get - // weird values, perhaps because of some conflict with the rendering window - // TODO2: get the screen resolution and make limits from that - if(GetPosition().x < 1000 && GetPosition().y < 1000 - && GetSize().GetWidth() < 1000 && GetSize().GetHeight() < 1000 - ) - { - _IniFile.Set("VideoWindow", "x", GetPosition().x); - _IniFile.Set("VideoWindow", "y", GetPosition().y); - _IniFile.Set("VideoWindow", "w", GetSize().GetWidth()); - _IniFile.Set("VideoWindow", "h", GetSize().GetHeight()); - } - _IniFile.Set("VideoWindow", "Console", m_Check[2]->IsChecked()); // save settings - _IniFile.Set("VideoWindow", "UpdateFrequency", m_RadioBox[1]->GetSelection()); - _IniFile.Set("VideoWindow", "LogLevel", g_Config.iLog); -} - - -void CDebugger::Load(IniFile& _IniFile) -{ - int x,y,w,h; - _IniFile.Get("VideoWindow", "x", &x, GetPosition().x); - _IniFile.Get("VideoWindow", "y", &y, GetPosition().y); - _IniFile.Get("VideoWindow", "w", &w, GetSize().GetWidth()); - _IniFile.Get("VideoWindow", "h", &h, GetSize().GetHeight()); - SetSize(x, y, w, h); - - // saved settings - bool Console; - _IniFile.Get("VideoWindow", "Console", &Console, m_Check[2]->IsChecked()); - m_Check[2]->SetValue(Console); - DoShowHideConsole(); - - _IniFile.Get("VideoWindow", "UpdateFrequency", &gUpdFreq, m_RadioBox[1]->GetSelection()); - m_RadioBox[1]->SetSelection(gUpdFreq); - DoChangeFrequency(); - - _IniFile.Get("VideoWindow", "LogLevel", &g_Config.iLog, 0); - m_settings->Check(g_Config.iLog - 1, true); -} - -void CDebugger::CreateGUIControls() -{ - // Basic settings - SetTitle(wxT("OpenGL Debugging")); - SetIcon(wxNullIcon); - SetSize(8, 8, 200, 100); // these will become the minimin sizes allowed by resizing - Center(); - - // Declarations - wxBoxSizer *sMain, *sGeneral; - wxButton* m_Upd; - wxButton* m_Ap; wxButton* m_Am; - wxButton* m_Bp; wxButton* m_Bm; - - wxStaticBoxSizer* sLeft; - - - // Notebook ----------------------------------------------------- - m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize); - m_PageMain = new wxPanel(m_Notebook, ID_PAGEMAIN, wxDefaultPosition, wxDefaultSize); - m_Notebook->AddPage(m_PageMain, wxT("Main")); - - - - // =================================================================== - // Main Page - - - // Buttons ----------------------------------------------------- - wxStaticBoxSizer * m_updSizer = new wxStaticBoxSizer (wxVERTICAL, m_PageMain, wxT("Update")); - m_Upd = new wxButton(m_PageMain, ID_UPD, wxT("Update"), - wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_updSizer->Add(m_Upd, 0, 0, 5); - // ------------------------ - - - // Variables ----------------------------------------------------- - wxStaticBoxSizer * m_buttonSizer = new wxStaticBoxSizer (wxVERTICAL, m_PageMain, wxT("Variables")); - m_Ap = new wxButton(m_PageMain, ID_AP, wxT("A +"), - wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - //m_SelC->Enable(false); - m_Am = new wxButton(m_PageMain, ID_AM, wxT("A -"), - wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - //m_Presets->Enable(false); - m_Bp = new wxButton(m_PageMain, ID_BP, wxT("B +"), - wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_Bm = new wxButton(m_PageMain, ID_BM, wxT("B -"), - wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - - m_buttonSizer->Add(m_Ap, 0, 0, 5); - m_buttonSizer->Add(m_Am, 0, 0, 5); - m_buttonSizer->Add(m_Bp, 0, 0, 5); - m_buttonSizer->Add(m_Bm, 0, 0, 5); - // ------------------------ - - - // -------------------------------------------------------------------- - // m_PageMain: Options - // ------------------------- - wxStaticBoxSizer * m_optionsSizer = new wxStaticBoxSizer(wxVERTICAL, m_PageMain, wxT("Options")); - //m_Label[0] = new wxStaticBox(m_PageMain, IDG_LABEL1, wxT("Options"), - // wxDefaultPosition, wxDefaultSize, 0); - //wxStaticBoxSizer * m_checkSizer3 = new wxStaticBoxSizer (m_Label[0], wxVERTICAL); - - // checkboxes - m_Check[0] = new wxCheckBox(m_PageMain, ID_SAVETOFILE, wxT("Save to file"), - wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_Check[2] = new wxCheckBox(m_PageMain, ID_SHOWCONSOLE, wxT("Show console"), - wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - - m_optionsSizer->Add(m_Check[0], 0, 0, 5); - m_optionsSizer->Add(m_Check[2], 0, 0, 5); - // ------------------------ - - - // -------------------------------------------------------------------- - // m_PageMain: Log settings checkboxes - // ------------------------- - wxStaticBoxSizer * m_logSizer = new wxStaticBoxSizer(wxVERTICAL, m_PageMain, wxT("Log setting")); - m_settings = new wxCheckListBox(m_PageMain, ID_CHECKLIST1, wxDefaultPosition, wxDefaultSize, - 0, NULL, wxNO_BORDER); - - m_settings->Append(wxT("Info log")); - m_settings->Append(wxT("Primary log")); - - m_settings->Check(0, bInfoLog); - m_settings->Check(1, bPrimLog); - - // because the wxCheckListBox is a little underdeveloped we have to help it with this - // to bad there's no windows xp styles for the checkboxes - m_settings->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); - m_settings->SetMinSize(wxSize(m_settings->GetSize().GetWidth() - 40, - m_settings->GetCount() * 15)); - - m_logSizer->Add(m_settings, 0, 0, 0); - // ------------------------ - - - // -------------------------------------------------------------------- - // m_PageMain: Radio boxes - // ------------------------- - int m_radioBoxNChoices[3]; - - wxString m_radioBoxChoices0[] = { wxT("Show base 10"), wxT("Show base 16") }; - m_radioBoxNChoices[0] = sizeof( m_radioBoxChoices0 ) / sizeof( wxString ); - m_RadioBox[0] = new wxRadioBox( m_PageMain, IDC_RADIO0, wxT("Show base"), - wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[0], m_radioBoxChoices0, 1, wxRA_SPECIFY_COLS); - m_RadioBox[0]->Enable(false); - - wxString m_radioBoxChoices1[] = { wxT("Never"), wxT("5 times/s"), wxT("15 times/s"), wxT("30 times/s") }; - m_radioBoxNChoices[1] = sizeof( m_radioBoxChoices1 ) / sizeof( wxString ); - m_RadioBox[1] = new wxRadioBox( m_PageMain, IDC_RADIO1, wxT("Update freq."), - wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[1], m_radioBoxChoices1, 1, wxRA_SPECIFY_COLS); - - wxString m_radioBoxChoices2[] = { wxT("Win stretch") }; - m_radioBoxNChoices[2] = sizeof( m_radioBoxChoices2 ) / sizeof( wxString ); - m_RadioBox[2] = new wxRadioBox( m_PageMain, IDC_RADIO2, wxT("Presets"), - wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[2], m_radioBoxChoices2, 1, wxRA_SPECIFY_COLS); - // ------------------------ - - - // -------------------------------------------------------------------- - // Main: Left buttons and checkboxes - // ------------------------ - wxBoxSizer* sButtons = new wxBoxSizer(wxVERTICAL); - - //sButtons->AddStretchSpacer(1); - - sButtons->Add(m_updSizer, 0, 0, 5); // update button - sButtons->Add(m_buttonSizer, 0, 0, 5); // variables buttons - sButtons->Add(m_logSizer, 0, 0, 5); // log settings - - sButtons->Add(m_optionsSizer, 0, 2, 5); // Log options, show console etc. - - - // -------------------------------------------------------------------- - // Main: Right buttons and checkboxes - // ------------------------ - wxBoxSizer* sButtons2 = new wxBoxSizer(wxVERTICAL); - - sButtons2->Add(m_RadioBox[0], 0, 0, 5); // Show base - sButtons2->Add(m_RadioBox[1], 0, 0, 5); // Update frequency - sButtons2->Add(m_RadioBox[2], 0, 0, 5); // Preset views - //sButtons2->AddStretchSpacer(1); - //sButtons2->Add(m_checkSizer2, 0, 2, 5); - - - // -------------------------------------------------------------------- - // Main: Parameter tables view, the big window - sLeft = new wxStaticBoxSizer(wxVERTICAL, m_PageMain, wxT("Current Status")); - - m_GPRListView = new CPBView(m_PageMain, ID_GPR, wxDefaultPosition, GetSize(), - wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT | wxLC_SINGLE_SEL | wxLC_SORT_ASCENDING); - - sLeft->Add(m_GPRListView, 1, wxEXPAND|wxALL, 5); - - - // -------------------------------------------------------------------- - // General container - // ----------------------------- - sGeneral = new wxBoxSizer(wxHORIZONTAL); - sGeneral->Add(sLeft, 1, wxEXPAND | wxALL, 5); - sGeneral->Add(sButtons, 0, wxEXPAND | (wxUP | wxDOWN), 5); - sGeneral->Add(sButtons2, 0, wxEXPAND | (wxUP | wxDOWN | wxRIGHT | wxLEFT), 5); - - - // -------------------------------------------------------------------- - // Main container - // ----------------------------- - sMain = new wxBoxSizer(wxVERTICAL); - sMain->Add(m_Notebook, 1, wxEXPAND | wxALL, 5); - - m_PageMain->SetSizer(sGeneral); - this->SetSizer(sMain); - //sGeneral->SetSizeHints(this); - - //NotifyUpdate(); - //Freeze(); // unfreeze this if you want to use it -} - - -// ========================================================================== -// System functions -// -------------- -void CDebugger::OnShow(wxShowEvent& /*event*/) -{ - // bring the console back to - if(m_Check[2]->IsChecked()) - { - OpenConsole(); - #ifdef _WIN32 - MoveWindow(GetConsoleHwnd(), 0,400, 1280,500, true); // Move window TODO: make this - // adjustable from the debugging window - #endif - } -} - -void CDebugger::OnClose(wxCloseEvent& /*event*/) -{ - // save the window position when we hide the window to - IniFile file; - file.Load(DEBUGGER_CONFIG_FILE); - this->Save(file); - file.Save(DEBUGGER_CONFIG_FILE); - - EndModal(0); // it seems like this works for Show() to, not just ShowModal(); - CloseConsole(); // The console goes with the wx window -} - - -void CDebugger::DoHide() -{ - Hide(); - CloseConsole(); // The console goes with the wx window -} - -void CDebugger::DoShow() -{ - Show(); - DoShowHideConsole(); // The console goes with the wx window -} - - -void CDebugger::OnUpdate(wxCommandEvent& /*event*/) -{ - this->NotifyUpdate(); -} -// =============== - - -// ======================================================================================= -// Change preset -// -------------- -void CDebugger::ChangePreset(wxCommandEvent& event) -{ - DoChangePreset(); -} - -void CDebugger::DoChangePreset() -{ - if(m_RadioBox[2]->GetSelection() == 0) - gPreset = 0; - else if(m_RadioBox[2]->GetSelection() == 1) - gPreset = 1; - else if(m_RadioBox[2]->GetSelection() == 2) - gPreset = 2; - else if(m_RadioBox[2]->GetSelection() == 3) - gPreset = 3; -} -// ============== - - -// ======================================================================================= -// Control variables -// -------------- -void CDebugger::Ap(wxCommandEvent& event) -{ - A += 50; - //MessageBox(0, "", "", 0); - __Log("%i", A); -} -void CDebugger::Am(wxCommandEvent& event) -{ - A -= 50; -} -void CDebugger::Bp(wxCommandEvent& event) -{ - B += 50; -} -void CDebugger::Bm(wxCommandEvent& event) -{ - B -= 50; -} -// ============== - - -// ======================================================================================= -// Change update frequency -// -------------- -void CDebugger::ChangeFrequency(wxCommandEvent& event) -{ - DoChangeFrequency(); -} - -void CDebugger::DoChangeFrequency() -{ - if(m_RadioBox[1]->GetSelection() == 0) - gUpdFreq = 0; - else if(m_RadioBox[1]->GetSelection() == 1) - gUpdFreq = 5; - else if(m_RadioBox[1]->GetSelection() == 2) - gUpdFreq = 15; - else - gUpdFreq = 30; -} -// ============== - - -// ======================================================================================= -// General settings -// -------------- -void CDebugger::GeneralSettings(wxCommandEvent& event) -{ - switch (event.GetId()) - { - case ID_SAVETOFILE: // Save to file - gSaveFile = m_Check[0]->IsChecked(); - break; - case ID_SHOWCONSOLE: - DoShowHideConsole(); - break; - } -} -// ============== - - -// ======================================================================================= -// Show or hide console window -// -------------- -void CDebugger::DoShowHideConsole() -{ - if(m_Check[2]->IsChecked()) - { - OpenConsole(); - #ifdef _WIN32 - MoveWindow(GetConsoleHwnd(), 0,400, 1280,500, true); // move window, TODO: make this - // adjustable from the debugging window - #endif - } - else - { - CloseConsole(); - } -} -// ============== - - -// ======================================================================================= -// Enable or disable logs -// -------------- -void CDebugger::LogSettings(wxCommandEvent& event) -{ - // Only allow one selected log at a time - for (u32 i = 0; i < m_settings->GetCount(); ++i) - if(i != (u32)event.GetInt()) m_settings->Check(i, false); - - if(m_settings->IsChecked(0)) g_Config.iLog = CONF_LOG; - else if(m_settings->IsChecked(1)) g_Config.iLog = CONF_PRIMLOG; - else g_Config.iLog = 0; -} -// ============== - - -// ======================================================================================= -// Update the wxListCtrl -// -------------- -void CDebugger::NotifyUpdate() -{ - if (m_GPRListView != NULL) - { - m_GPRListView->Update(); - } -} -// ============== +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "../Globals.h" + +#include "IniFile.h" // Common files + +#include "../Config.h" // Config settings + +#include "PBView.h" // Debugger files +#include "Debugger.h" +#include "../Logging/Console.h" // open and close console + +// externals +extern int gSaveFile; // make this an int to allow multiple save file options +extern int gPreset; +int A, B; + + +// ======================================================================================= +// Declare events +BEGIN_EVENT_TABLE(CDebugger,wxDialog) + EVT_SHOW(CDebugger::OnShow) + EVT_CLOSE(CDebugger::OnClose) + EVT_BUTTON(ID_UPD,CDebugger::OnUpdate) + + EVT_CHECKBOX(ID_SAVETOFILE,CDebugger::GeneralSettings) // General settings + EVT_CHECKBOX(ID_SHOWCONSOLE,CDebugger::GeneralSettings) + EVT_CHECKLISTBOX(ID_CHECKLIST1, CDebugger::LogSettings) // Check list box + EVT_RADIOBOX(IDC_RADIO1, CDebugger::ChangeFrequency) // Update freq. + + EVT_BUTTON(ID_AP,CDebugger::Ap) + EVT_BUTTON(ID_AM,CDebugger::Am) + EVT_BUTTON(ID_BP,CDebugger::Bp) + EVT_BUTTON(ID_BM,CDebugger::Bm) +END_EVENT_TABLE() +// ======================================================================================= + + +CDebugger::CDebugger(wxWindow *parent, wxWindowID id, const wxString &title, + const wxPoint &position, const wxSize& size, long style) + : wxDialog(parent, id, title, position, size, style) + , m_GPRListView(NULL) +{ + CreateGUIControls(); + + // load ini... + IniFile file; + file.Load(DEBUGGER_CONFIG_FILE); + this->Load(file); +} + +CDebugger::~CDebugger() +{ + // empty + IniFile file; + file.Load(DEBUGGER_CONFIG_FILE); + this->Save(file); + file.Save(DEBUGGER_CONFIG_FILE); +} + +void CDebugger::Save(IniFile& _IniFile) const +{ + // TODO1: make this work when we close the entire program to, currently on total close we get + // weird values, perhaps because of some conflict with the rendering window + // TODO2: get the screen resolution and make limits from that + if(GetPosition().x < 1000 && GetPosition().y < 1000 + && GetSize().GetWidth() < 1000 && GetSize().GetHeight() < 1000 + ) + { + _IniFile.Set("VideoWindow", "x", GetPosition().x); + _IniFile.Set("VideoWindow", "y", GetPosition().y); + _IniFile.Set("VideoWindow", "w", GetSize().GetWidth()); + _IniFile.Set("VideoWindow", "h", GetSize().GetHeight()); + } + _IniFile.Set("VideoWindow", "Console", m_Check[2]->IsChecked()); // save settings + _IniFile.Set("VideoWindow", "UpdateFrequency", m_RadioBox[1]->GetSelection()); + _IniFile.Set("VideoWindow", "LogLevel", g_Config.iLog); +} + + +void CDebugger::Load(IniFile& _IniFile) +{ + int x,y,w,h; + _IniFile.Get("VideoWindow", "x", &x, GetPosition().x); + _IniFile.Get("VideoWindow", "y", &y, GetPosition().y); + _IniFile.Get("VideoWindow", "w", &w, GetSize().GetWidth()); + _IniFile.Get("VideoWindow", "h", &h, GetSize().GetHeight()); + SetSize(x, y, w, h); + + // saved settings + bool Console; + _IniFile.Get("VideoWindow", "Console", &Console, m_Check[2]->IsChecked()); + m_Check[2]->SetValue(Console); + DoShowHideConsole(); + + _IniFile.Get("VideoWindow", "UpdateFrequency", &gUpdFreq, m_RadioBox[1]->GetSelection()); + m_RadioBox[1]->SetSelection(gUpdFreq); + DoChangeFrequency(); + + _IniFile.Get("VideoWindow", "LogLevel", &g_Config.iLog, 0); + m_settings->Check(g_Config.iLog - 1, true); +} + +void CDebugger::CreateGUIControls() +{ + // Basic settings + SetTitle(wxT("OpenGL Debugging")); + SetIcon(wxNullIcon); + SetSize(8, 8, 200, 100); // these will become the minimin sizes allowed by resizing + Center(); + + // Declarations + wxBoxSizer *sMain, *sGeneral; + wxButton* m_Upd; + wxButton* m_Ap; wxButton* m_Am; + wxButton* m_Bp; wxButton* m_Bm; + + wxStaticBoxSizer* sLeft; + + + // Notebook ----------------------------------------------------- + m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize); + m_PageMain = new wxPanel(m_Notebook, ID_PAGEMAIN, wxDefaultPosition, wxDefaultSize); + m_Notebook->AddPage(m_PageMain, wxT("Main")); + + + + // =================================================================== + // Main Page + + + // Buttons ----------------------------------------------------- + wxStaticBoxSizer * m_updSizer = new wxStaticBoxSizer (wxVERTICAL, m_PageMain, wxT("Update")); + m_Upd = new wxButton(m_PageMain, ID_UPD, wxT("Update"), + wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_updSizer->Add(m_Upd, 0, 0, 5); + // ------------------------ + + + // Variables ----------------------------------------------------- + wxStaticBoxSizer * m_buttonSizer = new wxStaticBoxSizer (wxVERTICAL, m_PageMain, wxT("Variables")); + m_Ap = new wxButton(m_PageMain, ID_AP, wxT("A +"), + wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + //m_SelC->Enable(false); + m_Am = new wxButton(m_PageMain, ID_AM, wxT("A -"), + wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + //m_Presets->Enable(false); + m_Bp = new wxButton(m_PageMain, ID_BP, wxT("B +"), + wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_Bm = new wxButton(m_PageMain, ID_BM, wxT("B -"), + wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + + m_buttonSizer->Add(m_Ap, 0, 0, 5); + m_buttonSizer->Add(m_Am, 0, 0, 5); + m_buttonSizer->Add(m_Bp, 0, 0, 5); + m_buttonSizer->Add(m_Bm, 0, 0, 5); + // ------------------------ + + + // -------------------------------------------------------------------- + // m_PageMain: Options + // ------------------------- + wxStaticBoxSizer * m_optionsSizer = new wxStaticBoxSizer(wxVERTICAL, m_PageMain, wxT("Options")); + //m_Label[0] = new wxStaticBox(m_PageMain, IDG_LABEL1, wxT("Options"), + // wxDefaultPosition, wxDefaultSize, 0); + //wxStaticBoxSizer * m_checkSizer3 = new wxStaticBoxSizer (m_Label[0], wxVERTICAL); + + // checkboxes + m_Check[0] = new wxCheckBox(m_PageMain, ID_SAVETOFILE, wxT("Save to file"), + wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_Check[2] = new wxCheckBox(m_PageMain, ID_SHOWCONSOLE, wxT("Show console"), + wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + + m_optionsSizer->Add(m_Check[0], 0, 0, 5); + m_optionsSizer->Add(m_Check[2], 0, 0, 5); + // ------------------------ + + + // -------------------------------------------------------------------- + // m_PageMain: Log settings checkboxes + // ------------------------- + wxStaticBoxSizer * m_logSizer = new wxStaticBoxSizer(wxVERTICAL, m_PageMain, wxT("Log setting")); + m_settings = new wxCheckListBox(m_PageMain, ID_CHECKLIST1, wxDefaultPosition, wxDefaultSize, + 0, NULL, wxNO_BORDER); + + m_settings->Append(wxT("Info log")); + m_settings->Append(wxT("Primary log")); + + m_settings->Check(0, bInfoLog); + m_settings->Check(1, bPrimLog); + + // because the wxCheckListBox is a little underdeveloped we have to help it with this + // to bad there's no windows xp styles for the checkboxes + m_settings->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); + m_settings->SetMinSize(wxSize(m_settings->GetSize().GetWidth() - 40, + m_settings->GetCount() * 15)); + + m_logSizer->Add(m_settings, 0, 0, 0); + // ------------------------ + + + // -------------------------------------------------------------------- + // m_PageMain: Radio boxes + // ------------------------- + int m_radioBoxNChoices[3]; + + wxString m_radioBoxChoices0[] = { wxT("Show base 10"), wxT("Show base 16") }; + m_radioBoxNChoices[0] = sizeof( m_radioBoxChoices0 ) / sizeof( wxString ); + m_RadioBox[0] = new wxRadioBox( m_PageMain, IDC_RADIO0, wxT("Show base"), + wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[0], m_radioBoxChoices0, 1, wxRA_SPECIFY_COLS); + m_RadioBox[0]->Enable(false); + + wxString m_radioBoxChoices1[] = { wxT("Never"), wxT("5 times/s"), wxT("15 times/s"), wxT("30 times/s") }; + m_radioBoxNChoices[1] = sizeof( m_radioBoxChoices1 ) / sizeof( wxString ); + m_RadioBox[1] = new wxRadioBox( m_PageMain, IDC_RADIO1, wxT("Update freq."), + wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[1], m_radioBoxChoices1, 1, wxRA_SPECIFY_COLS); + + wxString m_radioBoxChoices2[] = { wxT("Win stretch") }; + m_radioBoxNChoices[2] = sizeof( m_radioBoxChoices2 ) / sizeof( wxString ); + m_RadioBox[2] = new wxRadioBox( m_PageMain, IDC_RADIO2, wxT("Presets"), + wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[2], m_radioBoxChoices2, 1, wxRA_SPECIFY_COLS); + // ------------------------ + + + // -------------------------------------------------------------------- + // Main: Left buttons and checkboxes + // ------------------------ + wxBoxSizer* sButtons = new wxBoxSizer(wxVERTICAL); + + //sButtons->AddStretchSpacer(1); + + sButtons->Add(m_updSizer, 0, 0, 5); // update button + sButtons->Add(m_buttonSizer, 0, 0, 5); // variables buttons + sButtons->Add(m_logSizer, 0, 0, 5); // log settings + + sButtons->Add(m_optionsSizer, 0, 2, 5); // Log options, show console etc. + + + // -------------------------------------------------------------------- + // Main: Right buttons and checkboxes + // ------------------------ + wxBoxSizer* sButtons2 = new wxBoxSizer(wxVERTICAL); + + sButtons2->Add(m_RadioBox[0], 0, 0, 5); // Show base + sButtons2->Add(m_RadioBox[1], 0, 0, 5); // Update frequency + sButtons2->Add(m_RadioBox[2], 0, 0, 5); // Preset views + //sButtons2->AddStretchSpacer(1); + //sButtons2->Add(m_checkSizer2, 0, 2, 5); + + + // -------------------------------------------------------------------- + // Main: Parameter tables view, the big window + sLeft = new wxStaticBoxSizer(wxVERTICAL, m_PageMain, wxT("Current Status")); + + m_GPRListView = new CPBView(m_PageMain, ID_GPR, wxDefaultPosition, GetSize(), + wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT | wxLC_SINGLE_SEL | wxLC_SORT_ASCENDING); + + sLeft->Add(m_GPRListView, 1, wxEXPAND|wxALL, 5); + + + // -------------------------------------------------------------------- + // General container + // ----------------------------- + sGeneral = new wxBoxSizer(wxHORIZONTAL); + sGeneral->Add(sLeft, 1, wxEXPAND | wxALL, 5); + sGeneral->Add(sButtons, 0, wxEXPAND | (wxUP | wxDOWN), 5); + sGeneral->Add(sButtons2, 0, wxEXPAND | (wxUP | wxDOWN | wxRIGHT | wxLEFT), 5); + + + // -------------------------------------------------------------------- + // Main container + // ----------------------------- + sMain = new wxBoxSizer(wxVERTICAL); + sMain->Add(m_Notebook, 1, wxEXPAND | wxALL, 5); + + m_PageMain->SetSizer(sGeneral); + this->SetSizer(sMain); + //sGeneral->SetSizeHints(this); + + //NotifyUpdate(); + //Freeze(); // unfreeze this if you want to use it +} + + +// ========================================================================== +// System functions +// -------------- +void CDebugger::OnShow(wxShowEvent& /*event*/) +{ + // bring the console back to + if(m_Check[2]->IsChecked()) + { + OpenConsole(); + #ifdef _WIN32 + MoveWindow(GetConsoleHwnd(), 0,400, 1280,500, true); // Move window TODO: make this + // adjustable from the debugging window + #endif + } +} + +void CDebugger::OnClose(wxCloseEvent& /*event*/) +{ + // save the window position when we hide the window to + IniFile file; + file.Load(DEBUGGER_CONFIG_FILE); + this->Save(file); + file.Save(DEBUGGER_CONFIG_FILE); + + EndModal(0); // it seems like this works for Show() to, not just ShowModal(); + CloseConsole(); // The console goes with the wx window +} + + +void CDebugger::DoHide() +{ + Hide(); + CloseConsole(); // The console goes with the wx window +} + +void CDebugger::DoShow() +{ + Show(); + DoShowHideConsole(); // The console goes with the wx window +} + + +void CDebugger::OnUpdate(wxCommandEvent& /*event*/) +{ + this->NotifyUpdate(); +} +// =============== + + +// ======================================================================================= +// Change preset +// -------------- +void CDebugger::ChangePreset(wxCommandEvent& event) +{ + DoChangePreset(); +} + +void CDebugger::DoChangePreset() +{ + if(m_RadioBox[2]->GetSelection() == 0) + gPreset = 0; + else if(m_RadioBox[2]->GetSelection() == 1) + gPreset = 1; + else if(m_RadioBox[2]->GetSelection() == 2) + gPreset = 2; + else if(m_RadioBox[2]->GetSelection() == 3) + gPreset = 3; +} +// ============== + + +// ======================================================================================= +// Control variables +// -------------- +void CDebugger::Ap(wxCommandEvent& event) +{ + A += 50; + //MessageBox(0, "", "", 0); + __Log("%i", A); +} +void CDebugger::Am(wxCommandEvent& event) +{ + A -= 50; +} +void CDebugger::Bp(wxCommandEvent& event) +{ + B += 50; +} +void CDebugger::Bm(wxCommandEvent& event) +{ + B -= 50; +} +// ============== + + +// ======================================================================================= +// Change update frequency +// -------------- +void CDebugger::ChangeFrequency(wxCommandEvent& event) +{ + DoChangeFrequency(); +} + +void CDebugger::DoChangeFrequency() +{ + if(m_RadioBox[1]->GetSelection() == 0) + gUpdFreq = 0; + else if(m_RadioBox[1]->GetSelection() == 1) + gUpdFreq = 5; + else if(m_RadioBox[1]->GetSelection() == 2) + gUpdFreq = 15; + else + gUpdFreq = 30; +} +// ============== + + +// ======================================================================================= +// General settings +// -------------- +void CDebugger::GeneralSettings(wxCommandEvent& event) +{ + switch (event.GetId()) + { + case ID_SAVETOFILE: // Save to file + gSaveFile = m_Check[0]->IsChecked(); + break; + case ID_SHOWCONSOLE: + DoShowHideConsole(); + break; + } +} +// ============== + + +// ======================================================================================= +// Show or hide console window +// -------------- +void CDebugger::DoShowHideConsole() +{ + if(m_Check[2]->IsChecked()) + { + OpenConsole(); + #ifdef _WIN32 + MoveWindow(GetConsoleHwnd(), 0,400, 1280,500, true); // move window, TODO: make this + // adjustable from the debugging window + #endif + } + else + { + CloseConsole(); + } +} +// ============== + + +// ======================================================================================= +// Enable or disable logs +// -------------- +void CDebugger::LogSettings(wxCommandEvent& event) +{ + // Only allow one selected log at a time + for (u32 i = 0; i < m_settings->GetCount(); ++i) + if(i != (u32)event.GetInt()) m_settings->Check(i, false); + + if(m_settings->IsChecked(0)) g_Config.iLog = CONF_LOG; + else if(m_settings->IsChecked(1)) g_Config.iLog = CONF_PRIMLOG; + else g_Config.iLog = 0; +} +// ============== + + +// ======================================================================================= +// Update the wxListCtrl +// -------------- +void CDebugger::NotifyUpdate() +{ + if (m_GPRListView != NULL) + { + m_GPRListView->Update(); + } +} +// ============== diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Debugger/PBView.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Debugger/PBView.cpp index 80e048f574..f33fdfb91d 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Debugger/PBView.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Debugger/PBView.cpp @@ -1,124 +1,124 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "../Globals.h" -#include "PBView.h" - -#include -#include -#include -#include - -extern const char* GetGRPName(unsigned int index); - -BEGIN_EVENT_TABLE(CPBView, wxListCtrl) -END_EVENT_TABLE() - -CPBView::CPBView(wxWindow* parent, const wxWindowID id, const wxPoint& pos, const wxSize& size, long style) - : wxListCtrl(parent, id, pos, size, style) -{ - InsertColumn(0, wxT("Block"), wxLIST_FORMAT_CENTER, 40); - - SetFont(wxFont(8, wxSWISS, wxNORMAL, wxNORMAL, false, wxT("Segoe UI"))); - - for (int i = 0; i < 1; i++) - { - // Print values from 0 to 63 - char buffer [33]; - sprintf(buffer, "%02i", i); - int Item = InsertItem(0, wxString::FromAscii(buffer)); - - - wxListItem item; - item.SetId(Item); - item.SetBackgroundColour(0xFFFFFF); - item.SetData(i); - SetItem(item); - } - - // This is a wx call that leads to MSWDrawSubItem - Refresh(); -} - -void CPBView::Update() -{ - - Refresh(); - -} -#ifdef _WIN32 -bool CPBView::MSWDrawSubItem(wxPaintDC& rPainDC, int item, int subitem) -{ - bool Result = false; - - // don't change 0, it has the block values - if(subitem > 0) - { - #ifdef __WXMSW__ // what's this? should I use that? - const wxChar* bgColor = _T("#ffffff"); - wxBrush bgBrush(bgColor); - wxPen bgPen(bgColor); - - wxRect SubItemRect; - this->GetSubItemRect(item, subitem, SubItemRect); - rPainDC.SetBrush(bgBrush); - rPainDC.SetPen(bgPen); - rPainDC.DrawRectangle(SubItemRect); - #endif - // A somewhat primitive attempt to show the playing history for a certain block. - - wxString text; - if(subitem == 1) - { - char cbuff [33]; - - sprintf(cbuff, "%08i", m_CachedRegs[subitem][item]); - std::string c = cbuff; - int n[8]; - - for (int j = 0; j < 8; j++) - { - - n[j] = atoi( c.substr(j, 1).c_str()); - // 149 = dot, 160 = space - if (n[j] == 1){ - n[j] = 149;} else {n[j] = 160;} - } - // pretty neat huh? - text.Printf(wxT("%c%c%c%c%c%c%c%c"), n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); - - } - else - { - text.Printf(wxT("0x%08x"), m_CachedRegs[subitem][item]); - } - #ifdef __WXMSW__ - rPainDC.DrawText(text, SubItemRect.GetLeft() + 10, SubItemRect.GetTop() + 4); - #else - // May not show up pretty in !Win32 - rPainDC.DrawText(text, 10, 4); - #endif - - return true; - } - else - { - // what does this mean? - return Result; - } -} -#endif +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "../Globals.h" +#include "PBView.h" + +#include +#include +#include +#include + +extern const char* GetGRPName(unsigned int index); + +BEGIN_EVENT_TABLE(CPBView, wxListCtrl) +END_EVENT_TABLE() + +CPBView::CPBView(wxWindow* parent, const wxWindowID id, const wxPoint& pos, const wxSize& size, long style) + : wxListCtrl(parent, id, pos, size, style) +{ + InsertColumn(0, wxT("Block"), wxLIST_FORMAT_CENTER, 40); + + SetFont(wxFont(8, wxSWISS, wxNORMAL, wxNORMAL, false, wxT("Segoe UI"))); + + for (int i = 0; i < 1; i++) + { + // Print values from 0 to 63 + char buffer [33]; + sprintf(buffer, "%02i", i); + int Item = InsertItem(0, wxString::FromAscii(buffer)); + + + wxListItem item; + item.SetId(Item); + item.SetBackgroundColour(0xFFFFFF); + item.SetData(i); + SetItem(item); + } + + // This is a wx call that leads to MSWDrawSubItem + Refresh(); +} + +void CPBView::Update() +{ + + Refresh(); + +} +#ifdef _WIN32 +bool CPBView::MSWDrawSubItem(wxPaintDC& rPainDC, int item, int subitem) +{ + bool Result = false; + + // don't change 0, it has the block values + if(subitem > 0) + { + #ifdef __WXMSW__ // what's this? should I use that? + const wxChar* bgColor = _T("#ffffff"); + wxBrush bgBrush(bgColor); + wxPen bgPen(bgColor); + + wxRect SubItemRect; + this->GetSubItemRect(item, subitem, SubItemRect); + rPainDC.SetBrush(bgBrush); + rPainDC.SetPen(bgPen); + rPainDC.DrawRectangle(SubItemRect); + #endif + // A somewhat primitive attempt to show the playing history for a certain block. + + wxString text; + if(subitem == 1) + { + char cbuff [33]; + + sprintf(cbuff, "%08i", m_CachedRegs[subitem][item]); + std::string c = cbuff; + int n[8]; + + for (int j = 0; j < 8; j++) + { + + n[j] = atoi( c.substr(j, 1).c_str()); + // 149 = dot, 160 = space + if (n[j] == 1){ + n[j] = 149;} else {n[j] = 160;} + } + // pretty neat huh? + text.Printf(wxT("%c%c%c%c%c%c%c%c"), n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); + + } + else + { + text.Printf(wxT("0x%08x"), m_CachedRegs[subitem][item]); + } + #ifdef __WXMSW__ + rPainDC.DrawText(text, SubItemRect.GetLeft() + 10, SubItemRect.GetTop() + 4); + #else + // May not show up pretty in !Win32 + rPainDC.DrawText(text, 10, 4); + #endif + + return true; + } + else + { + // what does this mean? + return Result; + } +} +#endif diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp index ac45f1534f..65754bc32a 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp @@ -1,720 +1,720 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Globals.h" -#include "Config.h" -#include "IniFile.h" -#include "svnrev.h" - -#include "Render.h" - -#if defined(_WIN32) -#include "OS/Win32.h" -#else -struct RECT -{ - int left, top; - int right, bottom; -}; -#endif - -#include "GLUtil.h" - -#ifndef USE_SDL -#define USE_SDL 0 -#endif -#if USE_SDL -#include -#endif - -// Handles OpenGL and the window - -// externals -int gleft, gright, gtop, gbottom; -int nBackbufferWidth, nBackbufferHeight; // screen width -int nXoff, nYoff; // screen offset -float AR; // aspect ratio - -#ifndef _WIN32 -GLWindow GLWin; -#endif - -#if defined(_WIN32) -static HDC hDC = NULL; // Private GDI Device Context -static HGLRC hRC = NULL; // Permanent Rendering Context -extern HINSTANCE g_hInstance; -#endif - -void OpenGL_SwapBuffers() -{ -#if USE_SDL - SDL_GL_SwapBuffers(); -#elif defined(OSX64) - cocoaGLSwap(GLWin.cocoaCtx,GLWin.cocoaWin); -#elif defined(_WIN32) - SwapBuffers(hDC); -#else // GLX - glXSwapBuffers(GLWin.dpy, GLWin.win); -#endif -} - -void OpenGL_SetWindowText(const char *text) -{ -#if USE_SDL - SDL_WM_SetCaption(text, NULL); -#elif defined(OSX64) - cocoaGLSetTitle(); -#elif defined(_WIN32) - SetWindowText(EmuWindow::GetWnd(), text); -#elif defined(HAVE_X11) && HAVE_X11 // GLX - /** - * Tell X to ask the window manager to set the window title. (X - * itself doesn't provide window title functionality.) - */ - XStoreName(GLWin.dpy, GLWin.win, text); -#endif -} - -#if defined(OSX64) -unsigned int Callback_PeekMessages() -#else -BOOL Callback_PeekMessages() -#endif -{ -#ifdef _WIN32 - //TODO: peekmessage - MSG msg; - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) - { - if (msg.message == WM_QUIT) - return FALSE; - TranslateMessage(&msg); - DispatchMessage(&msg); - } - return TRUE; -#else - return FALSE; -#endif -} - -void UpdateFPSDisplay(const char *text) -{ - char temp[512]; - sprintf(temp, "SVN R%s: GL: %s", SVN_REV_STR, text); -#if defined(_WIN32) - SetWindowText(EmuWindow::GetWnd(), temp); -#endif - OpenGL_SetWindowText(temp); - -} - -// ======================================================================================= -// Create window. Called from main.cpp -bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight) -{ - int _twidth, _theight; - if(g_Config.bFullscreen) - { - if(strlen(g_Config.iFSResolution) > 1) - { - sscanf(g_Config.iFSResolution, "%dx%d", &_twidth, &_theight); - } - else // No full screen reso set, fall back to default reso - { - _twidth = _iwidth; - _theight = _iheight; - } - } - else // Going Windowed - { - if(strlen(g_Config.iWindowedRes) > 1) - { - sscanf(g_Config.iWindowedRes, "%dx%d", &_twidth, &_theight); - } - else // No Window reso set, fall back to default - { - _twidth = _iwidth; - _theight = _iheight; - } - } -#if defined(_WIN32) - EmuWindow::SetSize(_twidth, _theight); -#endif - - // --------------------------------------------------------------------------------------- - // Control window size and picture scaling - // ------------------ - // nBackbufferWidth and nBackbufferHeight = Screen resolution from ini, or 640x480 - // See OpenGL_Update() for documentation of the other variables - // ------------------ - nBackbufferWidth = _twidth; - nBackbufferHeight = _theight; - - float FactorW = 640.0f / (float)nBackbufferWidth; - float FactorH = 480.0f / (float)nBackbufferHeight; - float Max = (FactorW < FactorH) ? FactorH : FactorW; - - if(g_Config.bStretchToFit) - { - MValueX = 1.0f / FactorW; - MValueY = 1.0f / FactorH; - nXoff = 0; - nYoff = 0; - } - else - { - MValueX = 1.0f / Max; - MValueY = 1.0f / Max; - nXoff = (int)((nBackbufferWidth - (640 * MValueX)) / 2); - nYoff = (int)((nBackbufferHeight - (480 * MValueY)) / 2); - } - - g_VideoInitialize.pPeekMessages = &Callback_PeekMessages; - g_VideoInitialize.pUpdateFPSDisplay = &UpdateFPSDisplay; - - //char buff[100]; - //sprintf(buff, "%i %i %d %d %d", nBackbufferWidth, nBackbufferHeight, Max, MValueX, MValueY); - //MessageBox(0, buff, "", 0); - -#if USE_SDL - //init sdl video - if (SDL_Init(SDL_INIT_VIDEO) < 0) { - //TODO : Display an error message - SDL_Quit(); - return false; - } - - //setup ogl to use double buffering - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); -#elif defined(OSX64) - cocoaGLCreateApp(); - GLWin.width = nBackbufferWidth; - GLWin.height = nBackbufferHeight; - GLWin.cocoaWin = cocoaGLCreateWindow(GLWin.width, GLWin.height); - GLWin.cocoaCtx = cocoaGLInit(g_Config.iMultisampleMode); -#elif defined(_WIN32) - // create the window - if (!g_Config.renderToMainframe || g_VideoInitialize.pWindowHandle == NULL) - { - g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create(NULL, g_hInstance, "Please wait..."); - } - else - { - g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create((HWND)g_VideoInitialize.pWindowHandle, g_hInstance, "Please wait..."); - } - EmuWindow::Show(); - - if (g_VideoInitialize.pWindowHandle == NULL) - { - g_VideoInitialize.pSysMessage("failed to create window"); - return false; - } - - GLuint PixelFormat; // Holds The Results After Searching For A Match - DWORD dwExStyle; // Window Extended Style - DWORD dwStyle; // Window Style - - RECT rcdesktop; - GetWindowRect(GetDesktopWindow(), &rcdesktop); - - if (g_Config.bFullscreen) { - //nBackbufferWidth = rcdesktop.right - rcdesktop.left; - //nBackbufferHeight = rcdesktop.bottom - rcdesktop.top; - - DEVMODE dmScreenSettings; - memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); - dmScreenSettings.dmSize=sizeof(dmScreenSettings); - dmScreenSettings.dmPelsWidth = nBackbufferWidth; - dmScreenSettings.dmPelsHeight = nBackbufferHeight; - dmScreenSettings.dmBitsPerPel = 32; - dmScreenSettings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; - - // Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. - if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) - { - if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) - g_Config.bFullscreen = false; - else - return false; - } - } - else - { - // change to default resolution - ChangeDisplaySettings(NULL, 0); - } - - if (g_Config.bFullscreen && !g_Config.renderToMainframe) - { - ShowCursor(FALSE); - } - else - { - dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; - dwStyle = WS_OVERLAPPEDWINDOW; - } - - RECT rc; - rc.left = 0; rc.top = 0; - rc.right = nBackbufferWidth; rc.bottom = nBackbufferHeight; - AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle); - int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2; - int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2; - - SetWindowPos(EmuWindow::GetWnd(), NULL, X, Y, rc.right-rc.left, rc.bottom-rc.top, SWP_NOREPOSITION|SWP_NOZORDER); - - PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be - { - sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor - 1, // Version Number - PFD_DRAW_TO_WINDOW | // Format Must Support Window - PFD_SUPPORT_OPENGL | // Format Must Support OpenGL - PFD_DOUBLEBUFFER, // Must Support Double Buffering - PFD_TYPE_RGBA, // Request An RGBA Format - 32, // Select Our Color Depth - 0, 0, 0, 0, 0, 0, // Color Bits Ignored - 0, // 8bit Alpha Buffer - 0, // Shift Bit Ignored - 0, // No Accumulation Buffer - 0, 0, 0, 0, // Accumulation Bits Ignored - 24, // 24Bit Z-Buffer (Depth Buffer) - 8, // 8bit Stencil Buffer - 0, // No Auxiliary Buffer - PFD_MAIN_PLANE, // Main Drawing Layer - 0, // Reserved - 0, 0, 0 // Layer Masks Ignored - }; - - if (!(hDC=GetDC(EmuWindow::GetWnd()))) { - MessageBox(NULL,"(1) Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); - return false; - } - - if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) { - MessageBox(NULL,"(2) Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); - return false; - } - - if (!SetPixelFormat(hDC,PixelFormat,&pfd)) { - MessageBox(NULL,"(3) Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); - return false; - } - - if (!(hRC=wglCreateContext(hDC))) { - MessageBox(NULL,"(4) Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); - return false; - } - -#elif defined(HAVE_X11) && HAVE_X11 - XVisualInfo *vi; - Colormap cmap; - int dpyWidth, dpyHeight; - int glxMajorVersion, glxMinorVersion; - int vidModeMajorVersion, vidModeMinorVersion; - Atom wmDelete; - - // attributes for a single buffered visual in RGBA format with at least - // 8 bits per color and a 24 bit depth buffer - int attrListSgl[] = {GLX_RGBA, GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_DEPTH_SIZE, 24, - None}; - - // attributes for a double buffered visual in RGBA format with at least - // 8 bits per color and a 24 bit depth buffer - int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_DEPTH_SIZE, 24, - GLX_SAMPLE_BUFFERS_ARB, g_Config.iMultisampleMode, GLX_SAMPLES_ARB, 1, None }; - GLWin.dpy = XOpenDisplay(0); - g_VideoInitialize.pWindowHandle = (HWND)GLWin.dpy; - GLWin.screen = DefaultScreen(GLWin.dpy); - - GLWin.fs = g_Config.bFullscreen; //Set to setting in Options - - /* get an appropriate visual */ - vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListDbl); - if (vi == NULL) { - vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListSgl); - GLWin.doubleBuffered = False; - ERROR_LOG("Only Singlebuffered Visual!\n"); - } - else { - GLWin.doubleBuffered = True; - ERROR_LOG("Got Doublebuffered Visual!\n"); - } - - glXQueryVersion(GLWin.dpy, &glxMajorVersion, &glxMinorVersion); - ERROR_LOG("glX-Version %d.%d\n", glxMajorVersion, glxMinorVersion); - /* create a GLX context */ - GLWin.ctx = glXCreateContext(GLWin.dpy, vi, 0, GL_TRUE); - if(!GLWin.ctx) - { - ERROR_LOG("Couldn't Create GLX context.Quit"); - exit(0); // TODO: Don't bring down entire Emu - } - /* create a color map */ - cmap = XCreateColormap(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), - vi->visual, AllocNone); - GLWin.attr.colormap = cmap; - GLWin.attr.border_pixel = 0; - - // get a connection - XF86VidModeQueryVersion(GLWin.dpy, &vidModeMajorVersion, &vidModeMinorVersion); - - if (GLWin.fs) { - - XF86VidModeModeInfo **modes = NULL; - int modeNum = 0; - int bestMode = 0; - - // set best mode to current - bestMode = 0; - ERROR_LOG("XF86VidModeExtension-Version %d.%d\n", vidModeMajorVersion, vidModeMinorVersion); - XF86VidModeGetAllModeLines(GLWin.dpy, GLWin.screen, &modeNum, &modes); - - if (modeNum > 0 && modes != NULL) { - /* save desktop-resolution before switching modes */ - GLWin.deskMode = *modes[0]; - /* look for mode with requested resolution */ - for (int i = 0; i < modeNum; i++) { - if ((modes[i]->hdisplay == _twidth) && (modes[i]->vdisplay == _theight)) { - bestMode = i; - } - } - - XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, modes[bestMode]); - XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0); - dpyWidth = modes[bestMode]->hdisplay; - dpyHeight = modes[bestMode]->vdisplay; - ERROR_LOG("Resolution %dx%d\n", dpyWidth, dpyHeight); - XFree(modes); - - /* create a fullscreen window */ - GLWin.attr.override_redirect = True; - GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | KeyReleaseMask | ButtonReleaseMask | StructureNotifyMask; - GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), - 0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual, - CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, - &GLWin.attr); - XWarpPointer(GLWin.dpy, None, GLWin.win, 0, 0, 0, 0, 0, 0); - XMapRaised(GLWin.dpy, GLWin.win); - XGrabKeyboard(GLWin.dpy, GLWin.win, True, GrabModeAsync, GrabModeAsync, CurrentTime); - XGrabPointer(GLWin.dpy, GLWin.win, True, ButtonPressMask, - GrabModeAsync, GrabModeAsync, GLWin.win, None, CurrentTime); - } - else { - ERROR_LOG("Failed to start fullscreen. If you received the \n" - "\"XFree86-VidModeExtension\" extension is missing, add\n" - "Load \"extmod\"\n" - "to your X configuration file (under the Module Section)\n"); - GLWin.fs = 0; - } - } - - - if (!GLWin.fs) { - - //XRootWindow(dpy,screen) - //int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2; - //int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2; - - // create a window in window mode - GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | KeyReleaseMask | ButtonReleaseMask | - StructureNotifyMask | ResizeRedirectMask; - GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), - 0, 0, _twidth, _theight, 0, vi->depth, InputOutput, vi->visual, - CWBorderPixel | CWColormap | CWEventMask, &GLWin.attr); - // only set window title and handle wm_delete_events if in windowed mode - wmDelete = XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", True); - XSetWMProtocols(GLWin.dpy, GLWin.win, &wmDelete, 1); - XSetStandardProperties(GLWin.dpy, GLWin.win, "GPU", - "GPU", None, NULL, 0, NULL); - XMapRaised(GLWin.dpy, GLWin.win); - } -#endif - return true; -} - -bool OpenGL_MakeCurrent() -{ -#if USE_SDL - // Note: The reason for having the call to SDL_SetVideoMode in here instead - // of in OpenGL_Create() is that "make current" is part of the video - // mode setting and is not available as a separate call in SDL. We - // have to do "make current" here because this method runs in the CPU - // thread while OpenGL_Create() runs in a diferent thread and "make - // current" has to be done in the same thread that will be making - // calls to OpenGL. - - // Fetch video info. - const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo(); - if (!videoInfo) { - // TODO: Display an error message. - SDL_Quit(); - return false; - } - // Compute video mode flags. - const int videoFlags = SDL_OPENGL - | ( videoInfo->hw_available ? SDL_HWSURFACE : SDL_SWSURFACE ) - | ( g_Config.bFullscreen ? SDL_FULLSCREEN : 0); - // Set vide mode. - // TODO: Can we use this field or is a separate field needed? - int _twidth = nBackbufferWidth; - int _theight = nBackbufferHeight; - SDL_Surface *screen = SDL_SetVideoMode(_twidth, _theight, 0, videoFlags); - if (!screen) { - //TODO : Display an error message - SDL_Quit(); - return false; - } -#elif defined(OSX64) - cocoaGLMakeCurrent(GLWin.cocoaCtx,GLWin.cocoaWin); -#elif defined(_WIN32) - if (!wglMakeCurrent(hDC,hRC)) { - MessageBox(NULL,"(5) Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); - return false; - } -#else // GLX - Window winDummy; - unsigned int borderDummy; - // connect the glx-context to the window - glXMakeCurrent(GLWin.dpy, GLWin.win, GLWin.ctx); - XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y, - &GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth); - ERROR_LOG("GLWin Depth %d", GLWin.depth); - if (glXIsDirect(GLWin.dpy, GLWin.ctx)) - ERROR_LOG("you have Direct Rendering!"); - else - ERROR_LOG("no Direct Rendering possible!"); - - // better for pad plugin key input (thc) - XSelectInput(GLWin.dpy, GLWin.win, ExposureMask | KeyPressMask | ButtonPressMask | KeyReleaseMask | ButtonReleaseMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask | - FocusChangeMask ); -#endif - return true; -} - - -// ======================================================================================= -// Update window width, size and etc. Called from Render.cpp -// ---------------- -void OpenGL_Update() -{ -#if USE_SDL - SDL_Surface *surface = SDL_GetVideoSurface(); - if (!surface) return; - nBackbufferWidth = surface->w; - nBackbufferHeight = surface->h; -#elif defined(OSX64) - RECT rcWindow; - rcWindow.right = GLWin.width; - rcWindow.bottom = GLWin.height; - -#elif defined(_WIN32) - RECT rcWindow; - if (!EmuWindow::GetParentWnd()) { - if (!g_Config.bStretchToFit) - return; - GetWindowRect(EmuWindow::GetWnd(), &rcWindow); - rcWindow.top += 25; - } - else - { - GetWindowRect(EmuWindow::GetParentWnd(), &rcWindow); - } - - // --------------------------------------------------------------------------------------- - // Get the new window width and height - // ------------------ - // See below for documentation - // ------------------ - int width = rcWindow.right - rcWindow.left; - int height = rcWindow.bottom - rcWindow.top; - - if (EmuWindow::GetParentWnd() != 0) - ::MoveWindow(EmuWindow::GetWnd(), 0,0,width,height, FALSE); - - nBackbufferWidth = width; - nBackbufferHeight = height; - -#else // GLX - // We just check all of our events here - XEvent event; - KeySym key; - static RECT rcWindow; - static bool ShiftPressed = false; - static bool ControlPressed = false; - static int FKeyPressed = -1; - int num_events; - for (num_events = XPending(GLWin.dpy);num_events > 0;num_events--) { - XNextEvent(GLWin.dpy, &event); - switch(event.type) { - case KeyRelease: - key = XLookupKeysym((XKeyEvent*)&event, 0); - if(key >= XK_F1 && key <= XK_F9) { - g_VideoInitialize.pKeyPress(FKeyPressed, ShiftPressed, ControlPressed); - FKeyPressed = -1; - } else { - if(key == XK_Shift_L || key == XK_Shift_R) - ShiftPressed = false; - else if(key == XK_Control_L || key == XK_Control_R) - ControlPressed = false; - else - XPutBackEvent(GLWin.dpy, &event); - } - break; - case KeyPress: - key = XLookupKeysym((XKeyEvent*)&event, 0); - if(key >= XK_F1 && key <= XK_F9) - FKeyPressed = key - 0xff4e; - else { - if(key == XK_Shift_L || key == XK_Shift_R) - ShiftPressed = true; - else if(key == XK_Control_L || key == XK_Control_R) - ControlPressed = true; - else - XPutBackEvent(GLWin.dpy, &event); - } - break; - case ButtonPress: - case ButtonRelease: - XPutBackEvent(GLWin.dpy, &event); - break; - case ConfigureNotify: - Window winDummy; - unsigned int borderDummy; - XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y, - &GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth); - nBackbufferWidth = GLWin.width; - nBackbufferHeight = GLWin.height; - rcWindow.left = 0; - rcWindow.top = 0; - rcWindow.right = GLWin.width; - rcWindow.bottom = GLWin.height; - break; - case ClientMessage: //TODO: We aren't reading this correctly, It could be anything, highest chance is that it's a close event though - Video_Shutdown(); // Calling from here since returning false does nothing - return; - break; - default: - //TODO: Should we put the event back if we don't handle it? - // I think we handle all the needed ones, the rest shouldn't matter - // But to be safe, let's but them back anyway - //XPutBackEvent(GLWin.dpy, &event); - break; - } - } - return; -#endif - - // --------------------------------------------------------------------------------------- - // Get the new window width and height - // ------------------ - // nBackbufferWidth and nBackbufferHeight = now the actual screen size - // Max = the highest of w and h - // MValueX and MValueY = used for the picture resolution-change rescaling - // nXoff and nYoff = controls the picture's position inside the Dolphin window - // ------------------ - /* MValueX and MValueY will be used in - TextureMngr and VertexShaderManager: Rescale textures on resolution changes - BPStructs.cpp: Control glScissor() - */ - // ------------------ - float FactorW = 640.0f / (float)nBackbufferWidth; - float FactorH = 480.0f / (float)nBackbufferHeight; - float Max = (FactorW < FactorH) ? FactorH : FactorW; - AR = (float)nBackbufferWidth / (float)nBackbufferHeight; - - if (g_Config.bStretchToFit) - { - MValueX = 1; - MValueY = 1; - nXoff = 0; - nYoff = 0; - } - else - { - MValueX = 1.0f / Max; - MValueY = 1.0f / Max; - nXoff = (int)((nBackbufferWidth - (640 * MValueX)) / 2); - nYoff = (int)((nBackbufferHeight - (480 * MValueY)) / 2); - } - - // tell the debugger - gleft = rcWindow.left; gright = rcWindow.right; - gtop = rcWindow.top; gbottom = rcWindow.bottom; -} - - - -// ======================================================================================= -// Close plugin -// ---------------- -void OpenGL_Shutdown() -{ -#if USE_SDL - SDL_Quit(); -#elif defined(OSX64) - cocoaGLDelete(GLWin.cocoaCtx); -#elif defined(_WIN32) - if (hRC) // Do We Have A Rendering Context? - { - if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts? - { - // [F|RES]: if this fails i dont see the message box and - // cant get out of the modal state so i disable it. - // This function fails only if i render to main window - // MessageBox(NULL,"Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); - } - - if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC? - { - MessageBox(NULL,"Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); - } - hRC = NULL; // Set RC To NULL - } - - if (hDC && !ReleaseDC(EmuWindow::GetWnd(),hDC)) // Are We Able To Release The DC - { - MessageBox(NULL,"Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); - hDC = NULL; // Set DC To NULL - } -#elif defined(HAVE_X11) && HAVE_X11 - if (GLWin.ctx) - { - if (!glXMakeCurrent(GLWin.dpy, None, NULL)) - { - ERROR_LOG("Could not release drawing context.\n"); - } - XUnmapWindow(GLWin.dpy, GLWin.win); - glXDestroyContext(GLWin.dpy, GLWin.ctx); - XCloseDisplay(GLWin.dpy); - GLWin.ctx = NULL; - } - /* switch back to original desktop resolution if we were in fs */ - if (GLWin.dpy != NULL) { - if (GLWin.fs) { - XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, &GLWin.deskMode); - XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0); - } - } -#endif -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Globals.h" +#include "Config.h" +#include "IniFile.h" +#include "svnrev.h" + +#include "Render.h" + +#if defined(_WIN32) +#include "OS/Win32.h" +#else +struct RECT +{ + int left, top; + int right, bottom; +}; +#endif + +#include "GLUtil.h" + +#ifndef USE_SDL +#define USE_SDL 0 +#endif +#if USE_SDL +#include +#endif + +// Handles OpenGL and the window + +// externals +int gleft, gright, gtop, gbottom; +int nBackbufferWidth, nBackbufferHeight; // screen width +int nXoff, nYoff; // screen offset +float AR; // aspect ratio + +#ifndef _WIN32 +GLWindow GLWin; +#endif + +#if defined(_WIN32) +static HDC hDC = NULL; // Private GDI Device Context +static HGLRC hRC = NULL; // Permanent Rendering Context +extern HINSTANCE g_hInstance; +#endif + +void OpenGL_SwapBuffers() +{ +#if USE_SDL + SDL_GL_SwapBuffers(); +#elif defined(OSX64) + cocoaGLSwap(GLWin.cocoaCtx,GLWin.cocoaWin); +#elif defined(_WIN32) + SwapBuffers(hDC); +#else // GLX + glXSwapBuffers(GLWin.dpy, GLWin.win); +#endif +} + +void OpenGL_SetWindowText(const char *text) +{ +#if USE_SDL + SDL_WM_SetCaption(text, NULL); +#elif defined(OSX64) + cocoaGLSetTitle(); +#elif defined(_WIN32) + SetWindowText(EmuWindow::GetWnd(), text); +#elif defined(HAVE_X11) && HAVE_X11 // GLX + /** + * Tell X to ask the window manager to set the window title. (X + * itself doesn't provide window title functionality.) + */ + XStoreName(GLWin.dpy, GLWin.win, text); +#endif +} + +#if defined(OSX64) +unsigned int Callback_PeekMessages() +#else +BOOL Callback_PeekMessages() +#endif +{ +#ifdef _WIN32 + //TODO: peekmessage + MSG msg; + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + if (msg.message == WM_QUIT) + return FALSE; + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return TRUE; +#else + return FALSE; +#endif +} + +void UpdateFPSDisplay(const char *text) +{ + char temp[512]; + sprintf(temp, "SVN R%s: GL: %s", SVN_REV_STR, text); +#if defined(_WIN32) + SetWindowText(EmuWindow::GetWnd(), temp); +#endif + OpenGL_SetWindowText(temp); + +} + +// ======================================================================================= +// Create window. Called from main.cpp +bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight) +{ + int _twidth, _theight; + if(g_Config.bFullscreen) + { + if(strlen(g_Config.iFSResolution) > 1) + { + sscanf(g_Config.iFSResolution, "%dx%d", &_twidth, &_theight); + } + else // No full screen reso set, fall back to default reso + { + _twidth = _iwidth; + _theight = _iheight; + } + } + else // Going Windowed + { + if(strlen(g_Config.iWindowedRes) > 1) + { + sscanf(g_Config.iWindowedRes, "%dx%d", &_twidth, &_theight); + } + else // No Window reso set, fall back to default + { + _twidth = _iwidth; + _theight = _iheight; + } + } +#if defined(_WIN32) + EmuWindow::SetSize(_twidth, _theight); +#endif + + // --------------------------------------------------------------------------------------- + // Control window size and picture scaling + // ------------------ + // nBackbufferWidth and nBackbufferHeight = Screen resolution from ini, or 640x480 + // See OpenGL_Update() for documentation of the other variables + // ------------------ + nBackbufferWidth = _twidth; + nBackbufferHeight = _theight; + + float FactorW = 640.0f / (float)nBackbufferWidth; + float FactorH = 480.0f / (float)nBackbufferHeight; + float Max = (FactorW < FactorH) ? FactorH : FactorW; + + if(g_Config.bStretchToFit) + { + MValueX = 1.0f / FactorW; + MValueY = 1.0f / FactorH; + nXoff = 0; + nYoff = 0; + } + else + { + MValueX = 1.0f / Max; + MValueY = 1.0f / Max; + nXoff = (int)((nBackbufferWidth - (640 * MValueX)) / 2); + nYoff = (int)((nBackbufferHeight - (480 * MValueY)) / 2); + } + + g_VideoInitialize.pPeekMessages = &Callback_PeekMessages; + g_VideoInitialize.pUpdateFPSDisplay = &UpdateFPSDisplay; + + //char buff[100]; + //sprintf(buff, "%i %i %d %d %d", nBackbufferWidth, nBackbufferHeight, Max, MValueX, MValueY); + //MessageBox(0, buff, "", 0); + +#if USE_SDL + //init sdl video + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + //TODO : Display an error message + SDL_Quit(); + return false; + } + + //setup ogl to use double buffering + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); +#elif defined(OSX64) + cocoaGLCreateApp(); + GLWin.width = nBackbufferWidth; + GLWin.height = nBackbufferHeight; + GLWin.cocoaWin = cocoaGLCreateWindow(GLWin.width, GLWin.height); + GLWin.cocoaCtx = cocoaGLInit(g_Config.iMultisampleMode); +#elif defined(_WIN32) + // create the window + if (!g_Config.renderToMainframe || g_VideoInitialize.pWindowHandle == NULL) + { + g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create(NULL, g_hInstance, "Please wait..."); + } + else + { + g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create((HWND)g_VideoInitialize.pWindowHandle, g_hInstance, "Please wait..."); + } + EmuWindow::Show(); + + if (g_VideoInitialize.pWindowHandle == NULL) + { + g_VideoInitialize.pSysMessage("failed to create window"); + return false; + } + + GLuint PixelFormat; // Holds The Results After Searching For A Match + DWORD dwExStyle; // Window Extended Style + DWORD dwStyle; // Window Style + + RECT rcdesktop; + GetWindowRect(GetDesktopWindow(), &rcdesktop); + + if (g_Config.bFullscreen) { + //nBackbufferWidth = rcdesktop.right - rcdesktop.left; + //nBackbufferHeight = rcdesktop.bottom - rcdesktop.top; + + DEVMODE dmScreenSettings; + memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); + dmScreenSettings.dmSize=sizeof(dmScreenSettings); + dmScreenSettings.dmPelsWidth = nBackbufferWidth; + dmScreenSettings.dmPelsHeight = nBackbufferHeight; + dmScreenSettings.dmBitsPerPel = 32; + dmScreenSettings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; + + // Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. + if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) + { + if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) + g_Config.bFullscreen = false; + else + return false; + } + } + else + { + // change to default resolution + ChangeDisplaySettings(NULL, 0); + } + + if (g_Config.bFullscreen && !g_Config.renderToMainframe) + { + ShowCursor(FALSE); + } + else + { + dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + dwStyle = WS_OVERLAPPEDWINDOW; + } + + RECT rc; + rc.left = 0; rc.top = 0; + rc.right = nBackbufferWidth; rc.bottom = nBackbufferHeight; + AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle); + int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2; + int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2; + + SetWindowPos(EmuWindow::GetWnd(), NULL, X, Y, rc.right-rc.left, rc.bottom-rc.top, SWP_NOREPOSITION|SWP_NOZORDER); + + PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be + { + sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor + 1, // Version Number + PFD_DRAW_TO_WINDOW | // Format Must Support Window + PFD_SUPPORT_OPENGL | // Format Must Support OpenGL + PFD_DOUBLEBUFFER, // Must Support Double Buffering + PFD_TYPE_RGBA, // Request An RGBA Format + 32, // Select Our Color Depth + 0, 0, 0, 0, 0, 0, // Color Bits Ignored + 0, // 8bit Alpha Buffer + 0, // Shift Bit Ignored + 0, // No Accumulation Buffer + 0, 0, 0, 0, // Accumulation Bits Ignored + 24, // 24Bit Z-Buffer (Depth Buffer) + 8, // 8bit Stencil Buffer + 0, // No Auxiliary Buffer + PFD_MAIN_PLANE, // Main Drawing Layer + 0, // Reserved + 0, 0, 0 // Layer Masks Ignored + }; + + if (!(hDC=GetDC(EmuWindow::GetWnd()))) { + MessageBox(NULL,"(1) Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return false; + } + + if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) { + MessageBox(NULL,"(2) Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return false; + } + + if (!SetPixelFormat(hDC,PixelFormat,&pfd)) { + MessageBox(NULL,"(3) Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return false; + } + + if (!(hRC=wglCreateContext(hDC))) { + MessageBox(NULL,"(4) Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return false; + } + +#elif defined(HAVE_X11) && HAVE_X11 + XVisualInfo *vi; + Colormap cmap; + int dpyWidth, dpyHeight; + int glxMajorVersion, glxMinorVersion; + int vidModeMajorVersion, vidModeMinorVersion; + Atom wmDelete; + + // attributes for a single buffered visual in RGBA format with at least + // 8 bits per color and a 24 bit depth buffer + int attrListSgl[] = {GLX_RGBA, GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_DEPTH_SIZE, 24, + None}; + + // attributes for a double buffered visual in RGBA format with at least + // 8 bits per color and a 24 bit depth buffer + int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_DEPTH_SIZE, 24, + GLX_SAMPLE_BUFFERS_ARB, g_Config.iMultisampleMode, GLX_SAMPLES_ARB, 1, None }; + GLWin.dpy = XOpenDisplay(0); + g_VideoInitialize.pWindowHandle = (HWND)GLWin.dpy; + GLWin.screen = DefaultScreen(GLWin.dpy); + + GLWin.fs = g_Config.bFullscreen; //Set to setting in Options + + /* get an appropriate visual */ + vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListDbl); + if (vi == NULL) { + vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListSgl); + GLWin.doubleBuffered = False; + ERROR_LOG("Only Singlebuffered Visual!\n"); + } + else { + GLWin.doubleBuffered = True; + ERROR_LOG("Got Doublebuffered Visual!\n"); + } + + glXQueryVersion(GLWin.dpy, &glxMajorVersion, &glxMinorVersion); + ERROR_LOG("glX-Version %d.%d\n", glxMajorVersion, glxMinorVersion); + /* create a GLX context */ + GLWin.ctx = glXCreateContext(GLWin.dpy, vi, 0, GL_TRUE); + if(!GLWin.ctx) + { + ERROR_LOG("Couldn't Create GLX context.Quit"); + exit(0); // TODO: Don't bring down entire Emu + } + /* create a color map */ + cmap = XCreateColormap(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), + vi->visual, AllocNone); + GLWin.attr.colormap = cmap; + GLWin.attr.border_pixel = 0; + + // get a connection + XF86VidModeQueryVersion(GLWin.dpy, &vidModeMajorVersion, &vidModeMinorVersion); + + if (GLWin.fs) { + + XF86VidModeModeInfo **modes = NULL; + int modeNum = 0; + int bestMode = 0; + + // set best mode to current + bestMode = 0; + ERROR_LOG("XF86VidModeExtension-Version %d.%d\n", vidModeMajorVersion, vidModeMinorVersion); + XF86VidModeGetAllModeLines(GLWin.dpy, GLWin.screen, &modeNum, &modes); + + if (modeNum > 0 && modes != NULL) { + /* save desktop-resolution before switching modes */ + GLWin.deskMode = *modes[0]; + /* look for mode with requested resolution */ + for (int i = 0; i < modeNum; i++) { + if ((modes[i]->hdisplay == _twidth) && (modes[i]->vdisplay == _theight)) { + bestMode = i; + } + } + + XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, modes[bestMode]); + XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0); + dpyWidth = modes[bestMode]->hdisplay; + dpyHeight = modes[bestMode]->vdisplay; + ERROR_LOG("Resolution %dx%d\n", dpyWidth, dpyHeight); + XFree(modes); + + /* create a fullscreen window */ + GLWin.attr.override_redirect = True; + GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | KeyReleaseMask | ButtonReleaseMask | StructureNotifyMask; + GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), + 0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, + &GLWin.attr); + XWarpPointer(GLWin.dpy, None, GLWin.win, 0, 0, 0, 0, 0, 0); + XMapRaised(GLWin.dpy, GLWin.win); + XGrabKeyboard(GLWin.dpy, GLWin.win, True, GrabModeAsync, GrabModeAsync, CurrentTime); + XGrabPointer(GLWin.dpy, GLWin.win, True, ButtonPressMask, + GrabModeAsync, GrabModeAsync, GLWin.win, None, CurrentTime); + } + else { + ERROR_LOG("Failed to start fullscreen. If you received the \n" + "\"XFree86-VidModeExtension\" extension is missing, add\n" + "Load \"extmod\"\n" + "to your X configuration file (under the Module Section)\n"); + GLWin.fs = 0; + } + } + + + if (!GLWin.fs) { + + //XRootWindow(dpy,screen) + //int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2; + //int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2; + + // create a window in window mode + GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | KeyReleaseMask | ButtonReleaseMask | + StructureNotifyMask | ResizeRedirectMask; + GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), + 0, 0, _twidth, _theight, 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel | CWColormap | CWEventMask, &GLWin.attr); + // only set window title and handle wm_delete_events if in windowed mode + wmDelete = XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", True); + XSetWMProtocols(GLWin.dpy, GLWin.win, &wmDelete, 1); + XSetStandardProperties(GLWin.dpy, GLWin.win, "GPU", + "GPU", None, NULL, 0, NULL); + XMapRaised(GLWin.dpy, GLWin.win); + } +#endif + return true; +} + +bool OpenGL_MakeCurrent() +{ +#if USE_SDL + // Note: The reason for having the call to SDL_SetVideoMode in here instead + // of in OpenGL_Create() is that "make current" is part of the video + // mode setting and is not available as a separate call in SDL. We + // have to do "make current" here because this method runs in the CPU + // thread while OpenGL_Create() runs in a diferent thread and "make + // current" has to be done in the same thread that will be making + // calls to OpenGL. + + // Fetch video info. + const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo(); + if (!videoInfo) { + // TODO: Display an error message. + SDL_Quit(); + return false; + } + // Compute video mode flags. + const int videoFlags = SDL_OPENGL + | ( videoInfo->hw_available ? SDL_HWSURFACE : SDL_SWSURFACE ) + | ( g_Config.bFullscreen ? SDL_FULLSCREEN : 0); + // Set vide mode. + // TODO: Can we use this field or is a separate field needed? + int _twidth = nBackbufferWidth; + int _theight = nBackbufferHeight; + SDL_Surface *screen = SDL_SetVideoMode(_twidth, _theight, 0, videoFlags); + if (!screen) { + //TODO : Display an error message + SDL_Quit(); + return false; + } +#elif defined(OSX64) + cocoaGLMakeCurrent(GLWin.cocoaCtx,GLWin.cocoaWin); +#elif defined(_WIN32) + if (!wglMakeCurrent(hDC,hRC)) { + MessageBox(NULL,"(5) Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return false; + } +#else // GLX + Window winDummy; + unsigned int borderDummy; + // connect the glx-context to the window + glXMakeCurrent(GLWin.dpy, GLWin.win, GLWin.ctx); + XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y, + &GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth); + ERROR_LOG("GLWin Depth %d", GLWin.depth); + if (glXIsDirect(GLWin.dpy, GLWin.ctx)) + ERROR_LOG("you have Direct Rendering!"); + else + ERROR_LOG("no Direct Rendering possible!"); + + // better for pad plugin key input (thc) + XSelectInput(GLWin.dpy, GLWin.win, ExposureMask | KeyPressMask | ButtonPressMask | KeyReleaseMask | ButtonReleaseMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask | + FocusChangeMask ); +#endif + return true; +} + + +// ======================================================================================= +// Update window width, size and etc. Called from Render.cpp +// ---------------- +void OpenGL_Update() +{ +#if USE_SDL + SDL_Surface *surface = SDL_GetVideoSurface(); + if (!surface) return; + nBackbufferWidth = surface->w; + nBackbufferHeight = surface->h; +#elif defined(OSX64) + RECT rcWindow; + rcWindow.right = GLWin.width; + rcWindow.bottom = GLWin.height; + +#elif defined(_WIN32) + RECT rcWindow; + if (!EmuWindow::GetParentWnd()) { + if (!g_Config.bStretchToFit) + return; + GetWindowRect(EmuWindow::GetWnd(), &rcWindow); + rcWindow.top += 25; + } + else + { + GetWindowRect(EmuWindow::GetParentWnd(), &rcWindow); + } + + // --------------------------------------------------------------------------------------- + // Get the new window width and height + // ------------------ + // See below for documentation + // ------------------ + int width = rcWindow.right - rcWindow.left; + int height = rcWindow.bottom - rcWindow.top; + + if (EmuWindow::GetParentWnd() != 0) + ::MoveWindow(EmuWindow::GetWnd(), 0,0,width,height, FALSE); + + nBackbufferWidth = width; + nBackbufferHeight = height; + +#else // GLX + // We just check all of our events here + XEvent event; + KeySym key; + static RECT rcWindow; + static bool ShiftPressed = false; + static bool ControlPressed = false; + static int FKeyPressed = -1; + int num_events; + for (num_events = XPending(GLWin.dpy);num_events > 0;num_events--) { + XNextEvent(GLWin.dpy, &event); + switch(event.type) { + case KeyRelease: + key = XLookupKeysym((XKeyEvent*)&event, 0); + if(key >= XK_F1 && key <= XK_F9) { + g_VideoInitialize.pKeyPress(FKeyPressed, ShiftPressed, ControlPressed); + FKeyPressed = -1; + } else { + if(key == XK_Shift_L || key == XK_Shift_R) + ShiftPressed = false; + else if(key == XK_Control_L || key == XK_Control_R) + ControlPressed = false; + else + XPutBackEvent(GLWin.dpy, &event); + } + break; + case KeyPress: + key = XLookupKeysym((XKeyEvent*)&event, 0); + if(key >= XK_F1 && key <= XK_F9) + FKeyPressed = key - 0xff4e; + else { + if(key == XK_Shift_L || key == XK_Shift_R) + ShiftPressed = true; + else if(key == XK_Control_L || key == XK_Control_R) + ControlPressed = true; + else + XPutBackEvent(GLWin.dpy, &event); + } + break; + case ButtonPress: + case ButtonRelease: + XPutBackEvent(GLWin.dpy, &event); + break; + case ConfigureNotify: + Window winDummy; + unsigned int borderDummy; + XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y, + &GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth); + nBackbufferWidth = GLWin.width; + nBackbufferHeight = GLWin.height; + rcWindow.left = 0; + rcWindow.top = 0; + rcWindow.right = GLWin.width; + rcWindow.bottom = GLWin.height; + break; + case ClientMessage: //TODO: We aren't reading this correctly, It could be anything, highest chance is that it's a close event though + Video_Shutdown(); // Calling from here since returning false does nothing + return; + break; + default: + //TODO: Should we put the event back if we don't handle it? + // I think we handle all the needed ones, the rest shouldn't matter + // But to be safe, let's but them back anyway + //XPutBackEvent(GLWin.dpy, &event); + break; + } + } + return; +#endif + + // --------------------------------------------------------------------------------------- + // Get the new window width and height + // ------------------ + // nBackbufferWidth and nBackbufferHeight = now the actual screen size + // Max = the highest of w and h + // MValueX and MValueY = used for the picture resolution-change rescaling + // nXoff and nYoff = controls the picture's position inside the Dolphin window + // ------------------ + /* MValueX and MValueY will be used in + TextureMngr and VertexShaderManager: Rescale textures on resolution changes + BPStructs.cpp: Control glScissor() + */ + // ------------------ + float FactorW = 640.0f / (float)nBackbufferWidth; + float FactorH = 480.0f / (float)nBackbufferHeight; + float Max = (FactorW < FactorH) ? FactorH : FactorW; + AR = (float)nBackbufferWidth / (float)nBackbufferHeight; + + if (g_Config.bStretchToFit) + { + MValueX = 1; + MValueY = 1; + nXoff = 0; + nYoff = 0; + } + else + { + MValueX = 1.0f / Max; + MValueY = 1.0f / Max; + nXoff = (int)((nBackbufferWidth - (640 * MValueX)) / 2); + nYoff = (int)((nBackbufferHeight - (480 * MValueY)) / 2); + } + + // tell the debugger + gleft = rcWindow.left; gright = rcWindow.right; + gtop = rcWindow.top; gbottom = rcWindow.bottom; +} + + + +// ======================================================================================= +// Close plugin +// ---------------- +void OpenGL_Shutdown() +{ +#if USE_SDL + SDL_Quit(); +#elif defined(OSX64) + cocoaGLDelete(GLWin.cocoaCtx); +#elif defined(_WIN32) + if (hRC) // Do We Have A Rendering Context? + { + if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts? + { + // [F|RES]: if this fails i dont see the message box and + // cant get out of the modal state so i disable it. + // This function fails only if i render to main window + // MessageBox(NULL,"Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); + } + + if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC? + { + MessageBox(NULL,"Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); + } + hRC = NULL; // Set RC To NULL + } + + if (hDC && !ReleaseDC(EmuWindow::GetWnd(),hDC)) // Are We Able To Release The DC + { + MessageBox(NULL,"Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); + hDC = NULL; // Set DC To NULL + } +#elif defined(HAVE_X11) && HAVE_X11 + if (GLWin.ctx) + { + if (!glXMakeCurrent(GLWin.dpy, None, NULL)) + { + ERROR_LOG("Could not release drawing context.\n"); + } + XUnmapWindow(GLWin.dpy, GLWin.win); + glXDestroyContext(GLWin.dpy, GLWin.ctx); + XCloseDisplay(GLWin.dpy); + GLWin.ctx = NULL; + } + /* switch back to original desktop resolution if we were in fs */ + if (GLWin.dpy != NULL) { + if (GLWin.fs) { + XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, &GLWin.deskMode); + XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0); + } + } +#endif +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp index 58d2b8b906..ea91c19be8 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp @@ -1,414 +1,414 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -#include "ConfigDlg.h" -#include "../Globals.h" -#include "../Config.h" - -#include "../TextureMngr.h" - -BEGIN_EVENT_TABLE(ConfigDialog,wxDialog) - EVT_CLOSE(ConfigDialog::OnClose) - EVT_BUTTON(ID_CLOSE, ConfigDialog::CloseClick) - EVT_BUTTON(ID_ABOUTOGL, ConfigDialog::AboutClick) - EVT_CHECKBOX(ID_FULLSCREEN, ConfigDialog::GeneralSettingsChanged) - EVT_CHECKBOX(ID_RENDERTOMAINWINDOW, ConfigDialog::GeneralSettingsChanged) - EVT_COMBOBOX(ID_FULLSCREENCB, ConfigDialog::GeneralSettingsChanged) - EVT_COMBOBOX(ID_WINDOWRESOLUTIONCB, ConfigDialog::GeneralSettingsChanged) - EVT_COMBOBOX(ID_ALIASMODECB, ConfigDialog::GeneralSettingsChanged) - EVT_CHOICE(ID_MAXANISOTROPY, ConfigDialog::GeneralSettingsChanged) - EVT_CHECKBOX(ID_FORCEFILTERING, ConfigDialog::GeneralSettingsChanged) - EVT_CHECKBOX(ID_STRETCHTOFIT, ConfigDialog::GeneralSettingsChanged) - EVT_CHECKBOX(ID_KEEPAR, ConfigDialog::GeneralSettingsChanged) - EVT_CHECKBOX(ID_HIDECURSOR, ConfigDialog::GeneralSettingsChanged) - EVT_CHECKBOX(ID_WIREFRAME, ConfigDialog::AdvancedSettingsChanged) - EVT_CHECKBOX(ID_SHOWFPS, ConfigDialog::AdvancedSettingsChanged) - EVT_CHECKBOX(ID_STATISTICS, ConfigDialog::AdvancedSettingsChanged) - EVT_CHECKBOX(ID_SHADERERRORS, ConfigDialog::AdvancedSettingsChanged) - EVT_CHECKBOX(ID_TEXFMTOVERLAY, ConfigDialog::AdvancedSettingsChanged) - EVT_CHECKBOX(ID_TEXFMTCENTER, ConfigDialog::AdvancedSettingsChanged) - EVT_CHECKBOX(ID_USEXFB, ConfigDialog::AdvancedSettingsChanged) - EVT_CHECKBOX(ID_DUMPTEXTURES, ConfigDialog::AdvancedSettingsChanged) - EVT_CHECKBOX(ID_DISABLELIGHTING, ConfigDialog::AdvancedSettingsChanged) - EVT_CHECKBOX(ID_DISABLETEXTURING, ConfigDialog::AdvancedSettingsChanged) - EVT_CHECKBOX(ID_EFBTOTEXTUREDISABLE, ConfigDialog::AdvancedSettingsChanged) - EVT_CHECKBOX(ID_EFBTOTEXTUREDISABLEHOTKEY, ConfigDialog::AdvancedSettingsChanged) - EVT_CHECKBOX(ID_PROJECTIONHACK1,ConfigDialog::AdvancedSettingsChanged) - EVT_CHECKBOX(ID_PROJECTIONHACK2,ConfigDialog::AdvancedSettingsChanged) - EVT_CHECKBOX(ID_SAFETEXTURECACHE,ConfigDialog::AdvancedSettingsChanged) - EVT_DIRPICKER_CHANGED(ID_TEXTUREPATH, ConfigDialog::TexturePathChange) -END_EVENT_TABLE() - -ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) -: wxDialog(parent, id, title, position, size, style) -{ - g_Config.Load(); - CreateGUIControls(); -} - -ConfigDialog::~ConfigDialog() -{ -} - -void ConfigDialog::CreateGUIControls() -{ - // Notebook - m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize); - m_PageGeneral = new wxPanel(m_Notebook, ID_PAGEGENERAL, wxDefaultPosition, wxDefaultSize); - m_Notebook->AddPage(m_PageGeneral, wxT("General")); - m_PageAdvanced = new wxPanel(m_Notebook, ID_PAGEADVANCED, wxDefaultPosition, wxDefaultSize); - m_Notebook->AddPage(m_PageAdvanced, wxT("Advanced")); - - // Buttons - m_About = new wxButton(this, ID_ABOUTOGL, wxT("About"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_Close = new wxButton(this, ID_CLOSE, wxT("Close"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - - // Put notebook and buttons in sizers - wxBoxSizer* sButtons; - sButtons = new wxBoxSizer(wxHORIZONTAL); - sButtons->Add(m_About, 0, wxALL, 5); - sButtons->AddStretchSpacer(); - sButtons->Add(m_Close, 0, wxALL, 5); - - wxBoxSizer* sMain; - sMain = new wxBoxSizer(wxVERTICAL); - sMain->Add(m_Notebook, 1, wxEXPAND|wxALL, 5); - sMain->Add(sButtons, 0, wxEXPAND, 5); - - this->SetSizer(sMain); - this->Layout(); - - // General - sbBasic = new wxStaticBoxSizer(wxVERTICAL, m_PageGeneral, wxT("Basic Settings")); - m_Fullscreen = new wxCheckBox(m_PageGeneral, ID_FULLSCREEN, wxT("Fullscreen"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_Fullscreen->SetValue(g_Config.bFullscreen); - m_RenderToMainWindow = new wxCheckBox(m_PageGeneral, ID_RENDERTOMAINWINDOW, wxT("Render to main window"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_RenderToMainWindow->SetValue(g_Config.renderToMainframe); - m_StretchToFit = new wxCheckBox(m_PageGeneral, ID_STRETCHTOFIT, wxT("Stretch to fit"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_StretchToFit->SetToolTip - (wxT("This will use the game's native resolution and stretch it to fill the" - "\nwindow instead of changing the internal display resolution. It" - "\nmay result in a slightly blurrier image, but it may also give a higher" - "\nFPS if you have a slow graphics card.")); - m_StretchToFit->SetValue(g_Config.bStretchToFit); - m_KeepAR = new wxCheckBox(m_PageGeneral, ID_KEEPAR, wxT("Keep 4:3 aspect ratio"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_KeepAR->SetValue(g_Config.bKeepAR); - m_HideCursor = new wxCheckBox(m_PageGeneral, ID_HIDECURSOR, wxT("Hide mouse cursor"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_HideCursor->SetValue(g_Config.bHideCursor); - wxStaticText *FSText = new wxStaticText(m_PageGeneral, ID_FSTEXT, wxT("Fullscreen video mode:"), wxDefaultPosition, wxDefaultSize, 0); - m_FullscreenCB = new wxComboBox(m_PageGeneral, ID_FULLSCREENCB, wxEmptyString, wxDefaultPosition, wxDefaultSize, arrayStringFor_FullscreenCB, 0, wxDefaultValidator); - m_FullscreenCB->SetValue(wxString::FromAscii(g_Config.iFSResolution)); - wxStaticText *WMText = new wxStaticText(m_PageGeneral, ID_WMTEXT, wxT("Windowed resolution:"), wxDefaultPosition, wxDefaultSize, 0); - m_WindowResolutionCB = new wxComboBox(m_PageGeneral, ID_WINDOWRESOLUTIONCB, wxEmptyString, wxDefaultPosition, wxDefaultSize, arrayStringFor_WindowResolutionCB, 0, wxDefaultValidator); - m_WindowResolutionCB->SetValue(wxString::FromAscii(g_Config.iWindowedRes)); - - // Enhancements - sbEnhancements = new wxStaticBoxSizer(wxVERTICAL, m_PageGeneral, wxT("Enhancements")); - m_ForceFiltering = new wxCheckBox(m_PageGeneral, ID_FORCEFILTERING, wxT("Force bi/trilinear filtering (May cause small glitches)"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_ForceFiltering->SetValue(g_Config.bForceFiltering); - wxStaticText *AnisoText = new wxStaticText(m_PageGeneral, ID_WMTEXT, wxT("Anisotropic filter:"), wxDefaultPosition, wxDefaultSize, 0); - m_MaxAnisotropyCB = new wxChoice(m_PageGeneral, ID_MAXANISOTROPY, wxDefaultPosition, wxDefaultSize, arrayStringFor_MaxAnisotropyCB, 0, wxDefaultValidator); - m_MaxAnisotropyCB->Append(wxT("1x")); - m_MaxAnisotropyCB->Append(wxT("2x")); - m_MaxAnisotropyCB->Append(wxT("4x")); - m_MaxAnisotropyCB->Append(wxT("8x")); - m_MaxAnisotropyCB->Append(wxT("16x")); - m_MaxAnisotropyCB->SetSelection(g_Config.iMaxAnisotropy - 1); - - wxStaticText *AAText = new wxStaticText(m_PageGeneral, ID_AATEXT, wxT("Anti-alias mode:"), wxDefaultPosition, wxDefaultSize, 0); - wxArrayString arrayStringFor_AliasModeCB; - m_AliasModeCB = new wxComboBox(m_PageGeneral, ID_ALIASMODECB, wxEmptyString, wxDefaultPosition, wxDefaultSize, arrayStringFor_AliasModeCB, 0, wxDefaultValidator); - wxString tmp; - tmp << g_Config.iMultisampleMode; - m_AliasModeCB->SetValue(tmp); - - // Usage: The wxGBPosition() must have a column and row - sGeneral = new wxBoxSizer(wxVERTICAL); - sBasic = new wxGridBagSizer(0, 0); - sBasic->Add(m_Fullscreen, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL, 5); - sBasic->Add(m_RenderToMainWindow, wxGBPosition(1, 0), wxGBSpan(1, 2), wxALL, 5); - sBasic->Add(m_StretchToFit, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL, 5); - sBasic->Add(m_KeepAR, wxGBPosition(3, 0), wxGBSpan(1, 2), wxALL, 5); - sBasic->Add(m_HideCursor, wxGBPosition(4, 0), wxGBSpan(1, 2), wxALL, 5); - sBasic->Add(FSText, wxGBPosition(5, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); - sBasic->Add(m_FullscreenCB, wxGBPosition(5, 1), wxGBSpan(1, 1), wxALL, 5); - sBasic->Add(WMText, wxGBPosition(6, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); - sBasic->Add(m_WindowResolutionCB, wxGBPosition(6, 1), wxGBSpan(1, 1), wxALL, 5); - sbBasic->Add(sBasic); - sGeneral->Add(sbBasic, 0, wxEXPAND|wxALL, 5); - - sEnhancements = new wxGridBagSizer(0, 0); - sEnhancements->Add(m_ForceFiltering, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL, 5); - sEnhancements->Add(AnisoText, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); - sEnhancements->Add(m_MaxAnisotropyCB, wxGBPosition(1, 1), wxGBSpan(1, 2), wxALL, 5); - sEnhancements->Add(AAText, wxGBPosition(2, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); - sEnhancements->Add(m_AliasModeCB, wxGBPosition(2, 1), wxGBSpan(1, 2), wxALL, 5); - sbEnhancements->Add(sEnhancements); - sGeneral->Add(sbEnhancements, 0, wxEXPAND|wxALL, 5); - m_PageGeneral->SetSizer(sGeneral); - sGeneral->Layout(); - - // Information - sbInfo = new wxStaticBoxSizer(wxVERTICAL, m_PageAdvanced, wxT("Info")); - m_ShowFPS = new wxCheckBox(m_PageAdvanced, ID_SHOWFPS, wxT("Overlay FPS"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_ShowFPS->SetValue(g_Config.bShowFPS); - m_Statistics = new wxCheckBox(m_PageAdvanced, ID_STATISTICS, wxT("Overlay some statistics"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_Statistics->SetValue(g_Config.bOverlayStats); - m_ShaderErrors = new wxCheckBox(m_PageAdvanced, ID_SHADERERRORS, wxT("Show shader compilation issues"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - //m_ShaderErrors->SetValue(g_Config.bShowShaderErrors); - m_ShaderErrors->Enable(false); - m_TexFmtOverlay = new wxCheckBox(m_PageAdvanced, ID_TEXFMTOVERLAY, wxT("Overlay texture format"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_TexFmtOverlay->SetValue(g_Config.bTexFmtOverlayEnable); - m_TexFmtCenter = new wxCheckBox(m_PageAdvanced, ID_TEXFMTCENTER, wxT("centered"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_TexFmtCenter->SetValue(g_Config.bTexFmtOverlayCenter); - m_TexFmtCenter->Enable(m_TexFmtOverlay->IsChecked()); - - // Render - sbRendering = new wxStaticBoxSizer(wxVERTICAL, m_PageAdvanced, wxT("Rendering")); - m_UseXFB = new wxCheckBox(m_PageAdvanced, ID_USEXFB, wxT("Use External Framebuffer (XFB)"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_UseXFB->SetValue(g_Config.bUseXFB); - m_Wireframe = new wxCheckBox(m_PageAdvanced, ID_WIREFRAME, wxT("Enable Wireframe"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_Wireframe->SetValue(g_Config.bWireFrame); - m_Wireframe->Enable(true); - m_DisableLighting = new wxCheckBox(m_PageAdvanced, ID_DISABLELIGHTING, wxT("Disable Material Lighting"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_DisableLighting->SetValue(g_Config.bDisableLighting); - m_DisableLighting->Enable(true); - m_DisableTexturing = new wxCheckBox(m_PageAdvanced, ID_DISABLETEXTURING, wxT("Disable Texturing"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_DisableTexturing->SetValue(g_Config.bDisableTexturing); - m_DisableTexturing->Enable(true); - - // Utility - sbUtilities = new wxStaticBoxSizer(wxVERTICAL, m_PageAdvanced, wxT("Utilities")); - m_DumpTextures = new wxCheckBox(m_PageAdvanced, ID_DUMPTEXTURES, wxT("Dump textures to:"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_DumpTextures->SetValue(g_Config.bDumpTextures); - m_TexturePath = new wxDirPickerCtrl(m_PageAdvanced, ID_TEXTUREPATH, wxEmptyString, wxT("Choose a directory to store texture dumps:"), wxDefaultPosition, wxDefaultSize, wxDIRP_USE_TEXTCTRL); - m_TexturePath->SetPath(wxString::FromAscii(g_Config.texDumpPath)); - m_TexturePath->Enable(m_DumpTextures->IsChecked()); - - // Hacks - sbHacks = new wxStaticBoxSizer(wxVERTICAL, m_PageAdvanced, wxT("Hacks")); - m_EFBToTextureDisable = new wxCheckBox(m_PageAdvanced, - ID_EFBTOTEXTUREDISABLE, wxT("Disable copy EFB to texture"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_EFBToTextureDisable->SetToolTip(wxT("Do not copy the Embedded Framebuffer (EFB)" - " to the\nTexture. This may result in a speed increase.")); - m_EFBToTextureDisable->Enable(true); - m_EFBToTextureDisable->SetValue(g_Config.bEFBToTextureDisable); - m_EFBToTextureDisableHotKey = new wxCheckBox(m_PageAdvanced, - ID_EFBTOTEXTUREDISABLEHOTKEY, wxT("with hotkey E"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_EFBToTextureDisableHotKey->SetToolTip(wxT("Use the E key to turn this option on and off")); -#ifndef _WIN32 - // JPeterson set the hot key to be Win32-specific - m_EFBToTextureDisableHotKey->Enable(false); -#endif - m_EFBToTextureDisableHotKey->SetValue(g_Config.bEFBToTextureDisableHotKey); - - m_SafeTextureCache = new wxCheckBox(m_PageAdvanced, ID_SAFETEXTURECACHE, wxT("Safe texture cache"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_SafeTextureCache->SetToolTip(wxT("This is useful to prevent Metroid Prime from crashing, but can cause problems in other games.")); - m_SafeTextureCache->Enable(true); - m_SafeTextureCache->SetValue(g_Config.bSafeTextureCache); - - m_ProjectionHax1 = new wxCheckBox(m_PageAdvanced, ID_PROJECTIONHACK1, wxT("Projection before R945"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_ProjectionHax1->SetToolTip(wxT("This may reveal otherwise invisible graphics" - " in\ngames like Mario Galaxy or Ikaruga.")); - m_ProjectionHax1->Enable(true); - m_ProjectionHax1->SetValue(g_Config.bProjectionHax1); - - m_ProjectionHax2 = new wxCheckBox(m_PageAdvanced, ID_PROJECTIONHACK2, wxT("Projection hack of R844"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_ProjectionHax2->Enable(true); - m_ProjectionHax2->SetValue(g_Config.bProjectionHax2); - - sAdvanced = new wxBoxSizer(wxVERTICAL); - sInfo = new wxGridBagSizer(0, 0); - sInfo->Add(m_ShowFPS, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL, 5); - sInfo->Add(m_ShaderErrors, wxGBPosition(1, 0), wxGBSpan(1, 2), wxALL, 5); - sInfo->Add(m_Statistics, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL, 5); - sInfo->Add(m_TexFmtOverlay, wxGBPosition(3, 0), wxGBSpan(1, 1), wxALL, 5); - sInfo->Add(m_TexFmtCenter, wxGBPosition(3, 1), wxGBSpan(1, 1), wxALL, 5); - sbInfo->Add(sInfo); - sAdvanced->Add(sbInfo, 0, wxEXPAND|wxALL, 5); - - sRendering = new wxGridBagSizer(0, 0); - sRendering->Add(m_UseXFB, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALL, 5); - sRendering->Add(m_Wireframe, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALL, 5); - sRendering->Add(m_DisableLighting, wxGBPosition(2, 0), wxGBSpan(1, 1), wxALL, 5); - sRendering->Add(m_DisableTexturing, wxGBPosition(3, 0), wxGBSpan(1, 1), wxALL, 5); - sbRendering->Add(sRendering); - sAdvanced->Add(sbRendering, 0, wxEXPAND|wxALL, 5); - - sUtilities = new wxGridBagSizer(0, 0); - sUtilities->Add(m_DumpTextures, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); - sUtilities->Add(m_TexturePath, wxGBPosition(0, 1), wxGBSpan(1, 1), wxALL, 5); - sbUtilities->Add(sUtilities); - sAdvanced->Add(sbUtilities, 0, wxEXPAND|wxALL, 5); - - sHacks = new wxGridBagSizer(0, 0); - sHacks->Add(m_EFBToTextureDisable, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALL, 5); - sHacks->Add(m_EFBToTextureDisableHotKey, wxGBPosition(0, 1), wxGBSpan(1, 1), wxALL, 5); - sHacks->Add(m_ProjectionHax1, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALL, 5); - sHacks->Add(m_ProjectionHax2, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL, 5); - sHacks->Add(m_SafeTextureCache, wxGBPosition(3, 0), wxGBSpan(1, 1), wxALL, 5); - sbHacks->Add(sHacks); - sAdvanced->Add(sbHacks, 0, wxEXPAND|wxALL, 5); - m_PageAdvanced->SetSizer(sAdvanced); - sAdvanced->Layout(); - - Fit(); - Center(); -} - -void ConfigDialog::OnClose(wxCloseEvent& WXUNUSED (event)) -{ - /* notice that we don't run wxEntryCleanup(); here so the dll will - still be loaded */ - g_Config.Save(); - EndModal(0); -} - -void ConfigDialog::CloseClick(wxCommandEvent& WXUNUSED (event)) -{ - Close(); -} - -void ConfigDialog::AddFSReso(char *reso) -{ - m_FullscreenCB->Append(wxString::FromAscii(reso)); -} - -void ConfigDialog::AddWindowReso(char *reso) -{ - m_WindowResolutionCB->Append(wxString::FromAscii(reso)); -} - -void ConfigDialog::AddAAMode(int mode) -{ - wxString tmp; - tmp<Append(tmp); -} - -void ConfigDialog::AboutClick(wxCommandEvent& WXUNUSED (event)) -{ - wxMessageBox(_T("Dolphin OpenGL Plugin\nBy zerofrog(@gmail.com)\n\n" - "A card supporting Vertex/Pixel Shader 2.0 or higher, framebuffer objects, " - "and multiple render targets is required in order to use this plugin."), - _T("Dolphin OGL"), wxOK, this); -} - -void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event) -{ - switch (event.GetId()) - { - case ID_FULLSCREEN: - g_Config.bFullscreen = m_Fullscreen->IsChecked(); - break; - case ID_RENDERTOMAINWINDOW: - g_Config.renderToMainframe = m_RenderToMainWindow->IsChecked(); - break; - case ID_STRETCHTOFIT: - g_Config.bStretchToFit = m_StretchToFit->IsChecked(); - break; - case ID_KEEPAR: - g_Config.bKeepAR = m_KeepAR->IsChecked(); - break; - case ID_HIDECURSOR: - g_Config.bHideCursor = m_HideCursor->IsChecked(); - break; - case ID_FULLSCREENCB: - strcpy(g_Config.iFSResolution, m_FullscreenCB->GetValue().mb_str() ); - break; - case ID_WINDOWRESOLUTIONCB: - strcpy(g_Config.iWindowedRes, m_WindowResolutionCB->GetValue().mb_str() ); - break; - case ID_FORCEFILTERING: - g_Config.bForceFiltering = m_ForceFiltering->IsChecked(); - break; - case ID_MAXANISOTROPY: - g_Config.iMaxAnisotropy = m_MaxAnisotropyCB->GetSelection() + 1; - break; - case ID_ALIASMODECB: - g_Config.iMultisampleMode = atoi(m_AliasModeCB->GetValue().mb_str()); - break; - } -} - -void ConfigDialog::AdvancedSettingsChanged(wxCommandEvent& event) -{ - switch (event.GetId()) - { - case ID_SHOWFPS: - g_Config.bShowFPS = m_ShowFPS->IsChecked(); - break; - case ID_SHADERERRORS: - g_Config.bShowShaderErrors = m_ShaderErrors->IsChecked(); - break; - case ID_STATISTICS: - g_Config.bOverlayStats = m_Statistics->IsChecked(); - break; - case ID_TEXFMTOVERLAY: - g_Config.bTexFmtOverlayEnable = m_TexFmtOverlay->IsChecked(); - m_TexFmtCenter->Enable(m_TexFmtOverlay->IsChecked()); - TextureMngr::Invalidate(); - break; - case ID_TEXFMTCENTER: - g_Config.bTexFmtOverlayCenter = m_TexFmtCenter->IsChecked(); - TextureMngr::Invalidate(); - break; - case ID_USEXFB: - g_Config.bUseXFB = m_UseXFB->IsChecked(); - break; - case ID_WIREFRAME: - g_Config.bWireFrame = m_Wireframe->IsChecked(); - break; - case ID_DISABLELIGHTING: - g_Config.bDisableLighting = m_DisableLighting->IsChecked(); - break; - case ID_DISABLETEXTURING: - g_Config.bDisableTexturing = m_DisableTexturing->IsChecked(); - break; - case ID_DUMPTEXTURES: - m_TexturePath->Enable(m_DumpTextures->IsChecked()); - g_Config.bDumpTextures = m_DumpTextures->IsChecked(); - break; - case ID_TEXTUREPATH: - break; - case ID_EFBTOTEXTUREDISABLE: - g_Config.bEFBToTextureDisable = m_EFBToTextureDisable->IsChecked(); - break; - case ID_EFBTOTEXTUREDISABLEHOTKEY: - g_Config.bEFBToTextureDisableHotKey = m_EFBToTextureDisableHotKey->IsChecked(); - break; - case ID_PROJECTIONHACK1: - g_Config.bProjectionHax1 = m_ProjectionHax1->IsChecked(); - break; - case ID_PROJECTIONHACK2: - g_Config.bProjectionHax2 = m_ProjectionHax2->IsChecked(); - break; - case ID_SAFETEXTURECACHE: - g_Config.bSafeTextureCache = m_SafeTextureCache->IsChecked(); - break; - default: - break; - } -} - -void ConfigDialog::TexturePathChange(wxFileDirPickerEvent& event) -{ - // Note: if a user inputs an incorrect path(by typing, not by choosing from - // the combobox) this event wil not be fired. - strcpy(g_Config.texDumpPath, event.GetPath().mb_str()); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#include "ConfigDlg.h" +#include "../Globals.h" +#include "../Config.h" + +#include "../TextureMngr.h" + +BEGIN_EVENT_TABLE(ConfigDialog,wxDialog) + EVT_CLOSE(ConfigDialog::OnClose) + EVT_BUTTON(ID_CLOSE, ConfigDialog::CloseClick) + EVT_BUTTON(ID_ABOUTOGL, ConfigDialog::AboutClick) + EVT_CHECKBOX(ID_FULLSCREEN, ConfigDialog::GeneralSettingsChanged) + EVT_CHECKBOX(ID_RENDERTOMAINWINDOW, ConfigDialog::GeneralSettingsChanged) + EVT_COMBOBOX(ID_FULLSCREENCB, ConfigDialog::GeneralSettingsChanged) + EVT_COMBOBOX(ID_WINDOWRESOLUTIONCB, ConfigDialog::GeneralSettingsChanged) + EVT_COMBOBOX(ID_ALIASMODECB, ConfigDialog::GeneralSettingsChanged) + EVT_CHOICE(ID_MAXANISOTROPY, ConfigDialog::GeneralSettingsChanged) + EVT_CHECKBOX(ID_FORCEFILTERING, ConfigDialog::GeneralSettingsChanged) + EVT_CHECKBOX(ID_STRETCHTOFIT, ConfigDialog::GeneralSettingsChanged) + EVT_CHECKBOX(ID_KEEPAR, ConfigDialog::GeneralSettingsChanged) + EVT_CHECKBOX(ID_HIDECURSOR, ConfigDialog::GeneralSettingsChanged) + EVT_CHECKBOX(ID_WIREFRAME, ConfigDialog::AdvancedSettingsChanged) + EVT_CHECKBOX(ID_SHOWFPS, ConfigDialog::AdvancedSettingsChanged) + EVT_CHECKBOX(ID_STATISTICS, ConfigDialog::AdvancedSettingsChanged) + EVT_CHECKBOX(ID_SHADERERRORS, ConfigDialog::AdvancedSettingsChanged) + EVT_CHECKBOX(ID_TEXFMTOVERLAY, ConfigDialog::AdvancedSettingsChanged) + EVT_CHECKBOX(ID_TEXFMTCENTER, ConfigDialog::AdvancedSettingsChanged) + EVT_CHECKBOX(ID_USEXFB, ConfigDialog::AdvancedSettingsChanged) + EVT_CHECKBOX(ID_DUMPTEXTURES, ConfigDialog::AdvancedSettingsChanged) + EVT_CHECKBOX(ID_DISABLELIGHTING, ConfigDialog::AdvancedSettingsChanged) + EVT_CHECKBOX(ID_DISABLETEXTURING, ConfigDialog::AdvancedSettingsChanged) + EVT_CHECKBOX(ID_EFBTOTEXTUREDISABLE, ConfigDialog::AdvancedSettingsChanged) + EVT_CHECKBOX(ID_EFBTOTEXTUREDISABLEHOTKEY, ConfigDialog::AdvancedSettingsChanged) + EVT_CHECKBOX(ID_PROJECTIONHACK1,ConfigDialog::AdvancedSettingsChanged) + EVT_CHECKBOX(ID_PROJECTIONHACK2,ConfigDialog::AdvancedSettingsChanged) + EVT_CHECKBOX(ID_SAFETEXTURECACHE,ConfigDialog::AdvancedSettingsChanged) + EVT_DIRPICKER_CHANGED(ID_TEXTUREPATH, ConfigDialog::TexturePathChange) +END_EVENT_TABLE() + +ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) +: wxDialog(parent, id, title, position, size, style) +{ + g_Config.Load(); + CreateGUIControls(); +} + +ConfigDialog::~ConfigDialog() +{ +} + +void ConfigDialog::CreateGUIControls() +{ + // Notebook + m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize); + m_PageGeneral = new wxPanel(m_Notebook, ID_PAGEGENERAL, wxDefaultPosition, wxDefaultSize); + m_Notebook->AddPage(m_PageGeneral, wxT("General")); + m_PageAdvanced = new wxPanel(m_Notebook, ID_PAGEADVANCED, wxDefaultPosition, wxDefaultSize); + m_Notebook->AddPage(m_PageAdvanced, wxT("Advanced")); + + // Buttons + m_About = new wxButton(this, ID_ABOUTOGL, wxT("About"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_Close = new wxButton(this, ID_CLOSE, wxT("Close"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + + // Put notebook and buttons in sizers + wxBoxSizer* sButtons; + sButtons = new wxBoxSizer(wxHORIZONTAL); + sButtons->Add(m_About, 0, wxALL, 5); + sButtons->AddStretchSpacer(); + sButtons->Add(m_Close, 0, wxALL, 5); + + wxBoxSizer* sMain; + sMain = new wxBoxSizer(wxVERTICAL); + sMain->Add(m_Notebook, 1, wxEXPAND|wxALL, 5); + sMain->Add(sButtons, 0, wxEXPAND, 5); + + this->SetSizer(sMain); + this->Layout(); + + // General + sbBasic = new wxStaticBoxSizer(wxVERTICAL, m_PageGeneral, wxT("Basic Settings")); + m_Fullscreen = new wxCheckBox(m_PageGeneral, ID_FULLSCREEN, wxT("Fullscreen"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_Fullscreen->SetValue(g_Config.bFullscreen); + m_RenderToMainWindow = new wxCheckBox(m_PageGeneral, ID_RENDERTOMAINWINDOW, wxT("Render to main window"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_RenderToMainWindow->SetValue(g_Config.renderToMainframe); + m_StretchToFit = new wxCheckBox(m_PageGeneral, ID_STRETCHTOFIT, wxT("Stretch to fit"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_StretchToFit->SetToolTip + (wxT("This will use the game's native resolution and stretch it to fill the" + "\nwindow instead of changing the internal display resolution. It" + "\nmay result in a slightly blurrier image, but it may also give a higher" + "\nFPS if you have a slow graphics card.")); + m_StretchToFit->SetValue(g_Config.bStretchToFit); + m_KeepAR = new wxCheckBox(m_PageGeneral, ID_KEEPAR, wxT("Keep 4:3 aspect ratio"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_KeepAR->SetValue(g_Config.bKeepAR); + m_HideCursor = new wxCheckBox(m_PageGeneral, ID_HIDECURSOR, wxT("Hide mouse cursor"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_HideCursor->SetValue(g_Config.bHideCursor); + wxStaticText *FSText = new wxStaticText(m_PageGeneral, ID_FSTEXT, wxT("Fullscreen video mode:"), wxDefaultPosition, wxDefaultSize, 0); + m_FullscreenCB = new wxComboBox(m_PageGeneral, ID_FULLSCREENCB, wxEmptyString, wxDefaultPosition, wxDefaultSize, arrayStringFor_FullscreenCB, 0, wxDefaultValidator); + m_FullscreenCB->SetValue(wxString::FromAscii(g_Config.iFSResolution)); + wxStaticText *WMText = new wxStaticText(m_PageGeneral, ID_WMTEXT, wxT("Windowed resolution:"), wxDefaultPosition, wxDefaultSize, 0); + m_WindowResolutionCB = new wxComboBox(m_PageGeneral, ID_WINDOWRESOLUTIONCB, wxEmptyString, wxDefaultPosition, wxDefaultSize, arrayStringFor_WindowResolutionCB, 0, wxDefaultValidator); + m_WindowResolutionCB->SetValue(wxString::FromAscii(g_Config.iWindowedRes)); + + // Enhancements + sbEnhancements = new wxStaticBoxSizer(wxVERTICAL, m_PageGeneral, wxT("Enhancements")); + m_ForceFiltering = new wxCheckBox(m_PageGeneral, ID_FORCEFILTERING, wxT("Force bi/trilinear filtering (May cause small glitches)"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_ForceFiltering->SetValue(g_Config.bForceFiltering); + wxStaticText *AnisoText = new wxStaticText(m_PageGeneral, ID_WMTEXT, wxT("Anisotropic filter:"), wxDefaultPosition, wxDefaultSize, 0); + m_MaxAnisotropyCB = new wxChoice(m_PageGeneral, ID_MAXANISOTROPY, wxDefaultPosition, wxDefaultSize, arrayStringFor_MaxAnisotropyCB, 0, wxDefaultValidator); + m_MaxAnisotropyCB->Append(wxT("1x")); + m_MaxAnisotropyCB->Append(wxT("2x")); + m_MaxAnisotropyCB->Append(wxT("4x")); + m_MaxAnisotropyCB->Append(wxT("8x")); + m_MaxAnisotropyCB->Append(wxT("16x")); + m_MaxAnisotropyCB->SetSelection(g_Config.iMaxAnisotropy - 1); + + wxStaticText *AAText = new wxStaticText(m_PageGeneral, ID_AATEXT, wxT("Anti-alias mode:"), wxDefaultPosition, wxDefaultSize, 0); + wxArrayString arrayStringFor_AliasModeCB; + m_AliasModeCB = new wxComboBox(m_PageGeneral, ID_ALIASMODECB, wxEmptyString, wxDefaultPosition, wxDefaultSize, arrayStringFor_AliasModeCB, 0, wxDefaultValidator); + wxString tmp; + tmp << g_Config.iMultisampleMode; + m_AliasModeCB->SetValue(tmp); + + // Usage: The wxGBPosition() must have a column and row + sGeneral = new wxBoxSizer(wxVERTICAL); + sBasic = new wxGridBagSizer(0, 0); + sBasic->Add(m_Fullscreen, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL, 5); + sBasic->Add(m_RenderToMainWindow, wxGBPosition(1, 0), wxGBSpan(1, 2), wxALL, 5); + sBasic->Add(m_StretchToFit, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL, 5); + sBasic->Add(m_KeepAR, wxGBPosition(3, 0), wxGBSpan(1, 2), wxALL, 5); + sBasic->Add(m_HideCursor, wxGBPosition(4, 0), wxGBSpan(1, 2), wxALL, 5); + sBasic->Add(FSText, wxGBPosition(5, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); + sBasic->Add(m_FullscreenCB, wxGBPosition(5, 1), wxGBSpan(1, 1), wxALL, 5); + sBasic->Add(WMText, wxGBPosition(6, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); + sBasic->Add(m_WindowResolutionCB, wxGBPosition(6, 1), wxGBSpan(1, 1), wxALL, 5); + sbBasic->Add(sBasic); + sGeneral->Add(sbBasic, 0, wxEXPAND|wxALL, 5); + + sEnhancements = new wxGridBagSizer(0, 0); + sEnhancements->Add(m_ForceFiltering, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL, 5); + sEnhancements->Add(AnisoText, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); + sEnhancements->Add(m_MaxAnisotropyCB, wxGBPosition(1, 1), wxGBSpan(1, 2), wxALL, 5); + sEnhancements->Add(AAText, wxGBPosition(2, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); + sEnhancements->Add(m_AliasModeCB, wxGBPosition(2, 1), wxGBSpan(1, 2), wxALL, 5); + sbEnhancements->Add(sEnhancements); + sGeneral->Add(sbEnhancements, 0, wxEXPAND|wxALL, 5); + m_PageGeneral->SetSizer(sGeneral); + sGeneral->Layout(); + + // Information + sbInfo = new wxStaticBoxSizer(wxVERTICAL, m_PageAdvanced, wxT("Info")); + m_ShowFPS = new wxCheckBox(m_PageAdvanced, ID_SHOWFPS, wxT("Overlay FPS"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_ShowFPS->SetValue(g_Config.bShowFPS); + m_Statistics = new wxCheckBox(m_PageAdvanced, ID_STATISTICS, wxT("Overlay some statistics"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_Statistics->SetValue(g_Config.bOverlayStats); + m_ShaderErrors = new wxCheckBox(m_PageAdvanced, ID_SHADERERRORS, wxT("Show shader compilation issues"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + //m_ShaderErrors->SetValue(g_Config.bShowShaderErrors); + m_ShaderErrors->Enable(false); + m_TexFmtOverlay = new wxCheckBox(m_PageAdvanced, ID_TEXFMTOVERLAY, wxT("Overlay texture format"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_TexFmtOverlay->SetValue(g_Config.bTexFmtOverlayEnable); + m_TexFmtCenter = new wxCheckBox(m_PageAdvanced, ID_TEXFMTCENTER, wxT("centered"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_TexFmtCenter->SetValue(g_Config.bTexFmtOverlayCenter); + m_TexFmtCenter->Enable(m_TexFmtOverlay->IsChecked()); + + // Render + sbRendering = new wxStaticBoxSizer(wxVERTICAL, m_PageAdvanced, wxT("Rendering")); + m_UseXFB = new wxCheckBox(m_PageAdvanced, ID_USEXFB, wxT("Use External Framebuffer (XFB)"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_UseXFB->SetValue(g_Config.bUseXFB); + m_Wireframe = new wxCheckBox(m_PageAdvanced, ID_WIREFRAME, wxT("Enable Wireframe"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_Wireframe->SetValue(g_Config.bWireFrame); + m_Wireframe->Enable(true); + m_DisableLighting = new wxCheckBox(m_PageAdvanced, ID_DISABLELIGHTING, wxT("Disable Material Lighting"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_DisableLighting->SetValue(g_Config.bDisableLighting); + m_DisableLighting->Enable(true); + m_DisableTexturing = new wxCheckBox(m_PageAdvanced, ID_DISABLETEXTURING, wxT("Disable Texturing"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_DisableTexturing->SetValue(g_Config.bDisableTexturing); + m_DisableTexturing->Enable(true); + + // Utility + sbUtilities = new wxStaticBoxSizer(wxVERTICAL, m_PageAdvanced, wxT("Utilities")); + m_DumpTextures = new wxCheckBox(m_PageAdvanced, ID_DUMPTEXTURES, wxT("Dump textures to:"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_DumpTextures->SetValue(g_Config.bDumpTextures); + m_TexturePath = new wxDirPickerCtrl(m_PageAdvanced, ID_TEXTUREPATH, wxEmptyString, wxT("Choose a directory to store texture dumps:"), wxDefaultPosition, wxDefaultSize, wxDIRP_USE_TEXTCTRL); + m_TexturePath->SetPath(wxString::FromAscii(g_Config.texDumpPath)); + m_TexturePath->Enable(m_DumpTextures->IsChecked()); + + // Hacks + sbHacks = new wxStaticBoxSizer(wxVERTICAL, m_PageAdvanced, wxT("Hacks")); + m_EFBToTextureDisable = new wxCheckBox(m_PageAdvanced, + ID_EFBTOTEXTUREDISABLE, wxT("Disable copy EFB to texture"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_EFBToTextureDisable->SetToolTip(wxT("Do not copy the Embedded Framebuffer (EFB)" + " to the\nTexture. This may result in a speed increase.")); + m_EFBToTextureDisable->Enable(true); + m_EFBToTextureDisable->SetValue(g_Config.bEFBToTextureDisable); + m_EFBToTextureDisableHotKey = new wxCheckBox(m_PageAdvanced, + ID_EFBTOTEXTUREDISABLEHOTKEY, wxT("with hotkey E"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_EFBToTextureDisableHotKey->SetToolTip(wxT("Use the E key to turn this option on and off")); +#ifndef _WIN32 + // JPeterson set the hot key to be Win32-specific + m_EFBToTextureDisableHotKey->Enable(false); +#endif + m_EFBToTextureDisableHotKey->SetValue(g_Config.bEFBToTextureDisableHotKey); + + m_SafeTextureCache = new wxCheckBox(m_PageAdvanced, ID_SAFETEXTURECACHE, wxT("Safe texture cache"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_SafeTextureCache->SetToolTip(wxT("This is useful to prevent Metroid Prime from crashing, but can cause problems in other games.")); + m_SafeTextureCache->Enable(true); + m_SafeTextureCache->SetValue(g_Config.bSafeTextureCache); + + m_ProjectionHax1 = new wxCheckBox(m_PageAdvanced, ID_PROJECTIONHACK1, wxT("Projection before R945"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_ProjectionHax1->SetToolTip(wxT("This may reveal otherwise invisible graphics" + " in\ngames like Mario Galaxy or Ikaruga.")); + m_ProjectionHax1->Enable(true); + m_ProjectionHax1->SetValue(g_Config.bProjectionHax1); + + m_ProjectionHax2 = new wxCheckBox(m_PageAdvanced, ID_PROJECTIONHACK2, wxT("Projection hack of R844"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_ProjectionHax2->Enable(true); + m_ProjectionHax2->SetValue(g_Config.bProjectionHax2); + + sAdvanced = new wxBoxSizer(wxVERTICAL); + sInfo = new wxGridBagSizer(0, 0); + sInfo->Add(m_ShowFPS, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL, 5); + sInfo->Add(m_ShaderErrors, wxGBPosition(1, 0), wxGBSpan(1, 2), wxALL, 5); + sInfo->Add(m_Statistics, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL, 5); + sInfo->Add(m_TexFmtOverlay, wxGBPosition(3, 0), wxGBSpan(1, 1), wxALL, 5); + sInfo->Add(m_TexFmtCenter, wxGBPosition(3, 1), wxGBSpan(1, 1), wxALL, 5); + sbInfo->Add(sInfo); + sAdvanced->Add(sbInfo, 0, wxEXPAND|wxALL, 5); + + sRendering = new wxGridBagSizer(0, 0); + sRendering->Add(m_UseXFB, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALL, 5); + sRendering->Add(m_Wireframe, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALL, 5); + sRendering->Add(m_DisableLighting, wxGBPosition(2, 0), wxGBSpan(1, 1), wxALL, 5); + sRendering->Add(m_DisableTexturing, wxGBPosition(3, 0), wxGBSpan(1, 1), wxALL, 5); + sbRendering->Add(sRendering); + sAdvanced->Add(sbRendering, 0, wxEXPAND|wxALL, 5); + + sUtilities = new wxGridBagSizer(0, 0); + sUtilities->Add(m_DumpTextures, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); + sUtilities->Add(m_TexturePath, wxGBPosition(0, 1), wxGBSpan(1, 1), wxALL, 5); + sbUtilities->Add(sUtilities); + sAdvanced->Add(sbUtilities, 0, wxEXPAND|wxALL, 5); + + sHacks = new wxGridBagSizer(0, 0); + sHacks->Add(m_EFBToTextureDisable, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALL, 5); + sHacks->Add(m_EFBToTextureDisableHotKey, wxGBPosition(0, 1), wxGBSpan(1, 1), wxALL, 5); + sHacks->Add(m_ProjectionHax1, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALL, 5); + sHacks->Add(m_ProjectionHax2, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL, 5); + sHacks->Add(m_SafeTextureCache, wxGBPosition(3, 0), wxGBSpan(1, 1), wxALL, 5); + sbHacks->Add(sHacks); + sAdvanced->Add(sbHacks, 0, wxEXPAND|wxALL, 5); + m_PageAdvanced->SetSizer(sAdvanced); + sAdvanced->Layout(); + + Fit(); + Center(); +} + +void ConfigDialog::OnClose(wxCloseEvent& WXUNUSED (event)) +{ + /* notice that we don't run wxEntryCleanup(); here so the dll will + still be loaded */ + g_Config.Save(); + EndModal(0); +} + +void ConfigDialog::CloseClick(wxCommandEvent& WXUNUSED (event)) +{ + Close(); +} + +void ConfigDialog::AddFSReso(char *reso) +{ + m_FullscreenCB->Append(wxString::FromAscii(reso)); +} + +void ConfigDialog::AddWindowReso(char *reso) +{ + m_WindowResolutionCB->Append(wxString::FromAscii(reso)); +} + +void ConfigDialog::AddAAMode(int mode) +{ + wxString tmp; + tmp<Append(tmp); +} + +void ConfigDialog::AboutClick(wxCommandEvent& WXUNUSED (event)) +{ + wxMessageBox(_T("Dolphin OpenGL Plugin\nBy zerofrog(@gmail.com)\n\n" + "A card supporting Vertex/Pixel Shader 2.0 or higher, framebuffer objects, " + "and multiple render targets is required in order to use this plugin."), + _T("Dolphin OGL"), wxOK, this); +} + +void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event) +{ + switch (event.GetId()) + { + case ID_FULLSCREEN: + g_Config.bFullscreen = m_Fullscreen->IsChecked(); + break; + case ID_RENDERTOMAINWINDOW: + g_Config.renderToMainframe = m_RenderToMainWindow->IsChecked(); + break; + case ID_STRETCHTOFIT: + g_Config.bStretchToFit = m_StretchToFit->IsChecked(); + break; + case ID_KEEPAR: + g_Config.bKeepAR = m_KeepAR->IsChecked(); + break; + case ID_HIDECURSOR: + g_Config.bHideCursor = m_HideCursor->IsChecked(); + break; + case ID_FULLSCREENCB: + strcpy(g_Config.iFSResolution, m_FullscreenCB->GetValue().mb_str() ); + break; + case ID_WINDOWRESOLUTIONCB: + strcpy(g_Config.iWindowedRes, m_WindowResolutionCB->GetValue().mb_str() ); + break; + case ID_FORCEFILTERING: + g_Config.bForceFiltering = m_ForceFiltering->IsChecked(); + break; + case ID_MAXANISOTROPY: + g_Config.iMaxAnisotropy = m_MaxAnisotropyCB->GetSelection() + 1; + break; + case ID_ALIASMODECB: + g_Config.iMultisampleMode = atoi(m_AliasModeCB->GetValue().mb_str()); + break; + } +} + +void ConfigDialog::AdvancedSettingsChanged(wxCommandEvent& event) +{ + switch (event.GetId()) + { + case ID_SHOWFPS: + g_Config.bShowFPS = m_ShowFPS->IsChecked(); + break; + case ID_SHADERERRORS: + g_Config.bShowShaderErrors = m_ShaderErrors->IsChecked(); + break; + case ID_STATISTICS: + g_Config.bOverlayStats = m_Statistics->IsChecked(); + break; + case ID_TEXFMTOVERLAY: + g_Config.bTexFmtOverlayEnable = m_TexFmtOverlay->IsChecked(); + m_TexFmtCenter->Enable(m_TexFmtOverlay->IsChecked()); + TextureMngr::Invalidate(); + break; + case ID_TEXFMTCENTER: + g_Config.bTexFmtOverlayCenter = m_TexFmtCenter->IsChecked(); + TextureMngr::Invalidate(); + break; + case ID_USEXFB: + g_Config.bUseXFB = m_UseXFB->IsChecked(); + break; + case ID_WIREFRAME: + g_Config.bWireFrame = m_Wireframe->IsChecked(); + break; + case ID_DISABLELIGHTING: + g_Config.bDisableLighting = m_DisableLighting->IsChecked(); + break; + case ID_DISABLETEXTURING: + g_Config.bDisableTexturing = m_DisableTexturing->IsChecked(); + break; + case ID_DUMPTEXTURES: + m_TexturePath->Enable(m_DumpTextures->IsChecked()); + g_Config.bDumpTextures = m_DumpTextures->IsChecked(); + break; + case ID_TEXTUREPATH: + break; + case ID_EFBTOTEXTUREDISABLE: + g_Config.bEFBToTextureDisable = m_EFBToTextureDisable->IsChecked(); + break; + case ID_EFBTOTEXTUREDISABLEHOTKEY: + g_Config.bEFBToTextureDisableHotKey = m_EFBToTextureDisableHotKey->IsChecked(); + break; + case ID_PROJECTIONHACK1: + g_Config.bProjectionHax1 = m_ProjectionHax1->IsChecked(); + break; + case ID_PROJECTIONHACK2: + g_Config.bProjectionHax2 = m_ProjectionHax2->IsChecked(); + break; + case ID_SAFETEXTURECACHE: + g_Config.bSafeTextureCache = m_SafeTextureCache->IsChecked(); + break; + default: + break; + } +} + +void ConfigDialog::TexturePathChange(wxFileDirPickerEvent& event) +{ + // Note: if a user inputs an incorrect path(by typing, not by choosing from + // the combobox) this event wil not be fired. + strcpy(g_Config.texDumpPath, event.GetPath().mb_str()); +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Globals.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Globals.cpp index f41f9066e2..a934286d8f 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Globals.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Globals.cpp @@ -1,114 +1,114 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#if defined(HAVE_WX) && HAVE_WX -#include -#include -#include -#include -#include -#endif - -#include "Globals.h" - -#include "pluginspecs_video.h" -#include "main.h" - -#include "IniFile.h" -#include - -#ifdef _WIN32 - -// The one for Linux is in Linux/Linux.cpp -static HANDLE hConsole = NULL; - -void OpenConsole() -{ - COORD csize; - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - SMALL_RECT srect; - - if (hConsole) - return; - AllocConsole(); - SetConsoleTitle("Opengl Plugin Output"); - - // set width and height - csize.X = 155; // this fits on 1280 pixels TODO: make it adjustable from the wx debugging window - csize.Y = 300; // 300 rows - SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), csize); - - // make the internal buffer match the width we set - GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbiInfo); - srect = csbiInfo.srWindow; - srect.Right = srect.Left + csize.X - 1; // match - srect.Bottom = srect.Top + 44; - SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &srect); - - hConsole = GetStdHandle(STD_OUTPUT_HANDLE); -} - -void CloseConsole() -{ - if (hConsole == NULL) - return; - FreeConsole(); - hConsole = NULL; -} -#endif - -static FILE* pfLog = NULL; -void __Log(const char *fmt, ...) -{ - char* Msg = (char*)alloca(strlen(fmt)+512); - va_list ap; - - va_start( ap, fmt ); - vsnprintf( Msg, strlen(fmt)+512, fmt, ap ); - va_end( ap ); - - g_VideoInitialize.pLog(Msg, FALSE); - - if (pfLog == NULL) - pfLog = fopen(FULL_LOGS_DIR "oglgfx.txt", "w"); - - if (pfLog != NULL) - fwrite(Msg, strlen(Msg), 1, pfLog); -#ifdef _WIN32 - DWORD tmp; - WriteConsole(hConsole, Msg, (DWORD)strlen(Msg), &tmp, 0); -#else - //printf("%s", Msg); -#endif -} - -void __Log(int type, const char *fmt, ...) -{ - char* Msg = (char*)alloca(strlen(fmt)+512); - va_list ap; - - va_start( ap, fmt ); - vsnprintf( Msg, strlen(fmt)+512, fmt, ap ); - va_end( ap ); - - g_VideoInitialize.pLog(Msg, FALSE); - -#ifdef _WIN32 - DWORD tmp; - WriteConsole(hConsole, Msg, (DWORD)strlen(Msg), &tmp, 0); -#endif -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#if defined(HAVE_WX) && HAVE_WX +#include +#include +#include +#include +#include +#endif + +#include "Globals.h" + +#include "pluginspecs_video.h" +#include "main.h" + +#include "IniFile.h" +#include + +#ifdef _WIN32 + +// The one for Linux is in Linux/Linux.cpp +static HANDLE hConsole = NULL; + +void OpenConsole() +{ + COORD csize; + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + SMALL_RECT srect; + + if (hConsole) + return; + AllocConsole(); + SetConsoleTitle("Opengl Plugin Output"); + + // set width and height + csize.X = 155; // this fits on 1280 pixels TODO: make it adjustable from the wx debugging window + csize.Y = 300; // 300 rows + SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), csize); + + // make the internal buffer match the width we set + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbiInfo); + srect = csbiInfo.srWindow; + srect.Right = srect.Left + csize.X - 1; // match + srect.Bottom = srect.Top + 44; + SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &srect); + + hConsole = GetStdHandle(STD_OUTPUT_HANDLE); +} + +void CloseConsole() +{ + if (hConsole == NULL) + return; + FreeConsole(); + hConsole = NULL; +} +#endif + +static FILE* pfLog = NULL; +void __Log(const char *fmt, ...) +{ + char* Msg = (char*)alloca(strlen(fmt)+512); + va_list ap; + + va_start( ap, fmt ); + vsnprintf( Msg, strlen(fmt)+512, fmt, ap ); + va_end( ap ); + + g_VideoInitialize.pLog(Msg, FALSE); + + if (pfLog == NULL) + pfLog = fopen(FULL_LOGS_DIR "oglgfx.txt", "w"); + + if (pfLog != NULL) + fwrite(Msg, strlen(Msg), 1, pfLog); +#ifdef _WIN32 + DWORD tmp; + WriteConsole(hConsole, Msg, (DWORD)strlen(Msg), &tmp, 0); +#else + //printf("%s", Msg); +#endif +} + +void __Log(int type, const char *fmt, ...) +{ + char* Msg = (char*)alloca(strlen(fmt)+512); + va_list ap; + + va_start( ap, fmt ); + vsnprintf( Msg, strlen(fmt)+512, fmt, ap ); + va_end( ap ); + + g_VideoInitialize.pLog(Msg, FALSE); + +#ifdef _WIN32 + DWORD tmp; + WriteConsole(hConsole, Msg, (DWORD)strlen(Msg), &tmp, 0); +#endif +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/ImageWrite.cpp b/Source/Plugins/Plugin_VideoOGL/Src/ImageWrite.cpp index 2e14576a3e..64423b66e7 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/ImageWrite.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/ImageWrite.cpp @@ -1,100 +1,100 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Globals.h" -#include "GLUtil.h" - -#include -#include -#include - -#include "ImageWrite.h" - -#if defined(_MSC_VER) -#pragma pack(push, 1) -#endif - -struct TGA_HEADER -{ - u8 identsize; // size of ID field that follows 18 u8 header (0 usually) - u8 colourmaptype; // type of colour map 0=none, 1=has palette - u8 imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed - - s16 colourmapstart; // first colour map entry in palette - s16 colourmaplength; // number of colours in palette - u8 colourmapbits; // number of bits per palette entry 15,16,24,32 - - s16 xstart; // image x origin - s16 ystart; // image y origin - s16 width; // image width in pixels - s16 height; // image height in pixels - u8 bits; // image bits per pixel 8,16,24,32 - u8 descriptor; // image descriptor bits (vh flip bits) - - // pixel data follows header -}; - -#if defined(_MSC_VER) -#pragma pack(pop) -#endif - -bool SaveTGA(const char* filename, int width, int height, void* pdata) -{ - TGA_HEADER hdr; - FILE* f = fopen(filename, "wb"); - if (f == NULL) - return false; - - _assert_(sizeof(TGA_HEADER) == 18 && sizeof(hdr) == 18); - - memset(&hdr, 0, sizeof(hdr)); - hdr.imagetype = 2; - hdr.bits = 32; - hdr.width = width; - hdr.height = height; - hdr.descriptor |= 8|(1<<5); // 8bit alpha, flip vertical - - fwrite(&hdr, sizeof(hdr), 1, f); - fwrite(pdata, width * height * 4, 1, f); - fclose(f); - return true; -} - -bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height) -{ - GL_REPORT_ERRORD(); - std::vector data(width * height); - glBindTexture(textarget, tex); - glGetTexImage(textarget, 0, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]); - GLenum err; - GL_REPORT_ERROR(); - if (err != GL_NO_ERROR) - { - return false; - } - return SaveTGA(filename, width, height, &data[0]); -} - -bool SaveData(const char* filename, const char* data) -{ - FILE *f = fopen(filename, "wb"); - if (!f) - return false; - fwrite(data, strlen(data), 1, f); - fclose(f); - return true; -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Globals.h" +#include "GLUtil.h" + +#include +#include +#include + +#include "ImageWrite.h" + +#if defined(_MSC_VER) +#pragma pack(push, 1) +#endif + +struct TGA_HEADER +{ + u8 identsize; // size of ID field that follows 18 u8 header (0 usually) + u8 colourmaptype; // type of colour map 0=none, 1=has palette + u8 imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed + + s16 colourmapstart; // first colour map entry in palette + s16 colourmaplength; // number of colours in palette + u8 colourmapbits; // number of bits per palette entry 15,16,24,32 + + s16 xstart; // image x origin + s16 ystart; // image y origin + s16 width; // image width in pixels + s16 height; // image height in pixels + u8 bits; // image bits per pixel 8,16,24,32 + u8 descriptor; // image descriptor bits (vh flip bits) + + // pixel data follows header +}; + +#if defined(_MSC_VER) +#pragma pack(pop) +#endif + +bool SaveTGA(const char* filename, int width, int height, void* pdata) +{ + TGA_HEADER hdr; + FILE* f = fopen(filename, "wb"); + if (f == NULL) + return false; + + _assert_(sizeof(TGA_HEADER) == 18 && sizeof(hdr) == 18); + + memset(&hdr, 0, sizeof(hdr)); + hdr.imagetype = 2; + hdr.bits = 32; + hdr.width = width; + hdr.height = height; + hdr.descriptor |= 8|(1<<5); // 8bit alpha, flip vertical + + fwrite(&hdr, sizeof(hdr), 1, f); + fwrite(pdata, width * height * 4, 1, f); + fclose(f); + return true; +} + +bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height) +{ + GL_REPORT_ERRORD(); + std::vector data(width * height); + glBindTexture(textarget, tex); + glGetTexImage(textarget, 0, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]); + GLenum err; + GL_REPORT_ERROR(); + if (err != GL_NO_ERROR) + { + return false; + } + return SaveTGA(filename, width, height, &data[0]); +} + +bool SaveData(const char* filename, const char* data) +{ + FILE *f = fopen(filename, "wb"); + if (!f) + return false; + fwrite(data, strlen(data), 1, f); + fclose(f); + return true; +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Logging/Console.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Logging/Console.cpp index 971884a7a2..61cd38b01e 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Logging/Console.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Logging/Console.cpp @@ -1,202 +1,202 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -// -------------------- -// Includes -#include "../Globals.h" -#include -#include -#ifdef _WIN32 -#include -#endif - - -// -------------------- -// On and off -bool g_consoleEnable = true; -int gSaveFile = 0; -#define DEBUGG - - -// -------------------- -// Settings -int nFiles = 1; - - -// -------------------- -// Create handles - -#ifdef DEBUGG -FILE* __fStdOut[1]; // you have to update this manually, we can't place a nFiles in there -#endif -#ifdef _WIN32 -HANDLE __hStdOut = NULL; -#endif - - -// ======================================================================================= -/* Start console window - width and height is the size of console window, if you specify -fname, the output will also be written to this file. TODO: Close the file pointer when the app -is closed */ -// ------------- -void startConsoleWin(int width, int height, char* fname) -{ - -#if defined(DEBUGG) && defined(_WIN32) - - AllocConsole(); - - SetConsoleTitle(fname); - __hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); - - // swt the width and height of the window - COORD co = {width,height}; - SetConsoleScreenBufferSize(__hStdOut, co); - - // make the internal buffer match the width we set - SMALL_RECT coo = {0,0,(width - 1),70}; // top, left, right, bottom - SetConsoleWindowInfo(__hStdOut, TRUE, &coo); - - // --------------------------------------------------------------------------------------- - // Write to a file - if(fname) - { - for(int i = 0; i < nFiles; i++) - { - // Edit the log file name - std::string FileEnding = ".log"; - std::string FileName = fname; - char buffer[33]; itoa(i, buffer, 10); // convert number to string - std::string FullFilename = (FileName + buffer + FileEnding); - __fStdOut[i] = fopen(FullFilename.c_str(), "w"); - } - } - // --------------- -#endif -} - - -// --------------------------------------------------------------------------------------- -// File printf function -int aprintf(int a, char *fmt, ...) -{ -#if defined(DEBUGG) && defined(_WIN32) - if(gSaveFile) - { - char s[5000]; // WARNING: mind this value - va_list argptr; - int cnt; - - va_start(argptr, fmt); - cnt = vsnprintf(s, 5000, fmt, argptr); // remember to update this value to - va_end(argptr); - - // --------------------------------------------------------------------------------------- - if(__fStdOut[a]) // TODO: make this work, we have to set all default values to NULL - //to make it work - fprintf(__fStdOut[a], s); - // ------------- - - return(cnt); - } - else - { - return 0; - } -#else - return 0; -#endif -} - - - -void ClearScreen() -{ -#if defined(DEBUGG) && defined(_WIN32) - if(g_consoleEnable) - { - COORD coordScreen = { 0, 0 }; - DWORD cCharsWritten; - CONSOLE_SCREEN_BUFFER_INFO csbi; - DWORD dwConSize; - - HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - - GetConsoleScreenBufferInfo(hConsole, &csbi); - dwConSize = csbi.dwSize.X * csbi.dwSize.Y; - FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, - coordScreen, &cCharsWritten); - GetConsoleScreenBufferInfo(hConsole, &csbi); - FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, - coordScreen, &cCharsWritten); - SetConsoleCursorPosition(hConsole, coordScreen); - } -#endif -} - -#ifndef _WIN32 -// VERY UGLY! needs to be fixed soon, just fixing the biuld... -void CloseConsole() -{ -} -void OpenConsole() -{ -} -#endif - -#if defined(DEBUGG) && defined(_WIN32) -HWND GetConsoleHwnd(void) -{ - - #define MY_BUFSIZE 1024 // Buffer size for console window titles. - HWND hwndFound; // This is what is returned to the caller. - char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated - // WindowTitle. - char pszOldWindowTitle[MY_BUFSIZE]; // Contains original - // WindowTitle. - - // Fetch current window title. - - GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE); - - // Format a "unique" NewWindowTitle. - - wsprintf(pszNewWindowTitle,"%d/%d", - GetTickCount(), - GetCurrentProcessId()); - - // Change current window title. - - SetConsoleTitle(pszNewWindowTitle); - - // Ensure window title has been updated. - - Sleep(40); - - // Look for NewWindowTitle. - - hwndFound = FindWindow(NULL, pszNewWindowTitle); - - // Restore original window title. - - SetConsoleTitle(pszOldWindowTitle); - - return(hwndFound); - -} -#endif // win32 +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +// -------------------- +// Includes +#include "../Globals.h" +#include +#include +#ifdef _WIN32 +#include +#endif + + +// -------------------- +// On and off +bool g_consoleEnable = true; +int gSaveFile = 0; +#define DEBUGG + + +// -------------------- +// Settings +int nFiles = 1; + + +// -------------------- +// Create handles + +#ifdef DEBUGG +FILE* __fStdOut[1]; // you have to update this manually, we can't place a nFiles in there +#endif +#ifdef _WIN32 +HANDLE __hStdOut = NULL; +#endif + + +// ======================================================================================= +/* Start console window - width and height is the size of console window, if you specify +fname, the output will also be written to this file. TODO: Close the file pointer when the app +is closed */ +// ------------- +void startConsoleWin(int width, int height, char* fname) +{ + +#if defined(DEBUGG) && defined(_WIN32) + + AllocConsole(); + + SetConsoleTitle(fname); + __hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + + // swt the width and height of the window + COORD co = {width,height}; + SetConsoleScreenBufferSize(__hStdOut, co); + + // make the internal buffer match the width we set + SMALL_RECT coo = {0,0,(width - 1),70}; // top, left, right, bottom + SetConsoleWindowInfo(__hStdOut, TRUE, &coo); + + // --------------------------------------------------------------------------------------- + // Write to a file + if(fname) + { + for(int i = 0; i < nFiles; i++) + { + // Edit the log file name + std::string FileEnding = ".log"; + std::string FileName = fname; + char buffer[33]; itoa(i, buffer, 10); // convert number to string + std::string FullFilename = (FileName + buffer + FileEnding); + __fStdOut[i] = fopen(FullFilename.c_str(), "w"); + } + } + // --------------- +#endif +} + + +// --------------------------------------------------------------------------------------- +// File printf function +int aprintf(int a, char *fmt, ...) +{ +#if defined(DEBUGG) && defined(_WIN32) + if(gSaveFile) + { + char s[5000]; // WARNING: mind this value + va_list argptr; + int cnt; + + va_start(argptr, fmt); + cnt = vsnprintf(s, 5000, fmt, argptr); // remember to update this value to + va_end(argptr); + + // --------------------------------------------------------------------------------------- + if(__fStdOut[a]) // TODO: make this work, we have to set all default values to NULL + //to make it work + fprintf(__fStdOut[a], s); + // ------------- + + return(cnt); + } + else + { + return 0; + } +#else + return 0; +#endif +} + + + +void ClearScreen() +{ +#if defined(DEBUGG) && defined(_WIN32) + if(g_consoleEnable) + { + COORD coordScreen = { 0, 0 }; + DWORD cCharsWritten; + CONSOLE_SCREEN_BUFFER_INFO csbi; + DWORD dwConSize; + + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + + GetConsoleScreenBufferInfo(hConsole, &csbi); + dwConSize = csbi.dwSize.X * csbi.dwSize.Y; + FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, + coordScreen, &cCharsWritten); + GetConsoleScreenBufferInfo(hConsole, &csbi); + FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, + coordScreen, &cCharsWritten); + SetConsoleCursorPosition(hConsole, coordScreen); + } +#endif +} + +#ifndef _WIN32 +// VERY UGLY! needs to be fixed soon, just fixing the biuld... +void CloseConsole() +{ +} +void OpenConsole() +{ +} +#endif + +#if defined(DEBUGG) && defined(_WIN32) +HWND GetConsoleHwnd(void) +{ + + #define MY_BUFSIZE 1024 // Buffer size for console window titles. + HWND hwndFound; // This is what is returned to the caller. + char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated + // WindowTitle. + char pszOldWindowTitle[MY_BUFSIZE]; // Contains original + // WindowTitle. + + // Fetch current window title. + + GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE); + + // Format a "unique" NewWindowTitle. + + wsprintf(pszNewWindowTitle,"%d/%d", + GetTickCount(), + GetCurrentProcessId()); + + // Change current window title. + + SetConsoleTitle(pszNewWindowTitle); + + // Ensure window title has been updated. + + Sleep(40); + + // Look for NewWindowTitle. + + hwndFound = FindWindow(NULL, pszNewWindowTitle); + + // Restore original window title. + + SetConsoleTitle(pszOldWindowTitle); + + return(hwndFound); + +} +#endif // win32 diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Logging/Logging.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Logging/Logging.cpp index 789dd1ef77..4538873a67 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Logging/Logging.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Logging/Logging.cpp @@ -1,283 +1,283 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// -// Licensetype: GNU General Public License (GPL) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. -// -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ -// -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ -// -////////////////////////////////////////////////////////////////////////////////////////// - -#include "../Globals.h" // this is the precompiled header and must be the first ... - -// --------------------------------------------------------------------------------------- -// Includes -// ------------- -#include -#include -#include // so that we can test std::string == abc -#include // for the pow() function -#ifdef _WIN32 - #include -#endif - - -#if defined(HAVE_WX) && HAVE_WX -#include "../Debugger/Debugger.h" // for the CDebugger class -#include "../Debugger/PBView.h" -#include "Console.h" // open and close console, clear console window -#endif -#include "../Logging/Logging.h" // for global logging values - - - -// --------------------------------------------------------------------------------------- -// Externals -// ------------- -extern int nFiles; -float ratioFactor; // a global to get the ratio factor from MixAdd -int gPreset = 0; -u32 gLastBlock; -extern bool gSSBM; -extern bool gSSBMremedy1; -extern bool gSSBMremedy2; -extern bool gSequenced; -extern bool gReset; -bool gOnlyLooping = false; -extern int gSaveFile; - -extern int gleft, gright, gtop, gbottom; // from BPStructs.cpp - - -// --------------------------------------------------------------------------------------- -// Counters -// ------------- -int j = 0; -int k = 0; -bool iupdonce = false; -std::vector viupd(15); // the length of the update frequency bar - - -// --------------------------------------------------------------------------------------- -// Classes -// ------------- -#if defined(HAVE_WX) && HAVE_WX -extern CDebugger* m_frame; -#endif - - -// ======================================================================================= -// Write title -// -------------- -std::string writeTitle(int a) -{ - std::string b; - if(a == 0) - { - b = "lef rig top bot | wid hei\n"; - } - return b; -} -// ======================================================================================= - - - -// ======================================================================================= -// Write main message (presets) -// -------------- -std::string writeMessage(int a, int i) -{ - char buf [1000] = ""; - std::string sbuf; - // ======================================================================================= - // PRESETS - // --------------------------------------------------------------------------------------- - /* - PRESET 0 - "lef rig top bot | xof yof\n"; - "000 000 000 000 | 000 000 - */ - if(a == 0) - { - sprintf(buf,"%03i %03i %03i %03i | %03i %03i", - gleft, gright, gtop, gbottom, gright-gleft, gbottom-gtop - ); - } - - sbuf = buf; - return sbuf; -} - - -// ======================================================================================= - - - -// Logging -void Logging(int a) -{ - - - // ======================================================================================= - // Update parameter values - // -------------- - // AXPB base - - - // ============== - - - // --------------------------------------------------------------------------------------- - // Write to file - // -------------- - for (int ii = 0; ii < nFiles; ii++) - { - std::string sfbuff; - sfbuff = sfbuff + writeMessage(ii, 0); -#if defined(HAVE_WX) && HAVE_WX - aprintf(ii, (char *)sfbuff.c_str()); -#endif - } - // -------------- - - - // ======================================================================================= - // Control how often the screen is updated, and then update the screen - // -------------- - if(a == 0) j++; - //if(l == pow((double)2,32)) l=0; // reset l - //l++; - if (m_frame->gUpdFreq > 0 && j > (30 / m_frame->gUpdFreq)) - { - - - // ======================================================================================= - // Write header - // -------------- - char buffer [1000] = ""; - std::string sbuff; - sbuff = writeTitle(gPreset); - // ============== - - - // hopefully this is false if we don't have a debugging window and so it doesn't cause a crash - /* // nothing do do here yet - if(m_frame) - { - m_frame->m_GPRListView->m_CachedRegs[1][0] = 0; - } - */ - - // add new line - sbuff = sbuff + writeMessage(gPreset, 0); strcpy(buffer, ""); - sbuff = sbuff + "\n"; - - - // ======================================================================================= - // Write global values - // --------------- - /* - sprintf(buffer, "\nThe parameter blocks span from %08x to %08x | distance %i %i\n", m_addressPBs, gLastBlock, (gLastBlock-m_addressPBs), (gLastBlock-m_addressPBs) / 192); - sbuff = sbuff + buffer; strcpy(buffer, ""); - */ - // =============== - - - // ======================================================================================= - // Write settings - // --------------- - /* - sprintf(buffer, "\nSettings: SSBM fix %i | SSBM rem1 %i | SSBM rem2 %i | Sequenced %i | Reset %i | Only looping %i | Save file %i\n", - gSSBM, gSSBMremedy1, gSSBMremedy2, gSequenced, gReset, gOnlyLooping, gSaveFile); - sbuff = sbuff + buffer; strcpy(buffer, ""); - */ - // =============== - - - // ======================================================================================= - // Show update frequency - // --------------- - sbuff = sbuff + "\n"; - if(!iupdonce) - { - /* - for (int i = 0; i < 10; i++) - { - viupd.at(i) == 0; - } - */ - viupd.at(0) = 1; - viupd.at(1) = 1; - viupd.at(2) = 1; - iupdonce = true; - } - - for (u32 i = 0; i < viupd.size(); i++) // 0, 1,..., 9 - { - if (i < viupd.size()-1) - { - viupd.at(viupd.size()-i-1) = viupd.at(viupd.size()-i-2); // move all forward - } - else - { - viupd.at(0) = viupd.at(viupd.size()-1); - } - - // Correction - if (viupd.at(viupd.size()-3) == 1 && viupd.at(viupd.size()-2) == 1 && viupd.at(viupd.size()-1) == 1) - { - viupd.at(0) = 0; - } - if(viupd.at(0) == 0 && viupd.at(1) == 1 && viupd.at(2) == 1 && viupd.at(3) == 0) - { - viupd.at(0) = 1; - } - } - - for (u32 i = 0; i < viupd.size(); i++) - { - if(viupd.at(i) == 0) - sbuff = sbuff + " "; - else - sbuff = sbuff + "."; - } - // ================ - - - // ======================================================================================= - // Print - // ---------------- -#if defined(HAVE_WX) && HAVE_WX - ClearScreen(); -#endif - __Log("%s", sbuff.c_str()); - sbuff.clear(); strcpy(buffer, ""); - // ================ - - - // New values are written so update - DISABLED - It flickered a lot, even worse than a - // console window. So for now only the console windows is updated. - /* - if(m_frame) - { - m_frame->NotifyUpdate(); - } - */ - - k=0; - j=0; - - } // end of if (j>20) - -} // end of function +////////////////////////////////////////////////////////////////////////////////////////// +// +// Licensetype: GNU General Public License (GPL) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. +// +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ +// +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +// +////////////////////////////////////////////////////////////////////////////////////////// + +#include "../Globals.h" // this is the precompiled header and must be the first ... + +// --------------------------------------------------------------------------------------- +// Includes +// ------------- +#include +#include +#include // so that we can test std::string == abc +#include // for the pow() function +#ifdef _WIN32 + #include +#endif + + +#if defined(HAVE_WX) && HAVE_WX +#include "../Debugger/Debugger.h" // for the CDebugger class +#include "../Debugger/PBView.h" +#include "Console.h" // open and close console, clear console window +#endif +#include "../Logging/Logging.h" // for global logging values + + + +// --------------------------------------------------------------------------------------- +// Externals +// ------------- +extern int nFiles; +float ratioFactor; // a global to get the ratio factor from MixAdd +int gPreset = 0; +u32 gLastBlock; +extern bool gSSBM; +extern bool gSSBMremedy1; +extern bool gSSBMremedy2; +extern bool gSequenced; +extern bool gReset; +bool gOnlyLooping = false; +extern int gSaveFile; + +extern int gleft, gright, gtop, gbottom; // from BPStructs.cpp + + +// --------------------------------------------------------------------------------------- +// Counters +// ------------- +int j = 0; +int k = 0; +bool iupdonce = false; +std::vector viupd(15); // the length of the update frequency bar + + +// --------------------------------------------------------------------------------------- +// Classes +// ------------- +#if defined(HAVE_WX) && HAVE_WX +extern CDebugger* m_frame; +#endif + + +// ======================================================================================= +// Write title +// -------------- +std::string writeTitle(int a) +{ + std::string b; + if(a == 0) + { + b = "lef rig top bot | wid hei\n"; + } + return b; +} +// ======================================================================================= + + + +// ======================================================================================= +// Write main message (presets) +// -------------- +std::string writeMessage(int a, int i) +{ + char buf [1000] = ""; + std::string sbuf; + // ======================================================================================= + // PRESETS + // --------------------------------------------------------------------------------------- + /* + PRESET 0 + "lef rig top bot | xof yof\n"; + "000 000 000 000 | 000 000 + */ + if(a == 0) + { + sprintf(buf,"%03i %03i %03i %03i | %03i %03i", + gleft, gright, gtop, gbottom, gright-gleft, gbottom-gtop + ); + } + + sbuf = buf; + return sbuf; +} + + +// ======================================================================================= + + + +// Logging +void Logging(int a) +{ + + + // ======================================================================================= + // Update parameter values + // -------------- + // AXPB base + + + // ============== + + + // --------------------------------------------------------------------------------------- + // Write to file + // -------------- + for (int ii = 0; ii < nFiles; ii++) + { + std::string sfbuff; + sfbuff = sfbuff + writeMessage(ii, 0); +#if defined(HAVE_WX) && HAVE_WX + aprintf(ii, (char *)sfbuff.c_str()); +#endif + } + // -------------- + + + // ======================================================================================= + // Control how often the screen is updated, and then update the screen + // -------------- + if(a == 0) j++; + //if(l == pow((double)2,32)) l=0; // reset l + //l++; + if (m_frame->gUpdFreq > 0 && j > (30 / m_frame->gUpdFreq)) + { + + + // ======================================================================================= + // Write header + // -------------- + char buffer [1000] = ""; + std::string sbuff; + sbuff = writeTitle(gPreset); + // ============== + + + // hopefully this is false if we don't have a debugging window and so it doesn't cause a crash + /* // nothing do do here yet + if(m_frame) + { + m_frame->m_GPRListView->m_CachedRegs[1][0] = 0; + } + */ + + // add new line + sbuff = sbuff + writeMessage(gPreset, 0); strcpy(buffer, ""); + sbuff = sbuff + "\n"; + + + // ======================================================================================= + // Write global values + // --------------- + /* + sprintf(buffer, "\nThe parameter blocks span from %08x to %08x | distance %i %i\n", m_addressPBs, gLastBlock, (gLastBlock-m_addressPBs), (gLastBlock-m_addressPBs) / 192); + sbuff = sbuff + buffer; strcpy(buffer, ""); + */ + // =============== + + + // ======================================================================================= + // Write settings + // --------------- + /* + sprintf(buffer, "\nSettings: SSBM fix %i | SSBM rem1 %i | SSBM rem2 %i | Sequenced %i | Reset %i | Only looping %i | Save file %i\n", + gSSBM, gSSBMremedy1, gSSBMremedy2, gSequenced, gReset, gOnlyLooping, gSaveFile); + sbuff = sbuff + buffer; strcpy(buffer, ""); + */ + // =============== + + + // ======================================================================================= + // Show update frequency + // --------------- + sbuff = sbuff + "\n"; + if(!iupdonce) + { + /* + for (int i = 0; i < 10; i++) + { + viupd.at(i) == 0; + } + */ + viupd.at(0) = 1; + viupd.at(1) = 1; + viupd.at(2) = 1; + iupdonce = true; + } + + for (u32 i = 0; i < viupd.size(); i++) // 0, 1,..., 9 + { + if (i < viupd.size()-1) + { + viupd.at(viupd.size()-i-1) = viupd.at(viupd.size()-i-2); // move all forward + } + else + { + viupd.at(0) = viupd.at(viupd.size()-1); + } + + // Correction + if (viupd.at(viupd.size()-3) == 1 && viupd.at(viupd.size()-2) == 1 && viupd.at(viupd.size()-1) == 1) + { + viupd.at(0) = 0; + } + if(viupd.at(0) == 0 && viupd.at(1) == 1 && viupd.at(2) == 1 && viupd.at(3) == 0) + { + viupd.at(0) = 1; + } + } + + for (u32 i = 0; i < viupd.size(); i++) + { + if(viupd.at(i) == 0) + sbuff = sbuff + " "; + else + sbuff = sbuff + "."; + } + // ================ + + + // ======================================================================================= + // Print + // ---------------- +#if defined(HAVE_WX) && HAVE_WX + ClearScreen(); +#endif + __Log("%s", sbuff.c_str()); + sbuff.clear(); strcpy(buffer, ""); + // ================ + + + // New values are written so update - DISABLED - It flickered a lot, even worse than a + // console window. So for now only the console windows is updated. + /* + if(m_frame) + { + m_frame->NotifyUpdate(); + } + */ + + k=0; + j=0; + + } // end of if (j>20) + +} // end of function diff --git a/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp b/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp index d942d8c78c..ebe1ae70b6 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp @@ -1,188 +1,188 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "GLUtil.h" -#include "Profiler.h" -#include "x64Emitter.h" -#include "ABI.h" -#include "MemoryUtil.h" -#include "VertexShader.h" - -#include "CPMemory.h" -#include "NativeVertexFormat.h" - -#define COMPILED_CODE_SIZE 4096 - -#ifdef _WIN32 -#define USE_JIT -#endif - -// Note the use of CallCdeclFunction3I etc. -// This is a horrible hack that is necessary because in 64-bit mode, Opengl32.dll is based way, way above the 32-bit -// address space that is within reach of a CALL, and just doing &fn gives us these high uncallable addresses. So we -// want to grab the function pointers from the import table instead. - -// This problem does not apply to glew functions, only core opengl32 functions. - -// Here's some global state. We only use this to keep track of what we've sent to the OpenGL state -// machine. - -#ifdef USE_JIT -DECLARE_IMPORT(glNormalPointer); -DECLARE_IMPORT(glVertexPointer); -DECLARE_IMPORT(glColorPointer); -DECLARE_IMPORT(glTexCoordPointer); -#endif - -NativeVertexFormat::NativeVertexFormat() -{ -#ifdef USE_JIT - m_compiledCode = (u8 *)AllocateExecutableMemory(COMPILED_CODE_SIZE, false); - if (m_compiledCode) { - memset(m_compiledCode, 0, COMPILED_CODE_SIZE); - } -#endif -} - -NativeVertexFormat::~NativeVertexFormat() -{ -#ifdef USE_JIT - FreeMemoryPages(m_compiledCode, COMPILED_CODE_SIZE); - m_compiledCode = 0; -#endif -} - -inline GLuint VarToGL(VarType t) -{ - static const GLuint lookup[5] = {GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FLOAT}; - return lookup[t]; -} - -void NativeVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl) -{ - using namespace Gen; - - if (_vtx_decl.stride & 3) { - // We will not allow vertex components causing uneven strides. - PanicAlert("Uneven vertex stride: %i", _vtx_decl.stride); - } - -#ifdef USE_JIT - // Alright, we have our vertex declaration. Compile some crazy code to set it quickly using GL. - u8 *old_code_ptr = GetWritableCodePtr(); - SetCodePtr(m_compiledCode); - ABI_EmitPrologue(6); - - CallCdeclFunction4_I(glVertexPointer, 3, GL_FLOAT, _vtx_decl.stride, 0); - - if (_vtx_decl.num_normals >= 1) { - CallCdeclFunction3_I(glNormalPointer, VarToGL(_vtx_decl.normal_gl_type), _vtx_decl.stride, _vtx_decl.normal_offset[0]); - if (_vtx_decl.num_normals == 3) { - CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM1_ATTRIB, _vtx_decl.normal_gl_size, VarToGL(_vtx_decl.normal_gl_type), GL_TRUE, _vtx_decl.stride, _vtx_decl.normal_offset[1]); - CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM2_ATTRIB, _vtx_decl.normal_gl_size, VarToGL(_vtx_decl.normal_gl_type), GL_TRUE, _vtx_decl.stride, _vtx_decl.normal_offset[2]); - } - } - - for (int i = 0; i < 2; i++) { - if (_vtx_decl.color_offset[i] != -1) { - if (i == 0) - CallCdeclFunction4_I(glColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]); - else - CallCdeclFunction4((void *)glSecondaryColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]); - } - } - - for (int i = 0; i < 8; i++) { - if (_vtx_decl.texcoord_offset[i] != -1) { - int id = GL_TEXTURE0 + i; -#ifdef _M_X64 -#ifdef _MSC_VER - MOV(32, R(RCX), Imm32(id)); -#else - MOV(32, R(RDI), Imm32(id)); -#endif -#else - ABI_AlignStack(1 * 4); - PUSH(32, Imm32(id)); -#endif - CALL((void *)glClientActiveTexture); -#ifndef _M_X64 -#ifdef _WIN32 - // don't inc stack on windows, stdcall -#else - ABI_RestoreStack(1 * 4); -#endif -#endif - CallCdeclFunction4_I( - glTexCoordPointer, _vtx_decl.texcoord_size[i], VarToGL(_vtx_decl.texcoord_gl_type[i]), - _vtx_decl.stride, _vtx_decl.texcoord_offset[i]); - } - } - - if (_vtx_decl.posmtx_offset != -1) { - CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, _vtx_decl.stride, _vtx_decl.posmtx_offset); - } - - ABI_EmitEpilogue(6); - if (Gen::GetCodePtr() - (u8*)m_compiledCode > COMPILED_CODE_SIZE) - { - Crash(); - } - - SetCodePtr(old_code_ptr); -#endif - this->vtx_decl = _vtx_decl; -} - -void NativeVertexFormat::SetupVertexPointers() const { - // Cast a pointer to compiled code to a pointer to a function taking no parameters, through a (void *) cast first to - // get around type checking errors, and call it. -#ifdef USE_JIT - ((void (*)())(void*)m_compiledCode)(); -#else - glVertexPointer(3, GL_FLOAT, vtx_decl.stride, 0); - if (vtx_decl.num_normals >= 1) { - glNormalPointer(VarToGL(vtx_decl.normal_gl_type), vtx_decl.stride, (void *)vtx_decl.normal_offset[0]); - if (vtx_decl.num_normals == 3) { - glVertexAttribPointer(SHADER_NORM1_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)vtx_decl.normal_offset[1]); - glVertexAttribPointer(SHADER_NORM2_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)vtx_decl.normal_offset[2]); - } - } - - for (int i = 0; i < 2; i++) { - if (vtx_decl.color_offset[i] != -1) { - if (i == 0) - glColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)vtx_decl.color_offset[i]); - else - glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)vtx_decl.color_offset[i]); - } - } - - for (int i = 0; i < 8; i++) { - if (vtx_decl.texcoord_offset[i] != -1) { - int id = GL_TEXTURE0 + i; - glClientActiveTexture(id); - glTexCoordPointer(vtx_decl.texcoord_size[i], VarToGL(vtx_decl.texcoord_gl_type[i]), - vtx_decl.stride, (void *)vtx_decl.texcoord_offset[i]); - } - } - - if (vtx_decl.posmtx_offset != -1) { - glVertexAttribPointer(SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, vtx_decl.stride, (void *)vtx_decl.posmtx_offset); - } -#endif -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "GLUtil.h" +#include "Profiler.h" +#include "x64Emitter.h" +#include "ABI.h" +#include "MemoryUtil.h" +#include "VertexShader.h" + +#include "CPMemory.h" +#include "NativeVertexFormat.h" + +#define COMPILED_CODE_SIZE 4096 + +#ifdef _WIN32 +#define USE_JIT +#endif + +// Note the use of CallCdeclFunction3I etc. +// This is a horrible hack that is necessary because in 64-bit mode, Opengl32.dll is based way, way above the 32-bit +// address space that is within reach of a CALL, and just doing &fn gives us these high uncallable addresses. So we +// want to grab the function pointers from the import table instead. + +// This problem does not apply to glew functions, only core opengl32 functions. + +// Here's some global state. We only use this to keep track of what we've sent to the OpenGL state +// machine. + +#ifdef USE_JIT +DECLARE_IMPORT(glNormalPointer); +DECLARE_IMPORT(glVertexPointer); +DECLARE_IMPORT(glColorPointer); +DECLARE_IMPORT(glTexCoordPointer); +#endif + +NativeVertexFormat::NativeVertexFormat() +{ +#ifdef USE_JIT + m_compiledCode = (u8 *)AllocateExecutableMemory(COMPILED_CODE_SIZE, false); + if (m_compiledCode) { + memset(m_compiledCode, 0, COMPILED_CODE_SIZE); + } +#endif +} + +NativeVertexFormat::~NativeVertexFormat() +{ +#ifdef USE_JIT + FreeMemoryPages(m_compiledCode, COMPILED_CODE_SIZE); + m_compiledCode = 0; +#endif +} + +inline GLuint VarToGL(VarType t) +{ + static const GLuint lookup[5] = {GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FLOAT}; + return lookup[t]; +} + +void NativeVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl) +{ + using namespace Gen; + + if (_vtx_decl.stride & 3) { + // We will not allow vertex components causing uneven strides. + PanicAlert("Uneven vertex stride: %i", _vtx_decl.stride); + } + +#ifdef USE_JIT + // Alright, we have our vertex declaration. Compile some crazy code to set it quickly using GL. + u8 *old_code_ptr = GetWritableCodePtr(); + SetCodePtr(m_compiledCode); + ABI_EmitPrologue(6); + + CallCdeclFunction4_I(glVertexPointer, 3, GL_FLOAT, _vtx_decl.stride, 0); + + if (_vtx_decl.num_normals >= 1) { + CallCdeclFunction3_I(glNormalPointer, VarToGL(_vtx_decl.normal_gl_type), _vtx_decl.stride, _vtx_decl.normal_offset[0]); + if (_vtx_decl.num_normals == 3) { + CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM1_ATTRIB, _vtx_decl.normal_gl_size, VarToGL(_vtx_decl.normal_gl_type), GL_TRUE, _vtx_decl.stride, _vtx_decl.normal_offset[1]); + CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM2_ATTRIB, _vtx_decl.normal_gl_size, VarToGL(_vtx_decl.normal_gl_type), GL_TRUE, _vtx_decl.stride, _vtx_decl.normal_offset[2]); + } + } + + for (int i = 0; i < 2; i++) { + if (_vtx_decl.color_offset[i] != -1) { + if (i == 0) + CallCdeclFunction4_I(glColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]); + else + CallCdeclFunction4((void *)glSecondaryColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]); + } + } + + for (int i = 0; i < 8; i++) { + if (_vtx_decl.texcoord_offset[i] != -1) { + int id = GL_TEXTURE0 + i; +#ifdef _M_X64 +#ifdef _MSC_VER + MOV(32, R(RCX), Imm32(id)); +#else + MOV(32, R(RDI), Imm32(id)); +#endif +#else + ABI_AlignStack(1 * 4); + PUSH(32, Imm32(id)); +#endif + CALL((void *)glClientActiveTexture); +#ifndef _M_X64 +#ifdef _WIN32 + // don't inc stack on windows, stdcall +#else + ABI_RestoreStack(1 * 4); +#endif +#endif + CallCdeclFunction4_I( + glTexCoordPointer, _vtx_decl.texcoord_size[i], VarToGL(_vtx_decl.texcoord_gl_type[i]), + _vtx_decl.stride, _vtx_decl.texcoord_offset[i]); + } + } + + if (_vtx_decl.posmtx_offset != -1) { + CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, _vtx_decl.stride, _vtx_decl.posmtx_offset); + } + + ABI_EmitEpilogue(6); + if (Gen::GetCodePtr() - (u8*)m_compiledCode > COMPILED_CODE_SIZE) + { + Crash(); + } + + SetCodePtr(old_code_ptr); +#endif + this->vtx_decl = _vtx_decl; +} + +void NativeVertexFormat::SetupVertexPointers() const { + // Cast a pointer to compiled code to a pointer to a function taking no parameters, through a (void *) cast first to + // get around type checking errors, and call it. +#ifdef USE_JIT + ((void (*)())(void*)m_compiledCode)(); +#else + glVertexPointer(3, GL_FLOAT, vtx_decl.stride, 0); + if (vtx_decl.num_normals >= 1) { + glNormalPointer(VarToGL(vtx_decl.normal_gl_type), vtx_decl.stride, (void *)vtx_decl.normal_offset[0]); + if (vtx_decl.num_normals == 3) { + glVertexAttribPointer(SHADER_NORM1_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)vtx_decl.normal_offset[1]); + glVertexAttribPointer(SHADER_NORM2_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)vtx_decl.normal_offset[2]); + } + } + + for (int i = 0; i < 2; i++) { + if (vtx_decl.color_offset[i] != -1) { + if (i == 0) + glColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)vtx_decl.color_offset[i]); + else + glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)vtx_decl.color_offset[i]); + } + } + + for (int i = 0; i < 8; i++) { + if (vtx_decl.texcoord_offset[i] != -1) { + int id = GL_TEXTURE0 + i; + glClientActiveTexture(id); + glTexCoordPointer(vtx_decl.texcoord_size[i], VarToGL(vtx_decl.texcoord_gl_type[i]), + vtx_decl.stride, (void *)vtx_decl.texcoord_offset[i]); + } + } + + if (vtx_decl.posmtx_offset != -1) { + glVertexAttribPointer(SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, vtx_decl.stride, (void *)vtx_decl.posmtx_offset); + } +#endif +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp b/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp index 61cd5c9f7c..69fa5929eb 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp @@ -1,293 +1,293 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -#include - -#include -#include -#include -#include -#include - -#include "../Globals.h" -#include "../Config.h" -#include "main.h" - -#include "Win32.h" -#include "Render.h" // for AddMessage - -#include "StringUtil.h" // for StringFromFormat - -void OpenConsole(); -void CloseConsole(); - -HINSTANCE g_hInstance; - -class wxDLLApp : public wxApp -{ - bool OnInit() - { - return true; - } -}; -IMPLEMENT_APP_NO_MAIN(wxDLLApp) - -WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst); - - -BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle - DWORD dwReason, // reason called - LPVOID lpvReserved) // reserved -{ - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - { //use wxInitialize() if you don't want GUI instead of the following 12 lines - wxSetInstance((HINSTANCE)hinstDLL); - int argc = 0; - char **argv = NULL; - wxEntryStart(argc, argv); - if ( !wxTheApp || !wxTheApp->CallOnInit() ) - return FALSE; - } - break; - - case DLL_PROCESS_DETACH: - CloseConsole(); - wxEntryCleanup(); //use wxUninitialize() if you don't want GUI - break; - default: - break; - } - - g_hInstance = hinstDLL; - return TRUE; -} - -void DoDllDebugger(); -extern bool gShowDebugger; -namespace EmuWindow -{ - HWND m_hWnd = NULL; - HWND m_hParent = NULL; - HINSTANCE m_hInstance = NULL; - WNDCLASSEX wndClass; - const TCHAR m_szClassName[] = "DolphinEmuWnd"; - int g_winstyle; - - // ------------------------------------------ - /* Invisible cursor option. In the lack of a predefined IDC_BLANK we make - an empty transparent cursor */ - // ------------------ - HCURSOR hCursor = NULL, hCursorBlank = NULL; - void CreateCursors(HINSTANCE hInstance) - { - BYTE ANDmaskCursor[] = { 0xff }; - BYTE XORmaskCursor[] = { 0x00 }; - hCursorBlank = CreateCursor(hInstance, 0,0, 1,1, ANDmaskCursor,XORmaskCursor); - - hCursor = LoadCursor( NULL, IDC_ARROW ); - } - - - HWND GetWnd() - { - return m_hWnd; - } - - HWND GetParentWnd() - { - return m_hParent; - } - - LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam ) - { - HDC hdc; - PAINTSTRUCT ps; - switch( iMsg ) - { - case WM_PAINT: - hdc = BeginPaint( hWnd, &ps ); - EndPaint( hWnd, &ps ); - return 0; - - case WM_KEYDOWN: - switch( LOWORD( wParam )) - { - case VK_ESCAPE: /* Pressing esc quits */ - //DestroyWindow(hWnd); - //PostQuitMessage(0); - break; - /* - case MY_KEYS: - hypotheticalScene->sendMessage(KEYDOWN...); - */ - case 'E': // EFB hotkey - if(g_Config.bEFBToTextureDisableHotKey) - { - g_Config.bEFBToTextureDisable = !g_Config.bEFBToTextureDisable; - Renderer::AddMessage(StringFromFormat("Copy EFB was turned %s", - g_Config.bEFBToTextureDisable ? "off" : "on").c_str(), 5000); - } - break; - } - g_VideoInitialize.pKeyPress(LOWORD(wParam), GetAsyncKeyState(VK_SHIFT) != 0, GetAsyncKeyState(VK_CONTROL) != 0); - break; - - /* The reason we pick up the WM_MOUSEMOVE is to be able to change this option - during gameplay. The alternative is to load one of the cursors when the plugin - is loaded and go with that. This should only produce a minimal performance hit - because SetCursor is not supposed to actually change the cursor if it's the - same as the one before. */ - case WM_MOUSEMOVE: - if(g_Config.bHideCursor) - SetCursor(hCursorBlank); - else - SetCursor(hCursor); - break; - - case WM_CLOSE: - ExitProcess(0); - - //Core::SetState(Core::CORE_UNINITIALIZED); - return 0; - - case WM_DESTROY: - //Shutdown(); - //PostQuitMessage( 0 ); - break; - - case WM_SYSCOMMAND: - switch (wParam) - { - case SC_SCREENSAVE: - case SC_MONITORPOWER: - return 0; - } - break; - } - - return DefWindowProc(hWnd, iMsg, wParam, lParam); - } - - - HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title) - { - wndClass.cbSize = sizeof( wndClass ); - wndClass.style = CS_HREDRAW | CS_VREDRAW; - wndClass.lpfnWndProc = WndProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = 0; - wndClass.hInstance = hInstance; - wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION ); - //wndClass.hCursor = LoadCursor( NULL, IDC_ARROW ); - wndClass.hCursor = NULL; // to interfer less with SetCursor() later - wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ); - wndClass.lpszMenuName = NULL; - wndClass.lpszClassName = m_szClassName; - wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION ); - - m_hInstance = hInstance; - RegisterClassEx( &wndClass ); - - CreateCursors(m_hInstance); - - if (parent) - { - m_hWnd = CreateWindow(m_szClassName, title, - WS_CHILD, - CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, - parent, NULL, hInstance, NULL ); - - m_hParent = parent; - - ShowWindow(m_hWnd, SW_SHOWMAXIMIZED); - } - else - { - DWORD style = g_Config.bFullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW; - - RECT rc = {0, 0, width, height}; - AdjustWindowRect(&rc, style, false); - - int w = rc.right - rc.left; - int h = rc.bottom - rc.top; - - rc.left = (1280 - w)/2; - rc.right = rc.left + w; - rc.top = (1024 - h)/2; - rc.bottom = rc.top + h; - - - m_hWnd = CreateWindow(m_szClassName, title, - style, - rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, - parent, NULL, hInstance, NULL ); - - g_winstyle = GetWindowLong( m_hWnd, GWL_STYLE ); - g_winstyle &= ~WS_MAXIMIZE & ~WS_MINIMIZE; // remove minimize/maximize style - - } - - return m_hWnd; - } - - void Show() - { - ShowWindow(m_hWnd, SW_SHOW); - BringWindowToTop(m_hWnd); - UpdateWindow(m_hWnd); - - // gShowDebugger from main.cpp is forgotten between the Dolphin-Debugger is opened and a game is - // started so we have to use an ini file setting here - /* - bool bVideoWindow = false; - IniFile ini; - ini.Load(DEBUGGER_CONFIG_FILE); - ini.Get("ShowOnStart", "VideoWindow", &bVideoWindow, false); - if(bVideoWindow) DoDllDebugger(); - */ - } - - HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title) - { - return OpenWindow(hParent, hInstance, 640, 480, title); - } - - void Close() - { - DestroyWindow(m_hWnd); - UnregisterClass(m_szClassName, m_hInstance); - } - - - void SetSize(int width, int height) - { - RECT rc = {0, 0, width, height}; - AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false); - - int w = rc.right - rc.left; - int h = rc.bottom - rc.top; - - rc.left = (1280 - w)/2; - rc.right = rc.left + w; - rc.top = (1024 - h)/2; - rc.bottom = rc.top + h; - ::MoveWindow(m_hWnd, rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top, TRUE); - } -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#include + +#include +#include +#include +#include +#include + +#include "../Globals.h" +#include "../Config.h" +#include "main.h" + +#include "Win32.h" +#include "Render.h" // for AddMessage + +#include "StringUtil.h" // for StringFromFormat + +void OpenConsole(); +void CloseConsole(); + +HINSTANCE g_hInstance; + +class wxDLLApp : public wxApp +{ + bool OnInit() + { + return true; + } +}; +IMPLEMENT_APP_NO_MAIN(wxDLLApp) + +WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst); + + +BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle + DWORD dwReason, // reason called + LPVOID lpvReserved) // reserved +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + { //use wxInitialize() if you don't want GUI instead of the following 12 lines + wxSetInstance((HINSTANCE)hinstDLL); + int argc = 0; + char **argv = NULL; + wxEntryStart(argc, argv); + if ( !wxTheApp || !wxTheApp->CallOnInit() ) + return FALSE; + } + break; + + case DLL_PROCESS_DETACH: + CloseConsole(); + wxEntryCleanup(); //use wxUninitialize() if you don't want GUI + break; + default: + break; + } + + g_hInstance = hinstDLL; + return TRUE; +} + +void DoDllDebugger(); +extern bool gShowDebugger; +namespace EmuWindow +{ + HWND m_hWnd = NULL; + HWND m_hParent = NULL; + HINSTANCE m_hInstance = NULL; + WNDCLASSEX wndClass; + const TCHAR m_szClassName[] = "DolphinEmuWnd"; + int g_winstyle; + + // ------------------------------------------ + /* Invisible cursor option. In the lack of a predefined IDC_BLANK we make + an empty transparent cursor */ + // ------------------ + HCURSOR hCursor = NULL, hCursorBlank = NULL; + void CreateCursors(HINSTANCE hInstance) + { + BYTE ANDmaskCursor[] = { 0xff }; + BYTE XORmaskCursor[] = { 0x00 }; + hCursorBlank = CreateCursor(hInstance, 0,0, 1,1, ANDmaskCursor,XORmaskCursor); + + hCursor = LoadCursor( NULL, IDC_ARROW ); + } + + + HWND GetWnd() + { + return m_hWnd; + } + + HWND GetParentWnd() + { + return m_hParent; + } + + LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam ) + { + HDC hdc; + PAINTSTRUCT ps; + switch( iMsg ) + { + case WM_PAINT: + hdc = BeginPaint( hWnd, &ps ); + EndPaint( hWnd, &ps ); + return 0; + + case WM_KEYDOWN: + switch( LOWORD( wParam )) + { + case VK_ESCAPE: /* Pressing esc quits */ + //DestroyWindow(hWnd); + //PostQuitMessage(0); + break; + /* + case MY_KEYS: + hypotheticalScene->sendMessage(KEYDOWN...); + */ + case 'E': // EFB hotkey + if(g_Config.bEFBToTextureDisableHotKey) + { + g_Config.bEFBToTextureDisable = !g_Config.bEFBToTextureDisable; + Renderer::AddMessage(StringFromFormat("Copy EFB was turned %s", + g_Config.bEFBToTextureDisable ? "off" : "on").c_str(), 5000); + } + break; + } + g_VideoInitialize.pKeyPress(LOWORD(wParam), GetAsyncKeyState(VK_SHIFT) != 0, GetAsyncKeyState(VK_CONTROL) != 0); + break; + + /* The reason we pick up the WM_MOUSEMOVE is to be able to change this option + during gameplay. The alternative is to load one of the cursors when the plugin + is loaded and go with that. This should only produce a minimal performance hit + because SetCursor is not supposed to actually change the cursor if it's the + same as the one before. */ + case WM_MOUSEMOVE: + if(g_Config.bHideCursor) + SetCursor(hCursorBlank); + else + SetCursor(hCursor); + break; + + case WM_CLOSE: + ExitProcess(0); + + //Core::SetState(Core::CORE_UNINITIALIZED); + return 0; + + case WM_DESTROY: + //Shutdown(); + //PostQuitMessage( 0 ); + break; + + case WM_SYSCOMMAND: + switch (wParam) + { + case SC_SCREENSAVE: + case SC_MONITORPOWER: + return 0; + } + break; + } + + return DefWindowProc(hWnd, iMsg, wParam, lParam); + } + + + HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title) + { + wndClass.cbSize = sizeof( wndClass ); + wndClass.style = CS_HREDRAW | CS_VREDRAW; + wndClass.lpfnWndProc = WndProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hInstance = hInstance; + wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION ); + //wndClass.hCursor = LoadCursor( NULL, IDC_ARROW ); + wndClass.hCursor = NULL; // to interfer less with SetCursor() later + wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ); + wndClass.lpszMenuName = NULL; + wndClass.lpszClassName = m_szClassName; + wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION ); + + m_hInstance = hInstance; + RegisterClassEx( &wndClass ); + + CreateCursors(m_hInstance); + + if (parent) + { + m_hWnd = CreateWindow(m_szClassName, title, + WS_CHILD, + CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, + parent, NULL, hInstance, NULL ); + + m_hParent = parent; + + ShowWindow(m_hWnd, SW_SHOWMAXIMIZED); + } + else + { + DWORD style = g_Config.bFullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW; + + RECT rc = {0, 0, width, height}; + AdjustWindowRect(&rc, style, false); + + int w = rc.right - rc.left; + int h = rc.bottom - rc.top; + + rc.left = (1280 - w)/2; + rc.right = rc.left + w; + rc.top = (1024 - h)/2; + rc.bottom = rc.top + h; + + + m_hWnd = CreateWindow(m_szClassName, title, + style, + rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, + parent, NULL, hInstance, NULL ); + + g_winstyle = GetWindowLong( m_hWnd, GWL_STYLE ); + g_winstyle &= ~WS_MAXIMIZE & ~WS_MINIMIZE; // remove minimize/maximize style + + } + + return m_hWnd; + } + + void Show() + { + ShowWindow(m_hWnd, SW_SHOW); + BringWindowToTop(m_hWnd); + UpdateWindow(m_hWnd); + + // gShowDebugger from main.cpp is forgotten between the Dolphin-Debugger is opened and a game is + // started so we have to use an ini file setting here + /* + bool bVideoWindow = false; + IniFile ini; + ini.Load(DEBUGGER_CONFIG_FILE); + ini.Get("ShowOnStart", "VideoWindow", &bVideoWindow, false); + if(bVideoWindow) DoDllDebugger(); + */ + } + + HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title) + { + return OpenWindow(hParent, hInstance, 640, 480, title); + } + + void Close() + { + DestroyWindow(m_hWnd); + UnregisterClass(m_szClassName, m_hInstance); + } + + + void SetSize(int width, int height) + { + RECT rc = {0, 0, width, height}; + AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false); + + int w = rc.right - rc.left; + int h = rc.bottom - rc.top; + + rc.left = (1280 - w)/2; + rc.right = rc.left + w; + rc.top = (1024 - h)/2; + rc.bottom = rc.top + h; + ::MoveWindow(m_hWnd, rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top, TRUE); + } +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/OpcodeDecoding.cpp b/Source/Plugins/Plugin_VideoOGL/Src/OpcodeDecoding.cpp index 4c813734d7..a9f06a5ff0 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/OpcodeDecoding.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/OpcodeDecoding.cpp @@ -1,317 +1,317 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -//DL facts: -// Ikaruga uses (nearly) NO display lists! -// Zelda WW uses TONS of display lists -// Zelda TP uses almost 100% display lists except menus (we like this!) - -// Note that it IS NOT GENERALLY POSSIBLE to precompile display lists! You can compile them as they are -// and hope that the vertex format doesn't change, though, if you do it just when they are -// called. The reason is that the vertex format affects the sizes of the vertices. - -#include "Globals.h" -#include "Profiler.h" -#include "OpcodeDecoding.h" - -#include "VertexLoader.h" -#include "VertexLoaderManager.h" -#include "VertexManager.h" -#include "VertexShaderManager.h" - -#include "Statistics.h" - -#include "BPStructs.h" -#include "Fifo.h" -#include "DataReader.h" - -u8* g_pVideoData = 0; - -extern u8* FAKE_GetFifoStartPtr(); -extern u8* FAKE_GetFifoEndPtr(); - -static void Decode(); - -static void ExecuteDisplayList(u32 address, u32 size) -{ - u8* old_pVideoData = g_pVideoData; - - u8* startAddress = Memory_GetPtr(address); - - //Avoid the crash if Memory_GetPtr failed .. - if (startAddress!=0) - { - g_pVideoData = startAddress; - - // temporarily swap dl and non-dl (small "hack" for the stats) - Statistics::SwapDL(); - - while ((u32)(g_pVideoData - startAddress) < size) - { - Decode(); - } - INCSTAT(stats.numDListsCalled); - INCSTAT(stats.thisFrame.numDListsCalled); - - // un-swap - Statistics::SwapDL(); - } - - // reset to the old pointer - g_pVideoData = old_pVideoData; -} - -bool FifoCommandRunnable() -{ - u32 iBufferSize = (u32)(FAKE_GetFifoEndPtr() - g_pVideoData); - if (iBufferSize == 0) - return false; // can't peek - - u8 Cmd = DataPeek8(0); - u32 iCommandSize = 0; - - switch (Cmd) - { - case GX_NOP: - // Hm, this means that we scan over nop streams pretty slowly... - iCommandSize = 1; - break; - - case GX_LOAD_CP_REG: - iCommandSize = 6; - break; - - case GX_LOAD_INDX_A: - case GX_LOAD_INDX_B: - case GX_LOAD_INDX_C: - case GX_LOAD_INDX_D: - iCommandSize = 5; - break; - - case GX_CMD_CALL_DL: - iCommandSize = 9; - break; - - case 0x44: - iCommandSize = 1; - // zelda 4 swords calls it and checks the metrics registers after that - break; - - case GX_CMD_INVL_VC: // invalid vertex cache - no parameter? - iCommandSize = 1; - break; - - case GX_LOAD_BP_REG: - iCommandSize = 5; - break; - - case GX_LOAD_XF_REG: - { - // check if we can read the header - if (iBufferSize >= 5) - { - iCommandSize = 1 + 4; - u32 Cmd2 = DataPeek32(1); - int dwTransferSize = ((Cmd2 >> 16) & 15) + 1; - iCommandSize += dwTransferSize * 4; - } - else - { - return false; - } - } - break; - - default: - if (Cmd & 0x80) - { - // check if we can read the header - if (iBufferSize >= 3) - { - iCommandSize = 1 + 2; - u16 numVertices = DataPeek16(1); - iCommandSize += numVertices * VertexLoaderManager::GetVertexSize(Cmd & GX_VAT_MASK); - } - else - { - return false; - } - } - else - { - char szTemp[1024]; - sprintf(szTemp, "GFX: Unknown Opcode (0x%x).\n" - "This means one of the following:\n" - "* The emulated GPU got desynced, disabling dual core can help\n" - "* Command stream corrupted by some spurious memory bug\n" - "* This really is an unknown opcode (unlikely)\n" - "* Some other sort of bug\n\n" - "Dolphin will now likely crash or hang. Enjoy." , Cmd); - g_VideoInitialize.pSysMessage(szTemp); - g_VideoInitialize.pLog(szTemp, TRUE); - { - SCPFifoStruct &fifo = *g_VideoInitialize.pCPFifo; - - char szTmp[256]; - // sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr()); - sprintf(szTmp, "Illegal command %02x\n" - "CPBase: 0x%08x\n" - "CPEnd: 0x%08x\n" - "CPHiWatermark: 0x%08x\n" - "CPLoWatermark: 0x%08x\n" - "CPReadWriteDistance: 0x%08x\n" - "CPWritePointer: 0x%08x\n" - "CPReadPointer: 0x%08x\n" - "CPBreakpoint: 0x%08x\n" - "bFF_GPReadEnable: %s\n" - "bFF_BPEnable: %s\n" - "bFF_GPLinkEnable: %s\n" - "bFF_Breakpoint: %s\n" - ,Cmd, fifo.CPBase, fifo.CPEnd, fifo.CPHiWatermark, fifo.CPLoWatermark, fifo.CPReadWriteDistance - ,fifo.CPWritePointer, fifo.CPReadPointer, fifo.CPBreakpoint, fifo.bFF_GPReadEnable ? "true" : "false" - ,fifo.bFF_BPEnable ? "true" : "false" ,fifo.bFF_GPLinkEnable ? "true" : "false" - ,fifo.bFF_Breakpoint ? "true" : "false"); - - g_VideoInitialize.pSysMessage(szTmp); - g_VideoInitialize.pLog(szTmp, TRUE); - // _assert_msg_(0,szTmp,""); - - } - } - break; - } - - if (iCommandSize > iBufferSize) - return false; - - // INFO_LOG("OP detected: Cmd 0x%x size %i buffer %i",Cmd, iCommandSize, iBufferSize); - - return true; -} - -static void Decode() -{ - int Cmd = DataReadU8(); - switch(Cmd) - { - case GX_NOP: - break; - - case GX_LOAD_CP_REG: //0x08 - { - u32 SubCmd = DataReadU8(); - u32 Value = DataReadU32(); - LoadCPReg(SubCmd, Value); - INCSTAT(stats.thisFrame.numCPLoads); - } - break; - - case GX_LOAD_XF_REG: - { - u32 Cmd2 = DataReadU32(); - int dwTransferSize = ((Cmd2 >> 16) & 15) + 1; - u32 dwAddress = Cmd2 & 0xFFFF; - // TODO - speed this up. pshufb? - static u32 pData[16]; - for (int i = 0; i < dwTransferSize; i++) - pData[i] = DataReadU32(); - LoadXFReg(dwTransferSize, dwAddress, pData); - INCSTAT(stats.thisFrame.numXFLoads); - } - break; - - case GX_LOAD_INDX_A: //used for position matrices - LoadIndexedXF(DataReadU32(), 0xC); - break; - case GX_LOAD_INDX_B: //used for normal matrices - LoadIndexedXF(DataReadU32(), 0xD); - break; - case GX_LOAD_INDX_C: //used for postmatrices - LoadIndexedXF(DataReadU32(), 0xE); - break; - case GX_LOAD_INDX_D: //used for lights - LoadIndexedXF(DataReadU32(), 0xF); - break; - - case GX_CMD_CALL_DL: - { - u32 dwAddr = DataReadU32(); - u32 dwCount = DataReadU32(); - ExecuteDisplayList(dwAddr, dwCount); - } - break; - - case 0x44: - // zelda 4 swords calls it and checks the metrics registers after that - break; - - case GX_CMD_INVL_VC:// Invalidate (vertex cache?) - DebugLog("Invalidate (vertex cache?)"); - break; - - case GX_LOAD_BP_REG: //0x61 - { - u32 cmd = DataReadU32(); - LoadBPReg(cmd); - INCSTAT(stats.thisFrame.numBPLoads); - } - break; - - // draw primitives - default: - if (Cmd & 0x80) - { - // load vertices (use computed vertex size from FifoCommandRunnable above) - u16 numVertices = DataReadU16(); - VertexLoaderManager::RunVertices( - Cmd & GX_VAT_MASK, // Vertex loader index (0 - 7) - (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, - numVertices); - } - else - { - // char szTmp[256]; - //sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr()); - //g_VideoInitialize.pLog(szTmp); - //MessageBox(0,szTmp,"GFX ERROR",0); - // _assert_msg_(0,szTmp,""); - break; - } - break; - } -} - -void OpcodeDecoder_Init() -{ - g_pVideoData = FAKE_GetFifoStartPtr(); -} - - -void OpcodeDecoder_Shutdown() -{ -} - -void OpcodeDecoder_Run() -{ - DVSTARTPROFILE(); - while (FifoCommandRunnable()) - { - //TODO?: if really needed, do something like this: "InterlockedExchange((LONG*)&_fifo.CPCmdIdle, 0);" - Decode(); - } - //TODO?: if really needed, do something like this: "InterlockedExchange((LONG*)&_fifo.CPCmdIdle, 1);" -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +//DL facts: +// Ikaruga uses (nearly) NO display lists! +// Zelda WW uses TONS of display lists +// Zelda TP uses almost 100% display lists except menus (we like this!) + +// Note that it IS NOT GENERALLY POSSIBLE to precompile display lists! You can compile them as they are +// and hope that the vertex format doesn't change, though, if you do it just when they are +// called. The reason is that the vertex format affects the sizes of the vertices. + +#include "Globals.h" +#include "Profiler.h" +#include "OpcodeDecoding.h" + +#include "VertexLoader.h" +#include "VertexLoaderManager.h" +#include "VertexManager.h" +#include "VertexShaderManager.h" + +#include "Statistics.h" + +#include "BPStructs.h" +#include "Fifo.h" +#include "DataReader.h" + +u8* g_pVideoData = 0; + +extern u8* FAKE_GetFifoStartPtr(); +extern u8* FAKE_GetFifoEndPtr(); + +static void Decode(); + +static void ExecuteDisplayList(u32 address, u32 size) +{ + u8* old_pVideoData = g_pVideoData; + + u8* startAddress = Memory_GetPtr(address); + + //Avoid the crash if Memory_GetPtr failed .. + if (startAddress!=0) + { + g_pVideoData = startAddress; + + // temporarily swap dl and non-dl (small "hack" for the stats) + Statistics::SwapDL(); + + while ((u32)(g_pVideoData - startAddress) < size) + { + Decode(); + } + INCSTAT(stats.numDListsCalled); + INCSTAT(stats.thisFrame.numDListsCalled); + + // un-swap + Statistics::SwapDL(); + } + + // reset to the old pointer + g_pVideoData = old_pVideoData; +} + +bool FifoCommandRunnable() +{ + u32 iBufferSize = (u32)(FAKE_GetFifoEndPtr() - g_pVideoData); + if (iBufferSize == 0) + return false; // can't peek + + u8 Cmd = DataPeek8(0); + u32 iCommandSize = 0; + + switch (Cmd) + { + case GX_NOP: + // Hm, this means that we scan over nop streams pretty slowly... + iCommandSize = 1; + break; + + case GX_LOAD_CP_REG: + iCommandSize = 6; + break; + + case GX_LOAD_INDX_A: + case GX_LOAD_INDX_B: + case GX_LOAD_INDX_C: + case GX_LOAD_INDX_D: + iCommandSize = 5; + break; + + case GX_CMD_CALL_DL: + iCommandSize = 9; + break; + + case 0x44: + iCommandSize = 1; + // zelda 4 swords calls it and checks the metrics registers after that + break; + + case GX_CMD_INVL_VC: // invalid vertex cache - no parameter? + iCommandSize = 1; + break; + + case GX_LOAD_BP_REG: + iCommandSize = 5; + break; + + case GX_LOAD_XF_REG: + { + // check if we can read the header + if (iBufferSize >= 5) + { + iCommandSize = 1 + 4; + u32 Cmd2 = DataPeek32(1); + int dwTransferSize = ((Cmd2 >> 16) & 15) + 1; + iCommandSize += dwTransferSize * 4; + } + else + { + return false; + } + } + break; + + default: + if (Cmd & 0x80) + { + // check if we can read the header + if (iBufferSize >= 3) + { + iCommandSize = 1 + 2; + u16 numVertices = DataPeek16(1); + iCommandSize += numVertices * VertexLoaderManager::GetVertexSize(Cmd & GX_VAT_MASK); + } + else + { + return false; + } + } + else + { + char szTemp[1024]; + sprintf(szTemp, "GFX: Unknown Opcode (0x%x).\n" + "This means one of the following:\n" + "* The emulated GPU got desynced, disabling dual core can help\n" + "* Command stream corrupted by some spurious memory bug\n" + "* This really is an unknown opcode (unlikely)\n" + "* Some other sort of bug\n\n" + "Dolphin will now likely crash or hang. Enjoy." , Cmd); + g_VideoInitialize.pSysMessage(szTemp); + g_VideoInitialize.pLog(szTemp, TRUE); + { + SCPFifoStruct &fifo = *g_VideoInitialize.pCPFifo; + + char szTmp[256]; + // sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr()); + sprintf(szTmp, "Illegal command %02x\n" + "CPBase: 0x%08x\n" + "CPEnd: 0x%08x\n" + "CPHiWatermark: 0x%08x\n" + "CPLoWatermark: 0x%08x\n" + "CPReadWriteDistance: 0x%08x\n" + "CPWritePointer: 0x%08x\n" + "CPReadPointer: 0x%08x\n" + "CPBreakpoint: 0x%08x\n" + "bFF_GPReadEnable: %s\n" + "bFF_BPEnable: %s\n" + "bFF_GPLinkEnable: %s\n" + "bFF_Breakpoint: %s\n" + ,Cmd, fifo.CPBase, fifo.CPEnd, fifo.CPHiWatermark, fifo.CPLoWatermark, fifo.CPReadWriteDistance + ,fifo.CPWritePointer, fifo.CPReadPointer, fifo.CPBreakpoint, fifo.bFF_GPReadEnable ? "true" : "false" + ,fifo.bFF_BPEnable ? "true" : "false" ,fifo.bFF_GPLinkEnable ? "true" : "false" + ,fifo.bFF_Breakpoint ? "true" : "false"); + + g_VideoInitialize.pSysMessage(szTmp); + g_VideoInitialize.pLog(szTmp, TRUE); + // _assert_msg_(0,szTmp,""); + + } + } + break; + } + + if (iCommandSize > iBufferSize) + return false; + + // INFO_LOG("OP detected: Cmd 0x%x size %i buffer %i",Cmd, iCommandSize, iBufferSize); + + return true; +} + +static void Decode() +{ + int Cmd = DataReadU8(); + switch(Cmd) + { + case GX_NOP: + break; + + case GX_LOAD_CP_REG: //0x08 + { + u32 SubCmd = DataReadU8(); + u32 Value = DataReadU32(); + LoadCPReg(SubCmd, Value); + INCSTAT(stats.thisFrame.numCPLoads); + } + break; + + case GX_LOAD_XF_REG: + { + u32 Cmd2 = DataReadU32(); + int dwTransferSize = ((Cmd2 >> 16) & 15) + 1; + u32 dwAddress = Cmd2 & 0xFFFF; + // TODO - speed this up. pshufb? + static u32 pData[16]; + for (int i = 0; i < dwTransferSize; i++) + pData[i] = DataReadU32(); + LoadXFReg(dwTransferSize, dwAddress, pData); + INCSTAT(stats.thisFrame.numXFLoads); + } + break; + + case GX_LOAD_INDX_A: //used for position matrices + LoadIndexedXF(DataReadU32(), 0xC); + break; + case GX_LOAD_INDX_B: //used for normal matrices + LoadIndexedXF(DataReadU32(), 0xD); + break; + case GX_LOAD_INDX_C: //used for postmatrices + LoadIndexedXF(DataReadU32(), 0xE); + break; + case GX_LOAD_INDX_D: //used for lights + LoadIndexedXF(DataReadU32(), 0xF); + break; + + case GX_CMD_CALL_DL: + { + u32 dwAddr = DataReadU32(); + u32 dwCount = DataReadU32(); + ExecuteDisplayList(dwAddr, dwCount); + } + break; + + case 0x44: + // zelda 4 swords calls it and checks the metrics registers after that + break; + + case GX_CMD_INVL_VC:// Invalidate (vertex cache?) + DebugLog("Invalidate (vertex cache?)"); + break; + + case GX_LOAD_BP_REG: //0x61 + { + u32 cmd = DataReadU32(); + LoadBPReg(cmd); + INCSTAT(stats.thisFrame.numBPLoads); + } + break; + + // draw primitives + default: + if (Cmd & 0x80) + { + // load vertices (use computed vertex size from FifoCommandRunnable above) + u16 numVertices = DataReadU16(); + VertexLoaderManager::RunVertices( + Cmd & GX_VAT_MASK, // Vertex loader index (0 - 7) + (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, + numVertices); + } + else + { + // char szTmp[256]; + //sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr()); + //g_VideoInitialize.pLog(szTmp); + //MessageBox(0,szTmp,"GFX ERROR",0); + // _assert_msg_(0,szTmp,""); + break; + } + break; + } +} + +void OpcodeDecoder_Init() +{ + g_pVideoData = FAKE_GetFifoStartPtr(); +} + + +void OpcodeDecoder_Shutdown() +{ +} + +void OpcodeDecoder_Run() +{ + DVSTARTPROFILE(); + while (FifoCommandRunnable()) + { + //TODO?: if really needed, do something like this: "InterlockedExchange((LONG*)&_fifo.CPCmdIdle, 0);" + Decode(); + } + //TODO?: if really needed, do something like this: "InterlockedExchange((LONG*)&_fifo.CPCmdIdle, 1);" +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderManager.cpp index dd3c11fc78..09dab621eb 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderManager.cpp @@ -1,615 +1,615 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Globals.h" -#include "Profiler.h" - -#include "GLUtil.h" - -#include -#include - -#include - -#include "Statistics.h" -#include "Config.h" -#include "ImageWrite.h" -#include "Common.h" -#include "Render.h" -#include "VertexShader.h" -#include "PixelShaderManager.h" -#include "PixelShader.h" - -PixelShaderMngr::PSCache PixelShaderMngr::pshaders; -FRAGMENTSHADER* PixelShaderMngr::pShaderLast = NULL; -PIXELSHADERUID PixelShaderMngr::s_curuid; - -static int s_nMaxPixelInstructions; -static int s_nColorsChanged[2]; // 0 - regular colors, 1 - k colors -static int s_nIndTexMtxChanged = 0; -static bool s_bAlphaChanged, s_bZBiasChanged, s_bIndTexScaleChanged; -static float lastRGBAfull[2][4][4]; -static u8 s_nTexDimsChanged; -static u32 lastAlpha = 0; -static u32 lastTexDims[8]={0}; -static u32 lastZBias = 0; - -// lower byte describes if a texture is nonpow2 or pow2 -// next byte describes whether the repeat wrap mode is enabled for the s channel -// next byte is for t channel -u32 s_texturemask = 0; - -static int maptocoord[8]; // indexed by texture map, holds the texcoord associated with the map -static u32 maptocoord_mask=0; - -static GLuint s_ColorMatrixProgram=0; - -void PixelShaderMngr::SetPSConstant4f(int const_number, float f1, float f2, float f3, float f4) { - glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f1, f2, f3, f4); -} - -void PixelShaderMngr::SetPSConstant4fv(int const_number, const float *f) { - glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f); -} - -void PixelShaderMngr::Init() -{ - s_nColorsChanged[0] = s_nColorsChanged[1] = 0; - s_nTexDimsChanged = 0; - s_nIndTexMtxChanged = 15; - s_bAlphaChanged = s_bZBiasChanged = s_bIndTexScaleChanged = true; - GL_REPORT_ERRORD(); - for (int i = 0; i < 8; ++i) maptocoord[i] = -1; - maptocoord_mask = 0; - memset(lastRGBAfull, 0, sizeof(lastRGBAfull)); - - glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, (GLint *)&s_nMaxPixelInstructions); - - int maxinst, maxattribs; - glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&maxinst); - glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, (GLint *)&maxattribs); - ERROR_LOG("pixel max_alu=%d, max_inst=%d, max_attrib=%d\n", s_nMaxPixelInstructions, maxinst, maxattribs); - - char pmatrixprog[1024]; - sprintf(pmatrixprog, "!!ARBfp1.0" - "TEMP R0;\n" - "TEMP R1;\n" - "TEX R0, fragment.texcoord[0], texture[0], RECT;\n" - "DP4 R1.w, R0, program.env[%d];\n" - "DP4 R1.z, R0, program.env[%d];\n" - "DP4 R1.x, R0, program.env[%d];\n" - "DP4 R1.y, R0, program.env[%d];\n" - "ADD result.color, R1, program.env[%d];\n" - "END\n", C_COLORMATRIX+3, C_COLORMATRIX+2, C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+4); - glGenProgramsARB(1, &s_ColorMatrixProgram); - glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, s_ColorMatrixProgram); - glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pmatrixprog), pmatrixprog); - - GLenum err = GL_NO_ERROR; - GL_REPORT_ERROR(); - if (err != GL_NO_ERROR) { - ERROR_LOG("Failed to create color matrix fragment program\n"); - glDeleteProgramsARB(1, &s_ColorMatrixProgram); - s_ColorMatrixProgram = 0; - } -} - -void PixelShaderMngr::Shutdown() -{ - glDeleteProgramsARB(1, &s_ColorMatrixProgram); - s_ColorMatrixProgram = 0; - PSCache::iterator iter = pshaders.begin(); - for (; iter != pshaders.end(); iter++) - iter->second.Destroy(); - pshaders.clear(); -} - -FRAGMENTSHADER* PixelShaderMngr::GetShader() -{ - DVSTARTPROFILE(); - PIXELSHADERUID uid; - GetPixelShaderId(uid); - - PSCache::iterator iter = pshaders.find(uid); - - if (iter != pshaders.end()) { - iter->second.frameCount = frameCount; - PSCacheEntry &entry = iter->second; - if (&entry.shader != pShaderLast) - { - pShaderLast = &entry.shader; - } - return pShaderLast; - } - - PSCacheEntry& newentry = pshaders[uid]; - char *code = GeneratePixelShader(s_texturemask, - Renderer::GetZBufferTarget() != 0, - Renderer::GetRenderMode() != Renderer::RM_Normal); - -#if defined(_DEBUG) || defined(DEBUGFAST) - if (g_Config.iLog & CONF_SAVESHADERS && code) { - static int counter = 0; - char szTemp[MAX_PATH]; - sprintf(szTemp, "%s/ps_%04i.txt", g_Config.texDumpPath, counter++); - - SaveData(szTemp, code); - } -#endif - - // printf("Compiling pixel shader. size = %i\n", strlen(code)); - if (!code || !CompilePixelShader(newentry.shader, code)) { - ERROR_LOG("failed to create pixel shader\n"); - return NULL; - } - - //Make an entry in the table - newentry.frameCount = frameCount; - - pShaderLast = &newentry.shader; - INCSTAT(stats.numPixelShadersCreated); - SETSTAT(stats.numPixelShadersAlive, pshaders.size()); - return pShaderLast; -} - -void PixelShaderMngr::Cleanup() -{ - PSCache::iterator iter = pshaders.begin(); - while (iter != pshaders.end()) { - PSCacheEntry &entry = iter->second; - if (entry.frameCount < frameCount - 400) { - entry.Destroy(); -#ifdef _WIN32 - iter = pshaders.erase(iter); -#else - pshaders.erase(iter++); // (this is gcc standard!) -#endif - } - else - iter++; - } - SETSTAT(stats.numPixelShadersAlive,(int)pshaders.size()); -} - -bool PixelShaderMngr::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram) -{ - char stropt[64]; - sprintf(stropt, "MaxLocalParams=32,NumInstructionSlots=%d", s_nMaxPixelInstructions); - const char* opts[] = {"-profileopts", stropt, "-O2", "-q", NULL}; - CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts); - if (!cgIsProgram(tempprog) || cgGetError() != CG_NO_ERROR) { - ERROR_LOG("Failed to create ps %s:\n", cgGetLastListing(g_cgcontext)); - ERROR_LOG(pstrprogram); - return false; - } - - char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM); - char *plocal = strstr(pcompiledprog, "program.local"); - while (plocal != NULL) { - const char* penv = " program.env"; - memcpy(plocal, penv, 13); - plocal = strstr(plocal+13, "program.local"); - } - - if (Renderer::IsUsingATIDrawBuffers()) { - // sometimes compilation can use ARB_draw_buffers, which would fail for ATI cards - // replace the three characters ARB with ATI. TODO - check whether this is fixed in modern ATI drivers. - char* poptions = strstr(pcompiledprog, "ARB_draw_buffers"); - if (poptions != NULL) { - poptions[0] = 'A'; - poptions[1] = 'T'; - poptions[2] = 'I'; - } - } - - //ERROR_LOG(pcompiledprog); - //ERROR_LOG(pstrprogram); - glGenProgramsARB( 1, &ps.glprogid ); - glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, ps.glprogid ); - glProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog); - - GLenum err = GL_NO_ERROR; - GL_REPORT_ERROR(); - if (err != GL_NO_ERROR) { - ERROR_LOG(pstrprogram); - ERROR_LOG(pcompiledprog); - } - - cgDestroyProgram(tempprog); - // printf("Compiled pixel shader %i\n", ps.glprogid); - -#if defined(_DEBUG) || defined(DEBUGFAST) - ps.strprog = pstrprogram; -#endif - return true; -} - -void PixelShaderMngr::SetConstants() -{ - for (int i = 0; i < 2; ++i) { - if (s_nColorsChanged[i]) { - int baseind = i ? C_KCOLORS : C_COLORS; - for (int j = 0; j < 4; ++j) { - if (s_nColorsChanged[i] & (1 << j)) { - SetPSConstant4fv(baseind+j, &lastRGBAfull[i][j][0]); - } - } - s_nColorsChanged[i] = 0; - } - } - - u32 newmask = 0; - for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages+1; ++i) { - if (bpmem.tevorders[i/2].getEnable(i&1)) { - int texmap = bpmem.tevorders[i/2].getTexMap(i&1); - maptocoord[texmap] = bpmem.tevorders[i/2].getTexCoord(i&1); - newmask |= 1 << texmap; - SetTexDimsChanged(texmap); - } - } - - if (maptocoord_mask != newmask) { - //u32 changes = maptocoord_mask ^ newmask; - for (int i = 0; i < 8; ++i) { - if (newmask & (1 << i)) { - SetTexDimsChanged(i); - } - else { - maptocoord[i] = -1; - } - } - maptocoord_mask = newmask; - } - - if (s_nTexDimsChanged) { - for (int i = 0; i < 8; ++i) { - if (s_nTexDimsChanged & (1<>8)&0xff)/255.0f, 0, ((lastAlpha>>16)&0xff)/255.0f); - } - - if (s_bZBiasChanged) { - u32 bits; - float ffrac = 255.0f/256.0f; - float ftemp[4]; - switch (bpmem.ztex2.type) { - case 0: - bits = 8; - ftemp[0] = ffrac/(256.0f*256.0f); ftemp[1] = ffrac/256.0f; ftemp[2] = ffrac; ftemp[3] = 0; - break; - case 1: - bits = 16; - ftemp[0] = 0; ftemp[1] = ffrac/(256.0f*256.0f); ftemp[2] = ffrac/256.0f; ftemp[3] = ffrac; - break; - case 2: - bits = 24; - ftemp[0] = ffrac/(256.0f*256.0f); ftemp[1] = ffrac/256.0f; ftemp[2] = ffrac; ftemp[3] = 0; - break; - } - //ERROR_LOG("pixel=%x,%x, bias=%x\n", bpmem.zcontrol.pixel_format, bpmem.ztex2.type, lastZBias); - SetPSConstant4fv(C_ZBIAS, ftemp); - SetPSConstant4f(C_ZBIAS+1, 0, 0, 0, (float)( (((int)lastZBias<<8)>>8))/16777216.0f); - } - - // indirect incoming texture scales, update all! - if (s_bIndTexScaleChanged) { - // set as two sets of vec4s, each containing S and T of two ind stages. - float f[8]; - - for (u32 i = 0; i < bpmem.genMode.numindstages; ++i) { - int srctexmap = bpmem.tevindref.getTexMap(i); - int texcoord = bpmem.tevindref.getTexCoord(i); - TCoordInfo& tc = bpmem.texcoords[texcoord]; - - f[2*i] = bpmem.texscale[i/2].getScaleS(i&1) * - (float)(tc.s.scale_minus_1+1) / (float)(lastTexDims[srctexmap] & 0xffff); - f[2*i+1] = bpmem.texscale[i/2].getScaleT(i&1) * - (float)(tc.t.scale_minus_1+1) / (float)((lastTexDims[srctexmap] >> 16) & 0xfff); - // Yes, the above should really be 0xfff. The top 4 bits are used for other stuff. - PRIM_LOG("tex indscale%d: %f %f\n", i, f[2*i], f[2*i+1]); - } - - SetPSConstant4fv(C_INDTEXSCALE, f); - - if (bpmem.genMode.numindstages > 2) - SetPSConstant4fv(C_INDTEXSCALE+1, &f[4]); - - s_bIndTexScaleChanged = false; - } - - if (s_nIndTexMtxChanged) { - for (int i = 0; i < 3; ++i) { - if (s_nIndTexMtxChanged & (1 << i)) { - int scale = ((u32)bpmem.indmtx[i].col0.s0 << 0) | - ((u32)bpmem.indmtx[i].col1.s1 << 2) | - ((u32)bpmem.indmtx[i].col2.s2 << 4); - float fscale = powf(2.0f, (float)(scale - 17)) / 1024.0f; - - // xyz - static matrix - //TODO w - dynamic matrix scale / 256...... somehow / 4 works better - SetPSConstant4f(C_INDTEXMTX+2*i, - bpmem.indmtx[i].col0.ma * fscale, bpmem.indmtx[i].col1.mc * fscale, bpmem.indmtx[i].col2.me * fscale, fscale * 256.0f); - SetPSConstant4f(C_INDTEXMTX+2*i+1, - bpmem.indmtx[i].col0.mb * fscale, bpmem.indmtx[i].col1.md * fscale, bpmem.indmtx[i].col2.mf * fscale, fscale * 256.0f); - - PRIM_LOG("indmtx%d: scale=%f, mat=(%f %f %f; %f %f %f)\n", i, - 1024.0f*fscale, bpmem.indmtx[i].col0.ma * fscale, bpmem.indmtx[i].col1.mc * fscale, bpmem.indmtx[i].col2.me * fscale, - bpmem.indmtx[i].col0.mb * fscale, bpmem.indmtx[i].col1.md * fscale, bpmem.indmtx[i].col2.mf * fscale, fscale); - } - } - s_nIndTexMtxChanged = 0; - } -} - -void PixelShaderMngr::SetPSTextureDims(int texid) -{ - float fdims[4]; - if (s_texturemask & (1<= 0) { - TCoordInfo& tc = bpmem.texcoords[maptocoord[texid]]; - fdims[0] = (float)(lastTexDims[texid]&0xffff); - fdims[1] = (float)((lastTexDims[texid]>>16)&0xfff); - fdims[2] = (float)(tc.s.scale_minus_1+1)/(float)(lastTexDims[texid]&0xffff); - fdims[3] = (float)(tc.t.scale_minus_1+1)/(float)((lastTexDims[texid]>>16)&0xfff); - } - else { - fdims[0] = (float)(lastTexDims[texid]&0xffff); - fdims[1] = (float)((lastTexDims[texid]>>16)&0xfff); - fdims[2] = 1.0f; - fdims[3] = 1.0f; - } - } - else { - if (maptocoord[texid] >= 0) { - TCoordInfo& tc = bpmem.texcoords[maptocoord[texid]]; - fdims[0] = (float)(tc.s.scale_minus_1+1)/(float)(lastTexDims[texid]&0xffff); - fdims[1] = (float)(tc.t.scale_minus_1+1)/(float)((lastTexDims[texid]>>16)&0xfff); - fdims[2] = 1.0f/(float)(tc.s.scale_minus_1+1); - fdims[3] = 1.0f/(float)(tc.t.scale_minus_1+1); - } - else { - fdims[0] = 1.0f; - fdims[1] = 1.0f; - fdims[2] = 1.0f/(float)(lastTexDims[texid]&0xffff); - fdims[3] = 1.0f/(float)((lastTexDims[texid]>>16)&0xfff); - } - } - - PRIM_LOG("texdims%d: %f %f %f %f\n", texid, fdims[0], fdims[1], fdims[2], fdims[3]); - SetPSConstant4fv(C_TEXDIMS + texid, fdims); -} - -void PixelShaderMngr::SetColorChanged(int type, int num) -{ - int r = bpmem.tevregs[num].low.a; - int a = bpmem.tevregs[num].low.b; - int b = bpmem.tevregs[num].high.a; - int g = bpmem.tevregs[num].high.b; - float *pf = &lastRGBAfull[type][num][0]; - pf[0] = (float)r / 255.0f; - pf[1] = (float)g / 255.0f; - pf[2] = (float)b / 255.0f; - pf[3] = (float)a / 255.0f; - s_nColorsChanged[type] |= 1 << num; - PRIM_LOG("pixel %scolor%d: %f %f %f %f\n", type?"k":"", num, pf[0], pf[1], pf[2], pf[3]); -} - -void PixelShaderMngr::SetAlpha(const AlphaFunc& alpha) -{ - if ((alpha.hex & 0xffff) != lastAlpha) { - lastAlpha = (lastAlpha & ~0xffff) | (alpha.hex & 0xffff); - s_bAlphaChanged = true; - } -} - -void PixelShaderMngr::SetDestAlpha(const ConstantAlpha& alpha) -{ - if (alpha.alpha != (lastAlpha >> 16)) { - lastAlpha = (lastAlpha & ~0xff0000) | ((alpha.hex & 0xff) << 16); - s_bAlphaChanged = true; - } -} - -void PixelShaderMngr::SetTexDims(int texmapid, u32 width, u32 height, u32 wraps, u32 wrapt) -{ - u32 wh = width | (height << 16) | (wraps << 28) | (wrapt << 30); - if (lastTexDims[texmapid] != wh) { - lastTexDims[texmapid] = wh; - s_nTexDimsChanged |= 1 << texmapid; - } -} - -void PixelShaderMngr::SetZTetureBias(u32 bias) -{ - if (lastZBias != bias) { - s_bZBiasChanged = true; - lastZBias = bias; - } -} - -void PixelShaderMngr::SetIndTexScaleChanged() -{ - s_bIndTexScaleChanged = true; -} - -void PixelShaderMngr::SetIndMatrixChanged(int matrixidx) -{ - s_nIndTexMtxChanged |= 1 << matrixidx; -} - -void PixelShaderMngr::SetGenModeChanged() -{ -} - -void PixelShaderMngr::SetTevCombinerChanged(int id) -{ -} - -void PixelShaderMngr::SetTevKSelChanged(int id) -{ -} - -void PixelShaderMngr::SetTevOrderChanged(int id) -{ -} - -void PixelShaderMngr::SetTevIndirectChanged(int id) -{ -} - -void PixelShaderMngr::SetZTetureOpChanged() -{ - s_bZBiasChanged = true; -} - -void PixelShaderMngr::SetTexturesUsed(u32 nonpow2tex) -{ - if (s_texturemask != nonpow2tex) { - for (int i = 0; i < 8; ++i) { - if (nonpow2tex & (0x10101 << i)) { - // this check was previously implicit, but should it be here? - if (s_nTexDimsChanged ) - s_nTexDimsChanged |= 1 << i; - } - } - s_texturemask = nonpow2tex; - } -} - -void PixelShaderMngr::SetTexDimsChanged(int texmapid) -{ - // this check was previously implicit, but should it be here? - if (s_nTexDimsChanged) - s_nTexDimsChanged |= 1 << texmapid; - - SetIndTexScaleChanged(); -} - -void PixelShaderMngr::SetColorMatrix(const float* pmatrix, const float* pfConstAdd) -{ - SetPSConstant4fv(C_COLORMATRIX, pmatrix); - SetPSConstant4fv(C_COLORMATRIX+1, pmatrix+4); - SetPSConstant4fv(C_COLORMATRIX+2, pmatrix+8); - SetPSConstant4fv(C_COLORMATRIX+3, pmatrix+12); - SetPSConstant4fv(C_COLORMATRIX+4, pfConstAdd); -} - -GLuint PixelShaderMngr::GetColorMatrixProgram() -{ - return s_ColorMatrixProgram; -} - -// Mash together all the inputs that contribute to the code of a generated pixel shader into -// a unique identifier, basically containing all the bits. Yup, it's a lot .... -void PixelShaderMngr::GetPixelShaderId(PIXELSHADERUID &uid) -{ - u32 projtexcoords = 0; - for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; i++) { - if (bpmem.tevorders[i/2].getEnable(i&1)) { - int texcoord = bpmem.tevorders[i/2].getTexCoord(i&1); - if (xfregs.texcoords[texcoord].texmtxinfo.projection ) - projtexcoords |= 1 << texcoord; - } - } - u32 zbufrender = (Renderer::GetZBufferTarget() && bpmem.zmode.updateenable) ? 1 : 0; - u32 zBufRenderToCol0 = Renderer::GetRenderMode() != Renderer::RM_Normal; - uid.values[0] = (u32)bpmem.genMode.numtevstages | - ((u32)bpmem.genMode.numindstages << 4) | - ((u32)bpmem.genMode.numtexgens << 7) | - ((u32)bpmem.dstalpha.enable << 11) | - ((u32)((bpmem.alphaFunc.hex >> 16) & 0xff) << 12) | - (projtexcoords << 20) | - ((u32)bpmem.ztex2.op << 28) | - (zbufrender << 30) | - (zBufRenderToCol0 << 31); - - s_curuid.values[0] = (s_curuid.values[0] & ~0x0ff00000) | (projtexcoords << 20); - // swap table - for (int i = 0; i < 8; i += 2) - ((u8*)&uid.values[1])[i/2] = (bpmem.tevksel[i].hex & 0xf) | ((bpmem.tevksel[i + 1].hex & 0xf)<<4); - - uid.values[2] = s_texturemask; - int hdr = 3; - u32* pcurvalue = &uid.values[hdr]; - for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages+1; ++i) { - TevStageCombiner::ColorCombiner &cc = bpmem.combiners[i].colorC; - TevStageCombiner::AlphaCombiner &ac = bpmem.combiners[i].alphaC; - - u32 val0 = cc.hex&0xffffff; - u32 val1 = ac.hex&0xffffff; - val0 |= bpmem.tevksel[i/2].getKC(i&1)<<24; - val1 |= bpmem.tevksel[i/2].getKA(i&1)<<24; - pcurvalue[0] = val0; - pcurvalue[1] = val1; - pcurvalue += 2; - } - - for (u32 i = 0; i < ((u32)bpmem.genMode.numtevstages+1)/2; ++i) { - u32 val0, val1; - if (bpmem.tevorders[i].hex & 0x40) - val0 = bpmem.tevorders[i].hex & 0x3ff; - else - val0 = bpmem.tevorders[i].hex & 0x380; - if (bpmem.tevorders[i].hex & 0x40000) - val1 = (bpmem.tevorders[i].hex & 0x3ff000) >> 12; - else - val1 = (bpmem.tevorders[i].hex & 0x380000) >> 12; - - switch (i % 3) { - case 0: pcurvalue[0] = val0|(val1<<10); break; - case 1: pcurvalue[0] |= val0<<20; pcurvalue[1] = val1; pcurvalue++; break; - case 2: pcurvalue[1] |= (val0<<10)|(val1<<20); pcurvalue++; break; - } - } - - if ((bpmem.genMode.numtevstages + 1) & 1) { // odd - u32 val0; - if (bpmem.tevorders[bpmem.genMode.numtevstages/2].hex & 0x40) - val0 = bpmem.tevorders[bpmem.genMode.numtevstages/2].hex&0x3ff; - else - val0 = bpmem.tevorders[bpmem.genMode.numtevstages/2].hex & 0x380; - - switch (bpmem.genMode.numtevstages % 3) { - case 0: pcurvalue[0] = val0; break; - case 1: pcurvalue[0] |= val0 << 20; break; - case 2: pcurvalue[1] |= val0 << 10; pcurvalue++; break; - } - } - - if ((bpmem.genMode.numtevstages % 3) != 2) - ++pcurvalue; - - uid.tevstages = (u32)(pcurvalue-&uid.values[0]-hdr); - - for (u32 i = 0; i < bpmem.genMode.numindstages; ++i) { - u32 val = bpmem.tevind[i].hex & 0x1fffff; // 21 bits - switch (i%3) { - case 0: pcurvalue[0] = val; break; - case 1: pcurvalue[0] |= val << 21; pcurvalue[1] = val >> 11; ++pcurvalue; break; - case 2: pcurvalue[0] |= val << 10; ++pcurvalue; break; - } - } - - // yeah, well .... - uid.indstages = (u32)(pcurvalue - &uid.values[0] - 2 - uid.tevstages); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Globals.h" +#include "Profiler.h" + +#include "GLUtil.h" + +#include +#include + +#include + +#include "Statistics.h" +#include "Config.h" +#include "ImageWrite.h" +#include "Common.h" +#include "Render.h" +#include "VertexShader.h" +#include "PixelShaderManager.h" +#include "PixelShader.h" + +PixelShaderMngr::PSCache PixelShaderMngr::pshaders; +FRAGMENTSHADER* PixelShaderMngr::pShaderLast = NULL; +PIXELSHADERUID PixelShaderMngr::s_curuid; + +static int s_nMaxPixelInstructions; +static int s_nColorsChanged[2]; // 0 - regular colors, 1 - k colors +static int s_nIndTexMtxChanged = 0; +static bool s_bAlphaChanged, s_bZBiasChanged, s_bIndTexScaleChanged; +static float lastRGBAfull[2][4][4]; +static u8 s_nTexDimsChanged; +static u32 lastAlpha = 0; +static u32 lastTexDims[8]={0}; +static u32 lastZBias = 0; + +// lower byte describes if a texture is nonpow2 or pow2 +// next byte describes whether the repeat wrap mode is enabled for the s channel +// next byte is for t channel +u32 s_texturemask = 0; + +static int maptocoord[8]; // indexed by texture map, holds the texcoord associated with the map +static u32 maptocoord_mask=0; + +static GLuint s_ColorMatrixProgram=0; + +void PixelShaderMngr::SetPSConstant4f(int const_number, float f1, float f2, float f3, float f4) { + glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f1, f2, f3, f4); +} + +void PixelShaderMngr::SetPSConstant4fv(int const_number, const float *f) { + glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f); +} + +void PixelShaderMngr::Init() +{ + s_nColorsChanged[0] = s_nColorsChanged[1] = 0; + s_nTexDimsChanged = 0; + s_nIndTexMtxChanged = 15; + s_bAlphaChanged = s_bZBiasChanged = s_bIndTexScaleChanged = true; + GL_REPORT_ERRORD(); + for (int i = 0; i < 8; ++i) maptocoord[i] = -1; + maptocoord_mask = 0; + memset(lastRGBAfull, 0, sizeof(lastRGBAfull)); + + glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, (GLint *)&s_nMaxPixelInstructions); + + int maxinst, maxattribs; + glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&maxinst); + glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, (GLint *)&maxattribs); + ERROR_LOG("pixel max_alu=%d, max_inst=%d, max_attrib=%d\n", s_nMaxPixelInstructions, maxinst, maxattribs); + + char pmatrixprog[1024]; + sprintf(pmatrixprog, "!!ARBfp1.0" + "TEMP R0;\n" + "TEMP R1;\n" + "TEX R0, fragment.texcoord[0], texture[0], RECT;\n" + "DP4 R1.w, R0, program.env[%d];\n" + "DP4 R1.z, R0, program.env[%d];\n" + "DP4 R1.x, R0, program.env[%d];\n" + "DP4 R1.y, R0, program.env[%d];\n" + "ADD result.color, R1, program.env[%d];\n" + "END\n", C_COLORMATRIX+3, C_COLORMATRIX+2, C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+4); + glGenProgramsARB(1, &s_ColorMatrixProgram); + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, s_ColorMatrixProgram); + glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pmatrixprog), pmatrixprog); + + GLenum err = GL_NO_ERROR; + GL_REPORT_ERROR(); + if (err != GL_NO_ERROR) { + ERROR_LOG("Failed to create color matrix fragment program\n"); + glDeleteProgramsARB(1, &s_ColorMatrixProgram); + s_ColorMatrixProgram = 0; + } +} + +void PixelShaderMngr::Shutdown() +{ + glDeleteProgramsARB(1, &s_ColorMatrixProgram); + s_ColorMatrixProgram = 0; + PSCache::iterator iter = pshaders.begin(); + for (; iter != pshaders.end(); iter++) + iter->second.Destroy(); + pshaders.clear(); +} + +FRAGMENTSHADER* PixelShaderMngr::GetShader() +{ + DVSTARTPROFILE(); + PIXELSHADERUID uid; + GetPixelShaderId(uid); + + PSCache::iterator iter = pshaders.find(uid); + + if (iter != pshaders.end()) { + iter->second.frameCount = frameCount; + PSCacheEntry &entry = iter->second; + if (&entry.shader != pShaderLast) + { + pShaderLast = &entry.shader; + } + return pShaderLast; + } + + PSCacheEntry& newentry = pshaders[uid]; + char *code = GeneratePixelShader(s_texturemask, + Renderer::GetZBufferTarget() != 0, + Renderer::GetRenderMode() != Renderer::RM_Normal); + +#if defined(_DEBUG) || defined(DEBUGFAST) + if (g_Config.iLog & CONF_SAVESHADERS && code) { + static int counter = 0; + char szTemp[MAX_PATH]; + sprintf(szTemp, "%s/ps_%04i.txt", g_Config.texDumpPath, counter++); + + SaveData(szTemp, code); + } +#endif + + // printf("Compiling pixel shader. size = %i\n", strlen(code)); + if (!code || !CompilePixelShader(newentry.shader, code)) { + ERROR_LOG("failed to create pixel shader\n"); + return NULL; + } + + //Make an entry in the table + newentry.frameCount = frameCount; + + pShaderLast = &newentry.shader; + INCSTAT(stats.numPixelShadersCreated); + SETSTAT(stats.numPixelShadersAlive, pshaders.size()); + return pShaderLast; +} + +void PixelShaderMngr::Cleanup() +{ + PSCache::iterator iter = pshaders.begin(); + while (iter != pshaders.end()) { + PSCacheEntry &entry = iter->second; + if (entry.frameCount < frameCount - 400) { + entry.Destroy(); +#ifdef _WIN32 + iter = pshaders.erase(iter); +#else + pshaders.erase(iter++); // (this is gcc standard!) +#endif + } + else + iter++; + } + SETSTAT(stats.numPixelShadersAlive,(int)pshaders.size()); +} + +bool PixelShaderMngr::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram) +{ + char stropt[64]; + sprintf(stropt, "MaxLocalParams=32,NumInstructionSlots=%d", s_nMaxPixelInstructions); + const char* opts[] = {"-profileopts", stropt, "-O2", "-q", NULL}; + CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts); + if (!cgIsProgram(tempprog) || cgGetError() != CG_NO_ERROR) { + ERROR_LOG("Failed to create ps %s:\n", cgGetLastListing(g_cgcontext)); + ERROR_LOG(pstrprogram); + return false; + } + + char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM); + char *plocal = strstr(pcompiledprog, "program.local"); + while (plocal != NULL) { + const char* penv = " program.env"; + memcpy(plocal, penv, 13); + plocal = strstr(plocal+13, "program.local"); + } + + if (Renderer::IsUsingATIDrawBuffers()) { + // sometimes compilation can use ARB_draw_buffers, which would fail for ATI cards + // replace the three characters ARB with ATI. TODO - check whether this is fixed in modern ATI drivers. + char* poptions = strstr(pcompiledprog, "ARB_draw_buffers"); + if (poptions != NULL) { + poptions[0] = 'A'; + poptions[1] = 'T'; + poptions[2] = 'I'; + } + } + + //ERROR_LOG(pcompiledprog); + //ERROR_LOG(pstrprogram); + glGenProgramsARB( 1, &ps.glprogid ); + glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, ps.glprogid ); + glProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog); + + GLenum err = GL_NO_ERROR; + GL_REPORT_ERROR(); + if (err != GL_NO_ERROR) { + ERROR_LOG(pstrprogram); + ERROR_LOG(pcompiledprog); + } + + cgDestroyProgram(tempprog); + // printf("Compiled pixel shader %i\n", ps.glprogid); + +#if defined(_DEBUG) || defined(DEBUGFAST) + ps.strprog = pstrprogram; +#endif + return true; +} + +void PixelShaderMngr::SetConstants() +{ + for (int i = 0; i < 2; ++i) { + if (s_nColorsChanged[i]) { + int baseind = i ? C_KCOLORS : C_COLORS; + for (int j = 0; j < 4; ++j) { + if (s_nColorsChanged[i] & (1 << j)) { + SetPSConstant4fv(baseind+j, &lastRGBAfull[i][j][0]); + } + } + s_nColorsChanged[i] = 0; + } + } + + u32 newmask = 0; + for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages+1; ++i) { + if (bpmem.tevorders[i/2].getEnable(i&1)) { + int texmap = bpmem.tevorders[i/2].getTexMap(i&1); + maptocoord[texmap] = bpmem.tevorders[i/2].getTexCoord(i&1); + newmask |= 1 << texmap; + SetTexDimsChanged(texmap); + } + } + + if (maptocoord_mask != newmask) { + //u32 changes = maptocoord_mask ^ newmask; + for (int i = 0; i < 8; ++i) { + if (newmask & (1 << i)) { + SetTexDimsChanged(i); + } + else { + maptocoord[i] = -1; + } + } + maptocoord_mask = newmask; + } + + if (s_nTexDimsChanged) { + for (int i = 0; i < 8; ++i) { + if (s_nTexDimsChanged & (1<>8)&0xff)/255.0f, 0, ((lastAlpha>>16)&0xff)/255.0f); + } + + if (s_bZBiasChanged) { + u32 bits; + float ffrac = 255.0f/256.0f; + float ftemp[4]; + switch (bpmem.ztex2.type) { + case 0: + bits = 8; + ftemp[0] = ffrac/(256.0f*256.0f); ftemp[1] = ffrac/256.0f; ftemp[2] = ffrac; ftemp[3] = 0; + break; + case 1: + bits = 16; + ftemp[0] = 0; ftemp[1] = ffrac/(256.0f*256.0f); ftemp[2] = ffrac/256.0f; ftemp[3] = ffrac; + break; + case 2: + bits = 24; + ftemp[0] = ffrac/(256.0f*256.0f); ftemp[1] = ffrac/256.0f; ftemp[2] = ffrac; ftemp[3] = 0; + break; + } + //ERROR_LOG("pixel=%x,%x, bias=%x\n", bpmem.zcontrol.pixel_format, bpmem.ztex2.type, lastZBias); + SetPSConstant4fv(C_ZBIAS, ftemp); + SetPSConstant4f(C_ZBIAS+1, 0, 0, 0, (float)( (((int)lastZBias<<8)>>8))/16777216.0f); + } + + // indirect incoming texture scales, update all! + if (s_bIndTexScaleChanged) { + // set as two sets of vec4s, each containing S and T of two ind stages. + float f[8]; + + for (u32 i = 0; i < bpmem.genMode.numindstages; ++i) { + int srctexmap = bpmem.tevindref.getTexMap(i); + int texcoord = bpmem.tevindref.getTexCoord(i); + TCoordInfo& tc = bpmem.texcoords[texcoord]; + + f[2*i] = bpmem.texscale[i/2].getScaleS(i&1) * + (float)(tc.s.scale_minus_1+1) / (float)(lastTexDims[srctexmap] & 0xffff); + f[2*i+1] = bpmem.texscale[i/2].getScaleT(i&1) * + (float)(tc.t.scale_minus_1+1) / (float)((lastTexDims[srctexmap] >> 16) & 0xfff); + // Yes, the above should really be 0xfff. The top 4 bits are used for other stuff. + PRIM_LOG("tex indscale%d: %f %f\n", i, f[2*i], f[2*i+1]); + } + + SetPSConstant4fv(C_INDTEXSCALE, f); + + if (bpmem.genMode.numindstages > 2) + SetPSConstant4fv(C_INDTEXSCALE+1, &f[4]); + + s_bIndTexScaleChanged = false; + } + + if (s_nIndTexMtxChanged) { + for (int i = 0; i < 3; ++i) { + if (s_nIndTexMtxChanged & (1 << i)) { + int scale = ((u32)bpmem.indmtx[i].col0.s0 << 0) | + ((u32)bpmem.indmtx[i].col1.s1 << 2) | + ((u32)bpmem.indmtx[i].col2.s2 << 4); + float fscale = powf(2.0f, (float)(scale - 17)) / 1024.0f; + + // xyz - static matrix + //TODO w - dynamic matrix scale / 256...... somehow / 4 works better + SetPSConstant4f(C_INDTEXMTX+2*i, + bpmem.indmtx[i].col0.ma * fscale, bpmem.indmtx[i].col1.mc * fscale, bpmem.indmtx[i].col2.me * fscale, fscale * 256.0f); + SetPSConstant4f(C_INDTEXMTX+2*i+1, + bpmem.indmtx[i].col0.mb * fscale, bpmem.indmtx[i].col1.md * fscale, bpmem.indmtx[i].col2.mf * fscale, fscale * 256.0f); + + PRIM_LOG("indmtx%d: scale=%f, mat=(%f %f %f; %f %f %f)\n", i, + 1024.0f*fscale, bpmem.indmtx[i].col0.ma * fscale, bpmem.indmtx[i].col1.mc * fscale, bpmem.indmtx[i].col2.me * fscale, + bpmem.indmtx[i].col0.mb * fscale, bpmem.indmtx[i].col1.md * fscale, bpmem.indmtx[i].col2.mf * fscale, fscale); + } + } + s_nIndTexMtxChanged = 0; + } +} + +void PixelShaderMngr::SetPSTextureDims(int texid) +{ + float fdims[4]; + if (s_texturemask & (1<= 0) { + TCoordInfo& tc = bpmem.texcoords[maptocoord[texid]]; + fdims[0] = (float)(lastTexDims[texid]&0xffff); + fdims[1] = (float)((lastTexDims[texid]>>16)&0xfff); + fdims[2] = (float)(tc.s.scale_minus_1+1)/(float)(lastTexDims[texid]&0xffff); + fdims[3] = (float)(tc.t.scale_minus_1+1)/(float)((lastTexDims[texid]>>16)&0xfff); + } + else { + fdims[0] = (float)(lastTexDims[texid]&0xffff); + fdims[1] = (float)((lastTexDims[texid]>>16)&0xfff); + fdims[2] = 1.0f; + fdims[3] = 1.0f; + } + } + else { + if (maptocoord[texid] >= 0) { + TCoordInfo& tc = bpmem.texcoords[maptocoord[texid]]; + fdims[0] = (float)(tc.s.scale_minus_1+1)/(float)(lastTexDims[texid]&0xffff); + fdims[1] = (float)(tc.t.scale_minus_1+1)/(float)((lastTexDims[texid]>>16)&0xfff); + fdims[2] = 1.0f/(float)(tc.s.scale_minus_1+1); + fdims[3] = 1.0f/(float)(tc.t.scale_minus_1+1); + } + else { + fdims[0] = 1.0f; + fdims[1] = 1.0f; + fdims[2] = 1.0f/(float)(lastTexDims[texid]&0xffff); + fdims[3] = 1.0f/(float)((lastTexDims[texid]>>16)&0xfff); + } + } + + PRIM_LOG("texdims%d: %f %f %f %f\n", texid, fdims[0], fdims[1], fdims[2], fdims[3]); + SetPSConstant4fv(C_TEXDIMS + texid, fdims); +} + +void PixelShaderMngr::SetColorChanged(int type, int num) +{ + int r = bpmem.tevregs[num].low.a; + int a = bpmem.tevregs[num].low.b; + int b = bpmem.tevregs[num].high.a; + int g = bpmem.tevregs[num].high.b; + float *pf = &lastRGBAfull[type][num][0]; + pf[0] = (float)r / 255.0f; + pf[1] = (float)g / 255.0f; + pf[2] = (float)b / 255.0f; + pf[3] = (float)a / 255.0f; + s_nColorsChanged[type] |= 1 << num; + PRIM_LOG("pixel %scolor%d: %f %f %f %f\n", type?"k":"", num, pf[0], pf[1], pf[2], pf[3]); +} + +void PixelShaderMngr::SetAlpha(const AlphaFunc& alpha) +{ + if ((alpha.hex & 0xffff) != lastAlpha) { + lastAlpha = (lastAlpha & ~0xffff) | (alpha.hex & 0xffff); + s_bAlphaChanged = true; + } +} + +void PixelShaderMngr::SetDestAlpha(const ConstantAlpha& alpha) +{ + if (alpha.alpha != (lastAlpha >> 16)) { + lastAlpha = (lastAlpha & ~0xff0000) | ((alpha.hex & 0xff) << 16); + s_bAlphaChanged = true; + } +} + +void PixelShaderMngr::SetTexDims(int texmapid, u32 width, u32 height, u32 wraps, u32 wrapt) +{ + u32 wh = width | (height << 16) | (wraps << 28) | (wrapt << 30); + if (lastTexDims[texmapid] != wh) { + lastTexDims[texmapid] = wh; + s_nTexDimsChanged |= 1 << texmapid; + } +} + +void PixelShaderMngr::SetZTetureBias(u32 bias) +{ + if (lastZBias != bias) { + s_bZBiasChanged = true; + lastZBias = bias; + } +} + +void PixelShaderMngr::SetIndTexScaleChanged() +{ + s_bIndTexScaleChanged = true; +} + +void PixelShaderMngr::SetIndMatrixChanged(int matrixidx) +{ + s_nIndTexMtxChanged |= 1 << matrixidx; +} + +void PixelShaderMngr::SetGenModeChanged() +{ +} + +void PixelShaderMngr::SetTevCombinerChanged(int id) +{ +} + +void PixelShaderMngr::SetTevKSelChanged(int id) +{ +} + +void PixelShaderMngr::SetTevOrderChanged(int id) +{ +} + +void PixelShaderMngr::SetTevIndirectChanged(int id) +{ +} + +void PixelShaderMngr::SetZTetureOpChanged() +{ + s_bZBiasChanged = true; +} + +void PixelShaderMngr::SetTexturesUsed(u32 nonpow2tex) +{ + if (s_texturemask != nonpow2tex) { + for (int i = 0; i < 8; ++i) { + if (nonpow2tex & (0x10101 << i)) { + // this check was previously implicit, but should it be here? + if (s_nTexDimsChanged ) + s_nTexDimsChanged |= 1 << i; + } + } + s_texturemask = nonpow2tex; + } +} + +void PixelShaderMngr::SetTexDimsChanged(int texmapid) +{ + // this check was previously implicit, but should it be here? + if (s_nTexDimsChanged) + s_nTexDimsChanged |= 1 << texmapid; + + SetIndTexScaleChanged(); +} + +void PixelShaderMngr::SetColorMatrix(const float* pmatrix, const float* pfConstAdd) +{ + SetPSConstant4fv(C_COLORMATRIX, pmatrix); + SetPSConstant4fv(C_COLORMATRIX+1, pmatrix+4); + SetPSConstant4fv(C_COLORMATRIX+2, pmatrix+8); + SetPSConstant4fv(C_COLORMATRIX+3, pmatrix+12); + SetPSConstant4fv(C_COLORMATRIX+4, pfConstAdd); +} + +GLuint PixelShaderMngr::GetColorMatrixProgram() +{ + return s_ColorMatrixProgram; +} + +// Mash together all the inputs that contribute to the code of a generated pixel shader into +// a unique identifier, basically containing all the bits. Yup, it's a lot .... +void PixelShaderMngr::GetPixelShaderId(PIXELSHADERUID &uid) +{ + u32 projtexcoords = 0; + for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; i++) { + if (bpmem.tevorders[i/2].getEnable(i&1)) { + int texcoord = bpmem.tevorders[i/2].getTexCoord(i&1); + if (xfregs.texcoords[texcoord].texmtxinfo.projection ) + projtexcoords |= 1 << texcoord; + } + } + u32 zbufrender = (Renderer::GetZBufferTarget() && bpmem.zmode.updateenable) ? 1 : 0; + u32 zBufRenderToCol0 = Renderer::GetRenderMode() != Renderer::RM_Normal; + uid.values[0] = (u32)bpmem.genMode.numtevstages | + ((u32)bpmem.genMode.numindstages << 4) | + ((u32)bpmem.genMode.numtexgens << 7) | + ((u32)bpmem.dstalpha.enable << 11) | + ((u32)((bpmem.alphaFunc.hex >> 16) & 0xff) << 12) | + (projtexcoords << 20) | + ((u32)bpmem.ztex2.op << 28) | + (zbufrender << 30) | + (zBufRenderToCol0 << 31); + + s_curuid.values[0] = (s_curuid.values[0] & ~0x0ff00000) | (projtexcoords << 20); + // swap table + for (int i = 0; i < 8; i += 2) + ((u8*)&uid.values[1])[i/2] = (bpmem.tevksel[i].hex & 0xf) | ((bpmem.tevksel[i + 1].hex & 0xf)<<4); + + uid.values[2] = s_texturemask; + int hdr = 3; + u32* pcurvalue = &uid.values[hdr]; + for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages+1; ++i) { + TevStageCombiner::ColorCombiner &cc = bpmem.combiners[i].colorC; + TevStageCombiner::AlphaCombiner &ac = bpmem.combiners[i].alphaC; + + u32 val0 = cc.hex&0xffffff; + u32 val1 = ac.hex&0xffffff; + val0 |= bpmem.tevksel[i/2].getKC(i&1)<<24; + val1 |= bpmem.tevksel[i/2].getKA(i&1)<<24; + pcurvalue[0] = val0; + pcurvalue[1] = val1; + pcurvalue += 2; + } + + for (u32 i = 0; i < ((u32)bpmem.genMode.numtevstages+1)/2; ++i) { + u32 val0, val1; + if (bpmem.tevorders[i].hex & 0x40) + val0 = bpmem.tevorders[i].hex & 0x3ff; + else + val0 = bpmem.tevorders[i].hex & 0x380; + if (bpmem.tevorders[i].hex & 0x40000) + val1 = (bpmem.tevorders[i].hex & 0x3ff000) >> 12; + else + val1 = (bpmem.tevorders[i].hex & 0x380000) >> 12; + + switch (i % 3) { + case 0: pcurvalue[0] = val0|(val1<<10); break; + case 1: pcurvalue[0] |= val0<<20; pcurvalue[1] = val1; pcurvalue++; break; + case 2: pcurvalue[1] |= (val0<<10)|(val1<<20); pcurvalue++; break; + } + } + + if ((bpmem.genMode.numtevstages + 1) & 1) { // odd + u32 val0; + if (bpmem.tevorders[bpmem.genMode.numtevstages/2].hex & 0x40) + val0 = bpmem.tevorders[bpmem.genMode.numtevstages/2].hex&0x3ff; + else + val0 = bpmem.tevorders[bpmem.genMode.numtevstages/2].hex & 0x380; + + switch (bpmem.genMode.numtevstages % 3) { + case 0: pcurvalue[0] = val0; break; + case 1: pcurvalue[0] |= val0 << 20; break; + case 2: pcurvalue[1] |= val0 << 10; pcurvalue++; break; + } + } + + if ((bpmem.genMode.numtevstages % 3) != 2) + ++pcurvalue; + + uid.tevstages = (u32)(pcurvalue-&uid.values[0]-hdr); + + for (u32 i = 0; i < bpmem.genMode.numindstages; ++i) { + u32 val = bpmem.tevind[i].hex & 0x1fffff; // 21 bits + switch (i%3) { + case 0: pcurvalue[0] = val; break; + case 1: pcurvalue[0] |= val << 21; pcurvalue[1] = val >> 11; ++pcurvalue; break; + case 2: pcurvalue[0] |= val << 10; ++pcurvalue; break; + } + } + + // yeah, well .... + uid.indstages = (u32)(pcurvalue - &uid.values[0] - 2 - uid.tevstages); +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index 98c822170f..f05f170754 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -1,1048 +1,1048 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Globals.h" -#include -#include - -#include "GLUtil.h" - -#include -#include - -#ifdef _WIN32 -#include -#endif - -#include "Config.h" -#include "Profiler.h" -#include "Statistics.h" -#include "ImageWrite.h" -#include "Render.h" -#include "OpcodeDecoding.h" -#include "BPStructs.h" -#include "TextureMngr.h" -#include "rasterfont.h" -#include "VertexShader.h" -#include "PixelShaderManager.h" -#include "VertexLoaderManager.h" -#include "VertexLoader.h" -#include "XFB.h" -#if defined(HAVE_WX) && HAVE_WX -#include "Debugger/Debugger.h" // for the CDebugger class -#endif -#include "Logging/Logging.h" // for Logging() - -#ifdef _WIN32 -#include "OS/Win32.h" -#else -#endif -//#define USE_AA -#define AA_AMMOUNT 16 -struct MESSAGE -{ - MESSAGE() {} - MESSAGE(const char* p, u32 dw) { strcpy(str, p); dwTimeStamp = dw; } - char str[255]; - u32 dwTimeStamp; -}; - -CGcontext g_cgcontext; -CGprofile g_cgvProf, g_cgfProf; -#if defined(HAVE_WX) && HAVE_WX -extern CDebugger* m_frame; // the debugging class -#endif - -static int g_MaxTexWidth = 0, g_MaxTexHeight = 0; -static RasterFont* s_pfont = NULL; -static std::list s_listMsgs; -static bool s_bFullscreen = false; -static bool s_bOutputCgErrors = true; - -static int nZBufferRender = 0; // if > 0, then using zbuffer render -static u32 s_uFramebuffer = 0; -static u32 s_RenderTargets[1] = {0}, s_DepthTarget = 0, s_ZBufferTarget = 0; - -static bool s_bATIDrawBuffers = false, s_bHaveStencilBuffer = false; -static Renderer::RenderMode s_RenderMode = Renderer::RM_Normal; -static int s_nCurTarget = 0; -bool g_bBlendLogicOp = false; - -float MValueX, MValueY; // Since it can Stretch to fit Window, we need two different multiplication values -int frameCount; - -void HandleCgError(CGcontext ctx, CGerror err, void* appdata); - -bool Renderer::Create2() -{ - bool bSuccess = true; - GLenum err = GL_NO_ERROR; - g_cgcontext = cgCreateContext(); - cgGetError(); - cgSetErrorHandler(HandleCgError, NULL); - - // fill the opengl extension map - const char* ptoken = (const char*)glGetString( GL_EXTENSIONS ); - if (ptoken == NULL) return false; - - __Log("Supported OpenGL Extensions:\n"); - __Log(ptoken); // write to the log file - __Log("\n"); - - if( strstr(ptoken, "GL_EXT_blend_logic_op") != NULL ) - g_bBlendLogicOp = true; - if( strstr(ptoken, "ATI_draw_buffers") != NULL && strstr(ptoken, "ARB_draw_buffers") == NULL) - //Checks if it ONLY has the ATI_draw_buffers extension, some have both - s_bATIDrawBuffers = true; - - s_bFullscreen = g_Config.bFullscreen; - - if (glewInit() != GLEW_OK) { - ERROR_LOG("glewInit() failed!\n"); - return false; - } - - if (!GLEW_EXT_framebuffer_object) { - ERROR_LOG("*********\nGPU: ERROR: Need GL_EXT_framebufer_object for multiple render targets\nGPU: *********\n"); - bSuccess = false; - } - - if (!GLEW_EXT_secondary_color) { - ERROR_LOG("*********\nGPU: OGL ERROR: Need GL_EXT_secondary_color\nGPU: *********\n"); - bSuccess = false; - } - - int numvertexattribs=0; - glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, (GLint *)&numvertexattribs); - - if (numvertexattribs < 11) { - ERROR_LOG("*********\nGPU: OGL ERROR: Number of attributes %d not enough\nGPU: *********\n", numvertexattribs); - bSuccess = false; - } - - if (!bSuccess) - return false; - -#ifdef _WIN32 - if (WGLEW_EXT_swap_control) - wglSwapIntervalEXT(0); - else - ERROR_LOG("no support for SwapInterval (framerate clamped to monitor refresh rate)\n"); -#else -#ifdef __linux__ - if (glXSwapIntervalSGI) - glXSwapIntervalSGI(0); - else - ERROR_LOG("no support for SwapInterval (framerate clamped to monitor refresh rate)\n"); -#else - - //TODO - -#endif -#endif - // check the max texture width and height - glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&g_MaxTexWidth); - g_MaxTexHeight = g_MaxTexWidth; - - GL_REPORT_ERROR(); - if (err != GL_NO_ERROR) bSuccess = false; - - if (glDrawBuffers == NULL && !GLEW_ARB_draw_buffers) - glDrawBuffers = glDrawBuffersARB; - - glGenFramebuffersEXT( 1, (GLuint *)&s_uFramebuffer); - if (s_uFramebuffer == 0) { - ERROR_LOG("failed to create the renderbuffer\n"); - } - - _assert_( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); - glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer ); - - // create the framebuffer targets - glGenTextures(ARRAYSIZE(s_RenderTargets), (GLuint *)s_RenderTargets); - for(u32 i = 0; i < ARRAYSIZE(s_RenderTargets); ++i) { - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_RenderTargets[i]); - // initialize to default - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, nBackbufferWidth, nBackbufferHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if( glGetError() != GL_NO_ERROR) { - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP); - GL_REPORT_ERROR(); - } - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - #ifdef USE_AA - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_RenderTargets[i]); - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, AA_AMMOUNT, GL_RGBA, nBackbufferWidth, nBackbufferHeight); - #endif - } - s_nCurTarget = 0; - - GL_REPORT_ERROR(); - - int nMaxMRT = 0; - glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, (GLint *)&nMaxMRT); - - if (nMaxMRT > 1) { - // create zbuffer target - glGenTextures(1, (GLuint *)&s_ZBufferTarget); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, nBackbufferWidth, nBackbufferHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if( glGetError() != GL_NO_ERROR) { - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP); - GL_REPORT_ERROR(); - } - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - #ifdef USE_AA - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_ZBufferTarget); - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, AA_AMMOUNT, GL_RGBA, nBackbufferWidth, nBackbufferHeight); - #endif - } - - // create the depth buffer - glGenRenderbuffersEXT( 1, (GLuint *)&s_DepthTarget); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_DepthTarget); - #ifdef USE_AA - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, AA_AMMOUNT, GL_DEPTH24_STENCIL8_EXT, nBackbufferWidth, nBackbufferHeight); - #else - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, nBackbufferWidth, nBackbufferHeight); - #endif - - if (glGetError() != GL_NO_ERROR) { - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, nBackbufferWidth, nBackbufferHeight); - s_bHaveStencilBuffer = false; - } else { - s_bHaveStencilBuffer = true; - } - - GL_REPORT_ERROR(); - - // set as render targets - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, s_RenderTargets[s_nCurTarget], 0 ); - glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget ); - - #ifdef USE_AA - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_RenderTargets[s_nCurTarget]); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, s_RenderTargets[s_nCurTarget]); - - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget); - #endif - GL_REPORT_ERROR(); - - if (s_ZBufferTarget != 0) { - // test to make sure it works - glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget, 0); - bool bFailed = glGetError() != GL_NO_ERROR || glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT; - glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0); - - if( bFailed ) { - glDeleteTextures(1, (GLuint *)&s_ZBufferTarget); - s_ZBufferTarget = 0; - } - } - - if (s_ZBufferTarget == 0) - ERROR_LOG("disabling ztarget mrt feature (max mrt=%d)\n", nMaxMRT); - - //glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget ); - - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - nZBufferRender = 0; - - GL_REPORT_ERROR(); - if (err != GL_NO_ERROR) - bSuccess = false; - - s_pfont = new RasterFont(); - - SetAA(g_Config.iMultisampleMode); - GL_REPORT_ERROR(); - - // load the effect, find the best profiles (if any) - if (cgGLIsProfileSupported(CG_PROFILE_ARBVP1) != CG_TRUE) { - ERROR_LOG("arbvp1 not supported\n"); - return false; - } - if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1) != CG_TRUE) { - ERROR_LOG("arbfp1 not supported\n"); - return false; - } - - g_cgvProf = cgGLGetLatestProfile(CG_GL_VERTEX); - g_cgfProf = cgGLGetLatestProfile(CG_GL_FRAGMENT);//CG_PROFILE_ARBFP1; - cgGLSetOptimalOptions(g_cgvProf); - cgGLSetOptimalOptions(g_cgfProf); - - //ERROR_LOG("max buffer sizes: %d %d\n", cgGetProgramBufferMaxSize(g_cgvProf), cgGetProgramBufferMaxSize(g_cgfProf)); - int nenvvertparams, nenvfragparams, naddrregisters[2]; - glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, (GLint *)&nenvvertparams); - glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, (GLint *)&nenvfragparams); - glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, (GLint *)&naddrregisters[0]); - glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, (GLint *)&naddrregisters[1]); - __Log("max program env parameters: vert=%d, frag=%d\n", nenvvertparams, nenvfragparams); - __Log("max program address register parameters: vert=%d, frag=%d\n", naddrregisters[0], naddrregisters[1]); - - if( nenvvertparams < 238 ) - ERROR_LOG("not enough vertex shader environment constants!!\n"); - -#ifndef _DEBUG - cgGLSetDebugMode(GL_FALSE); -#endif - - if( cgGetError() != CG_NO_ERROR ) { - ERROR_LOG("cg error\n"); - return false; - } - - //glEnable(GL_POLYGON_OFFSET_FILL); - //glEnable(GL_POLYGON_OFFSET_LINE); - //glPolygonOffset(0, 1); - if (!Initialize()) - return false; - - XFB_Init(); - return glGetError() == GL_NO_ERROR && bSuccess; -} - -void Renderer::Shutdown(void) -{ - delete s_pfont; - s_pfont = 0; - - XFB_Shutdown(); - - if (g_cgcontext != 0) { - cgDestroyContext(g_cgcontext); - g_cgcontext = 0; - } - - if (s_RenderTargets[0]) { - glDeleteTextures(ARRAYSIZE(s_RenderTargets), (GLuint *)s_RenderTargets); - memset(s_RenderTargets, 0, sizeof(s_RenderTargets)); - } - if (s_DepthTarget) { - glDeleteRenderbuffersEXT(1, (GLuint *)&s_DepthTarget); s_DepthTarget = 0; - } - if (s_uFramebuffer != 0) { - glDeleteFramebuffersEXT( 1, (GLuint *)&s_uFramebuffer); - s_uFramebuffer = 0; - } -} - - -bool Renderer::Initialize() -{ - glStencilFunc(GL_ALWAYS, 0, 0); - glBlendFunc(GL_ONE, GL_ONE); - - glViewport(0, 0, GetTargetWidth(), GetTargetHeight()); // Reset The Current Viewport - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glShadeModel(GL_SMOOTH); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClearDepth(1.0f); - glEnable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glDepthFunc(GL_LEQUAL); - - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment - - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // perspective correct interpolation of colors and tex coords - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); - - glDisable(GL_STENCIL_TEST); - glEnable(GL_SCISSOR_TEST); - glScissor(0, 0, nBackbufferWidth, nBackbufferHeight); - glBlendColorEXT(0, 0, 0, 0.5f); - glClearDepth(1.0f); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - // legacy multitexturing: select texture channel only. - glActiveTexture(GL_TEXTURE0); - glClientActiveTexture(GL_TEXTURE0); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - s_RenderMode = Renderer::RM_Normal; - - GLenum err = GL_NO_ERROR; - GL_REPORT_ERROR(); - - return err == GL_NO_ERROR; -} - -void Renderer::AddMessage(const char* pstr, u32 ms) -{ - s_listMsgs.push_back(MESSAGE(pstr, timeGetTime() + ms)); -} - -void Renderer::ProcessMessages() -{ - GLboolean wasEnabled = glIsEnabled(GL_BLEND); - - if (!wasEnabled) glEnable(GL_BLEND); - - if (s_listMsgs.size() > 0) { - int left = 25, top = 15; - std::list::iterator it = s_listMsgs.begin(); - while (it != s_listMsgs.end()) - { - int time_left = (int)(it->dwTimeStamp - timeGetTime()); - int alpha = 255; - - if (time_left < 1024) - { - alpha = time_left >> 2; - if (time_left < 0) alpha = 0; - } - - alpha <<= 24; - - RenderText(it->str, left+1, top+1, 0x000000|alpha); - RenderText(it->str, left, top, 0xffff30|alpha); - top += 15; - - if (time_left <= 0) - it = s_listMsgs.erase(it); - else ++it; - } - } - - if(!wasEnabled) glDisable(GL_BLEND); -} - -void Renderer::RenderText(const char* pstr, int left, int top, u32 color) -{ - glColor4f( - ((color>>16) & 0xff)/255.0f, - ((color>> 8) & 0xff)/255.0f, - ((color>> 0) & 0xff)/255.0f, - ((color>>24) & 0xFF)/255.0f - ); - s_pfont->printMultilineText(pstr, left * 2.0f / (float)nBackbufferWidth - 1, 1 - top * 2.0f / (float)nBackbufferHeight,0,nBackbufferWidth,nBackbufferHeight); -} - -void Renderer::SetAA(int aa) -{ - -} - -void Renderer::ReinitView(int nNewWidth, int nNewHeight) -{ - int oldscreen = s_bFullscreen; - - OpenGL_Shutdown(); - int oldwidth = nBackbufferWidth, oldheight = nBackbufferHeight; - if (!OpenGL_Create(g_VideoInitialize, nNewWidth, nNewHeight)) {//nNewWidth&~7, nNewHeight&~7) ) { - ERROR_LOG("Failed to recreate, reverting to old settings\n"); - if (!OpenGL_Create(g_VideoInitialize, oldwidth, oldheight)) { - g_VideoInitialize.pSysMessage("Failed to revert, exiting...\n"); - // TODO - don't takedown the entire emu - exit(0); - } - } - OpenGL_MakeCurrent(); - - if (oldscreen && !g_Config.bFullscreen) { // if transitioning from full screen -#ifdef _WIN32 - RECT rc; - rc.left = 0; rc.top = 0; - rc.right = nNewWidth; rc.bottom = nNewHeight; - AdjustWindowRect(&rc, EmuWindow::g_winstyle, FALSE); - - RECT rcdesktop; - GetWindowRect(GetDesktopWindow(), &rcdesktop); - - SetWindowLong( EmuWindow::GetWnd(), GWL_STYLE, EmuWindow::g_winstyle ); - SetWindowPos(EmuWindow::GetWnd(), HWND_TOP, ((rcdesktop.right-rcdesktop.left)-(rc.right-rc.left))/2, - ((rcdesktop.bottom-rcdesktop.top)-(rc.bottom-rc.top))/2, - rc.right-rc.left, rc.bottom-rc.top, SWP_SHOWWINDOW); - UpdateWindow(EmuWindow::GetWnd()); -#else // linux -#endif - } - - nBackbufferWidth = nNewWidth > 16 ? nNewWidth : 16; - nBackbufferHeight = nNewHeight > 16 ? nNewHeight : 16; -} -int Renderer::GetTargetWidth() -{ - if(g_Config.bStretchToFit) - return 640; - else - return nBackbufferWidth; // return the actual window width -} - -int Renderer::GetTargetHeight() -{ - if(g_Config.bStretchToFit) - return 480; - else - return nBackbufferHeight; // return the actual window height -} - -bool Renderer::CanBlendLogicOp() -{ - return g_bBlendLogicOp; -} - -void Renderer::SetRenderTarget(u32 targ) -{ - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, targ!=0?targ:s_RenderTargets[s_nCurTarget], 0 ); -} - -void Renderer::SetDepthTarget(u32 targ) -{ - glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, targ != 0 ? targ : s_DepthTarget ); -} - -void Renderer::SetFramebuffer(u32 fb) -{ - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb != 0 ? fb : s_uFramebuffer); -} - -u32 Renderer::GetRenderTarget() -{ - return s_RenderTargets[s_nCurTarget]; -} - -void Renderer::ResetGLState() -{ - glDisable(GL_SCISSOR_TEST); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); - glDepthMask(GL_FALSE); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - glDisable(GL_VERTEX_PROGRAM_ARB); - glDisable(GL_FRAGMENT_PROGRAM_ARB); -} - -void Renderer::RestoreGLState() -{ - glEnable(GL_SCISSOR_TEST); - - if (bpmem.genMode.cullmode > 0) glEnable(GL_CULL_FACE); - if (bpmem.zmode.testenable) glEnable(GL_DEPTH_TEST); - if (bpmem.blendmode.blendenable) glEnable(GL_BLEND); - if(bpmem.zmode.updateenable) glDepthMask(GL_TRUE); - - glEnable(GL_VERTEX_PROGRAM_ARB); - glEnable(GL_FRAGMENT_PROGRAM_ARB); - SetColorMask(); -} - -void Renderer::SetColorMask() -{ - if (bpmem.blendmode.alphaupdate && bpmem.blendmode.colorupdate) - glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); - else if (bpmem.blendmode.alphaupdate) - glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_TRUE); - else if (bpmem.blendmode.colorupdate) - glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_FALSE); -} - - -// ======================================================================================= -// Call browser: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadBPReg() -// case 0x52 > SetScissorRect() -// --------------- -// This function handles the OpenGL glScissor() function -// --------------- -// bpmem.scissorTL.x, y = 342x342 -// bpmem.scissorBR.x, y = 981x821 -// Renderer::GetTargetHeight() = the fixed ini file setting -// --------------- -bool Renderer::SetScissorRect() -{ - int xoff = bpmem.scissorOffset.x * 2 - 342; - int yoff = bpmem.scissorOffset.y * 2 - 342; - - float rc_left = bpmem.scissorTL.x - xoff - 342; // left = 0 - rc_left *= MValueX; - if (rc_left < 0) rc_left = 0; - - float rc_top = bpmem.scissorTL.y - yoff - 342; // right = 0 - rc_top *= MValueY; - if (rc_top < 0) rc_top = 0; - - float rc_right = bpmem.scissorBR.x - xoff - 342; // right = 640 - rc_right *= MValueX; - if (rc_right > 640 * MValueX) rc_right = 640 * MValueX; - - float rc_bottom = bpmem.scissorBR.y - yoff - 342; // bottom = 480 - rc_bottom *= MValueY; - if (rc_bottom > 480 * MValueY) rc_bottom = 480 * MValueY; - - /*__Log("Scissor: lt=(%d,%d), rb=(%d,%d,%i), off=(%d,%d)\n", - rc_left, rc_top, - rc_right, rc_bottom, Renderer::GetTargetHeight(), - xoff, yoff - );*/ - - if (rc_right >= rc_left && rc_bottom >= rc_top ) - { - glScissor( - (int)rc_left, // x = 0 - Renderer::GetTargetHeight()-(int)(rc_bottom), // y = 0 - (int)(rc_right-rc_left), // y = 0 - (int)(rc_bottom-rc_top) // y = 0 - ); - return true; - } - - return false; -} - - -bool Renderer::IsUsingATIDrawBuffers() -{ - return s_bATIDrawBuffers; -} - -bool Renderer::HaveStencilBuffer() -{ - return s_bHaveStencilBuffer; -} - -void Renderer::SetZBufferRender() -{ - nZBufferRender = 10; // give it 10 frames - GLenum s_drawbuffers[2] = { - GL_COLOR_ATTACHMENT0_EXT, - GL_COLOR_ATTACHMENT1_EXT - }; - glDrawBuffers(2, s_drawbuffers); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget, 0); - _assert_(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT); -} - -void Renderer::FlushZBufferAlphaToTarget() -{ - ResetGLState(); - - SetRenderTarget(0); - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - - glViewport(0, 0, GetTargetWidth(), GetTargetHeight()); - - // texture map s_RenderTargets[s_curtarget] onto the main buffer - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget); - TextureMngr::EnableTexRECT(0); - // disable all other stages - for(int i = 1; i < 8; ++i) - TextureMngr::DisableStage(i); - GL_REPORT_ERRORD(); - - // setup the stencil to only accept pixels that have been written - glStencilFunc(GL_EQUAL, 1, 0xff); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - - if(g_Config.bStretchToFit) - { - //TODO: Do Correctly in a bit - float FactorW = (float)640 / (float)nBackbufferWidth; - float FactorH = (float)480 / (float)nBackbufferHeight; - - float Max = (FactorW < FactorH) ? FactorH : FactorW; - float Temp = 1 / Max; - FactorW *= Temp; - FactorH *= Temp; - - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2f(-FactorW,-FactorH); - glTexCoord2f(0, (float)GetTargetHeight()); glVertex2f(-FactorW,FactorH); - glTexCoord2f((float)GetTargetWidth(), (float)GetTargetHeight()); glVertex2f(FactorW,FactorH); - glTexCoord2f((float)GetTargetWidth(), 0); glVertex2f(FactorW,-FactorH); - - __Log("%d, %d", FactorW, FactorH); - } - else - { - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2f(-1,-1); - glTexCoord2f(0, (float)(GetTargetHeight())); glVertex2f(-1,1); - glTexCoord2f((float)(GetTargetWidth()), (float)(GetTargetHeight())); glVertex2f(1,1); - glTexCoord2f((float)(GetTargetWidth()), 0); glVertex2f(1,-1); - } - glEnd(); - - GL_REPORT_ERRORD(); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - RestoreGLState(); -} - -void Renderer::SetRenderMode(RenderMode mode) -{ - if (!s_bHaveStencilBuffer && mode == RM_ZBufferAlpha) - mode = RM_ZBufferOnly; - - if (s_RenderMode == mode) - return; - - if (mode == RM_Normal) { - // flush buffers - if( s_RenderMode == RM_ZBufferAlpha ) { - FlushZBufferAlphaToTarget(); - glDisable(GL_STENCIL_TEST); - } - SetColorMask(); - SetRenderTarget(0); - SetZBufferRender(); - GL_REPORT_ERRORD(); - } - else if (s_RenderMode == RM_Normal) { - // setup buffers - _assert_(GetZBufferTarget() && bpmem.zmode.updateenable); - - if( mode == RM_ZBufferAlpha ) { - glEnable(GL_STENCIL_TEST); - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); - glStencilFunc(GL_ALWAYS, 1, 0xff); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - } - - glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - GL_REPORT_ERRORD(); - } - else { - _assert_(GetZBufferTarget()); - _assert_(s_bHaveStencilBuffer); - - if( mode == RM_ZBufferOnly ) { - // flush and remove stencil - _assert_(s_RenderMode==RM_ZBufferAlpha); - FlushZBufferAlphaToTarget(); - glDisable(GL_STENCIL_TEST); - - SetRenderTarget(s_ZBufferTarget); - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - GL_REPORT_ERRORD(); - } - else { - _assert_(mode == RM_ZBufferAlpha&&s_RenderMode==RM_ZBufferOnly); - - // setup stencil - glEnable(GL_STENCIL_TEST); - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); - glStencilFunc(GL_ALWAYS, 1, 0xff); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - } - } - - s_RenderMode = mode; -} - -Renderer::RenderMode Renderer::GetRenderMode() -{ - return s_RenderMode; -} - -u32 Renderer::GetZBufferTarget() -{ - return nZBufferRender > 0 ? s_ZBufferTarget : 0; -} - -void Renderer::Swap(const TRectangle& rc) -{ - OpenGL_Update(); // just updates the render window position and the backbuffer size - - DVSTARTPROFILE(); - - Renderer::SetRenderMode(Renderer::RM_Normal); - - // render to the real buffer now - #ifdef USE_AA - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_RenderTargets[0]); - #else - glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer - #endif - glViewport(nXoff, nYoff, nBackbufferWidth, nBackbufferHeight); - - ResetGLState(); - - // texture map s_RenderTargets[s_curtarget] onto the main buffer - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_RenderTargets[s_nCurTarget]); - TextureMngr::EnableTexRECT(0); - // disable all other stages - for(int i = 1; i < 8; ++i) TextureMngr::DisableStage(i); - GL_REPORT_ERRORD(); - - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2f(-1,-1); - glTexCoord2f(0, (float)GetTargetHeight()); glVertex2f(-1,1); - glTexCoord2f((float)GetTargetWidth(), (float)GetTargetHeight()); glVertex2f(1,1); - glTexCoord2f((float)GetTargetWidth(), 0); glVertex2f(1,-1); - glEnd(); - - if (g_Config.bWireFrame) - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - TextureMngr::DisableStage(0); - - SwapBuffers(); - - RestoreGLState(); - #ifdef USE_AA - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, s_RenderTargets[s_nCurTarget]); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); - glBlitFramebufferEXT(0, 0, nBackbufferWidth, nBackbufferHeight, 0, 0, nBackbufferWidth, nBackbufferHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - #endif - GL_REPORT_ERRORD(); - - g_Config.iSaveTargetId = 0; - - // for testing zbuffer targets - //Renderer::SetZBufferRender(); - //SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget, GetTargetWidth(), GetTargetHeight()); -} - -void Renderer::SwapBuffers() -{ - static int fpscount; - static int s_fps; - static unsigned long lasttime; - ++fpscount; - if( timeGetTime() - lasttime > 1000 ) - { - lasttime = timeGetTime(); - s_fps = fpscount; - fpscount = 0; - } - - // Write logging data to debugger -#if defined(HAVE_WX) && HAVE_WX - if(m_frame) - { - Logging(0); - } -#endif - if (g_Config.bOverlayStats) { - char st[2048]; - char *p = st; - if(g_Config.bShowFPS) - p+=sprintf(p, "FPS: %d\n", s_fps); // So it shows up before the stats and doesn't make anyting ugly - p+=sprintf(p,"Num textures created: %i\n",stats.numTexturesCreated); - p+=sprintf(p,"Num textures alive: %i\n",stats.numTexturesAlive); - p+=sprintf(p,"Num pshaders created: %i\n",stats.numPixelShadersCreated); - p+=sprintf(p,"Num pshaders alive: %i\n",stats.numPixelShadersAlive); - p+=sprintf(p,"Num vshaders created: %i\n",stats.numVertexShadersCreated); - p+=sprintf(p,"Num vshaders alive: %i\n",stats.numVertexShadersAlive); - p+=sprintf(p,"Num dlists called: %i\n",stats.numDListsCalled); - p+=sprintf(p,"Num dlists called (frame): %i\n",stats.thisFrame.numDListsCalled); - // not used. - //p+=sprintf(p,"Num dlists created: %i\n",stats.numDListsCreated); - //p+=sprintf(p,"Num dlists alive: %i\n",stats.numDListsAlive); - //p+=sprintf(p,"Num strip joins: %i\n",stats.numJoins); - p+=sprintf(p,"Num primitives: %i\n",stats.thisFrame.numPrims); - p+=sprintf(p,"Num primitive joins: %i\n",stats.thisFrame.numPrimitiveJoins); - p+=sprintf(p,"Num buffer splits: %i\n",stats.thisFrame.numBufferSplits); - p+=sprintf(p,"Num draw calls: %i\n",stats.thisFrame.numDrawCalls); - p+=sprintf(p,"Num primitives (DL): %i\n",stats.thisFrame.numDLPrims); - p+=sprintf(p,"Num XF loads: %i\n",stats.thisFrame.numXFLoads); - p+=sprintf(p,"Num XF loads (DL): %i\n",stats.thisFrame.numXFLoadsInDL); - p+=sprintf(p,"Num CP loads: %i\n",stats.thisFrame.numCPLoads); - p+=sprintf(p,"Num CP loads (DL): %i\n",stats.thisFrame.numCPLoadsInDL); - p+=sprintf(p,"Num BP loads: %i\n",stats.thisFrame.numBPLoads); - p+=sprintf(p,"Num BP loads (DL): %i\n",stats.thisFrame.numBPLoadsInDL); - p+=sprintf(p,"Num vertex loaders: %i\n",stats.numVertexLoaders); - - - std::string text = st; - VertexLoaderManager::AppendListToString(&text); - - Renderer::RenderText(text.c_str(), 20, 20, 0xFF00FFFF); - } - else - { - if(g_Config.bShowFPS) - { - char strfps[25]; - sprintf(strfps, "%d\n", s_fps); - Renderer::RenderText(strfps, 20, 20, 0xFF00FFFF); - } - } - - Renderer::ProcessMessages(); - -#if defined(DVPROFILE) - if (g_bWriteProfile) { - //g_bWriteProfile = 0; - static int framenum = 0; - const int UPDATE_FRAMES = 8; - if (++framenum >= UPDATE_FRAMES) { - DVProfWrite("prof.txt", UPDATE_FRAMES); - DVProfClear(); - framenum = 0; - } - } -#endif - - // copy the rendered from to the real window - OpenGL_SwapBuffers(); - - glClearColor(0,0,0,0); - glClear(GL_COLOR_BUFFER_BIT); - - GL_REPORT_ERRORD(); - - //clean out old stuff from caches - frameCount++; - PixelShaderMngr::Cleanup(); - TextureMngr::Cleanup(); - - // New frame - stats.ResetFrame(); - - glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer ); - - if (nZBufferRender > 0) { - if (--nZBufferRender == 0) { - // turn off - nZBufferRender = 0; - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0); - Renderer::SetRenderMode(RM_Normal); // turn off any zwrites - } - } -} - -bool Renderer::SaveRenderTarget(const char* filename, int jpeg) -{ - bool bflip = true; - std::vector data(nBackbufferWidth * nBackbufferHeight); - glReadPixels(0, 0, nBackbufferWidth, nBackbufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]); - if (glGetError() != GL_NO_ERROR) - return false; - - if (bflip) { - // swap scanlines - std::vector scanline(nBackbufferWidth); - for(int i = 0; i < nBackbufferHeight/2; ++i) { - memcpy(&scanline[0], &data[i*nBackbufferWidth], nBackbufferWidth*4); - memcpy(&data[i*nBackbufferWidth], &data[(nBackbufferHeight-i-1)*nBackbufferWidth], nBackbufferWidth*4); - memcpy(&data[(nBackbufferHeight-i-1)*nBackbufferWidth], &scanline[0], nBackbufferWidth*4); - } - } - - return SaveTGA(filename, nBackbufferWidth, nBackbufferHeight, &data[0]); -} - -void Renderer::SetCgErrorOutput(bool bOutput) -{ - s_bOutputCgErrors = bOutput; -} - -void HandleGLError() -{ - const GLubyte* pstr = glGetString(GL_PROGRAM_ERROR_STRING_ARB); - if (pstr != NULL && pstr[0] != 0) - { - GLint loc = 0; - glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &loc); - ERROR_LOG("program error at %d: ", loc); - ERROR_LOG((char*)pstr); - ERROR_LOG("\n"); - } - - // check the error status of this framebuffer */ - GLenum error = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); - - // if error != GL_FRAMEBUFFER_COMPLETE_EXT, there's an error of some sort - if (!error) - return; - -// int w, h; -// GLint fmt; -// glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &fmt); -// glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_WIDTH_EXT, (GLint *)&w); -// glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_HEIGHT_EXT, (GLint *)&h); - - switch(error) - { - case GL_FRAMEBUFFER_COMPLETE_EXT: - break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: - ERROR_LOG("Error! missing a required image/buffer attachment!\n"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: - ERROR_LOG("Error! has no images/buffers attached!\n"); - break; -// case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: -// ERROR_LOG("Error! has an image/buffer attached in multiple locations!\n"); -// break; - case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: - ERROR_LOG("Error! has mismatched image/buffer dimensions!\n"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: - ERROR_LOG("Error! colorbuffer attachments have different types!\n"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: - ERROR_LOG("Error! trying to draw to non-attached color buffer!\n"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: - ERROR_LOG("Error! trying to read from a non-attached color buffer!\n"); - break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - ERROR_LOG("Error! format is not supported by current graphics card/driver!\n"); - break; - default: - ERROR_LOG("*UNKNOWN ERROR* reported from glCheckFramebufferStatusEXT()!\n"); - break; - } -} - -void HandleCgError(CGcontext ctx, CGerror err, void* appdata) -{ - if (s_bOutputCgErrors) - { - ERROR_LOG("Cg error: %s\n", cgGetErrorString(err)); - const char* listing = cgGetLastListing(g_cgcontext); - if (listing != NULL) { - ERROR_LOG(" last listing: %s\n", listing); - } - // glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &loc); - // printf("pos: %d\n", loc); - } -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Globals.h" +#include +#include + +#include "GLUtil.h" + +#include +#include + +#ifdef _WIN32 +#include +#endif + +#include "Config.h" +#include "Profiler.h" +#include "Statistics.h" +#include "ImageWrite.h" +#include "Render.h" +#include "OpcodeDecoding.h" +#include "BPStructs.h" +#include "TextureMngr.h" +#include "rasterfont.h" +#include "VertexShader.h" +#include "PixelShaderManager.h" +#include "VertexLoaderManager.h" +#include "VertexLoader.h" +#include "XFB.h" +#if defined(HAVE_WX) && HAVE_WX +#include "Debugger/Debugger.h" // for the CDebugger class +#endif +#include "Logging/Logging.h" // for Logging() + +#ifdef _WIN32 +#include "OS/Win32.h" +#else +#endif +//#define USE_AA +#define AA_AMMOUNT 16 +struct MESSAGE +{ + MESSAGE() {} + MESSAGE(const char* p, u32 dw) { strcpy(str, p); dwTimeStamp = dw; } + char str[255]; + u32 dwTimeStamp; +}; + +CGcontext g_cgcontext; +CGprofile g_cgvProf, g_cgfProf; +#if defined(HAVE_WX) && HAVE_WX +extern CDebugger* m_frame; // the debugging class +#endif + +static int g_MaxTexWidth = 0, g_MaxTexHeight = 0; +static RasterFont* s_pfont = NULL; +static std::list s_listMsgs; +static bool s_bFullscreen = false; +static bool s_bOutputCgErrors = true; + +static int nZBufferRender = 0; // if > 0, then using zbuffer render +static u32 s_uFramebuffer = 0; +static u32 s_RenderTargets[1] = {0}, s_DepthTarget = 0, s_ZBufferTarget = 0; + +static bool s_bATIDrawBuffers = false, s_bHaveStencilBuffer = false; +static Renderer::RenderMode s_RenderMode = Renderer::RM_Normal; +static int s_nCurTarget = 0; +bool g_bBlendLogicOp = false; + +float MValueX, MValueY; // Since it can Stretch to fit Window, we need two different multiplication values +int frameCount; + +void HandleCgError(CGcontext ctx, CGerror err, void* appdata); + +bool Renderer::Create2() +{ + bool bSuccess = true; + GLenum err = GL_NO_ERROR; + g_cgcontext = cgCreateContext(); + cgGetError(); + cgSetErrorHandler(HandleCgError, NULL); + + // fill the opengl extension map + const char* ptoken = (const char*)glGetString( GL_EXTENSIONS ); + if (ptoken == NULL) return false; + + __Log("Supported OpenGL Extensions:\n"); + __Log(ptoken); // write to the log file + __Log("\n"); + + if( strstr(ptoken, "GL_EXT_blend_logic_op") != NULL ) + g_bBlendLogicOp = true; + if( strstr(ptoken, "ATI_draw_buffers") != NULL && strstr(ptoken, "ARB_draw_buffers") == NULL) + //Checks if it ONLY has the ATI_draw_buffers extension, some have both + s_bATIDrawBuffers = true; + + s_bFullscreen = g_Config.bFullscreen; + + if (glewInit() != GLEW_OK) { + ERROR_LOG("glewInit() failed!\n"); + return false; + } + + if (!GLEW_EXT_framebuffer_object) { + ERROR_LOG("*********\nGPU: ERROR: Need GL_EXT_framebufer_object for multiple render targets\nGPU: *********\n"); + bSuccess = false; + } + + if (!GLEW_EXT_secondary_color) { + ERROR_LOG("*********\nGPU: OGL ERROR: Need GL_EXT_secondary_color\nGPU: *********\n"); + bSuccess = false; + } + + int numvertexattribs=0; + glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, (GLint *)&numvertexattribs); + + if (numvertexattribs < 11) { + ERROR_LOG("*********\nGPU: OGL ERROR: Number of attributes %d not enough\nGPU: *********\n", numvertexattribs); + bSuccess = false; + } + + if (!bSuccess) + return false; + +#ifdef _WIN32 + if (WGLEW_EXT_swap_control) + wglSwapIntervalEXT(0); + else + ERROR_LOG("no support for SwapInterval (framerate clamped to monitor refresh rate)\n"); +#else +#ifdef __linux__ + if (glXSwapIntervalSGI) + glXSwapIntervalSGI(0); + else + ERROR_LOG("no support for SwapInterval (framerate clamped to monitor refresh rate)\n"); +#else + + //TODO + +#endif +#endif + // check the max texture width and height + glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&g_MaxTexWidth); + g_MaxTexHeight = g_MaxTexWidth; + + GL_REPORT_ERROR(); + if (err != GL_NO_ERROR) bSuccess = false; + + if (glDrawBuffers == NULL && !GLEW_ARB_draw_buffers) + glDrawBuffers = glDrawBuffersARB; + + glGenFramebuffersEXT( 1, (GLuint *)&s_uFramebuffer); + if (s_uFramebuffer == 0) { + ERROR_LOG("failed to create the renderbuffer\n"); + } + + _assert_( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer ); + + // create the framebuffer targets + glGenTextures(ARRAYSIZE(s_RenderTargets), (GLuint *)s_RenderTargets); + for(u32 i = 0; i < ARRAYSIZE(s_RenderTargets); ++i) { + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_RenderTargets[i]); + // initialize to default + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, nBackbufferWidth, nBackbufferHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if( glGetError() != GL_NO_ERROR) { + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP); + GL_REPORT_ERROR(); + } + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + #ifdef USE_AA + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_RenderTargets[i]); + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, AA_AMMOUNT, GL_RGBA, nBackbufferWidth, nBackbufferHeight); + #endif + } + s_nCurTarget = 0; + + GL_REPORT_ERROR(); + + int nMaxMRT = 0; + glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, (GLint *)&nMaxMRT); + + if (nMaxMRT > 1) { + // create zbuffer target + glGenTextures(1, (GLuint *)&s_ZBufferTarget); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, nBackbufferWidth, nBackbufferHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if( glGetError() != GL_NO_ERROR) { + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP); + GL_REPORT_ERROR(); + } + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + #ifdef USE_AA + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_ZBufferTarget); + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, AA_AMMOUNT, GL_RGBA, nBackbufferWidth, nBackbufferHeight); + #endif + } + + // create the depth buffer + glGenRenderbuffersEXT( 1, (GLuint *)&s_DepthTarget); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_DepthTarget); + #ifdef USE_AA + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, AA_AMMOUNT, GL_DEPTH24_STENCIL8_EXT, nBackbufferWidth, nBackbufferHeight); + #else + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, nBackbufferWidth, nBackbufferHeight); + #endif + + if (glGetError() != GL_NO_ERROR) { + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, nBackbufferWidth, nBackbufferHeight); + s_bHaveStencilBuffer = false; + } else { + s_bHaveStencilBuffer = true; + } + + GL_REPORT_ERROR(); + + // set as render targets + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, s_RenderTargets[s_nCurTarget], 0 ); + glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget ); + + #ifdef USE_AA + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_RenderTargets[s_nCurTarget]); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, s_RenderTargets[s_nCurTarget]); + + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget); + #endif + GL_REPORT_ERROR(); + + if (s_ZBufferTarget != 0) { + // test to make sure it works + glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget, 0); + bool bFailed = glGetError() != GL_NO_ERROR || glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT; + glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0); + + if( bFailed ) { + glDeleteTextures(1, (GLuint *)&s_ZBufferTarget); + s_ZBufferTarget = 0; + } + } + + if (s_ZBufferTarget == 0) + ERROR_LOG("disabling ztarget mrt feature (max mrt=%d)\n", nMaxMRT); + + //glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget ); + + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + nZBufferRender = 0; + + GL_REPORT_ERROR(); + if (err != GL_NO_ERROR) + bSuccess = false; + + s_pfont = new RasterFont(); + + SetAA(g_Config.iMultisampleMode); + GL_REPORT_ERROR(); + + // load the effect, find the best profiles (if any) + if (cgGLIsProfileSupported(CG_PROFILE_ARBVP1) != CG_TRUE) { + ERROR_LOG("arbvp1 not supported\n"); + return false; + } + if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1) != CG_TRUE) { + ERROR_LOG("arbfp1 not supported\n"); + return false; + } + + g_cgvProf = cgGLGetLatestProfile(CG_GL_VERTEX); + g_cgfProf = cgGLGetLatestProfile(CG_GL_FRAGMENT);//CG_PROFILE_ARBFP1; + cgGLSetOptimalOptions(g_cgvProf); + cgGLSetOptimalOptions(g_cgfProf); + + //ERROR_LOG("max buffer sizes: %d %d\n", cgGetProgramBufferMaxSize(g_cgvProf), cgGetProgramBufferMaxSize(g_cgfProf)); + int nenvvertparams, nenvfragparams, naddrregisters[2]; + glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, (GLint *)&nenvvertparams); + glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, (GLint *)&nenvfragparams); + glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, (GLint *)&naddrregisters[0]); + glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, (GLint *)&naddrregisters[1]); + __Log("max program env parameters: vert=%d, frag=%d\n", nenvvertparams, nenvfragparams); + __Log("max program address register parameters: vert=%d, frag=%d\n", naddrregisters[0], naddrregisters[1]); + + if( nenvvertparams < 238 ) + ERROR_LOG("not enough vertex shader environment constants!!\n"); + +#ifndef _DEBUG + cgGLSetDebugMode(GL_FALSE); +#endif + + if( cgGetError() != CG_NO_ERROR ) { + ERROR_LOG("cg error\n"); + return false; + } + + //glEnable(GL_POLYGON_OFFSET_FILL); + //glEnable(GL_POLYGON_OFFSET_LINE); + //glPolygonOffset(0, 1); + if (!Initialize()) + return false; + + XFB_Init(); + return glGetError() == GL_NO_ERROR && bSuccess; +} + +void Renderer::Shutdown(void) +{ + delete s_pfont; + s_pfont = 0; + + XFB_Shutdown(); + + if (g_cgcontext != 0) { + cgDestroyContext(g_cgcontext); + g_cgcontext = 0; + } + + if (s_RenderTargets[0]) { + glDeleteTextures(ARRAYSIZE(s_RenderTargets), (GLuint *)s_RenderTargets); + memset(s_RenderTargets, 0, sizeof(s_RenderTargets)); + } + if (s_DepthTarget) { + glDeleteRenderbuffersEXT(1, (GLuint *)&s_DepthTarget); s_DepthTarget = 0; + } + if (s_uFramebuffer != 0) { + glDeleteFramebuffersEXT( 1, (GLuint *)&s_uFramebuffer); + s_uFramebuffer = 0; + } +} + + +bool Renderer::Initialize() +{ + glStencilFunc(GL_ALWAYS, 0, 0); + glBlendFunc(GL_ONE, GL_ONE); + + glViewport(0, 0, GetTargetWidth(), GetTargetHeight()); // Reset The Current Viewport + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glShadeModel(GL_SMOOTH); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClearDepth(1.0f); + glEnable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glDepthFunc(GL_LEQUAL); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment + + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // perspective correct interpolation of colors and tex coords + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + + glDisable(GL_STENCIL_TEST); + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, nBackbufferWidth, nBackbufferHeight); + glBlendColorEXT(0, 0, 0, 0.5f); + glClearDepth(1.0f); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // legacy multitexturing: select texture channel only. + glActiveTexture(GL_TEXTURE0); + glClientActiveTexture(GL_TEXTURE0); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + s_RenderMode = Renderer::RM_Normal; + + GLenum err = GL_NO_ERROR; + GL_REPORT_ERROR(); + + return err == GL_NO_ERROR; +} + +void Renderer::AddMessage(const char* pstr, u32 ms) +{ + s_listMsgs.push_back(MESSAGE(pstr, timeGetTime() + ms)); +} + +void Renderer::ProcessMessages() +{ + GLboolean wasEnabled = glIsEnabled(GL_BLEND); + + if (!wasEnabled) glEnable(GL_BLEND); + + if (s_listMsgs.size() > 0) { + int left = 25, top = 15; + std::list::iterator it = s_listMsgs.begin(); + while (it != s_listMsgs.end()) + { + int time_left = (int)(it->dwTimeStamp - timeGetTime()); + int alpha = 255; + + if (time_left < 1024) + { + alpha = time_left >> 2; + if (time_left < 0) alpha = 0; + } + + alpha <<= 24; + + RenderText(it->str, left+1, top+1, 0x000000|alpha); + RenderText(it->str, left, top, 0xffff30|alpha); + top += 15; + + if (time_left <= 0) + it = s_listMsgs.erase(it); + else ++it; + } + } + + if(!wasEnabled) glDisable(GL_BLEND); +} + +void Renderer::RenderText(const char* pstr, int left, int top, u32 color) +{ + glColor4f( + ((color>>16) & 0xff)/255.0f, + ((color>> 8) & 0xff)/255.0f, + ((color>> 0) & 0xff)/255.0f, + ((color>>24) & 0xFF)/255.0f + ); + s_pfont->printMultilineText(pstr, left * 2.0f / (float)nBackbufferWidth - 1, 1 - top * 2.0f / (float)nBackbufferHeight,0,nBackbufferWidth,nBackbufferHeight); +} + +void Renderer::SetAA(int aa) +{ + +} + +void Renderer::ReinitView(int nNewWidth, int nNewHeight) +{ + int oldscreen = s_bFullscreen; + + OpenGL_Shutdown(); + int oldwidth = nBackbufferWidth, oldheight = nBackbufferHeight; + if (!OpenGL_Create(g_VideoInitialize, nNewWidth, nNewHeight)) {//nNewWidth&~7, nNewHeight&~7) ) { + ERROR_LOG("Failed to recreate, reverting to old settings\n"); + if (!OpenGL_Create(g_VideoInitialize, oldwidth, oldheight)) { + g_VideoInitialize.pSysMessage("Failed to revert, exiting...\n"); + // TODO - don't takedown the entire emu + exit(0); + } + } + OpenGL_MakeCurrent(); + + if (oldscreen && !g_Config.bFullscreen) { // if transitioning from full screen +#ifdef _WIN32 + RECT rc; + rc.left = 0; rc.top = 0; + rc.right = nNewWidth; rc.bottom = nNewHeight; + AdjustWindowRect(&rc, EmuWindow::g_winstyle, FALSE); + + RECT rcdesktop; + GetWindowRect(GetDesktopWindow(), &rcdesktop); + + SetWindowLong( EmuWindow::GetWnd(), GWL_STYLE, EmuWindow::g_winstyle ); + SetWindowPos(EmuWindow::GetWnd(), HWND_TOP, ((rcdesktop.right-rcdesktop.left)-(rc.right-rc.left))/2, + ((rcdesktop.bottom-rcdesktop.top)-(rc.bottom-rc.top))/2, + rc.right-rc.left, rc.bottom-rc.top, SWP_SHOWWINDOW); + UpdateWindow(EmuWindow::GetWnd()); +#else // linux +#endif + } + + nBackbufferWidth = nNewWidth > 16 ? nNewWidth : 16; + nBackbufferHeight = nNewHeight > 16 ? nNewHeight : 16; +} +int Renderer::GetTargetWidth() +{ + if(g_Config.bStretchToFit) + return 640; + else + return nBackbufferWidth; // return the actual window width +} + +int Renderer::GetTargetHeight() +{ + if(g_Config.bStretchToFit) + return 480; + else + return nBackbufferHeight; // return the actual window height +} + +bool Renderer::CanBlendLogicOp() +{ + return g_bBlendLogicOp; +} + +void Renderer::SetRenderTarget(u32 targ) +{ + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, targ!=0?targ:s_RenderTargets[s_nCurTarget], 0 ); +} + +void Renderer::SetDepthTarget(u32 targ) +{ + glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, targ != 0 ? targ : s_DepthTarget ); +} + +void Renderer::SetFramebuffer(u32 fb) +{ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb != 0 ? fb : s_uFramebuffer); +} + +u32 Renderer::GetRenderTarget() +{ + return s_RenderTargets[s_nCurTarget]; +} + +void Renderer::ResetGLState() +{ + glDisable(GL_SCISSOR_TEST); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glDepthMask(GL_FALSE); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + glDisable(GL_VERTEX_PROGRAM_ARB); + glDisable(GL_FRAGMENT_PROGRAM_ARB); +} + +void Renderer::RestoreGLState() +{ + glEnable(GL_SCISSOR_TEST); + + if (bpmem.genMode.cullmode > 0) glEnable(GL_CULL_FACE); + if (bpmem.zmode.testenable) glEnable(GL_DEPTH_TEST); + if (bpmem.blendmode.blendenable) glEnable(GL_BLEND); + if(bpmem.zmode.updateenable) glDepthMask(GL_TRUE); + + glEnable(GL_VERTEX_PROGRAM_ARB); + glEnable(GL_FRAGMENT_PROGRAM_ARB); + SetColorMask(); +} + +void Renderer::SetColorMask() +{ + if (bpmem.blendmode.alphaupdate && bpmem.blendmode.colorupdate) + glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); + else if (bpmem.blendmode.alphaupdate) + glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_TRUE); + else if (bpmem.blendmode.colorupdate) + glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_FALSE); +} + + +// ======================================================================================= +// Call browser: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadBPReg() +// case 0x52 > SetScissorRect() +// --------------- +// This function handles the OpenGL glScissor() function +// --------------- +// bpmem.scissorTL.x, y = 342x342 +// bpmem.scissorBR.x, y = 981x821 +// Renderer::GetTargetHeight() = the fixed ini file setting +// --------------- +bool Renderer::SetScissorRect() +{ + int xoff = bpmem.scissorOffset.x * 2 - 342; + int yoff = bpmem.scissorOffset.y * 2 - 342; + + float rc_left = bpmem.scissorTL.x - xoff - 342; // left = 0 + rc_left *= MValueX; + if (rc_left < 0) rc_left = 0; + + float rc_top = bpmem.scissorTL.y - yoff - 342; // right = 0 + rc_top *= MValueY; + if (rc_top < 0) rc_top = 0; + + float rc_right = bpmem.scissorBR.x - xoff - 342; // right = 640 + rc_right *= MValueX; + if (rc_right > 640 * MValueX) rc_right = 640 * MValueX; + + float rc_bottom = bpmem.scissorBR.y - yoff - 342; // bottom = 480 + rc_bottom *= MValueY; + if (rc_bottom > 480 * MValueY) rc_bottom = 480 * MValueY; + + /*__Log("Scissor: lt=(%d,%d), rb=(%d,%d,%i), off=(%d,%d)\n", + rc_left, rc_top, + rc_right, rc_bottom, Renderer::GetTargetHeight(), + xoff, yoff + );*/ + + if (rc_right >= rc_left && rc_bottom >= rc_top ) + { + glScissor( + (int)rc_left, // x = 0 + Renderer::GetTargetHeight()-(int)(rc_bottom), // y = 0 + (int)(rc_right-rc_left), // y = 0 + (int)(rc_bottom-rc_top) // y = 0 + ); + return true; + } + + return false; +} + + +bool Renderer::IsUsingATIDrawBuffers() +{ + return s_bATIDrawBuffers; +} + +bool Renderer::HaveStencilBuffer() +{ + return s_bHaveStencilBuffer; +} + +void Renderer::SetZBufferRender() +{ + nZBufferRender = 10; // give it 10 frames + GLenum s_drawbuffers[2] = { + GL_COLOR_ATTACHMENT0_EXT, + GL_COLOR_ATTACHMENT1_EXT + }; + glDrawBuffers(2, s_drawbuffers); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget, 0); + _assert_(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT); +} + +void Renderer::FlushZBufferAlphaToTarget() +{ + ResetGLState(); + + SetRenderTarget(0); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + + glViewport(0, 0, GetTargetWidth(), GetTargetHeight()); + + // texture map s_RenderTargets[s_curtarget] onto the main buffer + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget); + TextureMngr::EnableTexRECT(0); + // disable all other stages + for(int i = 1; i < 8; ++i) + TextureMngr::DisableStage(i); + GL_REPORT_ERRORD(); + + // setup the stencil to only accept pixels that have been written + glStencilFunc(GL_EQUAL, 1, 0xff); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + if(g_Config.bStretchToFit) + { + //TODO: Do Correctly in a bit + float FactorW = (float)640 / (float)nBackbufferWidth; + float FactorH = (float)480 / (float)nBackbufferHeight; + + float Max = (FactorW < FactorH) ? FactorH : FactorW; + float Temp = 1 / Max; + FactorW *= Temp; + FactorH *= Temp; + + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2f(-FactorW,-FactorH); + glTexCoord2f(0, (float)GetTargetHeight()); glVertex2f(-FactorW,FactorH); + glTexCoord2f((float)GetTargetWidth(), (float)GetTargetHeight()); glVertex2f(FactorW,FactorH); + glTexCoord2f((float)GetTargetWidth(), 0); glVertex2f(FactorW,-FactorH); + + __Log("%d, %d", FactorW, FactorH); + } + else + { + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2f(-1,-1); + glTexCoord2f(0, (float)(GetTargetHeight())); glVertex2f(-1,1); + glTexCoord2f((float)(GetTargetWidth()), (float)(GetTargetHeight())); glVertex2f(1,1); + glTexCoord2f((float)(GetTargetWidth()), 0); glVertex2f(1,-1); + } + glEnd(); + + GL_REPORT_ERRORD(); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + RestoreGLState(); +} + +void Renderer::SetRenderMode(RenderMode mode) +{ + if (!s_bHaveStencilBuffer && mode == RM_ZBufferAlpha) + mode = RM_ZBufferOnly; + + if (s_RenderMode == mode) + return; + + if (mode == RM_Normal) { + // flush buffers + if( s_RenderMode == RM_ZBufferAlpha ) { + FlushZBufferAlphaToTarget(); + glDisable(GL_STENCIL_TEST); + } + SetColorMask(); + SetRenderTarget(0); + SetZBufferRender(); + GL_REPORT_ERRORD(); + } + else if (s_RenderMode == RM_Normal) { + // setup buffers + _assert_(GetZBufferTarget() && bpmem.zmode.updateenable); + + if( mode == RM_ZBufferAlpha ) { + glEnable(GL_STENCIL_TEST); + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); + glStencilFunc(GL_ALWAYS, 1, 0xff); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + } + + glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + GL_REPORT_ERRORD(); + } + else { + _assert_(GetZBufferTarget()); + _assert_(s_bHaveStencilBuffer); + + if( mode == RM_ZBufferOnly ) { + // flush and remove stencil + _assert_(s_RenderMode==RM_ZBufferAlpha); + FlushZBufferAlphaToTarget(); + glDisable(GL_STENCIL_TEST); + + SetRenderTarget(s_ZBufferTarget); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + GL_REPORT_ERRORD(); + } + else { + _assert_(mode == RM_ZBufferAlpha&&s_RenderMode==RM_ZBufferOnly); + + // setup stencil + glEnable(GL_STENCIL_TEST); + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); + glStencilFunc(GL_ALWAYS, 1, 0xff); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + } + } + + s_RenderMode = mode; +} + +Renderer::RenderMode Renderer::GetRenderMode() +{ + return s_RenderMode; +} + +u32 Renderer::GetZBufferTarget() +{ + return nZBufferRender > 0 ? s_ZBufferTarget : 0; +} + +void Renderer::Swap(const TRectangle& rc) +{ + OpenGL_Update(); // just updates the render window position and the backbuffer size + + DVSTARTPROFILE(); + + Renderer::SetRenderMode(Renderer::RM_Normal); + + // render to the real buffer now + #ifdef USE_AA + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_RenderTargets[0]); + #else + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer + #endif + glViewport(nXoff, nYoff, nBackbufferWidth, nBackbufferHeight); + + ResetGLState(); + + // texture map s_RenderTargets[s_curtarget] onto the main buffer + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_RenderTargets[s_nCurTarget]); + TextureMngr::EnableTexRECT(0); + // disable all other stages + for(int i = 1; i < 8; ++i) TextureMngr::DisableStage(i); + GL_REPORT_ERRORD(); + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2f(-1,-1); + glTexCoord2f(0, (float)GetTargetHeight()); glVertex2f(-1,1); + glTexCoord2f((float)GetTargetWidth(), (float)GetTargetHeight()); glVertex2f(1,1); + glTexCoord2f((float)GetTargetWidth(), 0); glVertex2f(1,-1); + glEnd(); + + if (g_Config.bWireFrame) + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + TextureMngr::DisableStage(0); + + SwapBuffers(); + + RestoreGLState(); + #ifdef USE_AA + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, s_RenderTargets[s_nCurTarget]); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); + glBlitFramebufferEXT(0, 0, nBackbufferWidth, nBackbufferHeight, 0, 0, nBackbufferWidth, nBackbufferHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + #endif + GL_REPORT_ERRORD(); + + g_Config.iSaveTargetId = 0; + + // for testing zbuffer targets + //Renderer::SetZBufferRender(); + //SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget, GetTargetWidth(), GetTargetHeight()); +} + +void Renderer::SwapBuffers() +{ + static int fpscount; + static int s_fps; + static unsigned long lasttime; + ++fpscount; + if( timeGetTime() - lasttime > 1000 ) + { + lasttime = timeGetTime(); + s_fps = fpscount; + fpscount = 0; + } + + // Write logging data to debugger +#if defined(HAVE_WX) && HAVE_WX + if(m_frame) + { + Logging(0); + } +#endif + if (g_Config.bOverlayStats) { + char st[2048]; + char *p = st; + if(g_Config.bShowFPS) + p+=sprintf(p, "FPS: %d\n", s_fps); // So it shows up before the stats and doesn't make anyting ugly + p+=sprintf(p,"Num textures created: %i\n",stats.numTexturesCreated); + p+=sprintf(p,"Num textures alive: %i\n",stats.numTexturesAlive); + p+=sprintf(p,"Num pshaders created: %i\n",stats.numPixelShadersCreated); + p+=sprintf(p,"Num pshaders alive: %i\n",stats.numPixelShadersAlive); + p+=sprintf(p,"Num vshaders created: %i\n",stats.numVertexShadersCreated); + p+=sprintf(p,"Num vshaders alive: %i\n",stats.numVertexShadersAlive); + p+=sprintf(p,"Num dlists called: %i\n",stats.numDListsCalled); + p+=sprintf(p,"Num dlists called (frame): %i\n",stats.thisFrame.numDListsCalled); + // not used. + //p+=sprintf(p,"Num dlists created: %i\n",stats.numDListsCreated); + //p+=sprintf(p,"Num dlists alive: %i\n",stats.numDListsAlive); + //p+=sprintf(p,"Num strip joins: %i\n",stats.numJoins); + p+=sprintf(p,"Num primitives: %i\n",stats.thisFrame.numPrims); + p+=sprintf(p,"Num primitive joins: %i\n",stats.thisFrame.numPrimitiveJoins); + p+=sprintf(p,"Num buffer splits: %i\n",stats.thisFrame.numBufferSplits); + p+=sprintf(p,"Num draw calls: %i\n",stats.thisFrame.numDrawCalls); + p+=sprintf(p,"Num primitives (DL): %i\n",stats.thisFrame.numDLPrims); + p+=sprintf(p,"Num XF loads: %i\n",stats.thisFrame.numXFLoads); + p+=sprintf(p,"Num XF loads (DL): %i\n",stats.thisFrame.numXFLoadsInDL); + p+=sprintf(p,"Num CP loads: %i\n",stats.thisFrame.numCPLoads); + p+=sprintf(p,"Num CP loads (DL): %i\n",stats.thisFrame.numCPLoadsInDL); + p+=sprintf(p,"Num BP loads: %i\n",stats.thisFrame.numBPLoads); + p+=sprintf(p,"Num BP loads (DL): %i\n",stats.thisFrame.numBPLoadsInDL); + p+=sprintf(p,"Num vertex loaders: %i\n",stats.numVertexLoaders); + + + std::string text = st; + VertexLoaderManager::AppendListToString(&text); + + Renderer::RenderText(text.c_str(), 20, 20, 0xFF00FFFF); + } + else + { + if(g_Config.bShowFPS) + { + char strfps[25]; + sprintf(strfps, "%d\n", s_fps); + Renderer::RenderText(strfps, 20, 20, 0xFF00FFFF); + } + } + + Renderer::ProcessMessages(); + +#if defined(DVPROFILE) + if (g_bWriteProfile) { + //g_bWriteProfile = 0; + static int framenum = 0; + const int UPDATE_FRAMES = 8; + if (++framenum >= UPDATE_FRAMES) { + DVProfWrite("prof.txt", UPDATE_FRAMES); + DVProfClear(); + framenum = 0; + } + } +#endif + + // copy the rendered from to the real window + OpenGL_SwapBuffers(); + + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT); + + GL_REPORT_ERRORD(); + + //clean out old stuff from caches + frameCount++; + PixelShaderMngr::Cleanup(); + TextureMngr::Cleanup(); + + // New frame + stats.ResetFrame(); + + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer ); + + if (nZBufferRender > 0) { + if (--nZBufferRender == 0) { + // turn off + nZBufferRender = 0; + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0); + Renderer::SetRenderMode(RM_Normal); // turn off any zwrites + } + } +} + +bool Renderer::SaveRenderTarget(const char* filename, int jpeg) +{ + bool bflip = true; + std::vector data(nBackbufferWidth * nBackbufferHeight); + glReadPixels(0, 0, nBackbufferWidth, nBackbufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]); + if (glGetError() != GL_NO_ERROR) + return false; + + if (bflip) { + // swap scanlines + std::vector scanline(nBackbufferWidth); + for(int i = 0; i < nBackbufferHeight/2; ++i) { + memcpy(&scanline[0], &data[i*nBackbufferWidth], nBackbufferWidth*4); + memcpy(&data[i*nBackbufferWidth], &data[(nBackbufferHeight-i-1)*nBackbufferWidth], nBackbufferWidth*4); + memcpy(&data[(nBackbufferHeight-i-1)*nBackbufferWidth], &scanline[0], nBackbufferWidth*4); + } + } + + return SaveTGA(filename, nBackbufferWidth, nBackbufferHeight, &data[0]); +} + +void Renderer::SetCgErrorOutput(bool bOutput) +{ + s_bOutputCgErrors = bOutput; +} + +void HandleGLError() +{ + const GLubyte* pstr = glGetString(GL_PROGRAM_ERROR_STRING_ARB); + if (pstr != NULL && pstr[0] != 0) + { + GLint loc = 0; + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &loc); + ERROR_LOG("program error at %d: ", loc); + ERROR_LOG((char*)pstr); + ERROR_LOG("\n"); + } + + // check the error status of this framebuffer */ + GLenum error = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + + // if error != GL_FRAMEBUFFER_COMPLETE_EXT, there's an error of some sort + if (!error) + return; + +// int w, h; +// GLint fmt; +// glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &fmt); +// glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_WIDTH_EXT, (GLint *)&w); +// glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_HEIGHT_EXT, (GLint *)&h); + + switch(error) + { + case GL_FRAMEBUFFER_COMPLETE_EXT: + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: + ERROR_LOG("Error! missing a required image/buffer attachment!\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: + ERROR_LOG("Error! has no images/buffers attached!\n"); + break; +// case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: +// ERROR_LOG("Error! has an image/buffer attached in multiple locations!\n"); +// break; + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: + ERROR_LOG("Error! has mismatched image/buffer dimensions!\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: + ERROR_LOG("Error! colorbuffer attachments have different types!\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: + ERROR_LOG("Error! trying to draw to non-attached color buffer!\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: + ERROR_LOG("Error! trying to read from a non-attached color buffer!\n"); + break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + ERROR_LOG("Error! format is not supported by current graphics card/driver!\n"); + break; + default: + ERROR_LOG("*UNKNOWN ERROR* reported from glCheckFramebufferStatusEXT()!\n"); + break; + } +} + +void HandleCgError(CGcontext ctx, CGerror err, void* appdata) +{ + if (s_bOutputCgErrors) + { + ERROR_LOG("Cg error: %s\n", cgGetErrorString(err)); + const char* listing = cgGetLastListing(g_cgcontext); + if (listing != NULL) { + ERROR_LOG(" last listing: %s\n", listing); + } + // glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &loc); + // printf("pos: %d\n", loc); + } +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp index 4826ff3d8b..6637560c7d 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp @@ -1,224 +1,224 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "TextureConverter.h" -#include "PixelShaderManager.h" -#include "VertexShaderManager.h" -#include "Globals.h" -#include "GLUtil.h" -#include "Render.h" - -namespace TextureConverter -{ - -static GLuint s_frameBuffer = 0; -static GLuint s_srcTexture = 0; // for decoding from RAM -static GLuint s_dstRenderBuffer = 0; // for encoding to RAM - -const int renderBufferWidth = 1024; -const int renderBufferHeight = 1024; - -static FRAGMENTSHADER s_rgbToYuyvProgram; -static FRAGMENTSHADER s_yuyvToRgbProgram; - -void CreateRgbToYuyvProgram() -{ - // output is BGRA because that is slightly faster than RGBA - char *FProgram = (char *) - "uniform samplerRECT samp0 : register(s0);\n" - "void main(\n" - " out float4 ocol0 : COLOR0,\n" - " in float2 uv0 : TEXCOORD0)\n" - "{\n" - " float2 uv1 = float2(uv0.x + 1.0f, uv0.y);\n" - " float3 c0 = texRECT(samp0, uv0).rgb;\n" - " float3 c1 = texRECT(samp0, uv1).rgb;\n" - - " float y0 = (0.257f * c0.r) + (0.504f * c0.g) + (0.098f * c0.b) + 0.0625f;\n" - " float u0 =-(0.148f * c0.r) - (0.291f * c0.g) + (0.439f * c0.b) + 0.5f;\n" - " float y1 = (0.257f * c1.r) + (0.504f * c1.g) + (0.098f * c1.b) + 0.0625f;\n" - " float v1 = (0.439f * c1.r) - (0.368f * c1.g) - (0.071f * c1.b) + 0.5f;\n" - - " ocol0 = float4(y1, u0, y0, v1);\n" - "}\n"; - - if (!PixelShaderMngr::CompilePixelShader(s_rgbToYuyvProgram, FProgram)) { - ERROR_LOG("Failed to create RGB to YUYV fragment program\n"); - } -} - -void CreateYuyvToRgbProgram() -{ - char *FProgram = (char *) - "uniform samplerRECT samp0 : register(s0);\n" - "void main(\n" - " out float4 ocol0 : COLOR0,\n" - " in float2 uv0 : TEXCOORD0)\n" - "{\n" - " float4 c0 = texRECT(samp0, uv0).rgba;\n" - - " float f = step(0.5, frac(uv0.x));\n" - " float y = lerp(c0.b, c0.r, f);\n" - " float yComp = 1.164f * (y - 0.0625f);\n" - " float uComp = c0.g - 0.5f;\n" - " float vComp = c0.a - 0.5f;\n" - - " ocol0 = float4(yComp + (1.596f * vComp),\n" - " yComp - (0.813f * vComp) - (0.391f * uComp),\n" - " yComp + (2.018f * uComp),\n" - " 1.0f);\n" - "}\n"; - - if (!PixelShaderMngr::CompilePixelShader(s_yuyvToRgbProgram, FProgram)) { - ERROR_LOG("Failed to create YUYV to RGB fragment program\n"); - } -} - -void Init() -{ - glGenFramebuffersEXT( 1, &s_frameBuffer); - - glGenRenderbuffersEXT(1, &s_dstRenderBuffer); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, renderBufferWidth, renderBufferHeight); - - glGenTextures(1, &s_srcTexture); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_srcTexture); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - CreateRgbToYuyvProgram(); - CreateYuyvToRgbProgram(); -} - -void Shutdown() -{ - glDeleteTextures(1, &s_srcTexture); - - glDeleteRenderbuffersEXT(1, &s_dstRenderBuffer); - - glDeleteFramebuffersEXT(1, &s_frameBuffer); -} - -void EncodeToRam(GLuint srcTexture, const TRectangle& sourceRc, - u8* destAddr, int dstWidth, int dstHeight) -{ - Renderer::SetRenderMode(Renderer::RM_Normal); - - Renderer::ResetGLState(); - - float dstFormatFactor = 0.5f; - float dstFmtWidth = dstWidth * dstFormatFactor; - - // switch to texture converter frame buffer - // attach render buffer as color destination - Renderer::SetFramebuffer(s_frameBuffer); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, s_dstRenderBuffer); - GL_REPORT_ERRORD(); - - // set source texture - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexture); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - TextureMngr::EnableTexRECT(0); - for (int i = 1; i < 8; ++i) - TextureMngr::DisableStage(i); - GL_REPORT_ERRORD(); - - glViewport(0, 0, dstFmtWidth, dstHeight); - - glEnable(GL_FRAGMENT_PROGRAM_ARB); - glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, s_rgbToYuyvProgram.glprogid); - - glBegin(GL_QUADS); - glTexCoord2f((float)sourceRc.left, (float)sourceRc.top); glVertex2f(-1,-1); - glTexCoord2f((float)sourceRc.left, (float)sourceRc.bottom); glVertex2f(-1,1); - glTexCoord2f((float)sourceRc.right, (float)sourceRc.bottom); glVertex2f(1,1); - glTexCoord2f((float)sourceRc.right, (float)sourceRc.top); glVertex2f(1,-1); - glEnd(); - GL_REPORT_ERRORD(); - - // TODO: this is real slow. try using a pixel buffer object. - glReadPixels(0, 0, dstFmtWidth, dstHeight, GL_BGRA, GL_UNSIGNED_BYTE, destAddr); - GL_REPORT_ERRORD(); - - Renderer::SetFramebuffer(0); - Renderer::RestoreGLState(); - VertexShaderMngr::SetViewportChanged(); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - TextureMngr::DisableStage(0); - - Renderer::RestoreGLState(); - GL_REPORT_ERRORD(); -} - -void DecodeToTexture(u8* srcAddr, int srcWidth, int srcHeight, GLuint destTexture) -{ - Renderer::SetRenderMode(Renderer::RM_Normal); - - Renderer::ResetGLState(); - - float srcFormatFactor = 0.5f; - float srcFmtWidth = srcWidth * srcFormatFactor; - - // swich to texture converter frame buffer - // attach destTexture as color destination - Renderer::SetFramebuffer(s_frameBuffer); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destTexture); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, destTexture, 0); - - // activate source texture - // set srcAddr as data for source texture - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_srcTexture); - - // TODO: this is slow. try using a pixel buffer object. - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, srcFmtWidth, srcHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr); - - TextureMngr::EnableTexRECT(0); - for (int i = 1; i < 8; ++i) - TextureMngr::DisableStage(i); - - glViewport(0, 0, srcWidth, srcHeight); - - glEnable(GL_FRAGMENT_PROGRAM_ARB); - glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, s_yuyvToRgbProgram.glprogid); - - GL_REPORT_ERRORD(); - - glBegin(GL_QUADS); - glTexCoord2f(srcFmtWidth, srcHeight); glVertex2f(1,-1); - glTexCoord2f(srcFmtWidth, 0); glVertex2f(1,1); - glTexCoord2f(0, 0); glVertex2f(-1,1); - glTexCoord2f(0, srcHeight); glVertex2f(-1,-1); - glEnd(); - - // reset state - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - TextureMngr::DisableStage(0); - - VertexShaderMngr::SetViewportChanged(); - - Renderer::RestoreGLState(); - GL_REPORT_ERRORD(); -} - -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "TextureConverter.h" +#include "PixelShaderManager.h" +#include "VertexShaderManager.h" +#include "Globals.h" +#include "GLUtil.h" +#include "Render.h" + +namespace TextureConverter +{ + +static GLuint s_frameBuffer = 0; +static GLuint s_srcTexture = 0; // for decoding from RAM +static GLuint s_dstRenderBuffer = 0; // for encoding to RAM + +const int renderBufferWidth = 1024; +const int renderBufferHeight = 1024; + +static FRAGMENTSHADER s_rgbToYuyvProgram; +static FRAGMENTSHADER s_yuyvToRgbProgram; + +void CreateRgbToYuyvProgram() +{ + // output is BGRA because that is slightly faster than RGBA + char *FProgram = (char *) + "uniform samplerRECT samp0 : register(s0);\n" + "void main(\n" + " out float4 ocol0 : COLOR0,\n" + " in float2 uv0 : TEXCOORD0)\n" + "{\n" + " float2 uv1 = float2(uv0.x + 1.0f, uv0.y);\n" + " float3 c0 = texRECT(samp0, uv0).rgb;\n" + " float3 c1 = texRECT(samp0, uv1).rgb;\n" + + " float y0 = (0.257f * c0.r) + (0.504f * c0.g) + (0.098f * c0.b) + 0.0625f;\n" + " float u0 =-(0.148f * c0.r) - (0.291f * c0.g) + (0.439f * c0.b) + 0.5f;\n" + " float y1 = (0.257f * c1.r) + (0.504f * c1.g) + (0.098f * c1.b) + 0.0625f;\n" + " float v1 = (0.439f * c1.r) - (0.368f * c1.g) - (0.071f * c1.b) + 0.5f;\n" + + " ocol0 = float4(y1, u0, y0, v1);\n" + "}\n"; + + if (!PixelShaderMngr::CompilePixelShader(s_rgbToYuyvProgram, FProgram)) { + ERROR_LOG("Failed to create RGB to YUYV fragment program\n"); + } +} + +void CreateYuyvToRgbProgram() +{ + char *FProgram = (char *) + "uniform samplerRECT samp0 : register(s0);\n" + "void main(\n" + " out float4 ocol0 : COLOR0,\n" + " in float2 uv0 : TEXCOORD0)\n" + "{\n" + " float4 c0 = texRECT(samp0, uv0).rgba;\n" + + " float f = step(0.5, frac(uv0.x));\n" + " float y = lerp(c0.b, c0.r, f);\n" + " float yComp = 1.164f * (y - 0.0625f);\n" + " float uComp = c0.g - 0.5f;\n" + " float vComp = c0.a - 0.5f;\n" + + " ocol0 = float4(yComp + (1.596f * vComp),\n" + " yComp - (0.813f * vComp) - (0.391f * uComp),\n" + " yComp + (2.018f * uComp),\n" + " 1.0f);\n" + "}\n"; + + if (!PixelShaderMngr::CompilePixelShader(s_yuyvToRgbProgram, FProgram)) { + ERROR_LOG("Failed to create YUYV to RGB fragment program\n"); + } +} + +void Init() +{ + glGenFramebuffersEXT( 1, &s_frameBuffer); + + glGenRenderbuffersEXT(1, &s_dstRenderBuffer); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, renderBufferWidth, renderBufferHeight); + + glGenTextures(1, &s_srcTexture); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_srcTexture); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + CreateRgbToYuyvProgram(); + CreateYuyvToRgbProgram(); +} + +void Shutdown() +{ + glDeleteTextures(1, &s_srcTexture); + + glDeleteRenderbuffersEXT(1, &s_dstRenderBuffer); + + glDeleteFramebuffersEXT(1, &s_frameBuffer); +} + +void EncodeToRam(GLuint srcTexture, const TRectangle& sourceRc, + u8* destAddr, int dstWidth, int dstHeight) +{ + Renderer::SetRenderMode(Renderer::RM_Normal); + + Renderer::ResetGLState(); + + float dstFormatFactor = 0.5f; + float dstFmtWidth = dstWidth * dstFormatFactor; + + // switch to texture converter frame buffer + // attach render buffer as color destination + Renderer::SetFramebuffer(s_frameBuffer); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, s_dstRenderBuffer); + GL_REPORT_ERRORD(); + + // set source texture + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexture); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + TextureMngr::EnableTexRECT(0); + for (int i = 1; i < 8; ++i) + TextureMngr::DisableStage(i); + GL_REPORT_ERRORD(); + + glViewport(0, 0, dstFmtWidth, dstHeight); + + glEnable(GL_FRAGMENT_PROGRAM_ARB); + glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, s_rgbToYuyvProgram.glprogid); + + glBegin(GL_QUADS); + glTexCoord2f((float)sourceRc.left, (float)sourceRc.top); glVertex2f(-1,-1); + glTexCoord2f((float)sourceRc.left, (float)sourceRc.bottom); glVertex2f(-1,1); + glTexCoord2f((float)sourceRc.right, (float)sourceRc.bottom); glVertex2f(1,1); + glTexCoord2f((float)sourceRc.right, (float)sourceRc.top); glVertex2f(1,-1); + glEnd(); + GL_REPORT_ERRORD(); + + // TODO: this is real slow. try using a pixel buffer object. + glReadPixels(0, 0, dstFmtWidth, dstHeight, GL_BGRA, GL_UNSIGNED_BYTE, destAddr); + GL_REPORT_ERRORD(); + + Renderer::SetFramebuffer(0); + Renderer::RestoreGLState(); + VertexShaderMngr::SetViewportChanged(); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + TextureMngr::DisableStage(0); + + Renderer::RestoreGLState(); + GL_REPORT_ERRORD(); +} + +void DecodeToTexture(u8* srcAddr, int srcWidth, int srcHeight, GLuint destTexture) +{ + Renderer::SetRenderMode(Renderer::RM_Normal); + + Renderer::ResetGLState(); + + float srcFormatFactor = 0.5f; + float srcFmtWidth = srcWidth * srcFormatFactor; + + // swich to texture converter frame buffer + // attach destTexture as color destination + Renderer::SetFramebuffer(s_frameBuffer); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destTexture); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, destTexture, 0); + + // activate source texture + // set srcAddr as data for source texture + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_srcTexture); + + // TODO: this is slow. try using a pixel buffer object. + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, srcFmtWidth, srcHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr); + + TextureMngr::EnableTexRECT(0); + for (int i = 1; i < 8; ++i) + TextureMngr::DisableStage(i); + + glViewport(0, 0, srcWidth, srcHeight); + + glEnable(GL_FRAGMENT_PROGRAM_ARB); + glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, s_yuyvToRgbProgram.glprogid); + + GL_REPORT_ERRORD(); + + glBegin(GL_QUADS); + glTexCoord2f(srcFmtWidth, srcHeight); glVertex2f(1,-1); + glTexCoord2f(srcFmtWidth, 0); glVertex2f(1,1); + glTexCoord2f(0, 0); glVertex2f(-1,1); + glTexCoord2f(0, srcHeight); glVertex2f(-1,-1); + glEnd(); + + // reset state + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + TextureMngr::DisableStage(0); + + VertexShaderMngr::SetViewportChanged(); + + Renderer::RestoreGLState(); + GL_REPORT_ERRORD(); +} + +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp index 457065afc4..9c0fdcd0f1 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp @@ -1,647 +1,647 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Globals.h" - -#ifdef _WIN32 -#define _interlockedbittestandset workaround_ms_header_bug_platform_sdk6_set -#define _interlockedbittestandreset workaround_ms_header_bug_platform_sdk6_reset -#define _interlockedbittestandset64 workaround_ms_header_bug_platform_sdk6_set64 -#define _interlockedbittestandreset64 workaround_ms_header_bug_platform_sdk6_reset64 -#include -#undef _interlockedbittestandset -#undef _interlockedbittestandreset -#undef _interlockedbittestandset64 -#undef _interlockedbittestandreset64 -#endif - -#include "Config.h" -#include "Statistics.h" -#include "Profiler.h" -#include "ImageWrite.h" - -#include "Render.h" - -#include "MemoryUtil.h" -#include "BPStructs.h" -#include "TextureDecoder.h" -#include "TextureMngr.h" -#include "PixelShaderManager.h" -#include "VertexShaderManager.h" - -u8 *TextureMngr::temp = NULL; -TextureMngr::TexCache TextureMngr::textures; -std::map TextureMngr::mapDepthTargets; -int TextureMngr::nTex2DEnabled, TextureMngr::nTexRECTEnabled; - -extern int frameCount; -static u32 s_TempFramebuffer = 0; - -#define TEMP_SIZE (1024*1024*4) -#define TEXTURE_KILL_THRESHOLD 200 - -const GLint c_MinLinearFilter[8] = { - GL_NEAREST, - GL_NEAREST_MIPMAP_NEAREST, - GL_NEAREST_MIPMAP_LINEAR, - GL_NEAREST, - GL_LINEAR, - GL_LINEAR_MIPMAP_NEAREST, - GL_LINEAR_MIPMAP_LINEAR, - GL_LINEAR -}; - -const GLint c_WrapSettings[4] = { GL_CLAMP_TO_EDGE, GL_REPEAT, GL_MIRRORED_REPEAT, GL_REPEAT }; - -void TextureMngr::TCacheEntry::SetTextureParameters(TexMode0 &newmode) -{ - mode = newmode; - if (isNonPow2) { - // very limited! - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, - (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, - (g_Config.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST); - if (newmode.wrap_s == 2 || newmode.wrap_t == 2) { - DEBUG_LOG("cannot support mirrorred repeat mode\n"); - } - if (newmode.wrap_s == 1 || newmode.wrap_t == 1) { - DEBUG_LOG("cannot support repeat mode\n"); - } - } - else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST); - - if (bHaveMipMaps) { - int filt = newmode.min_filter; - if (g_Config.bForceFiltering && newmode.min_filter < 4) - newmode.min_filter += 4; // take equivalent forced linear - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt]); - } - else - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - (g_Config.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c_WrapSettings[newmode.wrap_s]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]); - } - - if (g_Config.iMaxAnisotropy >= 1) - { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 << g_Config.iMaxAnisotropy); - } -} - -void TextureMngr::TCacheEntry::Destroy() -{ - if(!texture) - return; - glDeleteTextures(1, &texture); - if (!isRenderTarget) { - if (!g_Config.bSafeTextureCache) { - u32 *ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(addr + hashoffset * 4); - if (*ptr == hash) - *ptr = oldpixel; - } - } - texture = 0; -} - -void TextureMngr::Init() -{ - temp = (u8*)AllocateMemoryPages(TEMP_SIZE); - nTex2DEnabled = nTexRECTEnabled = 0; - TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter); -} - -void TextureMngr::Invalidate() -{ - TexCache::iterator iter = textures.begin(); - for (; iter!=textures.end(); iter++) - iter->second.Destroy(); - textures.clear(); - TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter); -} - -void TextureMngr::Shutdown() -{ - Invalidate(); - std::map::iterator itdepth = mapDepthTargets.begin(); - for (itdepth = mapDepthTargets.begin(); itdepth != mapDepthTargets.end(); ++itdepth) { - glDeleteRenderbuffersEXT(1, &itdepth->second.targ); - } - mapDepthTargets.clear(); - - if (s_TempFramebuffer) { - glDeleteFramebuffersEXT(1, (GLuint *)&s_TempFramebuffer); - s_TempFramebuffer = 0; - } - - FreeMemoryPages(temp, TEMP_SIZE); - temp = NULL; -} - -void TextureMngr::Cleanup() -{ - TexCache::iterator iter = textures.begin(); - while (iter != textures.end()) { - if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second.frameCount) { - if (!iter->second.isRenderTarget) { - iter->second.Destroy(); -#ifdef _WIN32 - iter = textures.erase(iter); -#else - textures.erase(iter++); -#endif - } - else { - iter->second.Destroy(); -#ifdef _WIN32 - iter = textures.erase(iter); -#else - textures.erase(iter++); -#endif - } - } - else - iter++; - } - - std::map::iterator itdepth = mapDepthTargets.begin(); - while (itdepth != mapDepthTargets.end()) { - if (frameCount > 20 + itdepth->second.framecount) { -#ifdef _WIN32 - itdepth = mapDepthTargets.erase(itdepth); -#else - mapDepthTargets.erase(itdepth++); -#endif - } - else ++itdepth; - } -} - -TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt) -{ - if (address == 0) - return NULL; - - TexCache::iterator iter = textures.find(address); - TexMode0 &tm0 = bpmem.tex[texstage > 3].texMode0[texstage & 3]; - u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address); - - // Needed for texture format using tlut. - // TODO: Slower == Safer. Recalculate tlut lenght for each cases just to be sure. - u32 hashseed = 0; - switch (format) { - case GX_TF_C4: - hashseed = TexDecoder_GetTlutHash((u16*)(texMem + tlutaddr), 128); - break; - case GX_TF_C8: - hashseed = TexDecoder_GetTlutHash((u16*)(texMem + tlutaddr), 256); - break; - case GX_TF_C14X2: - hashseed = TexDecoder_GetTlutHash((u16*)(texMem + tlutaddr), 384); - break; - } - - int palSize = TexDecoder_GetPaletteSize(format); - u32 palhash = 0xc0debabe; - - if (palSize) { - if (palSize > 32) - palSize = 32; //let's not do excessive amount of checking - u8 *pal = g_VideoInitialize.pGetMemoryPointer(tlutaddr); - if (pal != 0) { - for (int i = 0; i < palSize; i++) { - palhash = _rotl(palhash,13); - palhash ^= pal[i]; - palhash += 31; - } - } - } - - int bs = TexDecoder_GetBlockWidthInTexels(format) - 1; - int expandedWidth = (width + bs) & (~bs); - - if (iter != textures.end()) { - TCacheEntry &entry = iter->second; - - u32 hash_value; - if (g_Config.bSafeTextureCache) - hash_value = TexDecoder_GetSafeTextureHash(ptr, expandedWidth, height, format, hashseed); - else - hash_value = ((u32 *)ptr)[entry.hashoffset]; - - if (entry.isRenderTarget || (hash_value == entry.hash && palhash == entry.paletteHash)) { - entry.frameCount = frameCount; - //glEnable(entry.isNonPow2?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D); - glBindTexture(entry.isNonPow2 ? GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D, entry.texture); - if (entry.mode.hex != tm0.hex) - entry.SetTextureParameters(tm0); - return &entry; - } - else - { - // can potentially do some caching - - //TCacheEntry &entry = entry; - /*if (width == entry.w && height==entry.h && format==entry.fmt) - { - LPDIRECT3DTEXTURE9 tex = entry.texture; - int bs = TexDecoder_GetBlockWidthInTexels(format)-1; - int expandedWidth = (width+bs) & (~bs); - D3DFORMAT dfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt); - ReplaceTexture2D(tex,temp,width,height,expandedWidth,dfmt); - dev->SetTexture(texstage, stage,tex); - return; - } - else - {*/ - entry.Destroy(); - textures.erase(iter); - //} - } - } - - PC_TexFormat dfmt = TexDecoder_Decode(temp, ptr, expandedWidth, height, format, tlutaddr, tlutfmt); - - //Make an entry in the table - TCacheEntry& entry = textures[address]; - - entry.hashoffset = 0; - entry.paletteHash = palhash; - entry.oldpixel = ((u32 *)ptr)[entry.hashoffset]; - if (g_Config.bSafeTextureCache) { - entry.hash = TexDecoder_GetSafeTextureHash(ptr, expandedWidth, height, format, hashseed); - } else { - entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF); - ((u32 *)ptr)[entry.hashoffset] = entry.hash; - } - - entry.addr = address; - entry.isRenderTarget = false; - - entry.isNonPow2 = ((width & (width - 1)) || (height & (height - 1))); - - glGenTextures(1, (GLuint *)&entry.texture); - GLenum target = entry.isNonPow2 ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D; - glBindTexture(target, entry.texture); - - if (expandedWidth != width) - glPixelStorei(GL_UNPACK_ROW_LENGTH, expandedWidth); - - int gl_format; - int gl_type; - switch (dfmt) { - case PC_TEX_FMT_NONE: - PanicAlert("Invalid PC texture format %i", dfmt); - case PC_TEX_FMT_BGRA32: - gl_format = GL_BGRA; - gl_type = GL_UNSIGNED_BYTE; - break; - } - if (!entry.isNonPow2 && ((tm0.min_filter & 3) == 1 || (tm0.min_filter & 3) == 2)) { - gluBuild2DMipmaps(GL_TEXTURE_2D, 4, width, height, gl_format, gl_type, temp); - entry.bHaveMipMaps = true; - } - else - glTexImage2D(target, 0, 4, width, height, 0, gl_format, gl_type, temp); - - if (expandedWidth != width) // reset - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - - entry.frameCount = frameCount; - entry.w = width; - entry.h = height; - entry.fmt = format; - entry.SetTextureParameters(tm0); - - if (g_Config.bDumpTextures) { // dump texture to file - static int counter = 0; - char szTemp[MAX_PATH]; - sprintf(szTemp, "%s/txt_%04i_%i.tga", g_Config.texDumpPath, counter++, format); - - SaveTexture(szTemp,target, entry.texture, width, height); - } - - INCSTAT(stats.numTexturesCreated); - SETSTAT(stats.numTexturesAlive, textures.size()); - - //glEnable(entry.isNonPow2?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D); - - //SaveTexture("tex.tga", target, entry.texture, entry.w, entry.h); - return &entry; -} - -void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, bool bScaleByHalf, TRectangle *source) -{ - DVSTARTPROFILE(); - GL_REPORT_ERRORD(); - - // for intensity values, use Y of YUV format! - // for all purposes, treat 4bit equivalents as 8bit (probably just used for compression) - // RGBA8 - RGBA8 - // RGB565 - RGB565 - // RGB5A3 - RGB5A3 - // I4,R4,Z4 - I4 - // IA4,RA4 - IA4 - // Z8M,G8,I8,A8,Z8,R8,B8,Z8L - I8 - // Z16,GB8,RG8,Z16L,IA8,RA8 - IA8 - bool bIsInit = textures.find(address) != textures.end(); - - PRIM_LOG("copytarg: addr=0x%x, fromz=%d, intfmt=%d, copyfmt=%d\n", address, (int)bFromZBuffer,(int)bIsIntensityFmt,copyfmt); - - TCacheEntry& entry = textures[address]; - entry.isNonPow2 = true; - entry.hash = 0; - entry.hashoffset = 0; - entry.frameCount = frameCount; - - int mult = bScaleByHalf?2:1; - int w = (abs(source->right-source->left)/mult); - int h = (abs(source->bottom-source->top)/mult); - - GL_REPORT_ERRORD(); - - if (!bIsInit) { - glGenTextures(1, (GLuint *)&entry.texture); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, entry.texture); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - GL_REPORT_ERRORD(); - } - else { - _assert_(entry.texture); - bool bReInit = true; - - if (entry.w == w && entry.h == h) { - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, entry.texture); - // for some reason mario sunshine errors here... - GLenum err = GL_NO_ERROR; - GL_REPORT_ERROR(); - if (err == GL_NO_ERROR ) - bReInit = false; - } - - if (bReInit) { - // necessary, for some reason opengl gives errors when texture isn't deleted - glDeleteTextures(1,(GLuint *)&entry.texture); - glGenTextures(1, (GLuint *)&entry.texture); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, entry.texture); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - GL_REPORT_ERRORD(); - } - } - - if (!bIsInit || !entry.isRenderTarget) { - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (glGetError() != GL_NO_ERROR) { - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP); - GL_REPORT_ERRORD(); - } - } - - entry.w = w; - entry.h = h; - entry.isRenderTarget = true; - entry.fmt = copyfmt; - - float colmat[16]; - float fConstAdd[4] = {0}; - memset(colmat, 0, sizeof(colmat)); - - if (bFromZBuffer) { - switch(copyfmt) { - case 0: // Z4 - case 1: // Z8 - colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1; - break; - - case 3: // Z16 //? - case 11: // Z16 - colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1; - break; - case 6: // Z24X8 - colmat[0] = 1; - colmat[5] = 1; - colmat[10] = 1; - break; - case 9: // Z8M - colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1; - break; - case 10: // Z8L - colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1; - break; - case 12: // Z16L - colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1; - break; - default: - ERROR_LOG("Unknown copy zbuf format: 0x%x\n", copyfmt); - colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1; - break; - } - } - else if (bIsIntensityFmt) { - fConstAdd[0] = fConstAdd[1] = fConstAdd[2] = 16.0f/255.0f; - switch(copyfmt) { - case 0: // I4 - case 1: // I8 - case 2: // IA4 - case 3: // IA8 - // TODO - verify these coefficients - colmat[0] = 0.257f; colmat[1] = 0.504f; colmat[2] = 0.098f; - colmat[4] = 0.257f; colmat[5] = 0.504f; colmat[6] = 0.098f; - colmat[8] = 0.257f; colmat[9] = 0.504f; colmat[10] = 0.098f; - if (copyfmt < 2) { - fConstAdd[3] = 16.0f / 255.0f; - colmat[12] = 0.257f; colmat[13] = 0.504f; colmat[14] = 0.098f; - } - else { // alpha - colmat[15] = 1; - } - break; - default: - ERROR_LOG("Unknown copy intensity format: 0x%x\n", copyfmt); - colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1; - break; - } - } - else { - switch (copyfmt) { - case 0: // R4 - case 8: // R8 - colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1; - break; - case 2: // RA4 - case 3: // RA8 - colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1; - break; - - case 7: // A8 - colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1; - break; - case 9: // G8 - colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1; - break; - case 10: // B8 - colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1; - break; - case 11: // RG8 - colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1; - break; - case 12: // GB8 - colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1; - break; - - case 4: // RGB565 - colmat[0] = colmat[5] = colmat[10] = 1; - fConstAdd[3] = 1; // set alpha to 1 - break; - case 5: // RGB5A3 - case 6: // RGBA8 - colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1; - break; - - default: - ERROR_LOG("Unknown copy color format: 0x%x\n", copyfmt); - colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1; - break; - } - } - -// if (bCopyToTarget) { -// _assert_( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); -// glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); -// GL_REPORT_ERRORD(); -// glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, source->left, source->top, source->right-source->left, source->bottom-source->top); -// entry.isUpsideDown = true; // note that the copy is upside down!! -// GL_REPORT_ERRORD(); -// return; -// } - - Renderer::SetRenderMode(Renderer::RM_Normal); // set back to normal - GL_REPORT_ERRORD(); - - // have to run a pixel shader - - Renderer::ResetGLState(); // reset any game specific settings - - if (s_TempFramebuffer == 0 ) - glGenFramebuffersEXT( 1, (GLuint *)&s_TempFramebuffer); - - Renderer::SetFramebuffer(s_TempFramebuffer); - Renderer::SetRenderTarget(entry.texture); - GL_REPORT_ERRORD(); - - // create and attach the render target - std::map::iterator itdepth = mapDepthTargets.find((h << 16) | w); - - if (itdepth == mapDepthTargets.end()) { - DEPTHTARGET& depth = mapDepthTargets[(h << 16) | w]; - depth.framecount = frameCount; - glGenRenderbuffersEXT(1, &depth.targ); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth.targ); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT/*GL_DEPTH24_STENCIL8_EXT*/, w, h); - GL_REPORT_ERRORD(); - Renderer::SetDepthTarget(depth.targ); - GL_REPORT_ERRORD(); - } - else { - itdepth->second.framecount = frameCount; - Renderer::SetDepthTarget(itdepth->second.targ); - GL_REPORT_ERRORD(); - } - - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, bFromZBuffer?Renderer::GetZBufferTarget():Renderer::GetRenderTarget()); - TextureMngr::EnableTexRECT(0); - - glViewport(0, 0, w, h); - - glEnable(GL_FRAGMENT_PROGRAM_ARB); - glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, PixelShaderMngr::GetColorMatrixProgram()); - PixelShaderMngr::SetColorMatrix(colmat, fConstAdd); // set transformation - GL_REPORT_ERRORD(); - - glBegin(GL_QUADS); - glTexCoord2f((float)source->left * MValueX, Renderer::GetTargetHeight()-(float)source->bottom * MValueY); glVertex2f(-1,1); - glTexCoord2f((float)source->left * MValueX, Renderer::GetTargetHeight()-(float)source->top * MValueY); glVertex2f(-1,-1); - glTexCoord2f((float)source->right * MValueX, Renderer::GetTargetHeight()-(float)source->top * MValueY); glVertex2f(1,-1); - glTexCoord2f((float)source->right * MValueX, Renderer::GetTargetHeight()-(float)source->bottom * MValueY); glVertex2f(1,1); - glEnd(); - - GL_REPORT_ERRORD(); - - Renderer::SetFramebuffer(0); - Renderer::RestoreGLState(); - VertexShaderMngr::SetViewportChanged(); - - TextureMngr::DisableStage(0); - - if (bFromZBuffer ) - Renderer::SetZBufferRender(); // notify for future settings - - GL_REPORT_ERRORD(); - //SaveTexture("frame.tga", GL_TEXTURE_RECTANGLE_ARB, entry.texture, entry.w, entry.h); - //SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_ARB, Renderer::GetZBufferTarget(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight()); -} - -void TextureMngr::EnableTex2D(int stage) -{ - if (!(nTex2DEnabled & (1< +#undef _interlockedbittestandset +#undef _interlockedbittestandreset +#undef _interlockedbittestandset64 +#undef _interlockedbittestandreset64 +#endif + +#include "Config.h" +#include "Statistics.h" +#include "Profiler.h" +#include "ImageWrite.h" + +#include "Render.h" + +#include "MemoryUtil.h" +#include "BPStructs.h" +#include "TextureDecoder.h" +#include "TextureMngr.h" +#include "PixelShaderManager.h" +#include "VertexShaderManager.h" + +u8 *TextureMngr::temp = NULL; +TextureMngr::TexCache TextureMngr::textures; +std::map TextureMngr::mapDepthTargets; +int TextureMngr::nTex2DEnabled, TextureMngr::nTexRECTEnabled; + +extern int frameCount; +static u32 s_TempFramebuffer = 0; + +#define TEMP_SIZE (1024*1024*4) +#define TEXTURE_KILL_THRESHOLD 200 + +const GLint c_MinLinearFilter[8] = { + GL_NEAREST, + GL_NEAREST_MIPMAP_NEAREST, + GL_NEAREST_MIPMAP_LINEAR, + GL_NEAREST, + GL_LINEAR, + GL_LINEAR_MIPMAP_NEAREST, + GL_LINEAR_MIPMAP_LINEAR, + GL_LINEAR +}; + +const GLint c_WrapSettings[4] = { GL_CLAMP_TO_EDGE, GL_REPEAT, GL_MIRRORED_REPEAT, GL_REPEAT }; + +void TextureMngr::TCacheEntry::SetTextureParameters(TexMode0 &newmode) +{ + mode = newmode; + if (isNonPow2) { + // very limited! + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, + (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, + (g_Config.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST); + if (newmode.wrap_s == 2 || newmode.wrap_t == 2) { + DEBUG_LOG("cannot support mirrorred repeat mode\n"); + } + if (newmode.wrap_s == 1 || newmode.wrap_t == 1) { + DEBUG_LOG("cannot support repeat mode\n"); + } + } + else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST); + + if (bHaveMipMaps) { + int filt = newmode.min_filter; + if (g_Config.bForceFiltering && newmode.min_filter < 4) + newmode.min_filter += 4; // take equivalent forced linear + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt]); + } + else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + (g_Config.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c_WrapSettings[newmode.wrap_s]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]); + } + + if (g_Config.iMaxAnisotropy >= 1) + { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 << g_Config.iMaxAnisotropy); + } +} + +void TextureMngr::TCacheEntry::Destroy() +{ + if(!texture) + return; + glDeleteTextures(1, &texture); + if (!isRenderTarget) { + if (!g_Config.bSafeTextureCache) { + u32 *ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(addr + hashoffset * 4); + if (*ptr == hash) + *ptr = oldpixel; + } + } + texture = 0; +} + +void TextureMngr::Init() +{ + temp = (u8*)AllocateMemoryPages(TEMP_SIZE); + nTex2DEnabled = nTexRECTEnabled = 0; + TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter); +} + +void TextureMngr::Invalidate() +{ + TexCache::iterator iter = textures.begin(); + for (; iter!=textures.end(); iter++) + iter->second.Destroy(); + textures.clear(); + TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter); +} + +void TextureMngr::Shutdown() +{ + Invalidate(); + std::map::iterator itdepth = mapDepthTargets.begin(); + for (itdepth = mapDepthTargets.begin(); itdepth != mapDepthTargets.end(); ++itdepth) { + glDeleteRenderbuffersEXT(1, &itdepth->second.targ); + } + mapDepthTargets.clear(); + + if (s_TempFramebuffer) { + glDeleteFramebuffersEXT(1, (GLuint *)&s_TempFramebuffer); + s_TempFramebuffer = 0; + } + + FreeMemoryPages(temp, TEMP_SIZE); + temp = NULL; +} + +void TextureMngr::Cleanup() +{ + TexCache::iterator iter = textures.begin(); + while (iter != textures.end()) { + if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second.frameCount) { + if (!iter->second.isRenderTarget) { + iter->second.Destroy(); +#ifdef _WIN32 + iter = textures.erase(iter); +#else + textures.erase(iter++); +#endif + } + else { + iter->second.Destroy(); +#ifdef _WIN32 + iter = textures.erase(iter); +#else + textures.erase(iter++); +#endif + } + } + else + iter++; + } + + std::map::iterator itdepth = mapDepthTargets.begin(); + while (itdepth != mapDepthTargets.end()) { + if (frameCount > 20 + itdepth->second.framecount) { +#ifdef _WIN32 + itdepth = mapDepthTargets.erase(itdepth); +#else + mapDepthTargets.erase(itdepth++); +#endif + } + else ++itdepth; + } +} + +TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt) +{ + if (address == 0) + return NULL; + + TexCache::iterator iter = textures.find(address); + TexMode0 &tm0 = bpmem.tex[texstage > 3].texMode0[texstage & 3]; + u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address); + + // Needed for texture format using tlut. + // TODO: Slower == Safer. Recalculate tlut lenght for each cases just to be sure. + u32 hashseed = 0; + switch (format) { + case GX_TF_C4: + hashseed = TexDecoder_GetTlutHash((u16*)(texMem + tlutaddr), 128); + break; + case GX_TF_C8: + hashseed = TexDecoder_GetTlutHash((u16*)(texMem + tlutaddr), 256); + break; + case GX_TF_C14X2: + hashseed = TexDecoder_GetTlutHash((u16*)(texMem + tlutaddr), 384); + break; + } + + int palSize = TexDecoder_GetPaletteSize(format); + u32 palhash = 0xc0debabe; + + if (palSize) { + if (palSize > 32) + palSize = 32; //let's not do excessive amount of checking + u8 *pal = g_VideoInitialize.pGetMemoryPointer(tlutaddr); + if (pal != 0) { + for (int i = 0; i < palSize; i++) { + palhash = _rotl(palhash,13); + palhash ^= pal[i]; + palhash += 31; + } + } + } + + int bs = TexDecoder_GetBlockWidthInTexels(format) - 1; + int expandedWidth = (width + bs) & (~bs); + + if (iter != textures.end()) { + TCacheEntry &entry = iter->second; + + u32 hash_value; + if (g_Config.bSafeTextureCache) + hash_value = TexDecoder_GetSafeTextureHash(ptr, expandedWidth, height, format, hashseed); + else + hash_value = ((u32 *)ptr)[entry.hashoffset]; + + if (entry.isRenderTarget || (hash_value == entry.hash && palhash == entry.paletteHash)) { + entry.frameCount = frameCount; + //glEnable(entry.isNonPow2?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D); + glBindTexture(entry.isNonPow2 ? GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D, entry.texture); + if (entry.mode.hex != tm0.hex) + entry.SetTextureParameters(tm0); + return &entry; + } + else + { + // can potentially do some caching + + //TCacheEntry &entry = entry; + /*if (width == entry.w && height==entry.h && format==entry.fmt) + { + LPDIRECT3DTEXTURE9 tex = entry.texture; + int bs = TexDecoder_GetBlockWidthInTexels(format)-1; + int expandedWidth = (width+bs) & (~bs); + D3DFORMAT dfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt); + ReplaceTexture2D(tex,temp,width,height,expandedWidth,dfmt); + dev->SetTexture(texstage, stage,tex); + return; + } + else + {*/ + entry.Destroy(); + textures.erase(iter); + //} + } + } + + PC_TexFormat dfmt = TexDecoder_Decode(temp, ptr, expandedWidth, height, format, tlutaddr, tlutfmt); + + //Make an entry in the table + TCacheEntry& entry = textures[address]; + + entry.hashoffset = 0; + entry.paletteHash = palhash; + entry.oldpixel = ((u32 *)ptr)[entry.hashoffset]; + if (g_Config.bSafeTextureCache) { + entry.hash = TexDecoder_GetSafeTextureHash(ptr, expandedWidth, height, format, hashseed); + } else { + entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF); + ((u32 *)ptr)[entry.hashoffset] = entry.hash; + } + + entry.addr = address; + entry.isRenderTarget = false; + + entry.isNonPow2 = ((width & (width - 1)) || (height & (height - 1))); + + glGenTextures(1, (GLuint *)&entry.texture); + GLenum target = entry.isNonPow2 ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D; + glBindTexture(target, entry.texture); + + if (expandedWidth != width) + glPixelStorei(GL_UNPACK_ROW_LENGTH, expandedWidth); + + int gl_format; + int gl_type; + switch (dfmt) { + case PC_TEX_FMT_NONE: + PanicAlert("Invalid PC texture format %i", dfmt); + case PC_TEX_FMT_BGRA32: + gl_format = GL_BGRA; + gl_type = GL_UNSIGNED_BYTE; + break; + } + if (!entry.isNonPow2 && ((tm0.min_filter & 3) == 1 || (tm0.min_filter & 3) == 2)) { + gluBuild2DMipmaps(GL_TEXTURE_2D, 4, width, height, gl_format, gl_type, temp); + entry.bHaveMipMaps = true; + } + else + glTexImage2D(target, 0, 4, width, height, 0, gl_format, gl_type, temp); + + if (expandedWidth != width) // reset + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + + entry.frameCount = frameCount; + entry.w = width; + entry.h = height; + entry.fmt = format; + entry.SetTextureParameters(tm0); + + if (g_Config.bDumpTextures) { // dump texture to file + static int counter = 0; + char szTemp[MAX_PATH]; + sprintf(szTemp, "%s/txt_%04i_%i.tga", g_Config.texDumpPath, counter++, format); + + SaveTexture(szTemp,target, entry.texture, width, height); + } + + INCSTAT(stats.numTexturesCreated); + SETSTAT(stats.numTexturesAlive, textures.size()); + + //glEnable(entry.isNonPow2?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D); + + //SaveTexture("tex.tga", target, entry.texture, entry.w, entry.h); + return &entry; +} + +void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, bool bScaleByHalf, TRectangle *source) +{ + DVSTARTPROFILE(); + GL_REPORT_ERRORD(); + + // for intensity values, use Y of YUV format! + // for all purposes, treat 4bit equivalents as 8bit (probably just used for compression) + // RGBA8 - RGBA8 + // RGB565 - RGB565 + // RGB5A3 - RGB5A3 + // I4,R4,Z4 - I4 + // IA4,RA4 - IA4 + // Z8M,G8,I8,A8,Z8,R8,B8,Z8L - I8 + // Z16,GB8,RG8,Z16L,IA8,RA8 - IA8 + bool bIsInit = textures.find(address) != textures.end(); + + PRIM_LOG("copytarg: addr=0x%x, fromz=%d, intfmt=%d, copyfmt=%d\n", address, (int)bFromZBuffer,(int)bIsIntensityFmt,copyfmt); + + TCacheEntry& entry = textures[address]; + entry.isNonPow2 = true; + entry.hash = 0; + entry.hashoffset = 0; + entry.frameCount = frameCount; + + int mult = bScaleByHalf?2:1; + int w = (abs(source->right-source->left)/mult); + int h = (abs(source->bottom-source->top)/mult); + + GL_REPORT_ERRORD(); + + if (!bIsInit) { + glGenTextures(1, (GLuint *)&entry.texture); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, entry.texture); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + GL_REPORT_ERRORD(); + } + else { + _assert_(entry.texture); + bool bReInit = true; + + if (entry.w == w && entry.h == h) { + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, entry.texture); + // for some reason mario sunshine errors here... + GLenum err = GL_NO_ERROR; + GL_REPORT_ERROR(); + if (err == GL_NO_ERROR ) + bReInit = false; + } + + if (bReInit) { + // necessary, for some reason opengl gives errors when texture isn't deleted + glDeleteTextures(1,(GLuint *)&entry.texture); + glGenTextures(1, (GLuint *)&entry.texture); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, entry.texture); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + GL_REPORT_ERRORD(); + } + } + + if (!bIsInit || !entry.isRenderTarget) { + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (glGetError() != GL_NO_ERROR) { + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP); + GL_REPORT_ERRORD(); + } + } + + entry.w = w; + entry.h = h; + entry.isRenderTarget = true; + entry.fmt = copyfmt; + + float colmat[16]; + float fConstAdd[4] = {0}; + memset(colmat, 0, sizeof(colmat)); + + if (bFromZBuffer) { + switch(copyfmt) { + case 0: // Z4 + case 1: // Z8 + colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1; + break; + + case 3: // Z16 //? + case 11: // Z16 + colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1; + break; + case 6: // Z24X8 + colmat[0] = 1; + colmat[5] = 1; + colmat[10] = 1; + break; + case 9: // Z8M + colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1; + break; + case 10: // Z8L + colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1; + break; + case 12: // Z16L + colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1; + break; + default: + ERROR_LOG("Unknown copy zbuf format: 0x%x\n", copyfmt); + colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1; + break; + } + } + else if (bIsIntensityFmt) { + fConstAdd[0] = fConstAdd[1] = fConstAdd[2] = 16.0f/255.0f; + switch(copyfmt) { + case 0: // I4 + case 1: // I8 + case 2: // IA4 + case 3: // IA8 + // TODO - verify these coefficients + colmat[0] = 0.257f; colmat[1] = 0.504f; colmat[2] = 0.098f; + colmat[4] = 0.257f; colmat[5] = 0.504f; colmat[6] = 0.098f; + colmat[8] = 0.257f; colmat[9] = 0.504f; colmat[10] = 0.098f; + if (copyfmt < 2) { + fConstAdd[3] = 16.0f / 255.0f; + colmat[12] = 0.257f; colmat[13] = 0.504f; colmat[14] = 0.098f; + } + else { // alpha + colmat[15] = 1; + } + break; + default: + ERROR_LOG("Unknown copy intensity format: 0x%x\n", copyfmt); + colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1; + break; + } + } + else { + switch (copyfmt) { + case 0: // R4 + case 8: // R8 + colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1; + break; + case 2: // RA4 + case 3: // RA8 + colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1; + break; + + case 7: // A8 + colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1; + break; + case 9: // G8 + colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1; + break; + case 10: // B8 + colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1; + break; + case 11: // RG8 + colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1; + break; + case 12: // GB8 + colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1; + break; + + case 4: // RGB565 + colmat[0] = colmat[5] = colmat[10] = 1; + fConstAdd[3] = 1; // set alpha to 1 + break; + case 5: // RGB5A3 + case 6: // RGBA8 + colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1; + break; + + default: + ERROR_LOG("Unknown copy color format: 0x%x\n", copyfmt); + colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1; + break; + } + } + +// if (bCopyToTarget) { +// _assert_( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); +// glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); +// GL_REPORT_ERRORD(); +// glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, source->left, source->top, source->right-source->left, source->bottom-source->top); +// entry.isUpsideDown = true; // note that the copy is upside down!! +// GL_REPORT_ERRORD(); +// return; +// } + + Renderer::SetRenderMode(Renderer::RM_Normal); // set back to normal + GL_REPORT_ERRORD(); + + // have to run a pixel shader + + Renderer::ResetGLState(); // reset any game specific settings + + if (s_TempFramebuffer == 0 ) + glGenFramebuffersEXT( 1, (GLuint *)&s_TempFramebuffer); + + Renderer::SetFramebuffer(s_TempFramebuffer); + Renderer::SetRenderTarget(entry.texture); + GL_REPORT_ERRORD(); + + // create and attach the render target + std::map::iterator itdepth = mapDepthTargets.find((h << 16) | w); + + if (itdepth == mapDepthTargets.end()) { + DEPTHTARGET& depth = mapDepthTargets[(h << 16) | w]; + depth.framecount = frameCount; + glGenRenderbuffersEXT(1, &depth.targ); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth.targ); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT/*GL_DEPTH24_STENCIL8_EXT*/, w, h); + GL_REPORT_ERRORD(); + Renderer::SetDepthTarget(depth.targ); + GL_REPORT_ERRORD(); + } + else { + itdepth->second.framecount = frameCount; + Renderer::SetDepthTarget(itdepth->second.targ); + GL_REPORT_ERRORD(); + } + + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, bFromZBuffer?Renderer::GetZBufferTarget():Renderer::GetRenderTarget()); + TextureMngr::EnableTexRECT(0); + + glViewport(0, 0, w, h); + + glEnable(GL_FRAGMENT_PROGRAM_ARB); + glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, PixelShaderMngr::GetColorMatrixProgram()); + PixelShaderMngr::SetColorMatrix(colmat, fConstAdd); // set transformation + GL_REPORT_ERRORD(); + + glBegin(GL_QUADS); + glTexCoord2f((float)source->left * MValueX, Renderer::GetTargetHeight()-(float)source->bottom * MValueY); glVertex2f(-1,1); + glTexCoord2f((float)source->left * MValueX, Renderer::GetTargetHeight()-(float)source->top * MValueY); glVertex2f(-1,-1); + glTexCoord2f((float)source->right * MValueX, Renderer::GetTargetHeight()-(float)source->top * MValueY); glVertex2f(1,-1); + glTexCoord2f((float)source->right * MValueX, Renderer::GetTargetHeight()-(float)source->bottom * MValueY); glVertex2f(1,1); + glEnd(); + + GL_REPORT_ERRORD(); + + Renderer::SetFramebuffer(0); + Renderer::RestoreGLState(); + VertexShaderMngr::SetViewportChanged(); + + TextureMngr::DisableStage(0); + + if (bFromZBuffer ) + Renderer::SetZBufferRender(); // notify for future settings + + GL_REPORT_ERRORD(); + //SaveTexture("frame.tga", GL_TEXTURE_RECTANGLE_ARB, entry.texture, entry.w, entry.h); + //SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_ARB, Renderer::GetZBufferTarget(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight()); +} + +void TextureMngr::EnableTex2D(int stage) +{ + if (!(nTex2DEnabled & (1< - -#include "Common.h" -#include "Config.h" -#include "Profiler.h" -#include "MemoryUtil.h" -#include "StringUtil.h" -#include "x64Emitter.h" -#include "ABI.h" - -#include "LookUpTables.h" -#include "Statistics.h" -#include "VertexManager.h" -#include "VertexLoaderManager.h" -#include "VertexShaderManager.h" -#include "VertexManager.h" -#include "VertexLoader.h" -#include "BPStructs.h" -#include "DataReader.h" - -#include "VertexLoader_Position.h" -#include "VertexLoader_Normal.h" -#include "VertexLoader_Color.h" -#include "VertexLoader_TextCoord.h" - -#define USE_JIT - -#define COMPILED_CODE_SIZE 4096*4 - -NativeVertexFormat *g_nativeVertexFmt; - -//these don't need to be saved -#ifndef _WIN32 - #undef inline - #define inline -#endif - -// Direct -// ============================================================================== -static u8 s_curposmtx; -static u8 s_curtexmtx[8]; -static int s_texmtxwrite = 0; -static int s_texmtxread = 0; -static int loop_counter; - -// Vertex loaders read these. Although the scale ones should be baked into the shader. -int tcIndex; -int colIndex; -TVtxAttr* pVtxAttr; -int colElements[2]; -float posScale; -float tcScale[8]; - -using namespace Gen; - -void LOADERDECL PosMtx_ReadDirect_UByte() -{ - s_curposmtx = DataReadU8() & 0x3f; - PRIM_LOG("posmtx: %d, ", s_curposmtx); -} - -void LOADERDECL PosMtx_Write() -{ - *VertexManager::s_pCurBufferPointer++ = s_curposmtx; - *VertexManager::s_pCurBufferPointer++ = 0; - *VertexManager::s_pCurBufferPointer++ = 0; - *VertexManager::s_pCurBufferPointer++ = 0; -} - -void LOADERDECL TexMtx_ReadDirect_UByte() -{ - s_curtexmtx[s_texmtxread] = DataReadU8()&0x3f; - PRIM_LOG("texmtx%d: %d, ", s_texmtxread, s_curtexmtx[s_texmtxread]); - s_texmtxread++; -} - -void LOADERDECL TexMtx_Write_Float() -{ - *(float*)VertexManager::s_pCurBufferPointer = (float)s_curtexmtx[s_texmtxwrite++]; - VertexManager::s_pCurBufferPointer += 4; -} - -void LOADERDECL TexMtx_Write_Float2() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = 0; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)s_curtexmtx[s_texmtxwrite++]; - VertexManager::s_pCurBufferPointer += 8; -} - -void LOADERDECL TexMtx_Write_Short3() -{ - ((s16*)VertexManager::s_pCurBufferPointer)[0] = 0; - ((s16*)VertexManager::s_pCurBufferPointer)[1] = 0; - ((s16*)VertexManager::s_pCurBufferPointer)[2] = s_curtexmtx[s_texmtxwrite++]; - VertexManager::s_pCurBufferPointer += 8; -} - -VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr) -{ - m_numLoadedVertices = 0; - m_VertexSize = 0; - m_numPipelineStages = 0; - m_NativeFmt = new NativeVertexFormat(); - loop_counter = 0; - VertexLoader_Normal::Init(); - - m_VtxDesc = vtx_desc; - SetVAT(vtx_attr.g0.Hex, vtx_attr.g1.Hex, vtx_attr.g2.Hex); - - m_compiledCode = (u8 *)AllocateExecutableMemory(COMPILED_CODE_SIZE, false); - if (m_compiledCode) { - memset(m_compiledCode, 0, COMPILED_CODE_SIZE); - } - CompileVertexTranslator(); -} - -VertexLoader::~VertexLoader() -{ - FreeMemoryPages(m_compiledCode, COMPILED_CODE_SIZE); - delete m_NativeFmt; -} - -void VertexLoader::CompileVertexTranslator() -{ - m_VertexSize = 0; - const TVtxAttr &vtx_attr = m_VtxAttr; - //const TVtxDesc &vtx_desc = m_VtxDesc; - -#ifdef USE_JIT - u8 *old_code_ptr = GetWritableCodePtr(); - SetCodePtr(m_compiledCode); - ABI_EmitPrologue(4); - // MOV(32, R(EBX), M(&loop_counter)); - // Start loop here - const u8 *loop_start = GetCodePtr(); - - // Reset component counters if present in vertex format only. - if (m_VtxDesc.Tex0Coord || m_VtxDesc.Tex1Coord || m_VtxDesc.Tex2Coord || m_VtxDesc.Tex3Coord || - m_VtxDesc.Tex4Coord || m_VtxDesc.Tex5Coord || m_VtxDesc.Tex6Coord || m_VtxDesc.Tex7Coord) { - MOV(32, M(&tcIndex), Imm32(0)); - } - if (m_VtxDesc.Color0 || m_VtxDesc.Color1) { - MOV(32, M(&colIndex), Imm32(0)); - } - if (m_VtxDesc.Tex0MatIdx || m_VtxDesc.Tex1MatIdx || m_VtxDesc.Tex2MatIdx || m_VtxDesc.Tex3MatIdx || - m_VtxDesc.Tex4MatIdx || m_VtxDesc.Tex5MatIdx || m_VtxDesc.Tex6MatIdx || m_VtxDesc.Tex7MatIdx) { - MOV(32, M(&s_texmtxwrite), Imm32(0)); - MOV(32, M(&s_texmtxread), Imm32(0)); - } -#endif - - // Colors - const int col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1}; - // TextureCoord - // Since m_VtxDesc.Text7Coord is broken across a 32 bit word boundary, retrieve its value manually. - // If we didn't do this, the vertex format would be read as one bit offset from where it should be, making - // 01 become 00, and 10/11 become 01 - const int tc[8] = { - m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord, - m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, (m_VtxDesc.Hex >> 31) & 3 - }; - - // Reset pipeline - m_numPipelineStages = 0; - - // It's a bit ugly that we poke inside m_NativeFmt in this function. Planning to fix this. - m_NativeFmt->m_components = 0; - - // Position in pc vertex format. - int nat_offset = 0; - PortableVertexDeclaration vtx_decl; - memset(&vtx_decl, 0, sizeof(vtx_decl)); - for (int i = 0; i < 8; i++) { - vtx_decl.texcoord_offset[i] = -1; - } - - // m_VBVertexStride for texmtx and posmtx is computed later when writing. - - // Position Matrix Index - if (m_VtxDesc.PosMatIdx) { - WriteCall(PosMtx_ReadDirect_UByte); - m_NativeFmt->m_components |= VB_HAS_POSMTXIDX; - m_VertexSize += 1; - } - - if (m_VtxDesc.Tex0MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX0; WriteCall(TexMtx_ReadDirect_UByte); } - if (m_VtxDesc.Tex1MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX1; WriteCall(TexMtx_ReadDirect_UByte); } - if (m_VtxDesc.Tex2MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX2; WriteCall(TexMtx_ReadDirect_UByte); } - if (m_VtxDesc.Tex3MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX3; WriteCall(TexMtx_ReadDirect_UByte); } - if (m_VtxDesc.Tex4MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX4; WriteCall(TexMtx_ReadDirect_UByte); } - if (m_VtxDesc.Tex5MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX5; WriteCall(TexMtx_ReadDirect_UByte); } - if (m_VtxDesc.Tex6MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX6; WriteCall(TexMtx_ReadDirect_UByte); } - if (m_VtxDesc.Tex7MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX7; WriteCall(TexMtx_ReadDirect_UByte); } - - switch (m_VtxDesc.Position) { - case NOT_PRESENT: {_assert_msg_(0, "Vertex descriptor without position!", "WTF?");} break; - case DIRECT: - switch (m_VtxAttr.PosFormat) { - case FORMAT_UBYTE: m_VertexSize += m_VtxAttr.PosElements?3:2; WriteCall(Pos_ReadDirect_UByte); break; - case FORMAT_BYTE: m_VertexSize += m_VtxAttr.PosElements?3:2; WriteCall(Pos_ReadDirect_Byte); break; - case FORMAT_USHORT: m_VertexSize += m_VtxAttr.PosElements?6:4; WriteCall(Pos_ReadDirect_UShort); break; - case FORMAT_SHORT: m_VertexSize += m_VtxAttr.PosElements?6:4; WriteCall(Pos_ReadDirect_Short); break; - case FORMAT_FLOAT: m_VertexSize += m_VtxAttr.PosElements?12:8; WriteCall(Pos_ReadDirect_Float); break; - default: _assert_(0); break; - } - nat_offset += 12; - break; - case INDEX8: - switch (m_VtxAttr.PosFormat) { - case FORMAT_UBYTE: WriteCall(Pos_ReadIndex8_UByte); break; //WTF? - case FORMAT_BYTE: WriteCall(Pos_ReadIndex8_Byte); break; - case FORMAT_USHORT: WriteCall(Pos_ReadIndex8_UShort); break; - case FORMAT_SHORT: WriteCall(Pos_ReadIndex8_Short); break; - case FORMAT_FLOAT: WriteCall(Pos_ReadIndex8_Float); break; - default: _assert_(0); break; - } - m_VertexSize += 1; - nat_offset += 12; - break; - case INDEX16: - switch (m_VtxAttr.PosFormat) { - case FORMAT_UBYTE: WriteCall(Pos_ReadIndex16_UByte); break; - case FORMAT_BYTE: WriteCall(Pos_ReadIndex16_Byte); break; - case FORMAT_USHORT: WriteCall(Pos_ReadIndex16_UShort); break; - case FORMAT_SHORT: WriteCall(Pos_ReadIndex16_Short); break; - case FORMAT_FLOAT: WriteCall(Pos_ReadIndex16_Float); break; - default: _assert_(0); break; - } - m_VertexSize += 2; - nat_offset += 12; - break; - } - - // Normals - vtx_decl.num_normals = 0; - if (m_VtxDesc.Normal != NOT_PRESENT) { - m_VertexSize += VertexLoader_Normal::GetSize(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements, m_VtxAttr.NormalIndex3); - TPipelineFunction pFunc = VertexLoader_Normal::GetFunction(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements, m_VtxAttr.NormalIndex3); - if (pFunc == 0) - { - char temp[256]; - sprintf(temp,"%i %i %i %i", m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements, m_VtxAttr.NormalIndex3); - g_VideoInitialize.pSysMessage("VertexLoader_Normal::GetFunction returned zero!"); - } - WriteCall(pFunc); - - vtx_decl.num_normals = vtx_attr.NormalElements ? 3 : 1; - switch (vtx_attr.NormalFormat) { - case FORMAT_UBYTE: - case FORMAT_BYTE: - vtx_decl.normal_gl_type = VAR_BYTE; - vtx_decl.normal_gl_size = 4; - vtx_decl.normal_offset[0] = nat_offset; - nat_offset += 4; - if (vtx_attr.NormalElements) { - vtx_decl.normal_offset[1] = nat_offset; - nat_offset += 4; - vtx_decl.normal_offset[2] = nat_offset; - nat_offset += 4; - } - break; - case FORMAT_USHORT: - case FORMAT_SHORT: - vtx_decl.normal_gl_type = VAR_SHORT; - vtx_decl.normal_gl_size = 4; - vtx_decl.normal_offset[0] = nat_offset; - nat_offset += 8; - if (vtx_attr.NormalElements) { - vtx_decl.normal_offset[1] = nat_offset; - nat_offset += 8; - vtx_decl.normal_offset[2] = nat_offset; - nat_offset += 8; - } - break; - case FORMAT_FLOAT: - vtx_decl.normal_gl_type = VAR_FLOAT; - vtx_decl.normal_gl_size = 3; - vtx_decl.normal_offset[0] = nat_offset; - nat_offset += 12; - if (vtx_attr.NormalElements) { - vtx_decl.normal_offset[1] = nat_offset; - nat_offset += 12; - vtx_decl.normal_offset[2] = nat_offset; - nat_offset += 12; - } - break; - default: _assert_(0); break; - } - - int numNormals = (m_VtxAttr.NormalElements == 1) ? NRM_THREE : NRM_ONE; - m_NativeFmt->m_components |= VB_HAS_NRM0; - - if (numNormals == NRM_THREE) - m_NativeFmt->m_components |= VB_HAS_NRM1 | VB_HAS_NRM2; - } - - vtx_decl.color_gl_type = VAR_UNSIGNED_BYTE; - for (int i = 0; i < 2; i++) { - m_NativeFmt->m_components |= VB_HAS_COL0 << i; - switch (col[i]) - { - case NOT_PRESENT: - m_NativeFmt->m_components &= ~(VB_HAS_COL0 << i); - vtx_decl.color_offset[i] = -1; - break; - case DIRECT: - switch (m_VtxAttr.color[i].Comp) - { - case FORMAT_16B_565: m_VertexSize += 2; WriteCall(Color_ReadDirect_16b_565); break; - case FORMAT_24B_888: m_VertexSize += 3; WriteCall(Color_ReadDirect_24b_888); break; - case FORMAT_32B_888x: m_VertexSize += 4; WriteCall(Color_ReadDirect_32b_888x); break; - case FORMAT_16B_4444: m_VertexSize += 2; WriteCall(Color_ReadDirect_16b_4444); break; - case FORMAT_24B_6666: m_VertexSize += 3; WriteCall(Color_ReadDirect_24b_6666); break; - case FORMAT_32B_8888: m_VertexSize += 4; WriteCall(Color_ReadDirect_32b_8888); break; - default: _assert_(0); break; - } - break; - case INDEX8: - m_VertexSize += 1; - switch (m_VtxAttr.color[i].Comp) - { - case FORMAT_16B_565: WriteCall(Color_ReadIndex8_16b_565); break; - case FORMAT_24B_888: WriteCall(Color_ReadIndex8_24b_888); break; - case FORMAT_32B_888x: WriteCall(Color_ReadIndex8_32b_888x); break; - case FORMAT_16B_4444: WriteCall(Color_ReadIndex8_16b_4444); break; - case FORMAT_24B_6666: WriteCall(Color_ReadIndex8_24b_6666); break; - case FORMAT_32B_8888: WriteCall(Color_ReadIndex8_32b_8888); break; - default: _assert_(0); break; - } - break; - case INDEX16: - m_VertexSize += 2; - switch (m_VtxAttr.color[i].Comp) - { - case FORMAT_16B_565: WriteCall(Color_ReadIndex16_16b_565); break; - case FORMAT_24B_888: WriteCall(Color_ReadIndex16_24b_888); break; - case FORMAT_32B_888x: WriteCall(Color_ReadIndex16_32b_888x); break; - case FORMAT_16B_4444: WriteCall(Color_ReadIndex16_16b_4444); break; - case FORMAT_24B_6666: WriteCall(Color_ReadIndex16_24b_6666); break; - case FORMAT_32B_8888: WriteCall(Color_ReadIndex16_32b_8888); break; - default: _assert_(0); break; - } - break; - } - // Common for the three bottom cases - if (col[i] != NOT_PRESENT) { - vtx_decl.color_offset[i] = nat_offset; - nat_offset += 4; - } - } - - // Texture matrix indices (remove if corresponding texture coordinate isn't enabled) - for (int i = 0; i < 8; i++) { - m_NativeFmt->m_components |= VB_HAS_UV0 << i; - int elements = m_VtxAttr.texCoord[i].Elements; - switch (tc[i]) - { - case NOT_PRESENT: - m_NativeFmt->m_components &= ~(VB_HAS_UV0 << i); - break; - case DIRECT: - switch (m_VtxAttr.texCoord[i].Format) - { - case FORMAT_UBYTE: m_VertexSize += elements?2:1; WriteCall(elements?TexCoord_ReadDirect_UByte2:TexCoord_ReadDirect_UByte1); break; - case FORMAT_BYTE: m_VertexSize += elements?2:1; WriteCall(elements?TexCoord_ReadDirect_Byte2:TexCoord_ReadDirect_Byte1); break; - case FORMAT_USHORT: m_VertexSize += elements?4:2; WriteCall(elements?TexCoord_ReadDirect_UShort2:TexCoord_ReadDirect_UShort1); break; - case FORMAT_SHORT: m_VertexSize += elements?4:2; WriteCall(elements?TexCoord_ReadDirect_Short2:TexCoord_ReadDirect_Short1); break; - case FORMAT_FLOAT: m_VertexSize += elements?8:4; WriteCall(elements?TexCoord_ReadDirect_Float2:TexCoord_ReadDirect_Float1); break; - default: _assert_(0); break; - } - break; - case INDEX8: - m_VertexSize += 1; - switch (m_VtxAttr.texCoord[i].Format) - { - case FORMAT_UBYTE: WriteCall(elements?TexCoord_ReadIndex8_UByte2:TexCoord_ReadIndex8_UByte1); break; - case FORMAT_BYTE: WriteCall(elements?TexCoord_ReadIndex8_Byte2:TexCoord_ReadIndex8_Byte1); break; - case FORMAT_USHORT: WriteCall(elements?TexCoord_ReadIndex8_UShort2:TexCoord_ReadIndex8_UShort1); break; - case FORMAT_SHORT: WriteCall(elements?TexCoord_ReadIndex8_Short2:TexCoord_ReadIndex8_Short1); break; - case FORMAT_FLOAT: WriteCall(elements?TexCoord_ReadIndex8_Float2:TexCoord_ReadIndex8_Float1); break; - default: _assert_(0); break; - } - break; - case INDEX16: - m_VertexSize += 2; - switch (m_VtxAttr.texCoord[i].Format) - { - case FORMAT_UBYTE: WriteCall(elements?TexCoord_ReadIndex16_UByte2:TexCoord_ReadIndex16_UByte1); break; - case FORMAT_BYTE: WriteCall(elements?TexCoord_ReadIndex16_Byte2:TexCoord_ReadIndex16_Byte1); break; - case FORMAT_USHORT: WriteCall(elements?TexCoord_ReadIndex16_UShort2:TexCoord_ReadIndex16_UShort1); break; - case FORMAT_SHORT: WriteCall(elements?TexCoord_ReadIndex16_Short2:TexCoord_ReadIndex16_Short1); break; - case FORMAT_FLOAT: WriteCall(elements?TexCoord_ReadIndex16_Float2:TexCoord_ReadIndex16_Float1); break; - default: _assert_(0); - } - break; - } - - if (m_NativeFmt->m_components & (VB_HAS_TEXMTXIDX0 << i)) { - if (tc[i] != NOT_PRESENT) { - // if texmtx is included, texcoord will always be 3 floats, z will be the texmtx index - vtx_decl.texcoord_offset[i] = nat_offset; - vtx_decl.texcoord_gl_type[i] = VAR_FLOAT; - vtx_decl.texcoord_size[i] = 3; - nat_offset += 12; - WriteCall(m_VtxAttr.texCoord[i].Elements ? TexMtx_Write_Float : TexMtx_Write_Float2); - } - else { - m_NativeFmt->m_components |= VB_HAS_UV0 << i; // have to include since using now - vtx_decl.texcoord_offset[i] = nat_offset; - vtx_decl.texcoord_gl_type[i] = VAR_SHORT; - vtx_decl.texcoord_size[i] = 4; - nat_offset += 8; // still include the texture coordinate, but this time as 6 + 2 bytes - WriteCall(TexMtx_Write_Short3); - } - } - else { - if (tc[i] != NOT_PRESENT) { - vtx_decl.texcoord_offset[i] = nat_offset; - vtx_decl.texcoord_gl_type[i] = VAR_FLOAT; - vtx_decl.texcoord_size[i] = vtx_attr.texCoord[i].Elements ? 2 : 1; - nat_offset += 4 * (vtx_attr.texCoord[i].Elements ? 2 : 1); - } else { - vtx_decl.texcoord_offset[i] = -1; - } - } - - if (tc[i] == NOT_PRESENT) { - // if there's more tex coords later, have to write a dummy call - int j = i + 1; - for (; j < 8; ++j) { - if (tc[j] != NOT_PRESENT) { - WriteCall(TexCoord_Read_Dummy); // important to get indices right! - break; - } - } - // tricky! - if (j == 8 && !((m_NativeFmt->m_components & VB_HAS_TEXMTXIDXALL) & (VB_HAS_TEXMTXIDXALL << (i + 1)))) { - // no more tex coords and tex matrices, so exit loop - break; - } - } - } - - if (m_VtxDesc.PosMatIdx) { - WriteCall(PosMtx_Write); - vtx_decl.posmtx_offset = nat_offset; - nat_offset += 4; - } else { - vtx_decl.posmtx_offset = -1; - } - - native_stride = nat_offset; - vtx_decl.stride = native_stride; - -#ifdef USE_JIT - // End loop here - SUB(32, M(&loop_counter), Imm8(1)); - //SUB(32, R(EBX), Imm8(1)); - J_CC(CC_NZ, loop_start, true); - ABI_EmitEpilogue(4); - SetCodePtr(old_code_ptr); -#endif - m_NativeFmt->Initialize(vtx_decl); -} - -void VertexLoader::WriteCall(TPipelineFunction func) -{ -#ifdef USE_JIT - CALL((void*)func); -#else - m_PipelineStages[m_numPipelineStages++] = func; -#endif -} - -void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count) -{ - DVSTARTPROFILE(); - - m_numLoadedVertices += count; - - // Flush if our vertex format is different from the currently set. - if (g_nativeVertexFmt != NULL && g_nativeVertexFmt != m_NativeFmt) - { - VertexManager::Flush(); - // Also move the Set() here? - } - g_nativeVertexFmt = m_NativeFmt; - - if (bpmem.genMode.cullmode == 3 && primitive < 5) - { - // if cull mode is none, ignore triangles and quads - DataSkip(count * m_VertexSize); - return; - } - - VertexManager::EnableComponents(m_NativeFmt->m_components); - - // Load position and texcoord scale factors. - // TODO - figure out if we should leave these independent, or compile them into - // the vertexloaders. - m_VtxAttr.PosFrac = g_VtxAttr[vtx_attr_group].g0.PosFrac; - m_VtxAttr.texCoord[0].Frac = g_VtxAttr[vtx_attr_group].g0.Tex0Frac; - m_VtxAttr.texCoord[1].Frac = g_VtxAttr[vtx_attr_group].g1.Tex1Frac; - m_VtxAttr.texCoord[2].Frac = g_VtxAttr[vtx_attr_group].g1.Tex2Frac; - m_VtxAttr.texCoord[3].Frac = g_VtxAttr[vtx_attr_group].g1.Tex3Frac; - m_VtxAttr.texCoord[4].Frac = g_VtxAttr[vtx_attr_group].g2.Tex4Frac; - m_VtxAttr.texCoord[5].Frac = g_VtxAttr[vtx_attr_group].g2.Tex5Frac; - m_VtxAttr.texCoord[6].Frac = g_VtxAttr[vtx_attr_group].g2.Tex6Frac; - m_VtxAttr.texCoord[7].Frac = g_VtxAttr[vtx_attr_group].g2.Tex7Frac; - - pVtxAttr = &m_VtxAttr; - posScale = shiftLookup[m_VtxAttr.PosFrac]; - if (m_NativeFmt->m_components & VB_HAS_UVALL) { - for (int i = 0; i < 8; i++) - tcScale[i] = shiftLookup[m_VtxAttr.texCoord[i].Frac]; - } - for (int i = 0; i < 2; i++) - colElements[i] = m_VtxAttr.color[i].Elements; - - // if strips or fans, make sure all vertices can fit in buffer, otherwise flush - int granularity = 1; - switch (primitive) { - case 3: // strip .. hm, weird - case 4: // fan - if (VertexManager::GetRemainingSize() < 3 * native_stride) - VertexManager::Flush(); - break; - case 6: // line strip - if (VertexManager::GetRemainingSize() < 2 * native_stride) - VertexManager::Flush(); - break; - case 0: granularity = 4; break; // quads - case 2: granularity = 3; break; // tris - case 5: granularity = 2; break; // lines - } - - int startv = 0, extraverts = 0; - int v = 0; - - while (v < count) - { - int remainingVerts = VertexManager::GetRemainingSize() / native_stride; - if (remainingVerts < granularity) { - INCSTAT(stats.thisFrame.numBufferSplits); - // This buffer full - break current primitive and flush, to switch to the next buffer. - u8* plastptr = VertexManager::s_pCurBufferPointer; - if (v - startv > 0) - VertexManager::AddVertices(primitive, v - startv + extraverts); - VertexManager::Flush(); - // Why does this need to be so complicated? - switch (primitive) { - case 3: // triangle strip, copy last two vertices - // a little trick since we have to keep track of signs - if (v & 1) { - memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-2*native_stride, native_stride); - memcpy_gc(VertexManager::s_pCurBufferPointer+native_stride, plastptr-native_stride*2, 2*native_stride); - VertexManager::s_pCurBufferPointer += native_stride*3; - extraverts = 3; - } - else { - memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride*2, native_stride*2); - VertexManager::s_pCurBufferPointer += native_stride*2; - extraverts = 2; - } - break; - case 4: // tri fan, copy first and last vert - memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride*(v-startv+extraverts), native_stride); - VertexManager::s_pCurBufferPointer += native_stride; - memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride, native_stride); - VertexManager::s_pCurBufferPointer += native_stride; - extraverts = 2; - break; - case 6: // line strip - memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride, native_stride); - VertexManager::s_pCurBufferPointer += native_stride; - extraverts = 1; - break; - default: - extraverts = 0; - break; - } - startv = v; - } - int remainingPrims = remainingVerts / granularity; - remainingVerts = remainingPrims * granularity; - if (count - v < remainingVerts) - remainingVerts = count - v; - - // Clean tight loader loop. Todo - build the loop into the JIT code. - #ifdef USE_JIT - if (remainingVerts > 0) { - loop_counter = remainingVerts; - ((void (*)())(void*)m_compiledCode)(); - } - #else - for (int s = 0; s < remainingVerts; s++) - { - tcIndex = 0; - colIndex = 0; - s_texmtxwrite = s_texmtxread = 0; - for (int i = 0; i < m_numPipelineStages; i++) - m_PipelineStages[i](); - PRIM_LOG("\n"); - } - #endif - v += remainingVerts; - } - - if (startv < count) - VertexManager::AddVertices(primitive, count - startv + extraverts); -} - -void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2) -{ - VAT vat; - vat.g0.Hex = _group0; - vat.g1.Hex = _group1; - vat.g2.Hex = _group2; - - m_VtxAttr.PosElements = vat.g0.PosElements; - m_VtxAttr.PosFormat = vat.g0.PosFormat; - m_VtxAttr.PosFrac = vat.g0.PosFrac; - m_VtxAttr.NormalElements = vat.g0.NormalElements; - m_VtxAttr.NormalFormat = vat.g0.NormalFormat; - m_VtxAttr.color[0].Elements = vat.g0.Color0Elements; - m_VtxAttr.color[0].Comp = vat.g0.Color0Comp; - m_VtxAttr.color[1].Elements = vat.g0.Color1Elements; - m_VtxAttr.color[1].Comp = vat.g0.Color1Comp; - m_VtxAttr.texCoord[0].Elements = vat.g0.Tex0CoordElements; - m_VtxAttr.texCoord[0].Format = vat.g0.Tex0CoordFormat; - m_VtxAttr.texCoord[0].Frac = vat.g0.Tex0Frac; - m_VtxAttr.ByteDequant = vat.g0.ByteDequant; - m_VtxAttr.NormalIndex3 = vat.g0.NormalIndex3; - - m_VtxAttr.texCoord[1].Elements = vat.g1.Tex1CoordElements; - m_VtxAttr.texCoord[1].Format = vat.g1.Tex1CoordFormat; - m_VtxAttr.texCoord[1].Frac = vat.g1.Tex1Frac; - m_VtxAttr.texCoord[2].Elements = vat.g1.Tex2CoordElements; - m_VtxAttr.texCoord[2].Format = vat.g1.Tex2CoordFormat; - m_VtxAttr.texCoord[2].Frac = vat.g1.Tex2Frac; - m_VtxAttr.texCoord[3].Elements = vat.g1.Tex3CoordElements; - m_VtxAttr.texCoord[3].Format = vat.g1.Tex3CoordFormat; - m_VtxAttr.texCoord[3].Frac = vat.g1.Tex3Frac; - m_VtxAttr.texCoord[4].Elements = vat.g1.Tex4CoordElements; - m_VtxAttr.texCoord[4].Format = vat.g1.Tex4CoordFormat; - - m_VtxAttr.texCoord[4].Frac = vat.g2.Tex4Frac; - m_VtxAttr.texCoord[5].Elements = vat.g2.Tex5CoordElements; - m_VtxAttr.texCoord[5].Format = vat.g2.Tex5CoordFormat; - m_VtxAttr.texCoord[5].Frac = vat.g2.Tex5Frac; - m_VtxAttr.texCoord[6].Elements = vat.g2.Tex6CoordElements; - m_VtxAttr.texCoord[6].Format = vat.g2.Tex6CoordFormat; - m_VtxAttr.texCoord[6].Frac = vat.g2.Tex6Frac; - m_VtxAttr.texCoord[7].Elements = vat.g2.Tex7CoordElements; - m_VtxAttr.texCoord[7].Format = vat.g2.Tex7CoordFormat; - m_VtxAttr.texCoord[7].Frac = vat.g2.Tex7Frac; -}; - -void VertexLoader::AppendToString(std::string *dest) { - static const char *posMode[4] = { - "Invalid", - "Direct", - "Idx8", - "Idx16", - }; - static const char *posFormats[5] = { - "u8", "s8", "u16", "s16", "flt", - }; - dest->append(StringFromFormat("sz: %i skin: %i Pos: %i %s %s Nrm: %i %s %s - %i vtx\n", - m_VertexSize, m_VtxDesc.PosMatIdx, m_VtxAttr.PosElements ? 3 : 2, posMode[m_VtxDesc.Position], posFormats[m_VtxAttr.PosFormat], - m_VtxAttr.NormalElements, posMode[m_VtxDesc.Normal], posFormats[m_VtxAttr.NormalFormat], m_numLoadedVertices)); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Globals.h" + +#include + +#include "Common.h" +#include "Config.h" +#include "Profiler.h" +#include "MemoryUtil.h" +#include "StringUtil.h" +#include "x64Emitter.h" +#include "ABI.h" + +#include "LookUpTables.h" +#include "Statistics.h" +#include "VertexManager.h" +#include "VertexLoaderManager.h" +#include "VertexShaderManager.h" +#include "VertexManager.h" +#include "VertexLoader.h" +#include "BPStructs.h" +#include "DataReader.h" + +#include "VertexLoader_Position.h" +#include "VertexLoader_Normal.h" +#include "VertexLoader_Color.h" +#include "VertexLoader_TextCoord.h" + +#define USE_JIT + +#define COMPILED_CODE_SIZE 4096*4 + +NativeVertexFormat *g_nativeVertexFmt; + +//these don't need to be saved +#ifndef _WIN32 + #undef inline + #define inline +#endif + +// Direct +// ============================================================================== +static u8 s_curposmtx; +static u8 s_curtexmtx[8]; +static int s_texmtxwrite = 0; +static int s_texmtxread = 0; +static int loop_counter; + +// Vertex loaders read these. Although the scale ones should be baked into the shader. +int tcIndex; +int colIndex; +TVtxAttr* pVtxAttr; +int colElements[2]; +float posScale; +float tcScale[8]; + +using namespace Gen; + +void LOADERDECL PosMtx_ReadDirect_UByte() +{ + s_curposmtx = DataReadU8() & 0x3f; + PRIM_LOG("posmtx: %d, ", s_curposmtx); +} + +void LOADERDECL PosMtx_Write() +{ + *VertexManager::s_pCurBufferPointer++ = s_curposmtx; + *VertexManager::s_pCurBufferPointer++ = 0; + *VertexManager::s_pCurBufferPointer++ = 0; + *VertexManager::s_pCurBufferPointer++ = 0; +} + +void LOADERDECL TexMtx_ReadDirect_UByte() +{ + s_curtexmtx[s_texmtxread] = DataReadU8()&0x3f; + PRIM_LOG("texmtx%d: %d, ", s_texmtxread, s_curtexmtx[s_texmtxread]); + s_texmtxread++; +} + +void LOADERDECL TexMtx_Write_Float() +{ + *(float*)VertexManager::s_pCurBufferPointer = (float)s_curtexmtx[s_texmtxwrite++]; + VertexManager::s_pCurBufferPointer += 4; +} + +void LOADERDECL TexMtx_Write_Float2() +{ + ((float*)VertexManager::s_pCurBufferPointer)[0] = 0; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)s_curtexmtx[s_texmtxwrite++]; + VertexManager::s_pCurBufferPointer += 8; +} + +void LOADERDECL TexMtx_Write_Short3() +{ + ((s16*)VertexManager::s_pCurBufferPointer)[0] = 0; + ((s16*)VertexManager::s_pCurBufferPointer)[1] = 0; + ((s16*)VertexManager::s_pCurBufferPointer)[2] = s_curtexmtx[s_texmtxwrite++]; + VertexManager::s_pCurBufferPointer += 8; +} + +VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr) +{ + m_numLoadedVertices = 0; + m_VertexSize = 0; + m_numPipelineStages = 0; + m_NativeFmt = new NativeVertexFormat(); + loop_counter = 0; + VertexLoader_Normal::Init(); + + m_VtxDesc = vtx_desc; + SetVAT(vtx_attr.g0.Hex, vtx_attr.g1.Hex, vtx_attr.g2.Hex); + + m_compiledCode = (u8 *)AllocateExecutableMemory(COMPILED_CODE_SIZE, false); + if (m_compiledCode) { + memset(m_compiledCode, 0, COMPILED_CODE_SIZE); + } + CompileVertexTranslator(); +} + +VertexLoader::~VertexLoader() +{ + FreeMemoryPages(m_compiledCode, COMPILED_CODE_SIZE); + delete m_NativeFmt; +} + +void VertexLoader::CompileVertexTranslator() +{ + m_VertexSize = 0; + const TVtxAttr &vtx_attr = m_VtxAttr; + //const TVtxDesc &vtx_desc = m_VtxDesc; + +#ifdef USE_JIT + u8 *old_code_ptr = GetWritableCodePtr(); + SetCodePtr(m_compiledCode); + ABI_EmitPrologue(4); + // MOV(32, R(EBX), M(&loop_counter)); + // Start loop here + const u8 *loop_start = GetCodePtr(); + + // Reset component counters if present in vertex format only. + if (m_VtxDesc.Tex0Coord || m_VtxDesc.Tex1Coord || m_VtxDesc.Tex2Coord || m_VtxDesc.Tex3Coord || + m_VtxDesc.Tex4Coord || m_VtxDesc.Tex5Coord || m_VtxDesc.Tex6Coord || m_VtxDesc.Tex7Coord) { + MOV(32, M(&tcIndex), Imm32(0)); + } + if (m_VtxDesc.Color0 || m_VtxDesc.Color1) { + MOV(32, M(&colIndex), Imm32(0)); + } + if (m_VtxDesc.Tex0MatIdx || m_VtxDesc.Tex1MatIdx || m_VtxDesc.Tex2MatIdx || m_VtxDesc.Tex3MatIdx || + m_VtxDesc.Tex4MatIdx || m_VtxDesc.Tex5MatIdx || m_VtxDesc.Tex6MatIdx || m_VtxDesc.Tex7MatIdx) { + MOV(32, M(&s_texmtxwrite), Imm32(0)); + MOV(32, M(&s_texmtxread), Imm32(0)); + } +#endif + + // Colors + const int col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1}; + // TextureCoord + // Since m_VtxDesc.Text7Coord is broken across a 32 bit word boundary, retrieve its value manually. + // If we didn't do this, the vertex format would be read as one bit offset from where it should be, making + // 01 become 00, and 10/11 become 01 + const int tc[8] = { + m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord, + m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, (m_VtxDesc.Hex >> 31) & 3 + }; + + // Reset pipeline + m_numPipelineStages = 0; + + // It's a bit ugly that we poke inside m_NativeFmt in this function. Planning to fix this. + m_NativeFmt->m_components = 0; + + // Position in pc vertex format. + int nat_offset = 0; + PortableVertexDeclaration vtx_decl; + memset(&vtx_decl, 0, sizeof(vtx_decl)); + for (int i = 0; i < 8; i++) { + vtx_decl.texcoord_offset[i] = -1; + } + + // m_VBVertexStride for texmtx and posmtx is computed later when writing. + + // Position Matrix Index + if (m_VtxDesc.PosMatIdx) { + WriteCall(PosMtx_ReadDirect_UByte); + m_NativeFmt->m_components |= VB_HAS_POSMTXIDX; + m_VertexSize += 1; + } + + if (m_VtxDesc.Tex0MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX0; WriteCall(TexMtx_ReadDirect_UByte); } + if (m_VtxDesc.Tex1MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX1; WriteCall(TexMtx_ReadDirect_UByte); } + if (m_VtxDesc.Tex2MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX2; WriteCall(TexMtx_ReadDirect_UByte); } + if (m_VtxDesc.Tex3MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX3; WriteCall(TexMtx_ReadDirect_UByte); } + if (m_VtxDesc.Tex4MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX4; WriteCall(TexMtx_ReadDirect_UByte); } + if (m_VtxDesc.Tex5MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX5; WriteCall(TexMtx_ReadDirect_UByte); } + if (m_VtxDesc.Tex6MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX6; WriteCall(TexMtx_ReadDirect_UByte); } + if (m_VtxDesc.Tex7MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX7; WriteCall(TexMtx_ReadDirect_UByte); } + + switch (m_VtxDesc.Position) { + case NOT_PRESENT: {_assert_msg_(0, "Vertex descriptor without position!", "WTF?");} break; + case DIRECT: + switch (m_VtxAttr.PosFormat) { + case FORMAT_UBYTE: m_VertexSize += m_VtxAttr.PosElements?3:2; WriteCall(Pos_ReadDirect_UByte); break; + case FORMAT_BYTE: m_VertexSize += m_VtxAttr.PosElements?3:2; WriteCall(Pos_ReadDirect_Byte); break; + case FORMAT_USHORT: m_VertexSize += m_VtxAttr.PosElements?6:4; WriteCall(Pos_ReadDirect_UShort); break; + case FORMAT_SHORT: m_VertexSize += m_VtxAttr.PosElements?6:4; WriteCall(Pos_ReadDirect_Short); break; + case FORMAT_FLOAT: m_VertexSize += m_VtxAttr.PosElements?12:8; WriteCall(Pos_ReadDirect_Float); break; + default: _assert_(0); break; + } + nat_offset += 12; + break; + case INDEX8: + switch (m_VtxAttr.PosFormat) { + case FORMAT_UBYTE: WriteCall(Pos_ReadIndex8_UByte); break; //WTF? + case FORMAT_BYTE: WriteCall(Pos_ReadIndex8_Byte); break; + case FORMAT_USHORT: WriteCall(Pos_ReadIndex8_UShort); break; + case FORMAT_SHORT: WriteCall(Pos_ReadIndex8_Short); break; + case FORMAT_FLOAT: WriteCall(Pos_ReadIndex8_Float); break; + default: _assert_(0); break; + } + m_VertexSize += 1; + nat_offset += 12; + break; + case INDEX16: + switch (m_VtxAttr.PosFormat) { + case FORMAT_UBYTE: WriteCall(Pos_ReadIndex16_UByte); break; + case FORMAT_BYTE: WriteCall(Pos_ReadIndex16_Byte); break; + case FORMAT_USHORT: WriteCall(Pos_ReadIndex16_UShort); break; + case FORMAT_SHORT: WriteCall(Pos_ReadIndex16_Short); break; + case FORMAT_FLOAT: WriteCall(Pos_ReadIndex16_Float); break; + default: _assert_(0); break; + } + m_VertexSize += 2; + nat_offset += 12; + break; + } + + // Normals + vtx_decl.num_normals = 0; + if (m_VtxDesc.Normal != NOT_PRESENT) { + m_VertexSize += VertexLoader_Normal::GetSize(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements, m_VtxAttr.NormalIndex3); + TPipelineFunction pFunc = VertexLoader_Normal::GetFunction(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements, m_VtxAttr.NormalIndex3); + if (pFunc == 0) + { + char temp[256]; + sprintf(temp,"%i %i %i %i", m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements, m_VtxAttr.NormalIndex3); + g_VideoInitialize.pSysMessage("VertexLoader_Normal::GetFunction returned zero!"); + } + WriteCall(pFunc); + + vtx_decl.num_normals = vtx_attr.NormalElements ? 3 : 1; + switch (vtx_attr.NormalFormat) { + case FORMAT_UBYTE: + case FORMAT_BYTE: + vtx_decl.normal_gl_type = VAR_BYTE; + vtx_decl.normal_gl_size = 4; + vtx_decl.normal_offset[0] = nat_offset; + nat_offset += 4; + if (vtx_attr.NormalElements) { + vtx_decl.normal_offset[1] = nat_offset; + nat_offset += 4; + vtx_decl.normal_offset[2] = nat_offset; + nat_offset += 4; + } + break; + case FORMAT_USHORT: + case FORMAT_SHORT: + vtx_decl.normal_gl_type = VAR_SHORT; + vtx_decl.normal_gl_size = 4; + vtx_decl.normal_offset[0] = nat_offset; + nat_offset += 8; + if (vtx_attr.NormalElements) { + vtx_decl.normal_offset[1] = nat_offset; + nat_offset += 8; + vtx_decl.normal_offset[2] = nat_offset; + nat_offset += 8; + } + break; + case FORMAT_FLOAT: + vtx_decl.normal_gl_type = VAR_FLOAT; + vtx_decl.normal_gl_size = 3; + vtx_decl.normal_offset[0] = nat_offset; + nat_offset += 12; + if (vtx_attr.NormalElements) { + vtx_decl.normal_offset[1] = nat_offset; + nat_offset += 12; + vtx_decl.normal_offset[2] = nat_offset; + nat_offset += 12; + } + break; + default: _assert_(0); break; + } + + int numNormals = (m_VtxAttr.NormalElements == 1) ? NRM_THREE : NRM_ONE; + m_NativeFmt->m_components |= VB_HAS_NRM0; + + if (numNormals == NRM_THREE) + m_NativeFmt->m_components |= VB_HAS_NRM1 | VB_HAS_NRM2; + } + + vtx_decl.color_gl_type = VAR_UNSIGNED_BYTE; + for (int i = 0; i < 2; i++) { + m_NativeFmt->m_components |= VB_HAS_COL0 << i; + switch (col[i]) + { + case NOT_PRESENT: + m_NativeFmt->m_components &= ~(VB_HAS_COL0 << i); + vtx_decl.color_offset[i] = -1; + break; + case DIRECT: + switch (m_VtxAttr.color[i].Comp) + { + case FORMAT_16B_565: m_VertexSize += 2; WriteCall(Color_ReadDirect_16b_565); break; + case FORMAT_24B_888: m_VertexSize += 3; WriteCall(Color_ReadDirect_24b_888); break; + case FORMAT_32B_888x: m_VertexSize += 4; WriteCall(Color_ReadDirect_32b_888x); break; + case FORMAT_16B_4444: m_VertexSize += 2; WriteCall(Color_ReadDirect_16b_4444); break; + case FORMAT_24B_6666: m_VertexSize += 3; WriteCall(Color_ReadDirect_24b_6666); break; + case FORMAT_32B_8888: m_VertexSize += 4; WriteCall(Color_ReadDirect_32b_8888); break; + default: _assert_(0); break; + } + break; + case INDEX8: + m_VertexSize += 1; + switch (m_VtxAttr.color[i].Comp) + { + case FORMAT_16B_565: WriteCall(Color_ReadIndex8_16b_565); break; + case FORMAT_24B_888: WriteCall(Color_ReadIndex8_24b_888); break; + case FORMAT_32B_888x: WriteCall(Color_ReadIndex8_32b_888x); break; + case FORMAT_16B_4444: WriteCall(Color_ReadIndex8_16b_4444); break; + case FORMAT_24B_6666: WriteCall(Color_ReadIndex8_24b_6666); break; + case FORMAT_32B_8888: WriteCall(Color_ReadIndex8_32b_8888); break; + default: _assert_(0); break; + } + break; + case INDEX16: + m_VertexSize += 2; + switch (m_VtxAttr.color[i].Comp) + { + case FORMAT_16B_565: WriteCall(Color_ReadIndex16_16b_565); break; + case FORMAT_24B_888: WriteCall(Color_ReadIndex16_24b_888); break; + case FORMAT_32B_888x: WriteCall(Color_ReadIndex16_32b_888x); break; + case FORMAT_16B_4444: WriteCall(Color_ReadIndex16_16b_4444); break; + case FORMAT_24B_6666: WriteCall(Color_ReadIndex16_24b_6666); break; + case FORMAT_32B_8888: WriteCall(Color_ReadIndex16_32b_8888); break; + default: _assert_(0); break; + } + break; + } + // Common for the three bottom cases + if (col[i] != NOT_PRESENT) { + vtx_decl.color_offset[i] = nat_offset; + nat_offset += 4; + } + } + + // Texture matrix indices (remove if corresponding texture coordinate isn't enabled) + for (int i = 0; i < 8; i++) { + m_NativeFmt->m_components |= VB_HAS_UV0 << i; + int elements = m_VtxAttr.texCoord[i].Elements; + switch (tc[i]) + { + case NOT_PRESENT: + m_NativeFmt->m_components &= ~(VB_HAS_UV0 << i); + break; + case DIRECT: + switch (m_VtxAttr.texCoord[i].Format) + { + case FORMAT_UBYTE: m_VertexSize += elements?2:1; WriteCall(elements?TexCoord_ReadDirect_UByte2:TexCoord_ReadDirect_UByte1); break; + case FORMAT_BYTE: m_VertexSize += elements?2:1; WriteCall(elements?TexCoord_ReadDirect_Byte2:TexCoord_ReadDirect_Byte1); break; + case FORMAT_USHORT: m_VertexSize += elements?4:2; WriteCall(elements?TexCoord_ReadDirect_UShort2:TexCoord_ReadDirect_UShort1); break; + case FORMAT_SHORT: m_VertexSize += elements?4:2; WriteCall(elements?TexCoord_ReadDirect_Short2:TexCoord_ReadDirect_Short1); break; + case FORMAT_FLOAT: m_VertexSize += elements?8:4; WriteCall(elements?TexCoord_ReadDirect_Float2:TexCoord_ReadDirect_Float1); break; + default: _assert_(0); break; + } + break; + case INDEX8: + m_VertexSize += 1; + switch (m_VtxAttr.texCoord[i].Format) + { + case FORMAT_UBYTE: WriteCall(elements?TexCoord_ReadIndex8_UByte2:TexCoord_ReadIndex8_UByte1); break; + case FORMAT_BYTE: WriteCall(elements?TexCoord_ReadIndex8_Byte2:TexCoord_ReadIndex8_Byte1); break; + case FORMAT_USHORT: WriteCall(elements?TexCoord_ReadIndex8_UShort2:TexCoord_ReadIndex8_UShort1); break; + case FORMAT_SHORT: WriteCall(elements?TexCoord_ReadIndex8_Short2:TexCoord_ReadIndex8_Short1); break; + case FORMAT_FLOAT: WriteCall(elements?TexCoord_ReadIndex8_Float2:TexCoord_ReadIndex8_Float1); break; + default: _assert_(0); break; + } + break; + case INDEX16: + m_VertexSize += 2; + switch (m_VtxAttr.texCoord[i].Format) + { + case FORMAT_UBYTE: WriteCall(elements?TexCoord_ReadIndex16_UByte2:TexCoord_ReadIndex16_UByte1); break; + case FORMAT_BYTE: WriteCall(elements?TexCoord_ReadIndex16_Byte2:TexCoord_ReadIndex16_Byte1); break; + case FORMAT_USHORT: WriteCall(elements?TexCoord_ReadIndex16_UShort2:TexCoord_ReadIndex16_UShort1); break; + case FORMAT_SHORT: WriteCall(elements?TexCoord_ReadIndex16_Short2:TexCoord_ReadIndex16_Short1); break; + case FORMAT_FLOAT: WriteCall(elements?TexCoord_ReadIndex16_Float2:TexCoord_ReadIndex16_Float1); break; + default: _assert_(0); + } + break; + } + + if (m_NativeFmt->m_components & (VB_HAS_TEXMTXIDX0 << i)) { + if (tc[i] != NOT_PRESENT) { + // if texmtx is included, texcoord will always be 3 floats, z will be the texmtx index + vtx_decl.texcoord_offset[i] = nat_offset; + vtx_decl.texcoord_gl_type[i] = VAR_FLOAT; + vtx_decl.texcoord_size[i] = 3; + nat_offset += 12; + WriteCall(m_VtxAttr.texCoord[i].Elements ? TexMtx_Write_Float : TexMtx_Write_Float2); + } + else { + m_NativeFmt->m_components |= VB_HAS_UV0 << i; // have to include since using now + vtx_decl.texcoord_offset[i] = nat_offset; + vtx_decl.texcoord_gl_type[i] = VAR_SHORT; + vtx_decl.texcoord_size[i] = 4; + nat_offset += 8; // still include the texture coordinate, but this time as 6 + 2 bytes + WriteCall(TexMtx_Write_Short3); + } + } + else { + if (tc[i] != NOT_PRESENT) { + vtx_decl.texcoord_offset[i] = nat_offset; + vtx_decl.texcoord_gl_type[i] = VAR_FLOAT; + vtx_decl.texcoord_size[i] = vtx_attr.texCoord[i].Elements ? 2 : 1; + nat_offset += 4 * (vtx_attr.texCoord[i].Elements ? 2 : 1); + } else { + vtx_decl.texcoord_offset[i] = -1; + } + } + + if (tc[i] == NOT_PRESENT) { + // if there's more tex coords later, have to write a dummy call + int j = i + 1; + for (; j < 8; ++j) { + if (tc[j] != NOT_PRESENT) { + WriteCall(TexCoord_Read_Dummy); // important to get indices right! + break; + } + } + // tricky! + if (j == 8 && !((m_NativeFmt->m_components & VB_HAS_TEXMTXIDXALL) & (VB_HAS_TEXMTXIDXALL << (i + 1)))) { + // no more tex coords and tex matrices, so exit loop + break; + } + } + } + + if (m_VtxDesc.PosMatIdx) { + WriteCall(PosMtx_Write); + vtx_decl.posmtx_offset = nat_offset; + nat_offset += 4; + } else { + vtx_decl.posmtx_offset = -1; + } + + native_stride = nat_offset; + vtx_decl.stride = native_stride; + +#ifdef USE_JIT + // End loop here + SUB(32, M(&loop_counter), Imm8(1)); + //SUB(32, R(EBX), Imm8(1)); + J_CC(CC_NZ, loop_start, true); + ABI_EmitEpilogue(4); + SetCodePtr(old_code_ptr); +#endif + m_NativeFmt->Initialize(vtx_decl); +} + +void VertexLoader::WriteCall(TPipelineFunction func) +{ +#ifdef USE_JIT + CALL((void*)func); +#else + m_PipelineStages[m_numPipelineStages++] = func; +#endif +} + +void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count) +{ + DVSTARTPROFILE(); + + m_numLoadedVertices += count; + + // Flush if our vertex format is different from the currently set. + if (g_nativeVertexFmt != NULL && g_nativeVertexFmt != m_NativeFmt) + { + VertexManager::Flush(); + // Also move the Set() here? + } + g_nativeVertexFmt = m_NativeFmt; + + if (bpmem.genMode.cullmode == 3 && primitive < 5) + { + // if cull mode is none, ignore triangles and quads + DataSkip(count * m_VertexSize); + return; + } + + VertexManager::EnableComponents(m_NativeFmt->m_components); + + // Load position and texcoord scale factors. + // TODO - figure out if we should leave these independent, or compile them into + // the vertexloaders. + m_VtxAttr.PosFrac = g_VtxAttr[vtx_attr_group].g0.PosFrac; + m_VtxAttr.texCoord[0].Frac = g_VtxAttr[vtx_attr_group].g0.Tex0Frac; + m_VtxAttr.texCoord[1].Frac = g_VtxAttr[vtx_attr_group].g1.Tex1Frac; + m_VtxAttr.texCoord[2].Frac = g_VtxAttr[vtx_attr_group].g1.Tex2Frac; + m_VtxAttr.texCoord[3].Frac = g_VtxAttr[vtx_attr_group].g1.Tex3Frac; + m_VtxAttr.texCoord[4].Frac = g_VtxAttr[vtx_attr_group].g2.Tex4Frac; + m_VtxAttr.texCoord[5].Frac = g_VtxAttr[vtx_attr_group].g2.Tex5Frac; + m_VtxAttr.texCoord[6].Frac = g_VtxAttr[vtx_attr_group].g2.Tex6Frac; + m_VtxAttr.texCoord[7].Frac = g_VtxAttr[vtx_attr_group].g2.Tex7Frac; + + pVtxAttr = &m_VtxAttr; + posScale = shiftLookup[m_VtxAttr.PosFrac]; + if (m_NativeFmt->m_components & VB_HAS_UVALL) { + for (int i = 0; i < 8; i++) + tcScale[i] = shiftLookup[m_VtxAttr.texCoord[i].Frac]; + } + for (int i = 0; i < 2; i++) + colElements[i] = m_VtxAttr.color[i].Elements; + + // if strips or fans, make sure all vertices can fit in buffer, otherwise flush + int granularity = 1; + switch (primitive) { + case 3: // strip .. hm, weird + case 4: // fan + if (VertexManager::GetRemainingSize() < 3 * native_stride) + VertexManager::Flush(); + break; + case 6: // line strip + if (VertexManager::GetRemainingSize() < 2 * native_stride) + VertexManager::Flush(); + break; + case 0: granularity = 4; break; // quads + case 2: granularity = 3; break; // tris + case 5: granularity = 2; break; // lines + } + + int startv = 0, extraverts = 0; + int v = 0; + + while (v < count) + { + int remainingVerts = VertexManager::GetRemainingSize() / native_stride; + if (remainingVerts < granularity) { + INCSTAT(stats.thisFrame.numBufferSplits); + // This buffer full - break current primitive and flush, to switch to the next buffer. + u8* plastptr = VertexManager::s_pCurBufferPointer; + if (v - startv > 0) + VertexManager::AddVertices(primitive, v - startv + extraverts); + VertexManager::Flush(); + // Why does this need to be so complicated? + switch (primitive) { + case 3: // triangle strip, copy last two vertices + // a little trick since we have to keep track of signs + if (v & 1) { + memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-2*native_stride, native_stride); + memcpy_gc(VertexManager::s_pCurBufferPointer+native_stride, plastptr-native_stride*2, 2*native_stride); + VertexManager::s_pCurBufferPointer += native_stride*3; + extraverts = 3; + } + else { + memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride*2, native_stride*2); + VertexManager::s_pCurBufferPointer += native_stride*2; + extraverts = 2; + } + break; + case 4: // tri fan, copy first and last vert + memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride*(v-startv+extraverts), native_stride); + VertexManager::s_pCurBufferPointer += native_stride; + memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride, native_stride); + VertexManager::s_pCurBufferPointer += native_stride; + extraverts = 2; + break; + case 6: // line strip + memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride, native_stride); + VertexManager::s_pCurBufferPointer += native_stride; + extraverts = 1; + break; + default: + extraverts = 0; + break; + } + startv = v; + } + int remainingPrims = remainingVerts / granularity; + remainingVerts = remainingPrims * granularity; + if (count - v < remainingVerts) + remainingVerts = count - v; + + // Clean tight loader loop. Todo - build the loop into the JIT code. + #ifdef USE_JIT + if (remainingVerts > 0) { + loop_counter = remainingVerts; + ((void (*)())(void*)m_compiledCode)(); + } + #else + for (int s = 0; s < remainingVerts; s++) + { + tcIndex = 0; + colIndex = 0; + s_texmtxwrite = s_texmtxread = 0; + for (int i = 0; i < m_numPipelineStages; i++) + m_PipelineStages[i](); + PRIM_LOG("\n"); + } + #endif + v += remainingVerts; + } + + if (startv < count) + VertexManager::AddVertices(primitive, count - startv + extraverts); +} + +void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2) +{ + VAT vat; + vat.g0.Hex = _group0; + vat.g1.Hex = _group1; + vat.g2.Hex = _group2; + + m_VtxAttr.PosElements = vat.g0.PosElements; + m_VtxAttr.PosFormat = vat.g0.PosFormat; + m_VtxAttr.PosFrac = vat.g0.PosFrac; + m_VtxAttr.NormalElements = vat.g0.NormalElements; + m_VtxAttr.NormalFormat = vat.g0.NormalFormat; + m_VtxAttr.color[0].Elements = vat.g0.Color0Elements; + m_VtxAttr.color[0].Comp = vat.g0.Color0Comp; + m_VtxAttr.color[1].Elements = vat.g0.Color1Elements; + m_VtxAttr.color[1].Comp = vat.g0.Color1Comp; + m_VtxAttr.texCoord[0].Elements = vat.g0.Tex0CoordElements; + m_VtxAttr.texCoord[0].Format = vat.g0.Tex0CoordFormat; + m_VtxAttr.texCoord[0].Frac = vat.g0.Tex0Frac; + m_VtxAttr.ByteDequant = vat.g0.ByteDequant; + m_VtxAttr.NormalIndex3 = vat.g0.NormalIndex3; + + m_VtxAttr.texCoord[1].Elements = vat.g1.Tex1CoordElements; + m_VtxAttr.texCoord[1].Format = vat.g1.Tex1CoordFormat; + m_VtxAttr.texCoord[1].Frac = vat.g1.Tex1Frac; + m_VtxAttr.texCoord[2].Elements = vat.g1.Tex2CoordElements; + m_VtxAttr.texCoord[2].Format = vat.g1.Tex2CoordFormat; + m_VtxAttr.texCoord[2].Frac = vat.g1.Tex2Frac; + m_VtxAttr.texCoord[3].Elements = vat.g1.Tex3CoordElements; + m_VtxAttr.texCoord[3].Format = vat.g1.Tex3CoordFormat; + m_VtxAttr.texCoord[3].Frac = vat.g1.Tex3Frac; + m_VtxAttr.texCoord[4].Elements = vat.g1.Tex4CoordElements; + m_VtxAttr.texCoord[4].Format = vat.g1.Tex4CoordFormat; + + m_VtxAttr.texCoord[4].Frac = vat.g2.Tex4Frac; + m_VtxAttr.texCoord[5].Elements = vat.g2.Tex5CoordElements; + m_VtxAttr.texCoord[5].Format = vat.g2.Tex5CoordFormat; + m_VtxAttr.texCoord[5].Frac = vat.g2.Tex5Frac; + m_VtxAttr.texCoord[6].Elements = vat.g2.Tex6CoordElements; + m_VtxAttr.texCoord[6].Format = vat.g2.Tex6CoordFormat; + m_VtxAttr.texCoord[6].Frac = vat.g2.Tex6Frac; + m_VtxAttr.texCoord[7].Elements = vat.g2.Tex7CoordElements; + m_VtxAttr.texCoord[7].Format = vat.g2.Tex7CoordFormat; + m_VtxAttr.texCoord[7].Frac = vat.g2.Tex7Frac; +}; + +void VertexLoader::AppendToString(std::string *dest) { + static const char *posMode[4] = { + "Invalid", + "Direct", + "Idx8", + "Idx16", + }; + static const char *posFormats[5] = { + "u8", "s8", "u16", "s16", "flt", + }; + dest->append(StringFromFormat("sz: %i skin: %i Pos: %i %s %s Nrm: %i %s %s - %i vtx\n", + m_VertexSize, m_VtxDesc.PosMatIdx, m_VtxAttr.PosElements ? 3 : 2, posMode[m_VtxDesc.Position], posFormats[m_VtxAttr.PosFormat], + m_VtxAttr.NormalElements, posMode[m_VtxDesc.Normal], posFormats[m_VtxAttr.NormalFormat], m_numLoadedVertices)); +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoaderManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoaderManager.cpp index 464faf989f..34d81f1c12 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoaderManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoaderManager.cpp @@ -1,155 +1,155 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include - -#include "Statistics.h" - -#include "VertexShaderManager.h" -#include "VertexLoader.h" -#include "VertexLoaderManager.h" - -static int s_attr_dirty; // bitfield - -static VertexLoader *g_VertexLoaders[8]; - -namespace VertexLoaderManager -{ - -typedef std::map VertexLoaderMap; -static VertexLoaderMap g_VertexLoaderMap; -// TODO - change into array of pointers. Keep a map of all seen so far. - -void Init() -{ - MarkAllDirty(); - for (int i = 0; i < 8; i++) - g_VertexLoaders[i] = NULL; -} - -void Shutdown() -{ - for (VertexLoaderMap::iterator iter = g_VertexLoaderMap.begin(); iter != g_VertexLoaderMap.end(); ++iter) - { - delete iter->second; - } - g_VertexLoaderMap.clear(); -} - -void AppendListToString(std::string *dest) -{ - for (VertexLoaderMap::iterator iter = g_VertexLoaderMap.begin(); iter != g_VertexLoaderMap.end(); ++iter) - { - iter->second->AppendToString(dest); - } -} - -void MarkAllDirty() -{ - s_attr_dirty = 0xff; -} - -static void RefreshLoader(int vtx_attr_group) -{ - if ((s_attr_dirty >> vtx_attr_group) & 1) - { - VertexLoaderUID uid; - uid.InitFromCurrentState(vtx_attr_group); - VertexLoaderMap::iterator iter = g_VertexLoaderMap.find(uid); - if (iter != g_VertexLoaderMap.end()) - { - g_VertexLoaders[vtx_attr_group] = iter->second; - } - else - { - VertexLoader *loader = new VertexLoader(g_VtxDesc, g_VtxAttr[vtx_attr_group]); - g_VertexLoaderMap[uid] = loader; - g_VertexLoaders[vtx_attr_group] = loader; - INCSTAT(stats.numVertexLoaders); - } - } - s_attr_dirty &= ~(1 << vtx_attr_group); -} - -void RunVertices(int vtx_attr_group, int primitive, int count) -{ - if (!count) - return; - RefreshLoader(vtx_attr_group); - g_VertexLoaders[vtx_attr_group]->RunVertices(vtx_attr_group, primitive, count); -} - -int GetVertexSize(int vtx_attr_group) -{ - RefreshLoader(vtx_attr_group); - return g_VertexLoaders[vtx_attr_group]->GetVertexSize(); -} - -} // namespace - -void LoadCPReg(u32 sub_cmd, u32 value) -{ - switch (sub_cmd & 0xF0) - { - case 0x30: - VertexShaderMngr::SetTexMatrixChangedA(value); - break; - - case 0x40: - VertexShaderMngr::SetTexMatrixChangedB(value); - break; - - case 0x50: - g_VtxDesc.Hex &= ~0x1FFFF; // keep the Upper bits - g_VtxDesc.Hex |= value; - s_attr_dirty = 0xFF; - break; - - case 0x60: - g_VtxDesc.Hex &= 0x1FFFF; // keep the lower 17Bits - g_VtxDesc.Hex |= (u64)value << 17; - s_attr_dirty = 0xFF; - break; - - case 0x70: - _assert_((sub_cmd & 0x0F) < 8); - g_VtxAttr[sub_cmd & 7].g0.Hex = value; - s_attr_dirty |= 1 << (sub_cmd & 7); - break; - - case 0x80: - _assert_((sub_cmd & 0x0F) < 8); - g_VtxAttr[sub_cmd & 7].g1.Hex = value; - s_attr_dirty |= 1 << (sub_cmd & 7); - break; - - case 0x90: - _assert_((sub_cmd & 0x0F) < 8); - g_VtxAttr[sub_cmd & 7].g2.Hex = value; - s_attr_dirty |= 1 << (sub_cmd & 7); - break; - - // Pointers to vertex arrays in GC RAM - case 0xA0: - arraybases[sub_cmd & 0xF] = value & 0xFFFFFFFF; // huh, why the mask? - break; - - case 0xB0: - arraystrides[sub_cmd & 0xF] = value & 0xFF; - break; - } -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include + +#include "Statistics.h" + +#include "VertexShaderManager.h" +#include "VertexLoader.h" +#include "VertexLoaderManager.h" + +static int s_attr_dirty; // bitfield + +static VertexLoader *g_VertexLoaders[8]; + +namespace VertexLoaderManager +{ + +typedef std::map VertexLoaderMap; +static VertexLoaderMap g_VertexLoaderMap; +// TODO - change into array of pointers. Keep a map of all seen so far. + +void Init() +{ + MarkAllDirty(); + for (int i = 0; i < 8; i++) + g_VertexLoaders[i] = NULL; +} + +void Shutdown() +{ + for (VertexLoaderMap::iterator iter = g_VertexLoaderMap.begin(); iter != g_VertexLoaderMap.end(); ++iter) + { + delete iter->second; + } + g_VertexLoaderMap.clear(); +} + +void AppendListToString(std::string *dest) +{ + for (VertexLoaderMap::iterator iter = g_VertexLoaderMap.begin(); iter != g_VertexLoaderMap.end(); ++iter) + { + iter->second->AppendToString(dest); + } +} + +void MarkAllDirty() +{ + s_attr_dirty = 0xff; +} + +static void RefreshLoader(int vtx_attr_group) +{ + if ((s_attr_dirty >> vtx_attr_group) & 1) + { + VertexLoaderUID uid; + uid.InitFromCurrentState(vtx_attr_group); + VertexLoaderMap::iterator iter = g_VertexLoaderMap.find(uid); + if (iter != g_VertexLoaderMap.end()) + { + g_VertexLoaders[vtx_attr_group] = iter->second; + } + else + { + VertexLoader *loader = new VertexLoader(g_VtxDesc, g_VtxAttr[vtx_attr_group]); + g_VertexLoaderMap[uid] = loader; + g_VertexLoaders[vtx_attr_group] = loader; + INCSTAT(stats.numVertexLoaders); + } + } + s_attr_dirty &= ~(1 << vtx_attr_group); +} + +void RunVertices(int vtx_attr_group, int primitive, int count) +{ + if (!count) + return; + RefreshLoader(vtx_attr_group); + g_VertexLoaders[vtx_attr_group]->RunVertices(vtx_attr_group, primitive, count); +} + +int GetVertexSize(int vtx_attr_group) +{ + RefreshLoader(vtx_attr_group); + return g_VertexLoaders[vtx_attr_group]->GetVertexSize(); +} + +} // namespace + +void LoadCPReg(u32 sub_cmd, u32 value) +{ + switch (sub_cmd & 0xF0) + { + case 0x30: + VertexShaderMngr::SetTexMatrixChangedA(value); + break; + + case 0x40: + VertexShaderMngr::SetTexMatrixChangedB(value); + break; + + case 0x50: + g_VtxDesc.Hex &= ~0x1FFFF; // keep the Upper bits + g_VtxDesc.Hex |= value; + s_attr_dirty = 0xFF; + break; + + case 0x60: + g_VtxDesc.Hex &= 0x1FFFF; // keep the lower 17Bits + g_VtxDesc.Hex |= (u64)value << 17; + s_attr_dirty = 0xFF; + break; + + case 0x70: + _assert_((sub_cmd & 0x0F) < 8); + g_VtxAttr[sub_cmd & 7].g0.Hex = value; + s_attr_dirty |= 1 << (sub_cmd & 7); + break; + + case 0x80: + _assert_((sub_cmd & 0x0F) < 8); + g_VtxAttr[sub_cmd & 7].g1.Hex = value; + s_attr_dirty |= 1 << (sub_cmd & 7); + break; + + case 0x90: + _assert_((sub_cmd & 0x0F) < 8); + g_VtxAttr[sub_cmd & 7].g2.Hex = value; + s_attr_dirty |= 1 << (sub_cmd & 7); + break; + + // Pointers to vertex arrays in GC RAM + case 0xA0: + arraybases[sub_cmd & 0xF] = value & 0xFFFFFFFF; // huh, why the mask? + break; + + case 0xB0: + arraystrides[sub_cmd & 0xF] = value & 0xFF; + break; + } +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader_Color.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader_Color.cpp index 13b3c3fbce..8000893ce1 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader_Color.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader_Color.cpp @@ -1,231 +1,231 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifndef _VERTEXLOADERCOLOR_H -#define _VERTEXLOADERCOLOR_H - -#include "Globals.h" -#include "LookUpTables.h" -#include "VertexLoader.h" -#include "VertexManager.h" -#include "VertexLoader_Color.h" - -#define RSHIFT 0 -#define GSHIFT 8 -#define BSHIFT 16 -#define ASHIFT 24 - -extern int colIndex; -extern int colElements[2]; - -inline void _SetCol(u32 val) -{ - *(u32*)VertexManager::s_pCurBufferPointer = val; - VertexManager::s_pCurBufferPointer += 4; - colIndex++; -} - -void _SetCol4444(u16 val) -{ - u32 col = lut4to8[(val>>0)&0xF]<>12)&0xF] <>8)&0xF] <>4)&0xF] <>18)&0x3F] << RSHIFT; - col |= lut6to8[(val>>12)&0x3F] << GSHIFT; - col |= lut6to8[(val>>6)&0x3F] << BSHIFT; - col |= lut6to8[(val>>0)&0x3F] << ASHIFT; - _SetCol(col); -} - -void _SetCol565(u16 val) -{ - u32 col = lut5to8[(val>>11)&0x1f] << RSHIFT; - col |= lut6to8[(val>>5 )&0x3f] << GSHIFT; - col |= lut5to8[(val )&0x1f] << BSHIFT; - _SetCol(col | (0xFF<>0)&0xF]<>12)&0xF] <>8)&0xF] <>4)&0xF] <>18)&0x3F] << RSHIFT; + col |= lut6to8[(val>>12)&0x3F] << GSHIFT; + col |= lut6to8[(val>>6)&0x3F] << BSHIFT; + col |= lut6to8[(val>>0)&0x3F] << ASHIFT; + _SetCol(col); +} + +void _SetCol565(u16 val) +{ + u32 col = lut5to8[(val>>11)&0x1f] << RSHIFT; + col |= lut6to8[(val>>5 )&0x3f] << GSHIFT; + col |= lut5to8[(val )&0x1f] << BSHIFT; + _SetCol(col | (0xFF< -MULPS(XMM0, XMM7); -MOVUPS(MOffset(EDI, 0), XMM0); - - */ - -// ============================================================================== -// Direct -// ============================================================================== -void LOADERDECL Pos_ReadDirect_UByte() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU8() * posScale; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)DataReadU8() * posScale; - if (pVtxAttr->PosElements) - ((float*)VertexManager::s_pCurBufferPointer)[2] = (float)DataReadU8() * posScale; - else - ((float*)VertexManager::s_pCurBufferPointer)[2] = 1.0f; - LOG_VTX(); - VertexManager::s_pCurBufferPointer += 12; -} - -void LOADERDECL Pos_ReadDirect_Byte() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)DataReadU8() * posScale; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)DataReadU8() * posScale; - if (pVtxAttr->PosElements) - ((float*)VertexManager::s_pCurBufferPointer)[2] = (float)(s8)DataReadU8() * posScale; - else - ((float*)VertexManager::s_pCurBufferPointer)[2] = 1.0; - LOG_VTX(); - VertexManager::s_pCurBufferPointer += 12; -} - -void LOADERDECL Pos_ReadDirect_UShort() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU16() * posScale; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)DataReadU16() * posScale; - if (pVtxAttr->PosElements) - ((float*)VertexManager::s_pCurBufferPointer)[2] = (float)DataReadU16() * posScale; - else - ((float*)VertexManager::s_pCurBufferPointer)[2] = 1.0f; - LOG_VTX(); - VertexManager::s_pCurBufferPointer += 12; -} - -void LOADERDECL Pos_ReadDirect_Short() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)DataReadU16() * posScale; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)DataReadU16() * posScale; - if (pVtxAttr->PosElements) - ((float*)VertexManager::s_pCurBufferPointer)[2] = (float)(s16)DataReadU16() * posScale; - else - ((float*)VertexManager::s_pCurBufferPointer)[2] = 1.0f; - LOG_VTX(); - VertexManager::s_pCurBufferPointer += 12; -} - -void LOADERDECL Pos_ReadDirect_Float() -{ - // No need to use floating point here. - ((u32 *)VertexManager::s_pCurBufferPointer)[0] = DataReadU32(); - ((u32 *)VertexManager::s_pCurBufferPointer)[1] = DataReadU32(); - if (pVtxAttr->PosElements) - ((u32 *)VertexManager::s_pCurBufferPointer)[2] = DataReadU32(); - else - ((float*)VertexManager::s_pCurBufferPointer)[2] = 1.0f; - LOG_VTX(); - VertexManager::s_pCurBufferPointer += 12; -} - -#define Pos_ReadIndex_Byte(T) { \ - u32 iAddress = arraybases[ARRAY_POSITION] + ((u32)Index * arraystrides[ARRAY_POSITION]); \ - ((float*)VertexManager::s_pCurBufferPointer)[0] = ((float)(T)Memory_Read_U8(iAddress)) * posScale; \ - ((float*)VertexManager::s_pCurBufferPointer)[1] = ((float)(T)Memory_Read_U8(iAddress+1)) * posScale; \ - if (pVtxAttr->PosElements) \ - ((float*)VertexManager::s_pCurBufferPointer)[2] = ((float)(T)Memory_Read_U8(iAddress+2)) * posScale; \ - else \ - ((float*)VertexManager::s_pCurBufferPointer)[2] = 1.0f; \ - LOG_VTX(); \ - VertexManager::s_pCurBufferPointer += 12; \ -} - -#define Pos_ReadIndex_Short(T) { \ - u32 iAddress = arraybases[ARRAY_POSITION] + ((u32)Index * arraystrides[ARRAY_POSITION]); \ - ((float*)VertexManager::s_pCurBufferPointer)[0] = ((float)(T)Memory_Read_U16(iAddress)) * posScale; \ - ((float*)VertexManager::s_pCurBufferPointer)[1] = ((float)(T)Memory_Read_U16(iAddress+2)) * posScale; \ - if (pVtxAttr->PosElements) \ - ((float*)VertexManager::s_pCurBufferPointer)[2] = ((float)(T)Memory_Read_U16(iAddress+4)) * posScale; \ - else \ - ((float*)VertexManager::s_pCurBufferPointer)[2] = 1.0f; \ - LOG_VTX(); \ - VertexManager::s_pCurBufferPointer += 12; \ -} - -#define Pos_ReadIndex_Float() { \ - u32 iAddress = arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION]); \ - ((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress); \ - ((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress+4); \ - if (pVtxAttr->PosElements) \ - ((u32*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U32(iAddress+8); \ - else \ - ((float*)VertexManager::s_pCurBufferPointer)[2] = 1.0f; \ - LOG_VTX(); \ - VertexManager::s_pCurBufferPointer += 12; \ -} - -// ============================================================================== -// Index 8 -// ============================================================================== -void LOADERDECL Pos_ReadIndex8_UByte() -{ - u8 Index = DataReadU8(); - Pos_ReadIndex_Byte(u8); -} - -void LOADERDECL Pos_ReadIndex8_Byte() -{ - u8 Index = DataReadU8(); - Pos_ReadIndex_Byte(s8); -} - -void LOADERDECL Pos_ReadIndex8_UShort() -{ - u8 Index = DataReadU8(); - Pos_ReadIndex_Short(u16); -} - -void LOADERDECL Pos_ReadIndex8_Short() -{ - u8 Index = DataReadU8(); - Pos_ReadIndex_Short(s16); -} - -void LOADERDECL Pos_ReadIndex8_Float() -{ - u8 Index = DataReadU8(); - Pos_ReadIndex_Float(); -} - -// ============================================================================== -// Index 16 -// ============================================================================== - -void LOADERDECL Pos_ReadIndex16_UByte(){ - u16 Index = DataReadU16(); - Pos_ReadIndex_Byte(u8); -} - -void LOADERDECL Pos_ReadIndex16_Byte(){ - u16 Index = DataReadU16(); - Pos_ReadIndex_Byte(s8); -} - -void LOADERDECL Pos_ReadIndex16_UShort(){ - u16 Index = DataReadU16(); - Pos_ReadIndex_Short(u16); -} - -void LOADERDECL Pos_ReadIndex16_Short() -{ - u16 Index = DataReadU16(); - Pos_ReadIndex_Short(s16); -} - -void LOADERDECL Pos_ReadIndex16_Float() -{ - u16 Index = DataReadU16(); - Pos_ReadIndex_Float(); -} - -#endif +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef VERTEXLOADER_POSITION_H +#define VERTEXLOADER_POSITION_H + +#include "Globals.h" +#include "VertexLoader.h" +#include "VertexManager.h" +#include "VertexLoader_Position.h" + +extern float posScale; +extern TVtxAttr *pVtxAttr; + +#define LOG_VTX() PRIM_LOG("vtx: %f %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[0], ((float*)VertexManager::s_pCurBufferPointer)[1], ((float*)VertexManager::s_pCurBufferPointer)[2]); + +// Thoughts on the implementation of a vertex loader compiler. +// s_pCurBufferPointer should definitely be in a register. +// Could load the position scale factor in XMM7, for example. + +// The pointer inside DataReadU8 in another. +// Let's check out Pos_ReadDirect_UByte(). For Byte, replace MOVZX with MOVSX. + +/* +MOVZX(32, R(EAX), MOffset(ESI, 0)); +MOVZX(32, R(EBX), MOffset(ESI, 1)); +MOVZX(32, R(ECX), MOffset(ESI, 2)); +MOVD(XMM0, R(EAX)); +MOVD(XMM1, R(EBX)); +MOVD(XMM2, R(ECX)); +CVTDQ2PS(XMM0, XMM0); +CVTDQ2PS(XMM1, XMM1); +CVTDQ2PS(XMM2, XMM2); +MULSS(XMM0, XMM7); +MULSS(XMM1, XMM7); +MULSS(XMM2, XMM7); +MOVSS(MOffset(EDI, 0), XMM0); +MOVSS(MOffset(EDI, 4), XMM1); +MOVSS(MOffset(EDI, 8), XMM2); + +Alternatively, lookup table: +MOVZX(32, R(EAX), MOffset(ESI, 0)); +MOVZX(32, R(EBX), MOffset(ESI, 1)); +MOVZX(32, R(ECX), MOffset(ESI, 2)); +MOV(32, R(EAX), MComplex(LUTREG, EAX, 4)); +MOV(32, R(EBX), MComplex(LUTREG, EBX, 4)); +MOV(32, R(ECX), MComplex(LUTREG, ECX, 4)); +MOV(MOffset(EDI, 0), XMM0); +MOV(MOffset(EDI, 4), XMM1); +MOV(MOffset(EDI, 8), XMM2); + +SSE4: +PINSRB(XMM0, MOffset(ESI, 0), 0); +PINSRB(XMM0, MOffset(ESI, 1), 4); +PINSRB(XMM0, MOffset(ESI, 2), 8); +CVTDQ2PS(XMM0, XMM0); + +MULPS(XMM0, XMM7); +MOVUPS(MOffset(EDI, 0), XMM0); + + */ + +// ============================================================================== +// Direct +// ============================================================================== +void LOADERDECL Pos_ReadDirect_UByte() +{ + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU8() * posScale; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)DataReadU8() * posScale; + if (pVtxAttr->PosElements) + ((float*)VertexManager::s_pCurBufferPointer)[2] = (float)DataReadU8() * posScale; + else + ((float*)VertexManager::s_pCurBufferPointer)[2] = 1.0f; + LOG_VTX(); + VertexManager::s_pCurBufferPointer += 12; +} + +void LOADERDECL Pos_ReadDirect_Byte() +{ + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)DataReadU8() * posScale; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)DataReadU8() * posScale; + if (pVtxAttr->PosElements) + ((float*)VertexManager::s_pCurBufferPointer)[2] = (float)(s8)DataReadU8() * posScale; + else + ((float*)VertexManager::s_pCurBufferPointer)[2] = 1.0; + LOG_VTX(); + VertexManager::s_pCurBufferPointer += 12; +} + +void LOADERDECL Pos_ReadDirect_UShort() +{ + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU16() * posScale; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)DataReadU16() * posScale; + if (pVtxAttr->PosElements) + ((float*)VertexManager::s_pCurBufferPointer)[2] = (float)DataReadU16() * posScale; + else + ((float*)VertexManager::s_pCurBufferPointer)[2] = 1.0f; + LOG_VTX(); + VertexManager::s_pCurBufferPointer += 12; +} + +void LOADERDECL Pos_ReadDirect_Short() +{ + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)DataReadU16() * posScale; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)DataReadU16() * posScale; + if (pVtxAttr->PosElements) + ((float*)VertexManager::s_pCurBufferPointer)[2] = (float)(s16)DataReadU16() * posScale; + else + ((float*)VertexManager::s_pCurBufferPointer)[2] = 1.0f; + LOG_VTX(); + VertexManager::s_pCurBufferPointer += 12; +} + +void LOADERDECL Pos_ReadDirect_Float() +{ + // No need to use floating point here. + ((u32 *)VertexManager::s_pCurBufferPointer)[0] = DataReadU32(); + ((u32 *)VertexManager::s_pCurBufferPointer)[1] = DataReadU32(); + if (pVtxAttr->PosElements) + ((u32 *)VertexManager::s_pCurBufferPointer)[2] = DataReadU32(); + else + ((float*)VertexManager::s_pCurBufferPointer)[2] = 1.0f; + LOG_VTX(); + VertexManager::s_pCurBufferPointer += 12; +} + +#define Pos_ReadIndex_Byte(T) { \ + u32 iAddress = arraybases[ARRAY_POSITION] + ((u32)Index * arraystrides[ARRAY_POSITION]); \ + ((float*)VertexManager::s_pCurBufferPointer)[0] = ((float)(T)Memory_Read_U8(iAddress)) * posScale; \ + ((float*)VertexManager::s_pCurBufferPointer)[1] = ((float)(T)Memory_Read_U8(iAddress+1)) * posScale; \ + if (pVtxAttr->PosElements) \ + ((float*)VertexManager::s_pCurBufferPointer)[2] = ((float)(T)Memory_Read_U8(iAddress+2)) * posScale; \ + else \ + ((float*)VertexManager::s_pCurBufferPointer)[2] = 1.0f; \ + LOG_VTX(); \ + VertexManager::s_pCurBufferPointer += 12; \ +} + +#define Pos_ReadIndex_Short(T) { \ + u32 iAddress = arraybases[ARRAY_POSITION] + ((u32)Index * arraystrides[ARRAY_POSITION]); \ + ((float*)VertexManager::s_pCurBufferPointer)[0] = ((float)(T)Memory_Read_U16(iAddress)) * posScale; \ + ((float*)VertexManager::s_pCurBufferPointer)[1] = ((float)(T)Memory_Read_U16(iAddress+2)) * posScale; \ + if (pVtxAttr->PosElements) \ + ((float*)VertexManager::s_pCurBufferPointer)[2] = ((float)(T)Memory_Read_U16(iAddress+4)) * posScale; \ + else \ + ((float*)VertexManager::s_pCurBufferPointer)[2] = 1.0f; \ + LOG_VTX(); \ + VertexManager::s_pCurBufferPointer += 12; \ +} + +#define Pos_ReadIndex_Float() { \ + u32 iAddress = arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION]); \ + ((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress); \ + ((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress+4); \ + if (pVtxAttr->PosElements) \ + ((u32*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U32(iAddress+8); \ + else \ + ((float*)VertexManager::s_pCurBufferPointer)[2] = 1.0f; \ + LOG_VTX(); \ + VertexManager::s_pCurBufferPointer += 12; \ +} + +// ============================================================================== +// Index 8 +// ============================================================================== +void LOADERDECL Pos_ReadIndex8_UByte() +{ + u8 Index = DataReadU8(); + Pos_ReadIndex_Byte(u8); +} + +void LOADERDECL Pos_ReadIndex8_Byte() +{ + u8 Index = DataReadU8(); + Pos_ReadIndex_Byte(s8); +} + +void LOADERDECL Pos_ReadIndex8_UShort() +{ + u8 Index = DataReadU8(); + Pos_ReadIndex_Short(u16); +} + +void LOADERDECL Pos_ReadIndex8_Short() +{ + u8 Index = DataReadU8(); + Pos_ReadIndex_Short(s16); +} + +void LOADERDECL Pos_ReadIndex8_Float() +{ + u8 Index = DataReadU8(); + Pos_ReadIndex_Float(); +} + +// ============================================================================== +// Index 16 +// ============================================================================== + +void LOADERDECL Pos_ReadIndex16_UByte(){ + u16 Index = DataReadU16(); + Pos_ReadIndex_Byte(u8); +} + +void LOADERDECL Pos_ReadIndex16_Byte(){ + u16 Index = DataReadU16(); + Pos_ReadIndex_Byte(s8); +} + +void LOADERDECL Pos_ReadIndex16_UShort(){ + u16 Index = DataReadU16(); + Pos_ReadIndex_Short(u16); +} + +void LOADERDECL Pos_ReadIndex16_Short() +{ + u16 Index = DataReadU16(); + Pos_ReadIndex_Short(s16); +} + +void LOADERDECL Pos_ReadIndex16_Float() +{ + u16 Index = DataReadU16(); + Pos_ReadIndex_Float(); +} + +#endif diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader_TextCoord.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader_TextCoord.cpp index bc0125bcc6..01f1fe56ad 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader_TextCoord.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader_TextCoord.cpp @@ -1,337 +1,337 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifndef VERTEXLOADER_TEXCOORD_H -#define VERTEXLOADER_TEXCOORD_H - -#include "Globals.h" -#include "VertexLoader.h" -#include "VertexManager.h" -#include "VertexLoader_Position.h" - -#define LOG_TEX1() PRIM_LOG("tex: %f, ", ((float*)VertexManager::s_pCurBufferPointer)[0]); -#define LOG_TEX2() PRIM_LOG("tex: %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[0], ((float*)VertexManager::s_pCurBufferPointer)[1]); - -extern int tcIndex; -extern float tcScale[8]; - -void LOADERDECL TexCoord_Read_Dummy() -{ - tcIndex++; -} - -void LOADERDECL TexCoord_ReadDirect_UByte1() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU8() * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadDirect_UByte2() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU8() * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)DataReadU8() * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadDirect_Byte1() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)DataReadU8() * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadDirect_Byte2() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)DataReadU8() * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)DataReadU8() * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadDirect_UShort1() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU16() * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadDirect_UShort2() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU16() * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)DataReadU16() * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadDirect_Short1() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)DataReadU16() * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadDirect_Short2() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)DataReadU16() * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)DataReadU16() * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadDirect_Float1() -{ - ((u32*)VertexManager::s_pCurBufferPointer)[0] = DataReadU32(); - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadDirect_Float2() -{ - ((u32*)VertexManager::s_pCurBufferPointer)[0] = DataReadU32(); - ((u32*)VertexManager::s_pCurBufferPointer)[1] = DataReadU32(); - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -// ================================================================================== -void LOADERDECL TexCoord_ReadIndex8_UByte1() -{ - u8 Index = DataReadU8(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)Memory_Read_U8(iAddress) * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex8_UByte2() -{ - u8 Index = DataReadU8(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)Memory_Read_U8(iAddress) * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u8)Memory_Read_U8(iAddress+1) * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex8_Byte1() -{ - u8 Index = DataReadU8(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)Memory_Read_U8(iAddress) * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex8_Byte2() -{ - u8 Index = DataReadU8(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)Memory_Read_U8(iAddress) * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)Memory_Read_U8(iAddress+1) * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex8_UShort1() -{ - u8 Index = DataReadU8(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Memory_Read_U16(iAddress) * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex8_UShort2() -{ - u8 Index = DataReadU8(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Memory_Read_U16(iAddress) * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u16)Memory_Read_U16(iAddress+2) * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex8_Short1() -{ - u8 Index = DataReadU8(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Memory_Read_U16(iAddress) * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex8_Short2() -{ - u8 Index = DataReadU8(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Memory_Read_U16(iAddress) * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)Memory_Read_U16(iAddress+2) * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex8_Float1() -{ - u16 Index = DataReadU8(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - ((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress); - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex8_Float2() -{ - u16 Index = DataReadU8(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - ((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress); - ((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress+4); - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -// ================================================================================== -void LOADERDECL TexCoord_ReadIndex16_UByte1() -{ - u16 Index = DataReadU16(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)Memory_Read_U8(iAddress) * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex16_UByte2() -{ - u16 Index = DataReadU16(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)Memory_Read_U8(iAddress) * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u8)Memory_Read_U8(iAddress+1) * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex16_Byte1() -{ - u16 Index = DataReadU16(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)Memory_Read_U8(iAddress) * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex16_Byte2() -{ - u16 Index = DataReadU16(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)Memory_Read_U8(iAddress) * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)Memory_Read_U8(iAddress+1) * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex16_UShort1() -{ - u16 Index = DataReadU16(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Memory_Read_U16(iAddress) * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex16_UShort2() -{ - u16 Index = DataReadU16(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Memory_Read_U16(iAddress) * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u16)Memory_Read_U16(iAddress+2) * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex16_Short1() -{ - u16 Index = DataReadU16(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Memory_Read_U16(iAddress) * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex16_Short2() -{ - u16 Index = DataReadU16(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Memory_Read_U16(iAddress) * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)Memory_Read_U16(iAddress+2) * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex16_Float1() -{ - u16 Index = DataReadU16(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress); - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex16_Float2() -{ - u16 Index = DataReadU16(); - u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress); - ((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress + 4); - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -#endif +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef VERTEXLOADER_TEXCOORD_H +#define VERTEXLOADER_TEXCOORD_H + +#include "Globals.h" +#include "VertexLoader.h" +#include "VertexManager.h" +#include "VertexLoader_Position.h" + +#define LOG_TEX1() PRIM_LOG("tex: %f, ", ((float*)VertexManager::s_pCurBufferPointer)[0]); +#define LOG_TEX2() PRIM_LOG("tex: %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[0], ((float*)VertexManager::s_pCurBufferPointer)[1]); + +extern int tcIndex; +extern float tcScale[8]; + +void LOADERDECL TexCoord_Read_Dummy() +{ + tcIndex++; +} + +void LOADERDECL TexCoord_ReadDirect_UByte1() +{ + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU8() * tcScale[tcIndex]; + LOG_TEX1(); + VertexManager::s_pCurBufferPointer += 4; + tcIndex++; +} +void LOADERDECL TexCoord_ReadDirect_UByte2() +{ + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU8() * tcScale[tcIndex]; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)DataReadU8() * tcScale[tcIndex]; + LOG_TEX2(); + VertexManager::s_pCurBufferPointer += 8; + tcIndex++; +} + +void LOADERDECL TexCoord_ReadDirect_Byte1() +{ + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)DataReadU8() * tcScale[tcIndex]; + LOG_TEX1(); + VertexManager::s_pCurBufferPointer += 4; + tcIndex++; +} +void LOADERDECL TexCoord_ReadDirect_Byte2() +{ + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)DataReadU8() * tcScale[tcIndex]; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)DataReadU8() * tcScale[tcIndex]; + LOG_TEX2(); + VertexManager::s_pCurBufferPointer += 8; + tcIndex++; +} + +void LOADERDECL TexCoord_ReadDirect_UShort1() +{ + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU16() * tcScale[tcIndex]; + LOG_TEX1(); + VertexManager::s_pCurBufferPointer += 4; + tcIndex++; +} +void LOADERDECL TexCoord_ReadDirect_UShort2() +{ + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU16() * tcScale[tcIndex]; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)DataReadU16() * tcScale[tcIndex]; + LOG_TEX2(); + VertexManager::s_pCurBufferPointer += 8; + tcIndex++; +} + +void LOADERDECL TexCoord_ReadDirect_Short1() +{ + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)DataReadU16() * tcScale[tcIndex]; + LOG_TEX1(); + VertexManager::s_pCurBufferPointer += 4; + tcIndex++; +} +void LOADERDECL TexCoord_ReadDirect_Short2() +{ + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)DataReadU16() * tcScale[tcIndex]; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)DataReadU16() * tcScale[tcIndex]; + LOG_TEX2(); + VertexManager::s_pCurBufferPointer += 8; + tcIndex++; +} + +void LOADERDECL TexCoord_ReadDirect_Float1() +{ + ((u32*)VertexManager::s_pCurBufferPointer)[0] = DataReadU32(); + LOG_TEX1(); + VertexManager::s_pCurBufferPointer += 4; + tcIndex++; +} +void LOADERDECL TexCoord_ReadDirect_Float2() +{ + ((u32*)VertexManager::s_pCurBufferPointer)[0] = DataReadU32(); + ((u32*)VertexManager::s_pCurBufferPointer)[1] = DataReadU32(); + LOG_TEX2(); + VertexManager::s_pCurBufferPointer += 8; + tcIndex++; +} + +// ================================================================================== +void LOADERDECL TexCoord_ReadIndex8_UByte1() +{ + u8 Index = DataReadU8(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)Memory_Read_U8(iAddress) * tcScale[tcIndex]; + LOG_TEX1(); + VertexManager::s_pCurBufferPointer += 4; + tcIndex++; +} +void LOADERDECL TexCoord_ReadIndex8_UByte2() +{ + u8 Index = DataReadU8(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)Memory_Read_U8(iAddress) * tcScale[tcIndex]; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u8)Memory_Read_U8(iAddress+1) * tcScale[tcIndex]; + LOG_TEX2(); + VertexManager::s_pCurBufferPointer += 8; + tcIndex++; +} + +void LOADERDECL TexCoord_ReadIndex8_Byte1() +{ + u8 Index = DataReadU8(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)Memory_Read_U8(iAddress) * tcScale[tcIndex]; + LOG_TEX1(); + VertexManager::s_pCurBufferPointer += 4; + tcIndex++; +} +void LOADERDECL TexCoord_ReadIndex8_Byte2() +{ + u8 Index = DataReadU8(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)Memory_Read_U8(iAddress) * tcScale[tcIndex]; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)Memory_Read_U8(iAddress+1) * tcScale[tcIndex]; + LOG_TEX2(); + VertexManager::s_pCurBufferPointer += 8; + tcIndex++; +} + +void LOADERDECL TexCoord_ReadIndex8_UShort1() +{ + u8 Index = DataReadU8(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Memory_Read_U16(iAddress) * tcScale[tcIndex]; + LOG_TEX1(); + VertexManager::s_pCurBufferPointer += 4; + tcIndex++; +} +void LOADERDECL TexCoord_ReadIndex8_UShort2() +{ + u8 Index = DataReadU8(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Memory_Read_U16(iAddress) * tcScale[tcIndex]; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u16)Memory_Read_U16(iAddress+2) * tcScale[tcIndex]; + LOG_TEX2(); + VertexManager::s_pCurBufferPointer += 8; + tcIndex++; +} + +void LOADERDECL TexCoord_ReadIndex8_Short1() +{ + u8 Index = DataReadU8(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Memory_Read_U16(iAddress) * tcScale[tcIndex]; + LOG_TEX1(); + VertexManager::s_pCurBufferPointer += 4; + tcIndex++; +} +void LOADERDECL TexCoord_ReadIndex8_Short2() +{ + u8 Index = DataReadU8(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Memory_Read_U16(iAddress) * tcScale[tcIndex]; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)Memory_Read_U16(iAddress+2) * tcScale[tcIndex]; + LOG_TEX2(); + VertexManager::s_pCurBufferPointer += 8; + tcIndex++; +} + +void LOADERDECL TexCoord_ReadIndex8_Float1() +{ + u16 Index = DataReadU8(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + ((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress); + LOG_TEX1(); + VertexManager::s_pCurBufferPointer += 4; + tcIndex++; +} +void LOADERDECL TexCoord_ReadIndex8_Float2() +{ + u16 Index = DataReadU8(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + ((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress); + ((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress+4); + LOG_TEX2(); + VertexManager::s_pCurBufferPointer += 8; + tcIndex++; +} + +// ================================================================================== +void LOADERDECL TexCoord_ReadIndex16_UByte1() +{ + u16 Index = DataReadU16(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)Memory_Read_U8(iAddress) * tcScale[tcIndex]; + LOG_TEX1(); + VertexManager::s_pCurBufferPointer += 4; + tcIndex++; +} +void LOADERDECL TexCoord_ReadIndex16_UByte2() +{ + u16 Index = DataReadU16(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)Memory_Read_U8(iAddress) * tcScale[tcIndex]; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u8)Memory_Read_U8(iAddress+1) * tcScale[tcIndex]; + LOG_TEX2(); + VertexManager::s_pCurBufferPointer += 8; + tcIndex++; +} + +void LOADERDECL TexCoord_ReadIndex16_Byte1() +{ + u16 Index = DataReadU16(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)Memory_Read_U8(iAddress) * tcScale[tcIndex]; + LOG_TEX1(); + VertexManager::s_pCurBufferPointer += 4; + tcIndex++; +} +void LOADERDECL TexCoord_ReadIndex16_Byte2() +{ + u16 Index = DataReadU16(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)Memory_Read_U8(iAddress) * tcScale[tcIndex]; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)Memory_Read_U8(iAddress+1) * tcScale[tcIndex]; + LOG_TEX2(); + VertexManager::s_pCurBufferPointer += 8; + tcIndex++; +} + +void LOADERDECL TexCoord_ReadIndex16_UShort1() +{ + u16 Index = DataReadU16(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Memory_Read_U16(iAddress) * tcScale[tcIndex]; + LOG_TEX1(); + VertexManager::s_pCurBufferPointer += 4; + tcIndex++; +} +void LOADERDECL TexCoord_ReadIndex16_UShort2() +{ + u16 Index = DataReadU16(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Memory_Read_U16(iAddress) * tcScale[tcIndex]; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u16)Memory_Read_U16(iAddress+2) * tcScale[tcIndex]; + LOG_TEX2(); + VertexManager::s_pCurBufferPointer += 8; + tcIndex++; +} + +void LOADERDECL TexCoord_ReadIndex16_Short1() +{ + u16 Index = DataReadU16(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Memory_Read_U16(iAddress) * tcScale[tcIndex]; + LOG_TEX1(); + VertexManager::s_pCurBufferPointer += 4; + tcIndex++; +} +void LOADERDECL TexCoord_ReadIndex16_Short2() +{ + u16 Index = DataReadU16(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Memory_Read_U16(iAddress) * tcScale[tcIndex]; + ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)Memory_Read_U16(iAddress+2) * tcScale[tcIndex]; + LOG_TEX2(); + VertexManager::s_pCurBufferPointer += 8; + tcIndex++; +} + +void LOADERDECL TexCoord_ReadIndex16_Float1() +{ + u16 Index = DataReadU16(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress); + LOG_TEX1(); + VertexManager::s_pCurBufferPointer += 4; + tcIndex++; +} +void LOADERDECL TexCoord_ReadIndex16_Float2() +{ + u16 Index = DataReadU16(); + u32 iAddress = arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); + + ((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress); + ((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress + 4); + LOG_TEX2(); + VertexManager::s_pCurBufferPointer += 8; + tcIndex++; +} + +#endif diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index c7461cc7b2..eb41aa7683 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -1,379 +1,379 @@ -#include "Globals.h" - -#include -#include - -#include "Config.h" -#include "Statistics.h" -#include "MemoryUtil.h" -#include "Profiler.h" -#include "Render.h" -#include "ImageWrite.h" -#include "BPMemory.h" -#include "TextureMngr.h" -#include "PixelShaderManager.h" -#include "VertexShaderManager.h" -#include "VertexShader.h" -#include "VertexLoader.h" -#include "VertexManager.h" - -#define MAX_BUFFER_SIZE 0x4000 - -// internal state for loading vertices -extern NativeVertexFormat *g_nativeVertexFmt; - -namespace VertexManager -{ - -static GLuint s_vboBuffers[0x40] = {0}; -static int s_nCurVBOIndex = 0; // current free buffer -static u8 *s_pBaseBufferPointer = NULL; -static std::vector< std::pair > s_vStoredPrimitives; // every element, mode and count to be passed to glDrawArrays -static u32 s_prevcomponents; // previous state set - -u8* s_pCurBufferPointer = NULL; - - -static const GLenum c_primitiveType[8] = -{ - GL_QUADS, - 0, //nothing - GL_TRIANGLES, - GL_TRIANGLE_STRIP, - GL_TRIANGLE_FAN, - GL_LINES, - GL_LINE_STRIP, - GL_POINTS -}; - -bool Init() -{ - s_prevcomponents = 0; - s_pBaseBufferPointer = (u8*)AllocateMemoryPages(MAX_BUFFER_SIZE); - s_pCurBufferPointer = s_pBaseBufferPointer; - - s_nCurVBOIndex = 0; - glGenBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers); - for (u32 i = 0; i < ARRAYSIZE(s_vboBuffers); ++i) { - glBindBuffer(GL_ARRAY_BUFFER, s_vboBuffers[i]); - glBufferData(GL_ARRAY_BUFFER, MAX_BUFFER_SIZE, NULL, GL_STREAM_DRAW); - } - - glEnableClientState(GL_VERTEX_ARRAY); - g_nativeVertexFmt = NULL; - s_vStoredPrimitives.reserve(1000); - GL_REPORT_ERRORD(); - - return true; -} - -void Shutdown() -{ - FreeMemoryPages(s_pBaseBufferPointer, MAX_BUFFER_SIZE); s_pBaseBufferPointer = s_pCurBufferPointer = NULL; - glDeleteBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers); - memset(s_vboBuffers, 0, sizeof(s_vboBuffers)); - - s_vStoredPrimitives.resize(0); - s_nCurVBOIndex = 0; - ResetBuffer(); -} - -void ResetBuffer() -{ - s_nCurVBOIndex = (s_nCurVBOIndex + 1) % ARRAYSIZE(s_vboBuffers); - s_pCurBufferPointer = s_pBaseBufferPointer; - s_vStoredPrimitives.resize(0); -} - -int GetRemainingSize() -{ - return MAX_BUFFER_SIZE - (int)(s_pCurBufferPointer - s_pBaseBufferPointer); -} - -void AddVertices(int primitive, int numvertices) -{ - _assert_( numvertices > 0 ); - - ADDSTAT(stats.thisFrame.numPrims, numvertices); - if (s_vStoredPrimitives.size() && s_vStoredPrimitives[s_vStoredPrimitives.size() - 1].first == c_primitiveType[primitive]) { - // We can join primitives for free here. Not likely to help much, though, but whatever... - if (c_primitiveType[primitive] == GL_TRIANGLES || - c_primitiveType[primitive] == GL_LINES || - c_primitiveType[primitive] == GL_POINTS || - c_primitiveType[primitive] == GL_QUADS) { - INCSTAT(stats.thisFrame.numPrimitiveJoins); - // Easy join - std::pair &last_pair = s_vStoredPrimitives[s_vStoredPrimitives.size() - 1]; - last_pair.second += numvertices; - return; - } - // Joining strips is a lot more work but would bring more gain. Not sure if it's worth it though. - } - - s_vStoredPrimitives.push_back(std::pair(c_primitiveType[primitive], numvertices)); - -#if defined(_DEBUG) || defined(DEBUGFAST) - static const char *sprims[8] = {"quads", "nothing", "tris", "tstrip", "tfan", "lines", "lstrip", "points"}; - PRIM_LOG("prim: %s, c=%d\n", sprims[primitive], numvertices); -#endif -} - -void Flush() -{ - if (s_vStoredPrimitives.size() == 0) - return; - - _assert_(s_pCurBufferPointer != s_pBaseBufferPointer); - -#if defined(_DEBUG) || defined(DEBUGFAST) - PRIM_LOG("frame%d:\ncomps=0x%x, texgen=%d, numchan=%d, dualtex=%d, ztex=%d, cole=%d, alpe=%d, ze=%d\n", g_Config.iSaveTargetId, s_prevcomponents, xfregs.numTexGens, - xfregs.nNumChans, (int)xfregs.bEnableDualTexTransform, bpmem.ztex2.op, - bpmem.blendmode.colorupdate, bpmem.blendmode.alphaupdate, bpmem.zmode.updateenable); - for (int i = 0; i < xfregs.nNumChans; ++i) { - LitChannel* ch = &xfregs.colChans[i].color; - PRIM_LOG("colchan%d: matsrc=%d, light=0x%x, ambsrc=%d, diffunc=%d, attfunc=%d\n", i, ch->matsource, ch->GetFullLightMask(), ch->ambsource, ch->diffusefunc, ch->attnfunc); - ch = &xfregs.colChans[i].alpha; - PRIM_LOG("alpchan%d: matsrc=%d, light=0x%x, ambsrc=%d, diffunc=%d, attfunc=%d\n", i, ch->matsource, ch->GetFullLightMask(), ch->ambsource, ch->diffusefunc, ch->attnfunc); - } - - for (int i = 0; i < xfregs.numTexGens; ++i) { - TexMtxInfo tinfo = xfregs.texcoords[i].texmtxinfo; - if (tinfo.texgentype != XF_TEXGEN_EMBOSS_MAP ) tinfo.hex &= 0x7ff; - if (tinfo.texgentype != XF_TEXGEN_REGULAR ) tinfo.projection = 0; - - PRIM_LOG("txgen%d: proj=%d, input=%d, gentype=%d, srcrow=%d, embsrc=%d, emblght=%d, postmtx=%d, postnorm=%d\n", - i, tinfo.projection, tinfo.inputform, tinfo.texgentype, tinfo.sourcerow, tinfo.embosssourceshift, tinfo.embosslightshift, - xfregs.texcoords[i].postmtxinfo.index, xfregs.texcoords[i].postmtxinfo.normalize); - } - - PRIM_LOG("pixel: tev=%d, ind=%d, texgen=%d, dstalpha=%d, alphafunc=0x%x\n", bpmem.genMode.numtevstages+1, bpmem.genMode.numindstages, - bpmem.genMode.numtexgens, (u32)bpmem.dstalpha.enable, (bpmem.alphaFunc.hex>>16)&0xff); -#endif - - DVSTARTPROFILE(); - - GL_REPORT_ERRORD(); - - glBindBuffer(GL_ARRAY_BUFFER, s_vboBuffers[s_nCurVBOIndex]); - glBufferData(GL_ARRAY_BUFFER, s_pCurBufferPointer - s_pBaseBufferPointer, s_pBaseBufferPointer, GL_STREAM_DRAW); - GL_REPORT_ERRORD(); - - // setup the pointers - g_nativeVertexFmt->SetupVertexPointers(); - GL_REPORT_ERRORD(); - - // set the textures - { - DVSTARTSUBPROFILE("VertexManager::Flush:textures"); - - u32 usedtextures = 0; - for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i) { - if (bpmem.tevorders[i/2].getEnable(i & 1)) - usedtextures |= 1 << bpmem.tevorders[i/2].getTexMap(i & 1); - } - - if (bpmem.genMode.numindstages > 0) { - for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i) { - if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages) { - usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt); - } - } - } - - u32 nonpow2tex = 0; - for (int i = 0; i < 8; i++) { - if (usedtextures & (1 << i)) { - glActiveTexture(GL_TEXTURE0 + i); - - FourTexUnits &tex = bpmem.tex[i >> 2]; - TextureMngr::TCacheEntry* tentry = TextureMngr::Load(i, (tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5, - tex.texImage0[i&3].width+1, tex.texImage0[i&3].height+1, - tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, tex.texTlut[i&3].tlut_format); - - if (tentry != NULL) { - // texture loaded fine, set dims for pixel shader - if (tentry->isNonPow2) { - PixelShaderMngr::SetTexDims(i, tentry->w, tentry->h, tentry->mode.wrap_s, tentry->mode.wrap_t); - nonpow2tex |= 1 << i; - if (tentry->mode.wrap_s > 0) nonpow2tex |= 1 << (8 + i); - if (tentry->mode.wrap_t > 0) nonpow2tex |= 1 << (16 + i); - TextureMngr::EnableTexRECT(i); - } - // if texture is power of two, set to ones (since don't need scaling) - else - { - PixelShaderMngr::SetTexDims(i, tentry->w, tentry->h, 0, 0); - TextureMngr::EnableTex2D(i); - } - if (g_Config.iLog & CONF_PRIMLOG) { - // save the textures - char strfile[255]; - sprintf(strfile, "frames/tex%.3d_%d.tga", g_Config.iSaveTargetId, i); - SaveTexture(strfile, tentry->isNonPow2?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D, tentry->texture, tentry->w, tentry->h); - } - } - else { - ERROR_LOG("error loading tex\n"); - TextureMngr::DisableStage(i); // disable since won't be used - } - } - else { - TextureMngr::DisableStage(i); // disable since won't be used - } - } - - PixelShaderMngr::SetTexturesUsed(nonpow2tex); - } - - FRAGMENTSHADER* ps = PixelShaderMngr::GetShader(); - VERTEXSHADER* vs = VertexShaderMngr::GetShader(s_prevcomponents); - - bool bRestoreBuffers = false; - if (Renderer::GetZBufferTarget()) { - if (bpmem.zmode.updateenable) { - if (!bpmem.blendmode.colorupdate) { - Renderer::SetRenderMode(bpmem.blendmode.alphaupdate?Renderer::RM_ZBufferAlpha:Renderer::RM_ZBufferOnly); - } - } - else { - Renderer::SetRenderMode(Renderer::RM_Normal); - // remove temporarily - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - bRestoreBuffers = true; - } - } else { - Renderer::SetRenderMode(Renderer::RM_Normal); - } - - // set global constants - VertexShaderMngr::SetConstants(); - PixelShaderMngr::SetConstants(); - - // finally bind - - // TODO - cache progid, check if same as before. Maybe GL does this internally, though. - // This is the really annoying problem with GL - you never know whether it's worth caching stuff yourself. - if (vs) glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vs->glprogid); - if (ps) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ps->glprogid); // Lego Star Wars crashes here. - -#if defined(_DEBUG) || defined(DEBUGFAST) - PRIM_LOG("\n"); -#endif - - int offset = 0; - for (std::vector< std::pair >::const_iterator it = s_vStoredPrimitives.begin(); it != s_vStoredPrimitives.end(); ++it) - { - INCSTAT(stats.thisFrame.numDrawCalls); - glDrawArrays(it->first, offset, it->second); - offset += it->second; - } - -#if defined(_DEBUG) || defined(DEBUGFAST) - if (g_Config.iLog & CONF_PRIMLOG) { - // save the shaders - char strfile[255]; - sprintf(strfile, "frames/ps%.3d.txt", g_Config.iSaveTargetId); - std::ofstream fps(strfile); - fps << ps->strprog.c_str(); - sprintf(strfile, "frames/vs%.3d.txt", g_Config.iSaveTargetId); - std::ofstream fvs(strfile); - fvs << vs->strprog.c_str(); - } - - if (g_Config.iLog & CONF_SAVETARGETS) { - char str[128]; - sprintf(str, "frames/targ%.3d.tga", g_Config.iSaveTargetId); - Renderer::SaveRenderTarget(str, 0); - } -#endif - g_Config.iSaveTargetId++; - - GL_REPORT_ERRORD(); - - if (bRestoreBuffers) { - GLenum s_drawbuffers[2] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT}; - glDrawBuffers(2, s_drawbuffers); - Renderer::SetColorMask(); - } - - ResetBuffer(); -} - -// This should move into NativeVertexFormat -void EnableComponents(u32 components) -{ - if (s_prevcomponents != components) { - if (s_vStoredPrimitives.size() != 0) - VertexManager::Flush(); - - // matrices - if ((components & VB_HAS_POSMTXIDX) != (s_prevcomponents & VB_HAS_POSMTXIDX)) { - if (components & VB_HAS_POSMTXIDX) - glEnableVertexAttribArray(SHADER_POSMTX_ATTRIB); - else - glDisableVertexAttribArray(SHADER_POSMTX_ATTRIB); - } - - // normals - if ((components & VB_HAS_NRM0) != (s_prevcomponents & VB_HAS_NRM0)) { - if (components & VB_HAS_NRM0) - glEnableClientState(GL_NORMAL_ARRAY); - else - glDisableClientState(GL_NORMAL_ARRAY); - } - if ((components & VB_HAS_NRM1) != (s_prevcomponents & VB_HAS_NRM1)) { - if (components & VB_HAS_NRM1) { - glEnableVertexAttribArray(SHADER_NORM1_ATTRIB); - glEnableVertexAttribArray(SHADER_NORM2_ATTRIB); - } - else { - glDisableVertexAttribArray(SHADER_NORM1_ATTRIB); - glDisableVertexAttribArray(SHADER_NORM2_ATTRIB); - } - } - - // color - for (int i = 0; i < 2; ++i) { - if ((components & (VB_HAS_COL0 << i)) != (s_prevcomponents & (VB_HAS_COL0 << i))) { - if (components & (VB_HAS_COL0 << 0)) - glEnableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY); - else - glDisableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY); - } - } - - // tex - if (!g_Config.bDisableTexturing) { - for (int i = 0; i < 8; ++i) { - if ((components & (VB_HAS_UV0 << i)) != (s_prevcomponents & (VB_HAS_UV0 << i))) { - glClientActiveTexture(GL_TEXTURE0 + i); - if (components & (VB_HAS_UV0 << i)) - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - else - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } - } - } - else // Disable Texturing - { - for (int i = 0; i < 8; ++i) { - glClientActiveTexture(GL_TEXTURE0 + i); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } - } - - - // Disable Lighting - // TODO - move to better spot - if (g_Config.bDisableLighting) { - for (int i = 0; i < xfregs.nNumChans; i++) - { - xfregs.colChans[i].alpha.enablelighting = false; - xfregs.colChans[i].color.enablelighting = false; - } - } - s_prevcomponents = components; - } -} - -} // namespace +#include "Globals.h" + +#include +#include + +#include "Config.h" +#include "Statistics.h" +#include "MemoryUtil.h" +#include "Profiler.h" +#include "Render.h" +#include "ImageWrite.h" +#include "BPMemory.h" +#include "TextureMngr.h" +#include "PixelShaderManager.h" +#include "VertexShaderManager.h" +#include "VertexShader.h" +#include "VertexLoader.h" +#include "VertexManager.h" + +#define MAX_BUFFER_SIZE 0x4000 + +// internal state for loading vertices +extern NativeVertexFormat *g_nativeVertexFmt; + +namespace VertexManager +{ + +static GLuint s_vboBuffers[0x40] = {0}; +static int s_nCurVBOIndex = 0; // current free buffer +static u8 *s_pBaseBufferPointer = NULL; +static std::vector< std::pair > s_vStoredPrimitives; // every element, mode and count to be passed to glDrawArrays +static u32 s_prevcomponents; // previous state set + +u8* s_pCurBufferPointer = NULL; + + +static const GLenum c_primitiveType[8] = +{ + GL_QUADS, + 0, //nothing + GL_TRIANGLES, + GL_TRIANGLE_STRIP, + GL_TRIANGLE_FAN, + GL_LINES, + GL_LINE_STRIP, + GL_POINTS +}; + +bool Init() +{ + s_prevcomponents = 0; + s_pBaseBufferPointer = (u8*)AllocateMemoryPages(MAX_BUFFER_SIZE); + s_pCurBufferPointer = s_pBaseBufferPointer; + + s_nCurVBOIndex = 0; + glGenBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers); + for (u32 i = 0; i < ARRAYSIZE(s_vboBuffers); ++i) { + glBindBuffer(GL_ARRAY_BUFFER, s_vboBuffers[i]); + glBufferData(GL_ARRAY_BUFFER, MAX_BUFFER_SIZE, NULL, GL_STREAM_DRAW); + } + + glEnableClientState(GL_VERTEX_ARRAY); + g_nativeVertexFmt = NULL; + s_vStoredPrimitives.reserve(1000); + GL_REPORT_ERRORD(); + + return true; +} + +void Shutdown() +{ + FreeMemoryPages(s_pBaseBufferPointer, MAX_BUFFER_SIZE); s_pBaseBufferPointer = s_pCurBufferPointer = NULL; + glDeleteBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers); + memset(s_vboBuffers, 0, sizeof(s_vboBuffers)); + + s_vStoredPrimitives.resize(0); + s_nCurVBOIndex = 0; + ResetBuffer(); +} + +void ResetBuffer() +{ + s_nCurVBOIndex = (s_nCurVBOIndex + 1) % ARRAYSIZE(s_vboBuffers); + s_pCurBufferPointer = s_pBaseBufferPointer; + s_vStoredPrimitives.resize(0); +} + +int GetRemainingSize() +{ + return MAX_BUFFER_SIZE - (int)(s_pCurBufferPointer - s_pBaseBufferPointer); +} + +void AddVertices(int primitive, int numvertices) +{ + _assert_( numvertices > 0 ); + + ADDSTAT(stats.thisFrame.numPrims, numvertices); + if (s_vStoredPrimitives.size() && s_vStoredPrimitives[s_vStoredPrimitives.size() - 1].first == c_primitiveType[primitive]) { + // We can join primitives for free here. Not likely to help much, though, but whatever... + if (c_primitiveType[primitive] == GL_TRIANGLES || + c_primitiveType[primitive] == GL_LINES || + c_primitiveType[primitive] == GL_POINTS || + c_primitiveType[primitive] == GL_QUADS) { + INCSTAT(stats.thisFrame.numPrimitiveJoins); + // Easy join + std::pair &last_pair = s_vStoredPrimitives[s_vStoredPrimitives.size() - 1]; + last_pair.second += numvertices; + return; + } + // Joining strips is a lot more work but would bring more gain. Not sure if it's worth it though. + } + + s_vStoredPrimitives.push_back(std::pair(c_primitiveType[primitive], numvertices)); + +#if defined(_DEBUG) || defined(DEBUGFAST) + static const char *sprims[8] = {"quads", "nothing", "tris", "tstrip", "tfan", "lines", "lstrip", "points"}; + PRIM_LOG("prim: %s, c=%d\n", sprims[primitive], numvertices); +#endif +} + +void Flush() +{ + if (s_vStoredPrimitives.size() == 0) + return; + + _assert_(s_pCurBufferPointer != s_pBaseBufferPointer); + +#if defined(_DEBUG) || defined(DEBUGFAST) + PRIM_LOG("frame%d:\ncomps=0x%x, texgen=%d, numchan=%d, dualtex=%d, ztex=%d, cole=%d, alpe=%d, ze=%d\n", g_Config.iSaveTargetId, s_prevcomponents, xfregs.numTexGens, + xfregs.nNumChans, (int)xfregs.bEnableDualTexTransform, bpmem.ztex2.op, + bpmem.blendmode.colorupdate, bpmem.blendmode.alphaupdate, bpmem.zmode.updateenable); + for (int i = 0; i < xfregs.nNumChans; ++i) { + LitChannel* ch = &xfregs.colChans[i].color; + PRIM_LOG("colchan%d: matsrc=%d, light=0x%x, ambsrc=%d, diffunc=%d, attfunc=%d\n", i, ch->matsource, ch->GetFullLightMask(), ch->ambsource, ch->diffusefunc, ch->attnfunc); + ch = &xfregs.colChans[i].alpha; + PRIM_LOG("alpchan%d: matsrc=%d, light=0x%x, ambsrc=%d, diffunc=%d, attfunc=%d\n", i, ch->matsource, ch->GetFullLightMask(), ch->ambsource, ch->diffusefunc, ch->attnfunc); + } + + for (int i = 0; i < xfregs.numTexGens; ++i) { + TexMtxInfo tinfo = xfregs.texcoords[i].texmtxinfo; + if (tinfo.texgentype != XF_TEXGEN_EMBOSS_MAP ) tinfo.hex &= 0x7ff; + if (tinfo.texgentype != XF_TEXGEN_REGULAR ) tinfo.projection = 0; + + PRIM_LOG("txgen%d: proj=%d, input=%d, gentype=%d, srcrow=%d, embsrc=%d, emblght=%d, postmtx=%d, postnorm=%d\n", + i, tinfo.projection, tinfo.inputform, tinfo.texgentype, tinfo.sourcerow, tinfo.embosssourceshift, tinfo.embosslightshift, + xfregs.texcoords[i].postmtxinfo.index, xfregs.texcoords[i].postmtxinfo.normalize); + } + + PRIM_LOG("pixel: tev=%d, ind=%d, texgen=%d, dstalpha=%d, alphafunc=0x%x\n", bpmem.genMode.numtevstages+1, bpmem.genMode.numindstages, + bpmem.genMode.numtexgens, (u32)bpmem.dstalpha.enable, (bpmem.alphaFunc.hex>>16)&0xff); +#endif + + DVSTARTPROFILE(); + + GL_REPORT_ERRORD(); + + glBindBuffer(GL_ARRAY_BUFFER, s_vboBuffers[s_nCurVBOIndex]); + glBufferData(GL_ARRAY_BUFFER, s_pCurBufferPointer - s_pBaseBufferPointer, s_pBaseBufferPointer, GL_STREAM_DRAW); + GL_REPORT_ERRORD(); + + // setup the pointers + g_nativeVertexFmt->SetupVertexPointers(); + GL_REPORT_ERRORD(); + + // set the textures + { + DVSTARTSUBPROFILE("VertexManager::Flush:textures"); + + u32 usedtextures = 0; + for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i) { + if (bpmem.tevorders[i/2].getEnable(i & 1)) + usedtextures |= 1 << bpmem.tevorders[i/2].getTexMap(i & 1); + } + + if (bpmem.genMode.numindstages > 0) { + for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i) { + if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages) { + usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt); + } + } + } + + u32 nonpow2tex = 0; + for (int i = 0; i < 8; i++) { + if (usedtextures & (1 << i)) { + glActiveTexture(GL_TEXTURE0 + i); + + FourTexUnits &tex = bpmem.tex[i >> 2]; + TextureMngr::TCacheEntry* tentry = TextureMngr::Load(i, (tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5, + tex.texImage0[i&3].width+1, tex.texImage0[i&3].height+1, + tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, tex.texTlut[i&3].tlut_format); + + if (tentry != NULL) { + // texture loaded fine, set dims for pixel shader + if (tentry->isNonPow2) { + PixelShaderMngr::SetTexDims(i, tentry->w, tentry->h, tentry->mode.wrap_s, tentry->mode.wrap_t); + nonpow2tex |= 1 << i; + if (tentry->mode.wrap_s > 0) nonpow2tex |= 1 << (8 + i); + if (tentry->mode.wrap_t > 0) nonpow2tex |= 1 << (16 + i); + TextureMngr::EnableTexRECT(i); + } + // if texture is power of two, set to ones (since don't need scaling) + else + { + PixelShaderMngr::SetTexDims(i, tentry->w, tentry->h, 0, 0); + TextureMngr::EnableTex2D(i); + } + if (g_Config.iLog & CONF_PRIMLOG) { + // save the textures + char strfile[255]; + sprintf(strfile, "frames/tex%.3d_%d.tga", g_Config.iSaveTargetId, i); + SaveTexture(strfile, tentry->isNonPow2?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D, tentry->texture, tentry->w, tentry->h); + } + } + else { + ERROR_LOG("error loading tex\n"); + TextureMngr::DisableStage(i); // disable since won't be used + } + } + else { + TextureMngr::DisableStage(i); // disable since won't be used + } + } + + PixelShaderMngr::SetTexturesUsed(nonpow2tex); + } + + FRAGMENTSHADER* ps = PixelShaderMngr::GetShader(); + VERTEXSHADER* vs = VertexShaderMngr::GetShader(s_prevcomponents); + + bool bRestoreBuffers = false; + if (Renderer::GetZBufferTarget()) { + if (bpmem.zmode.updateenable) { + if (!bpmem.blendmode.colorupdate) { + Renderer::SetRenderMode(bpmem.blendmode.alphaupdate?Renderer::RM_ZBufferAlpha:Renderer::RM_ZBufferOnly); + } + } + else { + Renderer::SetRenderMode(Renderer::RM_Normal); + // remove temporarily + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + bRestoreBuffers = true; + } + } else { + Renderer::SetRenderMode(Renderer::RM_Normal); + } + + // set global constants + VertexShaderMngr::SetConstants(); + PixelShaderMngr::SetConstants(); + + // finally bind + + // TODO - cache progid, check if same as before. Maybe GL does this internally, though. + // This is the really annoying problem with GL - you never know whether it's worth caching stuff yourself. + if (vs) glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vs->glprogid); + if (ps) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ps->glprogid); // Lego Star Wars crashes here. + +#if defined(_DEBUG) || defined(DEBUGFAST) + PRIM_LOG("\n"); +#endif + + int offset = 0; + for (std::vector< std::pair >::const_iterator it = s_vStoredPrimitives.begin(); it != s_vStoredPrimitives.end(); ++it) + { + INCSTAT(stats.thisFrame.numDrawCalls); + glDrawArrays(it->first, offset, it->second); + offset += it->second; + } + +#if defined(_DEBUG) || defined(DEBUGFAST) + if (g_Config.iLog & CONF_PRIMLOG) { + // save the shaders + char strfile[255]; + sprintf(strfile, "frames/ps%.3d.txt", g_Config.iSaveTargetId); + std::ofstream fps(strfile); + fps << ps->strprog.c_str(); + sprintf(strfile, "frames/vs%.3d.txt", g_Config.iSaveTargetId); + std::ofstream fvs(strfile); + fvs << vs->strprog.c_str(); + } + + if (g_Config.iLog & CONF_SAVETARGETS) { + char str[128]; + sprintf(str, "frames/targ%.3d.tga", g_Config.iSaveTargetId); + Renderer::SaveRenderTarget(str, 0); + } +#endif + g_Config.iSaveTargetId++; + + GL_REPORT_ERRORD(); + + if (bRestoreBuffers) { + GLenum s_drawbuffers[2] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT}; + glDrawBuffers(2, s_drawbuffers); + Renderer::SetColorMask(); + } + + ResetBuffer(); +} + +// This should move into NativeVertexFormat +void EnableComponents(u32 components) +{ + if (s_prevcomponents != components) { + if (s_vStoredPrimitives.size() != 0) + VertexManager::Flush(); + + // matrices + if ((components & VB_HAS_POSMTXIDX) != (s_prevcomponents & VB_HAS_POSMTXIDX)) { + if (components & VB_HAS_POSMTXIDX) + glEnableVertexAttribArray(SHADER_POSMTX_ATTRIB); + else + glDisableVertexAttribArray(SHADER_POSMTX_ATTRIB); + } + + // normals + if ((components & VB_HAS_NRM0) != (s_prevcomponents & VB_HAS_NRM0)) { + if (components & VB_HAS_NRM0) + glEnableClientState(GL_NORMAL_ARRAY); + else + glDisableClientState(GL_NORMAL_ARRAY); + } + if ((components & VB_HAS_NRM1) != (s_prevcomponents & VB_HAS_NRM1)) { + if (components & VB_HAS_NRM1) { + glEnableVertexAttribArray(SHADER_NORM1_ATTRIB); + glEnableVertexAttribArray(SHADER_NORM2_ATTRIB); + } + else { + glDisableVertexAttribArray(SHADER_NORM1_ATTRIB); + glDisableVertexAttribArray(SHADER_NORM2_ATTRIB); + } + } + + // color + for (int i = 0; i < 2; ++i) { + if ((components & (VB_HAS_COL0 << i)) != (s_prevcomponents & (VB_HAS_COL0 << i))) { + if (components & (VB_HAS_COL0 << 0)) + glEnableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY); + else + glDisableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY); + } + } + + // tex + if (!g_Config.bDisableTexturing) { + for (int i = 0; i < 8; ++i) { + if ((components & (VB_HAS_UV0 << i)) != (s_prevcomponents & (VB_HAS_UV0 << i))) { + glClientActiveTexture(GL_TEXTURE0 + i); + if (components & (VB_HAS_UV0 << i)) + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + else + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + } + } + else // Disable Texturing + { + for (int i = 0; i < 8; ++i) { + glClientActiveTexture(GL_TEXTURE0 + i); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + } + + + // Disable Lighting + // TODO - move to better spot + if (g_Config.bDisableLighting) { + for (int i = 0; i < xfregs.nNumChans; i++) + { + xfregs.colChans[i].alpha.enablelighting = false; + xfregs.colChans[i].color.enablelighting = false; + } + } + s_prevcomponents = components; + } +} + +} // namespace diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderManager.cpp index fd02857bcc..48a5a7cc86 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderManager.cpp @@ -1,906 +1,906 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Globals.h" -#include "Profiler.h" -#include "Config.h" - -#include "GLUtil.h" - -#include -#include - -#include - -#include "Statistics.h" -#include "ImageWrite.h" -#include "Render.h" -#include "VertexShader.h" -#include "VertexShaderManager.h" -#include "VertexManager.h" -#include "VertexLoader.h" -#include "BPMemory.h" -#include "XFMemory.h" - -VertexShaderMngr::VSCache VertexShaderMngr::vshaders; -VERTEXSHADER* VertexShaderMngr::pShaderLast = NULL; - -float GC_ALIGNED16(g_fProjectionMatrix[16]); - -extern int A, B; -extern float AR; -extern int nBackbufferWidth, nBackbufferHeight; - -// Internal Variables -static int s_nMaxVertexInstructions; - -static float s_fMaterials[16]; - -// track changes -static bool bTexMatricesChanged[2], bPosNormalMatrixChanged, bProjectionChanged, bViewportChanged; -static int nMaterialsChanged; -static int nTransformMatricesChanged[2]; // min,max -static int nNormalMatricesChanged[2]; // min,max -static int nPostTransformMatricesChanged[2]; // min,max -static int nLightsChanged[2]; // min,max - -void VertexShaderMngr::SetVSConstant4f(int const_number, float f1, float f2, float f3, float f4) { - glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, const_number, f1, f2, f3, f4); -} - -void VertexShaderMngr::SetVSConstant4fv(int const_number, const float *f) { - glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f); -} - -void VertexShaderMngr::Init() -{ - nTransformMatricesChanged[0] = nTransformMatricesChanged[1] = -1; - nNormalMatricesChanged[0] = nNormalMatricesChanged[1] = -1; - nPostTransformMatricesChanged[0] = nPostTransformMatricesChanged[1] = -1; - nLightsChanged[0] = nLightsChanged[1] = -1; - bTexMatricesChanged[0] = bTexMatricesChanged[1] = false; - bPosNormalMatrixChanged = bProjectionChanged = bViewportChanged = false; - nMaterialsChanged = 0; - - memset(&xfregs, 0, sizeof(xfregs)); - memset(xfmem, 0, sizeof(xfmem)); - - glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&s_nMaxVertexInstructions); -} - -void VertexShaderMngr::Shutdown() -{ - for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); iter++) - iter->second.Destroy(); - vshaders.clear(); -} - -float VertexShaderMngr::GetPixelAspectRatio() { - return xfregs.rawViewport[0] != 0 ? (float)Renderer::GetTargetWidth() / 640.0f : 1.0f; -} - -VERTEXSHADER* VertexShaderMngr::GetShader(u32 components) -{ - DVSTARTPROFILE(); - VERTEXSHADERUID uid; - GetVertexShaderId(uid, components); - - VSCache::iterator iter = vshaders.find(uid); - - if (iter != vshaders.end()) { - iter->second.frameCount = frameCount; - VSCacheEntry &entry = iter->second; - if (&entry.shader != pShaderLast) { - pShaderLast = &entry.shader; - } - return pShaderLast; - } - - VSCacheEntry& entry = vshaders[uid]; - char *code = GenerateVertexShader(components, Renderer::GetZBufferTarget() != 0); - -#if defined(_DEBUG) || defined(DEBUGFAST) - if (g_Config.iLog & CONF_SAVESHADERS && code) { - static int counter = 0; - char szTemp[MAX_PATH]; - sprintf(szTemp, "%s/vs_%04i.txt", g_Config.texDumpPath, counter++); - - SaveData(szTemp, code); - } -#endif - - if (!code || !VertexShaderMngr::CompileVertexShader(entry.shader, code)) { - ERROR_LOG("failed to create vertex shader\n"); - return NULL; - } - - //Make an entry in the table - entry.frameCount=frameCount; - - pShaderLast = &entry.shader; - INCSTAT(stats.numVertexShadersCreated); - SETSTAT(stats.numVertexShadersAlive,vshaders.size()); - return pShaderLast; -} - -void VertexShaderMngr::Cleanup() -{ - VSCache::iterator iter=vshaders.begin(); - while (iter != vshaders.end()) { - VSCacheEntry &entry = iter->second; - if (entry.frameCount < frameCount-200) { - entry.Destroy(); -#ifdef _WIN32 - iter = vshaders.erase(iter); -#else - vshaders.erase(iter++); -#endif - } - else { - ++iter; - } - } - -// static int frame = 0; -// if( frame++ > 30 ) { -// VSCache::iterator iter=vshaders.begin(); -// while(iter!=vshaders.end()) { -// iter->second.Destroy(); -// ++iter; -// } -// vshaders.clear(); -// } - - SETSTAT(stats.numPixelShadersAlive,vshaders.size()); -} - -bool VertexShaderMngr::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram) -{ - char stropt[64]; - sprintf(stropt, "MaxLocalParams=256,MaxInstructions=%d", s_nMaxVertexInstructions); - const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL}; - CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgvProf, "main", opts); - if (!cgIsProgram(tempprog) || cgGetError() != CG_NO_ERROR) { - ERROR_LOG("Failed to load vs %s:\n", cgGetLastListing(g_cgcontext)); - ERROR_LOG(pstrprogram); - return false; - } - - //ERROR_LOG(pstrprogram); - //ERROR_LOG("id: %d\n", g_Config.iSaveTargetId); - - char* pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM); - char* plocal = strstr(pcompiledprog, "program.local"); - - while (plocal != NULL) { - const char* penv = " program.env"; - memcpy(plocal, penv, 13); - plocal = strstr(plocal+13, "program.local"); - } - - glGenProgramsARB(1, &vs.glprogid); - glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vs.glprogid); - glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog); - - GLenum err = GL_NO_ERROR; - GL_REPORT_ERROR(); - if( err != GL_NO_ERROR ) { - ERROR_LOG(pstrprogram); - ERROR_LOG(pcompiledprog); - } - - cgDestroyProgram(tempprog); - // printf("Compiled vertex shader %i\n", vs.glprogid); - -#if defined(_DEBUG) || defined(DEBUGFAST) - vs.strprog = pstrprogram; -#endif - - return true; -} - -const u16 s_mtrltable[16][2] = {{0, 0}, {0, 1}, {1, 1}, {0, 2}, - {2, 1}, {0, 3}, {1, 2}, {0, 3}, - {3, 1}, {0, 4}, {1, 3}, {0, 4}, - {2, 2}, {0, 4}, {1, 3}, {0, 4}}; - - -// ======================================================================================= -// Syncs the shader constant buffers with xfmem -// ---------------- -void VertexShaderMngr::SetConstants() -{ - //nTransformMatricesChanged[0] = 0; nTransformMatricesChanged[1] = 256; - //nNormalMatricesChanged[0] = 0; nNormalMatricesChanged[1] = 96; - //nPostTransformMatricesChanged[0] = 0; nPostTransformMatricesChanged[1] = 256; - //nLightsChanged[0] = 0; nLightsChanged[1] = 0x80; - //bPosNormalMatrixChanged = true; - //bTexMatricesChanged[0] = bTexMatricesChanged[1] = true; - //bProjectionChanged = true; -// bPosNormalMatrixChanged = bTexMatricesChanged[0] = bTexMatricesChanged[1] = true; -// nMaterialsChanged = 15; - - if (nTransformMatricesChanged[0] >= 0) { - int startn = nTransformMatricesChanged[0]/4; - int endn = (nTransformMatricesChanged[1]+3)/4; - const float* pstart = (const float*)&xfmem[startn*4]; - for(int i = startn; i < endn; ++i, pstart += 4) - SetVSConstant4fv(C_TRANSFORMMATRICES+i, pstart); - nTransformMatricesChanged[0] = nTransformMatricesChanged[1] = -1; - } - if (nNormalMatricesChanged[0] >= 0) { - int startn = nNormalMatricesChanged[0]/3; - int endn = (nNormalMatricesChanged[1]+2)/3; - const float* pnstart = (const float*)&xfmem[XFMEM_NORMALMATRICES+3*startn]; - - for(int i = startn; i < endn; ++i, pnstart += 3) - SetVSConstant4fv(C_NORMALMATRICES+i, pnstart); - - nNormalMatricesChanged[0] = nNormalMatricesChanged[1] = -1; - } - - if (nPostTransformMatricesChanged[0] >= 0) { - int startn = nPostTransformMatricesChanged[0]/4; - int endn = (nPostTransformMatricesChanged[1]+3)/4; - const float* pstart = (const float*)&xfmem[XFMEM_POSTMATRICES + startn*4]; - for(int i = startn; i < endn; ++i, pstart += 4) - SetVSConstant4fv(C_POSTTRANSFORMMATRICES + i, pstart); - } - - if (nLightsChanged[0] >= 0) { - // lights don't have a 1 to 1 mapping, the color component needs to be converted to 4 floats - int istart = nLightsChanged[0] / 0x10; - int iend = (nLightsChanged[1] + 15) / 0x10; - const float* xfmemptr = (const float*)&xfmem[0x10*istart + XFMEM_LIGHTS]; - - for (int i = istart; i < iend; ++i) { - u32 color = *(const u32*)(xfmemptr + 3); - SetVSConstant4f(C_LIGHTS + 5*i, - ((color >> 24) & 0xFF)/255.0f, - ((color >> 16) & 0xFF)/255.0f, - ((color >> 8) & 0xFF)/255.0f, - ((color) & 0xFF)/255.0f); - xfmemptr += 4; - for (int j = 0; j < 4; ++j, xfmemptr += 3) { - if (j == 1 && - fabs(xfmemptr[0]) < 0.00001f && - fabs(xfmemptr[1]) < 0.00001f && - fabs(xfmemptr[2]) < 0.00001f) { - // dist attenuation, make sure not equal to 0!!! - SetVSConstant4f(C_LIGHTS+5*i+j+1, 0.00001f, xfmemptr[1], xfmemptr[2], 0); - } - else - SetVSConstant4fv(C_LIGHTS+5*i+j+1, xfmemptr); - } - } - - nLightsChanged[0] = nLightsChanged[1] = -1; - } - - if (nMaterialsChanged) { - for (int i = 0; i < 4; ++i) { - if (nMaterialsChanged & (1 << i)) - SetVSConstant4fv(C_MATERIALS + i, &s_fMaterials[4*i]); - } - nMaterialsChanged = 0; - } - - if (bPosNormalMatrixChanged) { - bPosNormalMatrixChanged = false; - - float* pos = (float*)xfmem + MatrixIndexA.PosNormalMtxIdx * 4; - float* norm = (float*)xfmem + XFMEM_NORMALMATRICES + 3 * (MatrixIndexA.PosNormalMtxIdx & 31); - - SetVSConstant4fv(C_POSNORMALMATRIX, pos); - SetVSConstant4fv(C_POSNORMALMATRIX+1, pos+4); - SetVSConstant4fv(C_POSNORMALMATRIX+2, pos+8); - SetVSConstant4fv(C_POSNORMALMATRIX+3, norm); - SetVSConstant4fv(C_POSNORMALMATRIX+4, norm+3); - SetVSConstant4fv(C_POSNORMALMATRIX+5, norm+6); - } - - if (bTexMatricesChanged[0]) { - bTexMatricesChanged[0] = false; - float* fptrs[] = { - (float*)xfmem + MatrixIndexA.Tex0MtxIdx * 4, (float*)xfmem + MatrixIndexA.Tex1MtxIdx * 4, - (float*)xfmem + MatrixIndexA.Tex2MtxIdx * 4, (float*)xfmem + MatrixIndexA.Tex3MtxIdx * 4 - }; - - for (int i = 0; i < 4; ++i) { - SetVSConstant4fv(C_TEXMATRICES+3*i, fptrs[i]); - SetVSConstant4fv(C_TEXMATRICES+3*i+1, fptrs[i]+4); - SetVSConstant4fv(C_TEXMATRICES+3*i+2, fptrs[i]+8); - } - } - - if (bTexMatricesChanged[1]) { - bTexMatricesChanged[1] = false; - - float* fptrs[] = {(float*)xfmem + MatrixIndexB.Tex4MtxIdx * 4, (float*)xfmem + MatrixIndexB.Tex5MtxIdx * 4, - (float*)xfmem + MatrixIndexB.Tex6MtxIdx * 4, (float*)xfmem + MatrixIndexB.Tex7MtxIdx * 4 }; - - for (int i = 0; i < 4; ++i) { - SetVSConstant4fv(C_TEXMATRICES+3*i+12, fptrs[i]); - SetVSConstant4fv(C_TEXMATRICES+3*i+12+1, fptrs[i]+4); - SetVSConstant4fv(C_TEXMATRICES+3*i+12+2, fptrs[i]+8); - } - } - - if (bViewportChanged) { - bViewportChanged = false; - - // reversed gxsetviewport(xorig, yorig, width, height, nearz, farz) - // [0] = width/2 - // [1] = height/2 - // [2] = 16777215 * (farz-nearz) - // [3] = xorig + width/2 + 342 - // [4] = yorig + height/2 + 342 - // [5] = 16777215 * farz - /*INFO_LOG("view: topleft=(%f,%f), wh=(%f,%f), z=(%f,%f)\n", - rawViewport[3]-rawViewport[0]-342, rawViewport[4]+rawViewport[1]-342, - 2 * rawViewport[0], 2 * rawViewport[1], - (rawViewport[5] - rawViewport[2]) / 16777215.0f, rawViewport[5] / 16777215.0f);*/ - - // Keep aspect ratio at 4:3 - // rawViewport[0] = 320, rawViewport[1] = -240 - int scissorXOff = bpmem.scissorOffset.x * 2 - 342; - int scissorYOff = bpmem.scissorOffset.y * 2 - 342; - float fourThree = 4.0f / 3.0f; - float ratio = AR / fourThree; - float wAdj, hAdj; - float actualRatiow, actualRatioh; - int overfl; - int xoffs = 0, yoffs = 0; - int wid, hei, actualWid, actualHei; - int winw = nBackbufferWidth; - int winh = nBackbufferHeight; - if (g_Config.bKeepAR) - { - // Check if height or width is the limiting factor - if (ratio > 1) // then we are to wide and have to limit the width - { - wAdj = ratio; - hAdj = 1; - - wid = ceil(fabs(2 * xfregs.rawViewport[0]) / wAdj); - hei = ceil(fabs(2 * xfregs.rawViewport[1]) / hAdj); - - actualWid = ceil((float)winw / ratio); - actualRatiow = (float)actualWid / (float)wid; // the picture versus the screen - overfl = (winw - actualWid) / actualRatiow; - xoffs = overfl / 2; - } - else // the window is to high, we have to limit the height - { - ratio = 1 / ratio; - - wAdj = 1; - hAdj = ratio; - - wid = ceil(fabs(2 * xfregs.rawViewport[0]) / wAdj); - hei = ceil(fabs(2 * xfregs.rawViewport[1]) / hAdj); - - actualHei = ceil((float)winh / ratio); - actualRatioh = (float)actualHei / (float)hei; // the picture versus the screen - overfl = (winh - actualHei) / actualRatioh; - yoffs = overfl / 2; - } - } - else - { - wid = ceil(fabs(2 * xfregs.rawViewport[0])); - hei = ceil(fabs(2 * xfregs.rawViewport[1])); - } - - if (g_Config.bStretchToFit) - { - glViewport( - (int)(xfregs.rawViewport[3]-xfregs.rawViewport[0]-342-scissorXOff) + xoffs, - Renderer::GetTargetHeight() - ((int)(xfregs.rawViewport[4]-xfregs.rawViewport[1]-342-scissorYOff)) + yoffs, - wid, // width - hei // height - ); - } - else - { - glViewport((int)(xfregs.rawViewport[3]-xfregs.rawViewport[0]-342-scissorXOff) * MValueX, - Renderer::GetTargetHeight()-((int)(xfregs.rawViewport[4]-xfregs.rawViewport[1]-342-scissorYOff)) * MValueY, - abs((int)(2 * xfregs.rawViewport[0])) * MValueX, abs((int)(2 * xfregs.rawViewport[1])) * MValueY); - } - glDepthRange((xfregs.rawViewport[5]- xfregs.rawViewport[2])/16777215.0f, xfregs.rawViewport[5]/16777215.0f); - } - - if (bProjectionChanged) { - bProjectionChanged = false; - - if (xfregs.rawProjection[6] == 0) { - g_fProjectionMatrix[0] = xfregs.rawProjection[0]; - g_fProjectionMatrix[1] = 0.0f; - g_fProjectionMatrix[2] = xfregs.rawProjection[1]; - g_fProjectionMatrix[3] = 0; - - g_fProjectionMatrix[4] = 0.0f; - g_fProjectionMatrix[5] = xfregs.rawProjection[2]; - g_fProjectionMatrix[6] = xfregs.rawProjection[3]; - g_fProjectionMatrix[7] = 0; - - g_fProjectionMatrix[8] = 0.0f; - g_fProjectionMatrix[9] = 0.0f; - g_fProjectionMatrix[10] = xfregs.rawProjection[4]; - - //---------Projection[11]--------- - // No hacks - if ((!g_Config.bProjectionHax1 && !g_Config.bProjectionHax2) || (g_Config.bProjectionHax1 && g_Config.bProjectionHax2)) - g_fProjectionMatrix[11] = -(0.0f - xfregs.rawProjection[5]); - - // Before R945 Hack - if(g_Config.bProjectionHax1 && !g_Config.bProjectionHax2) - g_fProjectionMatrix[11] = -(1.0f - xfregs.rawProjection[5]); - - // R844 Hack - if(!g_Config.bProjectionHax1 && g_Config.bProjectionHax2) - g_fProjectionMatrix[11] = xfregs.rawProjection[5]; - //-------------------------------- - - g_fProjectionMatrix[12] = 0.0f; - g_fProjectionMatrix[13] = 0.0f; - // donkopunchstania: GC GPU rounds differently? - // -(1 + epsilon) so objects are clipped as they are on the real HW - g_fProjectionMatrix[14] = -1.00000011921f; - g_fProjectionMatrix[15] = 0.0f; - } - else { - g_fProjectionMatrix[0] = xfregs.rawProjection[0]; - g_fProjectionMatrix[1] = 0.0f; - g_fProjectionMatrix[2] = 0.0f; - g_fProjectionMatrix[3] = xfregs.rawProjection[1]; - - g_fProjectionMatrix[4] = 0.0f; - g_fProjectionMatrix[5] = xfregs.rawProjection[2]; - g_fProjectionMatrix[6] = 0.0f; - g_fProjectionMatrix[7] = xfregs.rawProjection[3]; - - g_fProjectionMatrix[8] = 0.0f; - g_fProjectionMatrix[9] = 0.0f; - g_fProjectionMatrix[10] = xfregs.rawProjection[4]; - - //---------Projection[11]--------- - // No hacks - if ((!g_Config.bProjectionHax1 && !g_Config.bProjectionHax2) || (g_Config.bProjectionHax1 && g_Config.bProjectionHax2)) - g_fProjectionMatrix[11] = -(-1.0f - xfregs.rawProjection[5]); - - // Before R945 Hack - if (g_Config.bProjectionHax1 && !g_Config.bProjectionHax2) - g_fProjectionMatrix[11] = -(0.0f - xfregs.rawProjection[5]); - - // R844 Hack - if (!g_Config.bProjectionHax1 && g_Config.bProjectionHax2) - g_fProjectionMatrix[11] = -xfregs.rawProjection[5]; - - //-------------------------------- - - g_fProjectionMatrix[12] = 0; - g_fProjectionMatrix[13] = 0; - g_fProjectionMatrix[14] = 0.0f; - g_fProjectionMatrix[15] = 1.0f; - } - - PRIM_LOG("Projection: %f %f %f %f %f %f\n", xfregs.rawProjection[0], xfregs.rawProjection[1], xfregs.rawProjection[2], xfregs.rawProjection[3], xfregs.rawProjection[4], xfregs.rawProjection[5]); - SetVSConstant4fv(C_PROJECTION, &g_fProjectionMatrix[0]); - SetVSConstant4fv(C_PROJECTION+1, &g_fProjectionMatrix[4]); - SetVSConstant4fv(C_PROJECTION+2, &g_fProjectionMatrix[8]); - SetVSConstant4fv(C_PROJECTION+3, &g_fProjectionMatrix[12]); - } -} - -void VertexShaderMngr::InvalidateXFRange(int start, int end) -{ - if (((u32)start >= (u32)MatrixIndexA.PosNormalMtxIdx*4 && - (u32)start < (u32)MatrixIndexA.PosNormalMtxIdx*4 + 12) || - ((u32)start >= XFMEM_NORMALMATRICES + ((u32)MatrixIndexA.PosNormalMtxIdx & 31)*3 && - (u32)start < XFMEM_NORMALMATRICES + ((u32)MatrixIndexA.PosNormalMtxIdx & 31)*3 + 9)) { - bPosNormalMatrixChanged = true; - } - - if (((u32)start >= (u32)MatrixIndexA.Tex0MtxIdx*4 && (u32)start < (u32)MatrixIndexA.Tex0MtxIdx*4+12) || - ((u32)start >= (u32)MatrixIndexA.Tex1MtxIdx*4 && (u32)start < (u32)MatrixIndexA.Tex1MtxIdx*4+12) || - ((u32)start >= (u32)MatrixIndexA.Tex2MtxIdx*4 && (u32)start < (u32)MatrixIndexA.Tex2MtxIdx*4+12) || - ((u32)start >= (u32)MatrixIndexA.Tex3MtxIdx*4 && (u32)start < (u32)MatrixIndexA.Tex3MtxIdx*4+12)) { - bTexMatricesChanged[0] = true; - } - - if (((u32)start >= (u32)MatrixIndexB.Tex4MtxIdx*4 && (u32)start < (u32)MatrixIndexB.Tex4MtxIdx*4+12) || - ((u32)start >= (u32)MatrixIndexB.Tex5MtxIdx*4 && (u32)start < (u32)MatrixIndexB.Tex5MtxIdx*4+12) || - ((u32)start >= (u32)MatrixIndexB.Tex6MtxIdx*4 && (u32)start < (u32)MatrixIndexB.Tex6MtxIdx*4+12) || - ((u32)start >= (u32)MatrixIndexB.Tex7MtxIdx*4 && (u32)start < (u32)MatrixIndexB.Tex7MtxIdx*4+12)) { - bTexMatricesChanged[1] = true; - } - - if (start < XFMEM_POSMATRICES_END) { - if (nTransformMatricesChanged[0] == -1) { - nTransformMatricesChanged[0] = start; - nTransformMatricesChanged[1] = end>XFMEM_POSMATRICES_END?XFMEM_POSMATRICES_END:end; - } - else { - if (nTransformMatricesChanged[0] > start) nTransformMatricesChanged[0] = start; - if (nTransformMatricesChanged[1] < end) nTransformMatricesChanged[1] = end>XFMEM_POSMATRICES_END?XFMEM_POSMATRICES_END:end; - } - } - - if (start < XFMEM_NORMALMATRICES_END && end > XFMEM_NORMALMATRICES) { - int _start = start < XFMEM_NORMALMATRICES ? 0 : start-XFMEM_NORMALMATRICES; - int _end = end < XFMEM_NORMALMATRICES_END ? end-XFMEM_NORMALMATRICES : XFMEM_NORMALMATRICES_END-XFMEM_NORMALMATRICES; - - if (nNormalMatricesChanged[0] == -1 ) { - nNormalMatricesChanged[0] = _start; - nNormalMatricesChanged[1] = _end; - } - else { - if (nNormalMatricesChanged[0] > _start) nNormalMatricesChanged[0] = _start; - if (nNormalMatricesChanged[1] < _end) nNormalMatricesChanged[1] = _end; - } - } - - if (start < XFMEM_POSTMATRICES_END && end > XFMEM_POSTMATRICES) { - int _start = start < XFMEM_POSTMATRICES ? XFMEM_POSTMATRICES : start-XFMEM_POSTMATRICES; - int _end = end < XFMEM_POSTMATRICES_END ? end-XFMEM_POSTMATRICES : XFMEM_POSTMATRICES_END-XFMEM_POSTMATRICES; - - if (nPostTransformMatricesChanged[0] == -1 ) { - nPostTransformMatricesChanged[0] = _start; - nPostTransformMatricesChanged[1] = _end; - } - else { - if (nPostTransformMatricesChanged[0] > _start) nPostTransformMatricesChanged[0] = _start; - if (nPostTransformMatricesChanged[1] < _end) nPostTransformMatricesChanged[1] = _end; - } - } - - if (start < XFMEM_LIGHTS_END && end > XFMEM_LIGHTS) { - int _start = start < XFMEM_LIGHTS ? XFMEM_LIGHTS : start-XFMEM_LIGHTS; - int _end = end < XFMEM_LIGHTS_END ? end-XFMEM_LIGHTS : XFMEM_LIGHTS_END-XFMEM_LIGHTS; - - if (nLightsChanged[0] == -1 ) { - nLightsChanged[0] = _start; - nLightsChanged[1] = _end; - } - else { - if (nLightsChanged[0] > _start) nLightsChanged[0] = _start; - if (nLightsChanged[1] < _end) nLightsChanged[1] = _end; - } - } -} - -void VertexShaderMngr::SetTexMatrixChangedA(u32 Value) -{ - if (MatrixIndexA.Hex != Value) { - VertexManager::Flush(); - if (MatrixIndexA.PosNormalMtxIdx != (Value&0x3f)) - bPosNormalMatrixChanged = true; - bTexMatricesChanged[0] = true; - MatrixIndexA.Hex = Value; - } -} - -void VertexShaderMngr::SetTexMatrixChangedB(u32 Value) -{ - if (MatrixIndexB.Hex != Value) { - VertexManager::Flush(); - bTexMatricesChanged[1] = true; - MatrixIndexB.Hex = Value; - } -} - -void VertexShaderMngr::SetViewport(float* _Viewport) -{ - // Workaround for paper mario, yep this is bizarre. - for (size_t i = 0; i < ARRAYSIZE(xfregs.rawViewport); ++i) { - if (*(u32*)(_Viewport + i) == 0x7f800000) // invalid fp number - return; - } - memcpy(xfregs.rawViewport, _Viewport, sizeof(xfregs.rawViewport)); - bViewportChanged = true; -} - -void VertexShaderMngr::SetViewportChanged() -{ - bViewportChanged = true; -} - -void VertexShaderMngr::SetProjection(float* _pProjection, int constantIndex) -{ - memcpy(xfregs.rawProjection, _pProjection, sizeof(xfregs.rawProjection)); - bProjectionChanged = true; -} - -float* VertexShaderMngr::GetPosNormalMat() -{ - return (float*)xfmem + MatrixIndexA.PosNormalMtxIdx * 4; -} - -// Mash together all the inputs that contribute to the code of a generated vertex shader into -// a unique identifier, basically containing all the bits. Yup, it's a lot .... -void VertexShaderMngr::GetVertexShaderId(VERTEXSHADERUID& vid, u32 components) -{ - u32 zbufrender = (bpmem.ztex2.op == ZTEXTURE_ADD) || Renderer::GetZBufferTarget() != 0; - vid.values[0] = components | - (xfregs.numTexGens << 23) | - (xfregs.nNumChans << 27) | - ((u32)xfregs.bEnableDualTexTransform << 29) | - (zbufrender << 30); - - for (int i = 0; i < 2; ++i) { - vid.values[1+i] = xfregs.colChans[i].color.enablelighting ? - (u32)xfregs.colChans[i].color.hex : - (u32)xfregs.colChans[i].color.matsource; - vid.values[1+i] |= (xfregs.colChans[i].alpha.enablelighting ? - (u32)xfregs.colChans[i].alpha.hex : - (u32)xfregs.colChans[i].alpha.matsource) << 15; - } - - // fog - vid.values[1] |= (((u32)bpmem.fog.c_proj_fsel.fsel & 3) << 30); - vid.values[2] |= (((u32)bpmem.fog.c_proj_fsel.fsel >> 2) << 30); - - u32* pcurvalue = &vid.values[3]; - for (int i = 0; i < xfregs.numTexGens; ++i) { - TexMtxInfo tinfo = xfregs.texcoords[i].texmtxinfo; - if (tinfo.texgentype != XF_TEXGEN_EMBOSS_MAP) - tinfo.hex &= 0x7ff; - if (tinfo.texgentype != XF_TEXGEN_REGULAR) - tinfo.projection = 0; - - u32 val = ((tinfo.hex >> 1) & 0x1ffff); - if (xfregs.bEnableDualTexTransform && tinfo.texgentype == XF_TEXGEN_REGULAR) { - // rewrite normalization and post index - val |= ((u32)xfregs.texcoords[i].postmtxinfo.index << 17) | ((u32)xfregs.texcoords[i].postmtxinfo.normalize << 23); - } - - switch (i & 3) { - case 0: pcurvalue[0] |= val; break; - case 1: pcurvalue[0] |= val << 24; pcurvalue[1] = val >> 8; ++pcurvalue; break; - case 2: pcurvalue[0] |= val << 16; pcurvalue[1] = val >> 16; ++pcurvalue; break; - case 3: pcurvalue[0] |= val << 8; ++pcurvalue; break; - } - } -} - - -// LoadXFReg 0x10 -void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData) -{ - u32 address = baseAddress; - for (int i = 0; i < (int)transferSize; i++) - { - address = baseAddress + i; - - // Setup a Matrix - if (address < 0x1000) - { - VertexManager::Flush(); - VertexShaderMngr::InvalidateXFRange(address, address + transferSize); - //PRIM_LOG("xfmem write: 0x%x-0x%x\n", address, address+transferSize); - - u32* p1 = &xfmem[address]; - memcpy_gc(p1, &pData[i], transferSize*4); - i += transferSize; - } - else if (address<0x2000) - { - u32 data = pData[i]; - switch (address) - { - case 0x1000: // error - break; - case 0x1001: // diagnostics - break; - case 0x1002: // internal state 0 - break; - case 0x1003: // internal state 1 - break; - case 0x1004: // xf_clock - break; - case 0x1005: // clipdisable - if (data & 1) { // disable clipping detection - } - if (data & 2) { // disable trivial rejection - } - if (data & 4) { // disable cpoly clipping acceleration - } - break; - case 0x1006: //SetGPMetric - break; - case 0x1008: //__GXXfVtxSpecs, wrote 0004 - xfregs.hostinfo = *(INVTXSPEC*)&data; - break; - case 0x1009: //GXSetNumChans (no) - if ((u32)xfregs.nNumChans != (data&3)) { - VertexManager::Flush(); - xfregs.nNumChans = data&3; - } - break; - case 0x100a: //GXSetChanAmbientcolor - if (xfregs.colChans[0].ambColor != data) { - VertexManager::Flush(); - nMaterialsChanged |= 1; - xfregs.colChans[0].ambColor = data; - s_fMaterials[0] = ((data>>24)&0xFF)/255.0f; - s_fMaterials[1] = ((data>>16)&0xFF)/255.0f; - s_fMaterials[2] = ((data>>8)&0xFF)/255.0f; - s_fMaterials[3] = ((data)&0xFF)/255.0f; - } - break; - case 0x100b: //GXSetChanAmbientcolor - if (xfregs.colChans[1].ambColor != data) { - VertexManager::Flush(); - nMaterialsChanged |= 2; - xfregs.colChans[1].ambColor = data; - s_fMaterials[4] = ((data>>24)&0xFF)/255.0f; - s_fMaterials[5] = ((data>>16)&0xFF)/255.0f; - s_fMaterials[6] = ((data>>8)&0xFF)/255.0f; - s_fMaterials[7] = ((data)&0xFF)/255.0f; - } - break; - case 0x100c: //GXSetChanMatcolor (rgba) - if (xfregs.colChans[0].matColor != data) { - VertexManager::Flush(); - nMaterialsChanged |= 4; - xfregs.colChans[0].matColor = data; - s_fMaterials[8] = ((data>>24)&0xFF)/255.0f; - s_fMaterials[9] = ((data>>16)&0xFF)/255.0f; - s_fMaterials[10] = ((data>>8)&0xFF)/255.0f; - s_fMaterials[11] = ((data)&0xFF)/255.0f; - } - break; - case 0x100d: //GXSetChanMatcolor (rgba) - if (xfregs.colChans[1].matColor != data) { - VertexManager::Flush(); - nMaterialsChanged |= 8; - xfregs.colChans[1].matColor = data; - s_fMaterials[12] = ((data>>24)&0xFF)/255.0f; - s_fMaterials[13] = ((data>>16)&0xFF)/255.0f; - s_fMaterials[14] = ((data>>8)&0xFF)/255.0f; - s_fMaterials[15] = ((data)&0xFF)/255.0f; - } - break; - - case 0x100e: // color0 - if (xfregs.colChans[0].color.hex != (data&0x7fff) ) { - VertexManager::Flush(); - xfregs.colChans[0].color.hex = data; - } - break; - case 0x100f: // color1 - if (xfregs.colChans[1].color.hex != (data&0x7fff) ) { - VertexManager::Flush(); - xfregs.colChans[1].color.hex = data; - } - break; - case 0x1010: // alpha0 - if (xfregs.colChans[0].alpha.hex != (data&0x7fff) ) { - VertexManager::Flush(); - xfregs.colChans[0].alpha.hex = data; - } - break; - case 0x1011: // alpha1 - if (xfregs.colChans[1].alpha.hex != (data&0x7fff) ) { - VertexManager::Flush(); - xfregs.colChans[1].alpha.hex = data; - } - break; - case 0x1012: // dual tex transform - if (xfregs.bEnableDualTexTransform != (data&1)) { - VertexManager::Flush(); - xfregs.bEnableDualTexTransform = data&1; - } - break; - - case 0x1013: - case 0x1014: - case 0x1015: - case 0x1016: - case 0x1017: - DEBUG_LOG("xf addr: %x=%x\n", address, data); - break; - case 0x1018: - //_assert_msg_(GX_XF, 0, "XF matrixindex0"); - VertexShaderMngr::SetTexMatrixChangedA(data); //? - break; - case 0x1019: - //_assert_msg_(GX_XF, 0, "XF matrixindex1"); - VertexShaderMngr::SetTexMatrixChangedB(data); //? - break; - - case 0x101a: - VertexManager::Flush(); - VertexShaderMngr::SetViewport((float*)&pData[i]); - i += 6; - break; - - case 0x101c: // paper mario writes 16777216.0f, 1677721.75 - break; - case 0x101f: // paper mario writes 16777216.0f, 5033165.0f - break; - - case 0x1020: - VertexManager::Flush(); - VertexShaderMngr::SetProjection((float*)&pData[i]); - i += 7; - return; - - case 0x103f: // GXSetNumTexGens - if ((u32)xfregs.numTexGens != data) { - VertexManager::Flush(); - xfregs.numTexGens = data; - } - break; - - case 0x1040: xfregs.texcoords[0].texmtxinfo.hex = data; break; - case 0x1041: xfregs.texcoords[1].texmtxinfo.hex = data; break; - case 0x1042: xfregs.texcoords[2].texmtxinfo.hex = data; break; - case 0x1043: xfregs.texcoords[3].texmtxinfo.hex = data; break; - case 0x1044: xfregs.texcoords[4].texmtxinfo.hex = data; break; - case 0x1045: xfregs.texcoords[5].texmtxinfo.hex = data; break; - case 0x1046: xfregs.texcoords[6].texmtxinfo.hex = data; break; - case 0x1047: xfregs.texcoords[7].texmtxinfo.hex = data; break; - - case 0x1048: - case 0x1049: - case 0x104a: - case 0x104b: - case 0x104c: - case 0x104d: - case 0x104e: - case 0x104f: - DEBUG_LOG("xf addr: %x=%x\n", address, data); - break; - case 0x1050: xfregs.texcoords[0].postmtxinfo.hex = data; break; - case 0x1051: xfregs.texcoords[1].postmtxinfo.hex = data; break; - case 0x1052: xfregs.texcoords[2].postmtxinfo.hex = data; break; - case 0x1053: xfregs.texcoords[3].postmtxinfo.hex = data; break; - case 0x1054: xfregs.texcoords[4].postmtxinfo.hex = data; break; - case 0x1055: xfregs.texcoords[5].postmtxinfo.hex = data; break; - case 0x1056: xfregs.texcoords[6].postmtxinfo.hex = data; break; - case 0x1057: xfregs.texcoords[7].postmtxinfo.hex = data; break; - - default: - DEBUG_LOG("xf addr: %x=%x\n", address, data); - break; - } - } - else if (address >= 0x4000) - { - // MessageBox(NULL, "1", "1", MB_OK); - //4010 __GXSetGenMode - } - } -} - -// TODO - verify that it is correct. Seems to work, though. -void LoadIndexedXF(u32 val, int array) -{ - int index = val >> 16; - int address = val & 0xFFF; //check mask - int size = ((val >> 12) & 0xF) + 1; - //load stuff from array to address in xf mem - - VertexManager::Flush(); - VertexShaderMngr::InvalidateXFRange(address, address+size); - //PRIM_LOG("xfmem iwrite: 0x%x-0x%x\n", address, address+size); - - for (int i = 0; i < size; i++) - xfmem[address + i] = Memory_Read_U32(arraybases[array] + arraystrides[array]*index + i*4); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Globals.h" +#include "Profiler.h" +#include "Config.h" + +#include "GLUtil.h" + +#include +#include + +#include + +#include "Statistics.h" +#include "ImageWrite.h" +#include "Render.h" +#include "VertexShader.h" +#include "VertexShaderManager.h" +#include "VertexManager.h" +#include "VertexLoader.h" +#include "BPMemory.h" +#include "XFMemory.h" + +VertexShaderMngr::VSCache VertexShaderMngr::vshaders; +VERTEXSHADER* VertexShaderMngr::pShaderLast = NULL; + +float GC_ALIGNED16(g_fProjectionMatrix[16]); + +extern int A, B; +extern float AR; +extern int nBackbufferWidth, nBackbufferHeight; + +// Internal Variables +static int s_nMaxVertexInstructions; + +static float s_fMaterials[16]; + +// track changes +static bool bTexMatricesChanged[2], bPosNormalMatrixChanged, bProjectionChanged, bViewportChanged; +static int nMaterialsChanged; +static int nTransformMatricesChanged[2]; // min,max +static int nNormalMatricesChanged[2]; // min,max +static int nPostTransformMatricesChanged[2]; // min,max +static int nLightsChanged[2]; // min,max + +void VertexShaderMngr::SetVSConstant4f(int const_number, float f1, float f2, float f3, float f4) { + glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, const_number, f1, f2, f3, f4); +} + +void VertexShaderMngr::SetVSConstant4fv(int const_number, const float *f) { + glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f); +} + +void VertexShaderMngr::Init() +{ + nTransformMatricesChanged[0] = nTransformMatricesChanged[1] = -1; + nNormalMatricesChanged[0] = nNormalMatricesChanged[1] = -1; + nPostTransformMatricesChanged[0] = nPostTransformMatricesChanged[1] = -1; + nLightsChanged[0] = nLightsChanged[1] = -1; + bTexMatricesChanged[0] = bTexMatricesChanged[1] = false; + bPosNormalMatrixChanged = bProjectionChanged = bViewportChanged = false; + nMaterialsChanged = 0; + + memset(&xfregs, 0, sizeof(xfregs)); + memset(xfmem, 0, sizeof(xfmem)); + + glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&s_nMaxVertexInstructions); +} + +void VertexShaderMngr::Shutdown() +{ + for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); iter++) + iter->second.Destroy(); + vshaders.clear(); +} + +float VertexShaderMngr::GetPixelAspectRatio() { + return xfregs.rawViewport[0] != 0 ? (float)Renderer::GetTargetWidth() / 640.0f : 1.0f; +} + +VERTEXSHADER* VertexShaderMngr::GetShader(u32 components) +{ + DVSTARTPROFILE(); + VERTEXSHADERUID uid; + GetVertexShaderId(uid, components); + + VSCache::iterator iter = vshaders.find(uid); + + if (iter != vshaders.end()) { + iter->second.frameCount = frameCount; + VSCacheEntry &entry = iter->second; + if (&entry.shader != pShaderLast) { + pShaderLast = &entry.shader; + } + return pShaderLast; + } + + VSCacheEntry& entry = vshaders[uid]; + char *code = GenerateVertexShader(components, Renderer::GetZBufferTarget() != 0); + +#if defined(_DEBUG) || defined(DEBUGFAST) + if (g_Config.iLog & CONF_SAVESHADERS && code) { + static int counter = 0; + char szTemp[MAX_PATH]; + sprintf(szTemp, "%s/vs_%04i.txt", g_Config.texDumpPath, counter++); + + SaveData(szTemp, code); + } +#endif + + if (!code || !VertexShaderMngr::CompileVertexShader(entry.shader, code)) { + ERROR_LOG("failed to create vertex shader\n"); + return NULL; + } + + //Make an entry in the table + entry.frameCount=frameCount; + + pShaderLast = &entry.shader; + INCSTAT(stats.numVertexShadersCreated); + SETSTAT(stats.numVertexShadersAlive,vshaders.size()); + return pShaderLast; +} + +void VertexShaderMngr::Cleanup() +{ + VSCache::iterator iter=vshaders.begin(); + while (iter != vshaders.end()) { + VSCacheEntry &entry = iter->second; + if (entry.frameCount < frameCount-200) { + entry.Destroy(); +#ifdef _WIN32 + iter = vshaders.erase(iter); +#else + vshaders.erase(iter++); +#endif + } + else { + ++iter; + } + } + +// static int frame = 0; +// if( frame++ > 30 ) { +// VSCache::iterator iter=vshaders.begin(); +// while(iter!=vshaders.end()) { +// iter->second.Destroy(); +// ++iter; +// } +// vshaders.clear(); +// } + + SETSTAT(stats.numPixelShadersAlive,vshaders.size()); +} + +bool VertexShaderMngr::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram) +{ + char stropt[64]; + sprintf(stropt, "MaxLocalParams=256,MaxInstructions=%d", s_nMaxVertexInstructions); + const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL}; + CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgvProf, "main", opts); + if (!cgIsProgram(tempprog) || cgGetError() != CG_NO_ERROR) { + ERROR_LOG("Failed to load vs %s:\n", cgGetLastListing(g_cgcontext)); + ERROR_LOG(pstrprogram); + return false; + } + + //ERROR_LOG(pstrprogram); + //ERROR_LOG("id: %d\n", g_Config.iSaveTargetId); + + char* pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM); + char* plocal = strstr(pcompiledprog, "program.local"); + + while (plocal != NULL) { + const char* penv = " program.env"; + memcpy(plocal, penv, 13); + plocal = strstr(plocal+13, "program.local"); + } + + glGenProgramsARB(1, &vs.glprogid); + glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vs.glprogid); + glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog); + + GLenum err = GL_NO_ERROR; + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) { + ERROR_LOG(pstrprogram); + ERROR_LOG(pcompiledprog); + } + + cgDestroyProgram(tempprog); + // printf("Compiled vertex shader %i\n", vs.glprogid); + +#if defined(_DEBUG) || defined(DEBUGFAST) + vs.strprog = pstrprogram; +#endif + + return true; +} + +const u16 s_mtrltable[16][2] = {{0, 0}, {0, 1}, {1, 1}, {0, 2}, + {2, 1}, {0, 3}, {1, 2}, {0, 3}, + {3, 1}, {0, 4}, {1, 3}, {0, 4}, + {2, 2}, {0, 4}, {1, 3}, {0, 4}}; + + +// ======================================================================================= +// Syncs the shader constant buffers with xfmem +// ---------------- +void VertexShaderMngr::SetConstants() +{ + //nTransformMatricesChanged[0] = 0; nTransformMatricesChanged[1] = 256; + //nNormalMatricesChanged[0] = 0; nNormalMatricesChanged[1] = 96; + //nPostTransformMatricesChanged[0] = 0; nPostTransformMatricesChanged[1] = 256; + //nLightsChanged[0] = 0; nLightsChanged[1] = 0x80; + //bPosNormalMatrixChanged = true; + //bTexMatricesChanged[0] = bTexMatricesChanged[1] = true; + //bProjectionChanged = true; +// bPosNormalMatrixChanged = bTexMatricesChanged[0] = bTexMatricesChanged[1] = true; +// nMaterialsChanged = 15; + + if (nTransformMatricesChanged[0] >= 0) { + int startn = nTransformMatricesChanged[0]/4; + int endn = (nTransformMatricesChanged[1]+3)/4; + const float* pstart = (const float*)&xfmem[startn*4]; + for(int i = startn; i < endn; ++i, pstart += 4) + SetVSConstant4fv(C_TRANSFORMMATRICES+i, pstart); + nTransformMatricesChanged[0] = nTransformMatricesChanged[1] = -1; + } + if (nNormalMatricesChanged[0] >= 0) { + int startn = nNormalMatricesChanged[0]/3; + int endn = (nNormalMatricesChanged[1]+2)/3; + const float* pnstart = (const float*)&xfmem[XFMEM_NORMALMATRICES+3*startn]; + + for(int i = startn; i < endn; ++i, pnstart += 3) + SetVSConstant4fv(C_NORMALMATRICES+i, pnstart); + + nNormalMatricesChanged[0] = nNormalMatricesChanged[1] = -1; + } + + if (nPostTransformMatricesChanged[0] >= 0) { + int startn = nPostTransformMatricesChanged[0]/4; + int endn = (nPostTransformMatricesChanged[1]+3)/4; + const float* pstart = (const float*)&xfmem[XFMEM_POSTMATRICES + startn*4]; + for(int i = startn; i < endn; ++i, pstart += 4) + SetVSConstant4fv(C_POSTTRANSFORMMATRICES + i, pstart); + } + + if (nLightsChanged[0] >= 0) { + // lights don't have a 1 to 1 mapping, the color component needs to be converted to 4 floats + int istart = nLightsChanged[0] / 0x10; + int iend = (nLightsChanged[1] + 15) / 0x10; + const float* xfmemptr = (const float*)&xfmem[0x10*istart + XFMEM_LIGHTS]; + + for (int i = istart; i < iend; ++i) { + u32 color = *(const u32*)(xfmemptr + 3); + SetVSConstant4f(C_LIGHTS + 5*i, + ((color >> 24) & 0xFF)/255.0f, + ((color >> 16) & 0xFF)/255.0f, + ((color >> 8) & 0xFF)/255.0f, + ((color) & 0xFF)/255.0f); + xfmemptr += 4; + for (int j = 0; j < 4; ++j, xfmemptr += 3) { + if (j == 1 && + fabs(xfmemptr[0]) < 0.00001f && + fabs(xfmemptr[1]) < 0.00001f && + fabs(xfmemptr[2]) < 0.00001f) { + // dist attenuation, make sure not equal to 0!!! + SetVSConstant4f(C_LIGHTS+5*i+j+1, 0.00001f, xfmemptr[1], xfmemptr[2], 0); + } + else + SetVSConstant4fv(C_LIGHTS+5*i+j+1, xfmemptr); + } + } + + nLightsChanged[0] = nLightsChanged[1] = -1; + } + + if (nMaterialsChanged) { + for (int i = 0; i < 4; ++i) { + if (nMaterialsChanged & (1 << i)) + SetVSConstant4fv(C_MATERIALS + i, &s_fMaterials[4*i]); + } + nMaterialsChanged = 0; + } + + if (bPosNormalMatrixChanged) { + bPosNormalMatrixChanged = false; + + float* pos = (float*)xfmem + MatrixIndexA.PosNormalMtxIdx * 4; + float* norm = (float*)xfmem + XFMEM_NORMALMATRICES + 3 * (MatrixIndexA.PosNormalMtxIdx & 31); + + SetVSConstant4fv(C_POSNORMALMATRIX, pos); + SetVSConstant4fv(C_POSNORMALMATRIX+1, pos+4); + SetVSConstant4fv(C_POSNORMALMATRIX+2, pos+8); + SetVSConstant4fv(C_POSNORMALMATRIX+3, norm); + SetVSConstant4fv(C_POSNORMALMATRIX+4, norm+3); + SetVSConstant4fv(C_POSNORMALMATRIX+5, norm+6); + } + + if (bTexMatricesChanged[0]) { + bTexMatricesChanged[0] = false; + float* fptrs[] = { + (float*)xfmem + MatrixIndexA.Tex0MtxIdx * 4, (float*)xfmem + MatrixIndexA.Tex1MtxIdx * 4, + (float*)xfmem + MatrixIndexA.Tex2MtxIdx * 4, (float*)xfmem + MatrixIndexA.Tex3MtxIdx * 4 + }; + + for (int i = 0; i < 4; ++i) { + SetVSConstant4fv(C_TEXMATRICES+3*i, fptrs[i]); + SetVSConstant4fv(C_TEXMATRICES+3*i+1, fptrs[i]+4); + SetVSConstant4fv(C_TEXMATRICES+3*i+2, fptrs[i]+8); + } + } + + if (bTexMatricesChanged[1]) { + bTexMatricesChanged[1] = false; + + float* fptrs[] = {(float*)xfmem + MatrixIndexB.Tex4MtxIdx * 4, (float*)xfmem + MatrixIndexB.Tex5MtxIdx * 4, + (float*)xfmem + MatrixIndexB.Tex6MtxIdx * 4, (float*)xfmem + MatrixIndexB.Tex7MtxIdx * 4 }; + + for (int i = 0; i < 4; ++i) { + SetVSConstant4fv(C_TEXMATRICES+3*i+12, fptrs[i]); + SetVSConstant4fv(C_TEXMATRICES+3*i+12+1, fptrs[i]+4); + SetVSConstant4fv(C_TEXMATRICES+3*i+12+2, fptrs[i]+8); + } + } + + if (bViewportChanged) { + bViewportChanged = false; + + // reversed gxsetviewport(xorig, yorig, width, height, nearz, farz) + // [0] = width/2 + // [1] = height/2 + // [2] = 16777215 * (farz-nearz) + // [3] = xorig + width/2 + 342 + // [4] = yorig + height/2 + 342 + // [5] = 16777215 * farz + /*INFO_LOG("view: topleft=(%f,%f), wh=(%f,%f), z=(%f,%f)\n", + rawViewport[3]-rawViewport[0]-342, rawViewport[4]+rawViewport[1]-342, + 2 * rawViewport[0], 2 * rawViewport[1], + (rawViewport[5] - rawViewport[2]) / 16777215.0f, rawViewport[5] / 16777215.0f);*/ + + // Keep aspect ratio at 4:3 + // rawViewport[0] = 320, rawViewport[1] = -240 + int scissorXOff = bpmem.scissorOffset.x * 2 - 342; + int scissorYOff = bpmem.scissorOffset.y * 2 - 342; + float fourThree = 4.0f / 3.0f; + float ratio = AR / fourThree; + float wAdj, hAdj; + float actualRatiow, actualRatioh; + int overfl; + int xoffs = 0, yoffs = 0; + int wid, hei, actualWid, actualHei; + int winw = nBackbufferWidth; + int winh = nBackbufferHeight; + if (g_Config.bKeepAR) + { + // Check if height or width is the limiting factor + if (ratio > 1) // then we are to wide and have to limit the width + { + wAdj = ratio; + hAdj = 1; + + wid = ceil(fabs(2 * xfregs.rawViewport[0]) / wAdj); + hei = ceil(fabs(2 * xfregs.rawViewport[1]) / hAdj); + + actualWid = ceil((float)winw / ratio); + actualRatiow = (float)actualWid / (float)wid; // the picture versus the screen + overfl = (winw - actualWid) / actualRatiow; + xoffs = overfl / 2; + } + else // the window is to high, we have to limit the height + { + ratio = 1 / ratio; + + wAdj = 1; + hAdj = ratio; + + wid = ceil(fabs(2 * xfregs.rawViewport[0]) / wAdj); + hei = ceil(fabs(2 * xfregs.rawViewport[1]) / hAdj); + + actualHei = ceil((float)winh / ratio); + actualRatioh = (float)actualHei / (float)hei; // the picture versus the screen + overfl = (winh - actualHei) / actualRatioh; + yoffs = overfl / 2; + } + } + else + { + wid = ceil(fabs(2 * xfregs.rawViewport[0])); + hei = ceil(fabs(2 * xfregs.rawViewport[1])); + } + + if (g_Config.bStretchToFit) + { + glViewport( + (int)(xfregs.rawViewport[3]-xfregs.rawViewport[0]-342-scissorXOff) + xoffs, + Renderer::GetTargetHeight() - ((int)(xfregs.rawViewport[4]-xfregs.rawViewport[1]-342-scissorYOff)) + yoffs, + wid, // width + hei // height + ); + } + else + { + glViewport((int)(xfregs.rawViewport[3]-xfregs.rawViewport[0]-342-scissorXOff) * MValueX, + Renderer::GetTargetHeight()-((int)(xfregs.rawViewport[4]-xfregs.rawViewport[1]-342-scissorYOff)) * MValueY, + abs((int)(2 * xfregs.rawViewport[0])) * MValueX, abs((int)(2 * xfregs.rawViewport[1])) * MValueY); + } + glDepthRange((xfregs.rawViewport[5]- xfregs.rawViewport[2])/16777215.0f, xfregs.rawViewport[5]/16777215.0f); + } + + if (bProjectionChanged) { + bProjectionChanged = false; + + if (xfregs.rawProjection[6] == 0) { + g_fProjectionMatrix[0] = xfregs.rawProjection[0]; + g_fProjectionMatrix[1] = 0.0f; + g_fProjectionMatrix[2] = xfregs.rawProjection[1]; + g_fProjectionMatrix[3] = 0; + + g_fProjectionMatrix[4] = 0.0f; + g_fProjectionMatrix[5] = xfregs.rawProjection[2]; + g_fProjectionMatrix[6] = xfregs.rawProjection[3]; + g_fProjectionMatrix[7] = 0; + + g_fProjectionMatrix[8] = 0.0f; + g_fProjectionMatrix[9] = 0.0f; + g_fProjectionMatrix[10] = xfregs.rawProjection[4]; + + //---------Projection[11]--------- + // No hacks + if ((!g_Config.bProjectionHax1 && !g_Config.bProjectionHax2) || (g_Config.bProjectionHax1 && g_Config.bProjectionHax2)) + g_fProjectionMatrix[11] = -(0.0f - xfregs.rawProjection[5]); + + // Before R945 Hack + if(g_Config.bProjectionHax1 && !g_Config.bProjectionHax2) + g_fProjectionMatrix[11] = -(1.0f - xfregs.rawProjection[5]); + + // R844 Hack + if(!g_Config.bProjectionHax1 && g_Config.bProjectionHax2) + g_fProjectionMatrix[11] = xfregs.rawProjection[5]; + //-------------------------------- + + g_fProjectionMatrix[12] = 0.0f; + g_fProjectionMatrix[13] = 0.0f; + // donkopunchstania: GC GPU rounds differently? + // -(1 + epsilon) so objects are clipped as they are on the real HW + g_fProjectionMatrix[14] = -1.00000011921f; + g_fProjectionMatrix[15] = 0.0f; + } + else { + g_fProjectionMatrix[0] = xfregs.rawProjection[0]; + g_fProjectionMatrix[1] = 0.0f; + g_fProjectionMatrix[2] = 0.0f; + g_fProjectionMatrix[3] = xfregs.rawProjection[1]; + + g_fProjectionMatrix[4] = 0.0f; + g_fProjectionMatrix[5] = xfregs.rawProjection[2]; + g_fProjectionMatrix[6] = 0.0f; + g_fProjectionMatrix[7] = xfregs.rawProjection[3]; + + g_fProjectionMatrix[8] = 0.0f; + g_fProjectionMatrix[9] = 0.0f; + g_fProjectionMatrix[10] = xfregs.rawProjection[4]; + + //---------Projection[11]--------- + // No hacks + if ((!g_Config.bProjectionHax1 && !g_Config.bProjectionHax2) || (g_Config.bProjectionHax1 && g_Config.bProjectionHax2)) + g_fProjectionMatrix[11] = -(-1.0f - xfregs.rawProjection[5]); + + // Before R945 Hack + if (g_Config.bProjectionHax1 && !g_Config.bProjectionHax2) + g_fProjectionMatrix[11] = -(0.0f - xfregs.rawProjection[5]); + + // R844 Hack + if (!g_Config.bProjectionHax1 && g_Config.bProjectionHax2) + g_fProjectionMatrix[11] = -xfregs.rawProjection[5]; + + //-------------------------------- + + g_fProjectionMatrix[12] = 0; + g_fProjectionMatrix[13] = 0; + g_fProjectionMatrix[14] = 0.0f; + g_fProjectionMatrix[15] = 1.0f; + } + + PRIM_LOG("Projection: %f %f %f %f %f %f\n", xfregs.rawProjection[0], xfregs.rawProjection[1], xfregs.rawProjection[2], xfregs.rawProjection[3], xfregs.rawProjection[4], xfregs.rawProjection[5]); + SetVSConstant4fv(C_PROJECTION, &g_fProjectionMatrix[0]); + SetVSConstant4fv(C_PROJECTION+1, &g_fProjectionMatrix[4]); + SetVSConstant4fv(C_PROJECTION+2, &g_fProjectionMatrix[8]); + SetVSConstant4fv(C_PROJECTION+3, &g_fProjectionMatrix[12]); + } +} + +void VertexShaderMngr::InvalidateXFRange(int start, int end) +{ + if (((u32)start >= (u32)MatrixIndexA.PosNormalMtxIdx*4 && + (u32)start < (u32)MatrixIndexA.PosNormalMtxIdx*4 + 12) || + ((u32)start >= XFMEM_NORMALMATRICES + ((u32)MatrixIndexA.PosNormalMtxIdx & 31)*3 && + (u32)start < XFMEM_NORMALMATRICES + ((u32)MatrixIndexA.PosNormalMtxIdx & 31)*3 + 9)) { + bPosNormalMatrixChanged = true; + } + + if (((u32)start >= (u32)MatrixIndexA.Tex0MtxIdx*4 && (u32)start < (u32)MatrixIndexA.Tex0MtxIdx*4+12) || + ((u32)start >= (u32)MatrixIndexA.Tex1MtxIdx*4 && (u32)start < (u32)MatrixIndexA.Tex1MtxIdx*4+12) || + ((u32)start >= (u32)MatrixIndexA.Tex2MtxIdx*4 && (u32)start < (u32)MatrixIndexA.Tex2MtxIdx*4+12) || + ((u32)start >= (u32)MatrixIndexA.Tex3MtxIdx*4 && (u32)start < (u32)MatrixIndexA.Tex3MtxIdx*4+12)) { + bTexMatricesChanged[0] = true; + } + + if (((u32)start >= (u32)MatrixIndexB.Tex4MtxIdx*4 && (u32)start < (u32)MatrixIndexB.Tex4MtxIdx*4+12) || + ((u32)start >= (u32)MatrixIndexB.Tex5MtxIdx*4 && (u32)start < (u32)MatrixIndexB.Tex5MtxIdx*4+12) || + ((u32)start >= (u32)MatrixIndexB.Tex6MtxIdx*4 && (u32)start < (u32)MatrixIndexB.Tex6MtxIdx*4+12) || + ((u32)start >= (u32)MatrixIndexB.Tex7MtxIdx*4 && (u32)start < (u32)MatrixIndexB.Tex7MtxIdx*4+12)) { + bTexMatricesChanged[1] = true; + } + + if (start < XFMEM_POSMATRICES_END) { + if (nTransformMatricesChanged[0] == -1) { + nTransformMatricesChanged[0] = start; + nTransformMatricesChanged[1] = end>XFMEM_POSMATRICES_END?XFMEM_POSMATRICES_END:end; + } + else { + if (nTransformMatricesChanged[0] > start) nTransformMatricesChanged[0] = start; + if (nTransformMatricesChanged[1] < end) nTransformMatricesChanged[1] = end>XFMEM_POSMATRICES_END?XFMEM_POSMATRICES_END:end; + } + } + + if (start < XFMEM_NORMALMATRICES_END && end > XFMEM_NORMALMATRICES) { + int _start = start < XFMEM_NORMALMATRICES ? 0 : start-XFMEM_NORMALMATRICES; + int _end = end < XFMEM_NORMALMATRICES_END ? end-XFMEM_NORMALMATRICES : XFMEM_NORMALMATRICES_END-XFMEM_NORMALMATRICES; + + if (nNormalMatricesChanged[0] == -1 ) { + nNormalMatricesChanged[0] = _start; + nNormalMatricesChanged[1] = _end; + } + else { + if (nNormalMatricesChanged[0] > _start) nNormalMatricesChanged[0] = _start; + if (nNormalMatricesChanged[1] < _end) nNormalMatricesChanged[1] = _end; + } + } + + if (start < XFMEM_POSTMATRICES_END && end > XFMEM_POSTMATRICES) { + int _start = start < XFMEM_POSTMATRICES ? XFMEM_POSTMATRICES : start-XFMEM_POSTMATRICES; + int _end = end < XFMEM_POSTMATRICES_END ? end-XFMEM_POSTMATRICES : XFMEM_POSTMATRICES_END-XFMEM_POSTMATRICES; + + if (nPostTransformMatricesChanged[0] == -1 ) { + nPostTransformMatricesChanged[0] = _start; + nPostTransformMatricesChanged[1] = _end; + } + else { + if (nPostTransformMatricesChanged[0] > _start) nPostTransformMatricesChanged[0] = _start; + if (nPostTransformMatricesChanged[1] < _end) nPostTransformMatricesChanged[1] = _end; + } + } + + if (start < XFMEM_LIGHTS_END && end > XFMEM_LIGHTS) { + int _start = start < XFMEM_LIGHTS ? XFMEM_LIGHTS : start-XFMEM_LIGHTS; + int _end = end < XFMEM_LIGHTS_END ? end-XFMEM_LIGHTS : XFMEM_LIGHTS_END-XFMEM_LIGHTS; + + if (nLightsChanged[0] == -1 ) { + nLightsChanged[0] = _start; + nLightsChanged[1] = _end; + } + else { + if (nLightsChanged[0] > _start) nLightsChanged[0] = _start; + if (nLightsChanged[1] < _end) nLightsChanged[1] = _end; + } + } +} + +void VertexShaderMngr::SetTexMatrixChangedA(u32 Value) +{ + if (MatrixIndexA.Hex != Value) { + VertexManager::Flush(); + if (MatrixIndexA.PosNormalMtxIdx != (Value&0x3f)) + bPosNormalMatrixChanged = true; + bTexMatricesChanged[0] = true; + MatrixIndexA.Hex = Value; + } +} + +void VertexShaderMngr::SetTexMatrixChangedB(u32 Value) +{ + if (MatrixIndexB.Hex != Value) { + VertexManager::Flush(); + bTexMatricesChanged[1] = true; + MatrixIndexB.Hex = Value; + } +} + +void VertexShaderMngr::SetViewport(float* _Viewport) +{ + // Workaround for paper mario, yep this is bizarre. + for (size_t i = 0; i < ARRAYSIZE(xfregs.rawViewport); ++i) { + if (*(u32*)(_Viewport + i) == 0x7f800000) // invalid fp number + return; + } + memcpy(xfregs.rawViewport, _Viewport, sizeof(xfregs.rawViewport)); + bViewportChanged = true; +} + +void VertexShaderMngr::SetViewportChanged() +{ + bViewportChanged = true; +} + +void VertexShaderMngr::SetProjection(float* _pProjection, int constantIndex) +{ + memcpy(xfregs.rawProjection, _pProjection, sizeof(xfregs.rawProjection)); + bProjectionChanged = true; +} + +float* VertexShaderMngr::GetPosNormalMat() +{ + return (float*)xfmem + MatrixIndexA.PosNormalMtxIdx * 4; +} + +// Mash together all the inputs that contribute to the code of a generated vertex shader into +// a unique identifier, basically containing all the bits. Yup, it's a lot .... +void VertexShaderMngr::GetVertexShaderId(VERTEXSHADERUID& vid, u32 components) +{ + u32 zbufrender = (bpmem.ztex2.op == ZTEXTURE_ADD) || Renderer::GetZBufferTarget() != 0; + vid.values[0] = components | + (xfregs.numTexGens << 23) | + (xfregs.nNumChans << 27) | + ((u32)xfregs.bEnableDualTexTransform << 29) | + (zbufrender << 30); + + for (int i = 0; i < 2; ++i) { + vid.values[1+i] = xfregs.colChans[i].color.enablelighting ? + (u32)xfregs.colChans[i].color.hex : + (u32)xfregs.colChans[i].color.matsource; + vid.values[1+i] |= (xfregs.colChans[i].alpha.enablelighting ? + (u32)xfregs.colChans[i].alpha.hex : + (u32)xfregs.colChans[i].alpha.matsource) << 15; + } + + // fog + vid.values[1] |= (((u32)bpmem.fog.c_proj_fsel.fsel & 3) << 30); + vid.values[2] |= (((u32)bpmem.fog.c_proj_fsel.fsel >> 2) << 30); + + u32* pcurvalue = &vid.values[3]; + for (int i = 0; i < xfregs.numTexGens; ++i) { + TexMtxInfo tinfo = xfregs.texcoords[i].texmtxinfo; + if (tinfo.texgentype != XF_TEXGEN_EMBOSS_MAP) + tinfo.hex &= 0x7ff; + if (tinfo.texgentype != XF_TEXGEN_REGULAR) + tinfo.projection = 0; + + u32 val = ((tinfo.hex >> 1) & 0x1ffff); + if (xfregs.bEnableDualTexTransform && tinfo.texgentype == XF_TEXGEN_REGULAR) { + // rewrite normalization and post index + val |= ((u32)xfregs.texcoords[i].postmtxinfo.index << 17) | ((u32)xfregs.texcoords[i].postmtxinfo.normalize << 23); + } + + switch (i & 3) { + case 0: pcurvalue[0] |= val; break; + case 1: pcurvalue[0] |= val << 24; pcurvalue[1] = val >> 8; ++pcurvalue; break; + case 2: pcurvalue[0] |= val << 16; pcurvalue[1] = val >> 16; ++pcurvalue; break; + case 3: pcurvalue[0] |= val << 8; ++pcurvalue; break; + } + } +} + + +// LoadXFReg 0x10 +void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData) +{ + u32 address = baseAddress; + for (int i = 0; i < (int)transferSize; i++) + { + address = baseAddress + i; + + // Setup a Matrix + if (address < 0x1000) + { + VertexManager::Flush(); + VertexShaderMngr::InvalidateXFRange(address, address + transferSize); + //PRIM_LOG("xfmem write: 0x%x-0x%x\n", address, address+transferSize); + + u32* p1 = &xfmem[address]; + memcpy_gc(p1, &pData[i], transferSize*4); + i += transferSize; + } + else if (address<0x2000) + { + u32 data = pData[i]; + switch (address) + { + case 0x1000: // error + break; + case 0x1001: // diagnostics + break; + case 0x1002: // internal state 0 + break; + case 0x1003: // internal state 1 + break; + case 0x1004: // xf_clock + break; + case 0x1005: // clipdisable + if (data & 1) { // disable clipping detection + } + if (data & 2) { // disable trivial rejection + } + if (data & 4) { // disable cpoly clipping acceleration + } + break; + case 0x1006: //SetGPMetric + break; + case 0x1008: //__GXXfVtxSpecs, wrote 0004 + xfregs.hostinfo = *(INVTXSPEC*)&data; + break; + case 0x1009: //GXSetNumChans (no) + if ((u32)xfregs.nNumChans != (data&3)) { + VertexManager::Flush(); + xfregs.nNumChans = data&3; + } + break; + case 0x100a: //GXSetChanAmbientcolor + if (xfregs.colChans[0].ambColor != data) { + VertexManager::Flush(); + nMaterialsChanged |= 1; + xfregs.colChans[0].ambColor = data; + s_fMaterials[0] = ((data>>24)&0xFF)/255.0f; + s_fMaterials[1] = ((data>>16)&0xFF)/255.0f; + s_fMaterials[2] = ((data>>8)&0xFF)/255.0f; + s_fMaterials[3] = ((data)&0xFF)/255.0f; + } + break; + case 0x100b: //GXSetChanAmbientcolor + if (xfregs.colChans[1].ambColor != data) { + VertexManager::Flush(); + nMaterialsChanged |= 2; + xfregs.colChans[1].ambColor = data; + s_fMaterials[4] = ((data>>24)&0xFF)/255.0f; + s_fMaterials[5] = ((data>>16)&0xFF)/255.0f; + s_fMaterials[6] = ((data>>8)&0xFF)/255.0f; + s_fMaterials[7] = ((data)&0xFF)/255.0f; + } + break; + case 0x100c: //GXSetChanMatcolor (rgba) + if (xfregs.colChans[0].matColor != data) { + VertexManager::Flush(); + nMaterialsChanged |= 4; + xfregs.colChans[0].matColor = data; + s_fMaterials[8] = ((data>>24)&0xFF)/255.0f; + s_fMaterials[9] = ((data>>16)&0xFF)/255.0f; + s_fMaterials[10] = ((data>>8)&0xFF)/255.0f; + s_fMaterials[11] = ((data)&0xFF)/255.0f; + } + break; + case 0x100d: //GXSetChanMatcolor (rgba) + if (xfregs.colChans[1].matColor != data) { + VertexManager::Flush(); + nMaterialsChanged |= 8; + xfregs.colChans[1].matColor = data; + s_fMaterials[12] = ((data>>24)&0xFF)/255.0f; + s_fMaterials[13] = ((data>>16)&0xFF)/255.0f; + s_fMaterials[14] = ((data>>8)&0xFF)/255.0f; + s_fMaterials[15] = ((data)&0xFF)/255.0f; + } + break; + + case 0x100e: // color0 + if (xfregs.colChans[0].color.hex != (data&0x7fff) ) { + VertexManager::Flush(); + xfregs.colChans[0].color.hex = data; + } + break; + case 0x100f: // color1 + if (xfregs.colChans[1].color.hex != (data&0x7fff) ) { + VertexManager::Flush(); + xfregs.colChans[1].color.hex = data; + } + break; + case 0x1010: // alpha0 + if (xfregs.colChans[0].alpha.hex != (data&0x7fff) ) { + VertexManager::Flush(); + xfregs.colChans[0].alpha.hex = data; + } + break; + case 0x1011: // alpha1 + if (xfregs.colChans[1].alpha.hex != (data&0x7fff) ) { + VertexManager::Flush(); + xfregs.colChans[1].alpha.hex = data; + } + break; + case 0x1012: // dual tex transform + if (xfregs.bEnableDualTexTransform != (data&1)) { + VertexManager::Flush(); + xfregs.bEnableDualTexTransform = data&1; + } + break; + + case 0x1013: + case 0x1014: + case 0x1015: + case 0x1016: + case 0x1017: + DEBUG_LOG("xf addr: %x=%x\n", address, data); + break; + case 0x1018: + //_assert_msg_(GX_XF, 0, "XF matrixindex0"); + VertexShaderMngr::SetTexMatrixChangedA(data); //? + break; + case 0x1019: + //_assert_msg_(GX_XF, 0, "XF matrixindex1"); + VertexShaderMngr::SetTexMatrixChangedB(data); //? + break; + + case 0x101a: + VertexManager::Flush(); + VertexShaderMngr::SetViewport((float*)&pData[i]); + i += 6; + break; + + case 0x101c: // paper mario writes 16777216.0f, 1677721.75 + break; + case 0x101f: // paper mario writes 16777216.0f, 5033165.0f + break; + + case 0x1020: + VertexManager::Flush(); + VertexShaderMngr::SetProjection((float*)&pData[i]); + i += 7; + return; + + case 0x103f: // GXSetNumTexGens + if ((u32)xfregs.numTexGens != data) { + VertexManager::Flush(); + xfregs.numTexGens = data; + } + break; + + case 0x1040: xfregs.texcoords[0].texmtxinfo.hex = data; break; + case 0x1041: xfregs.texcoords[1].texmtxinfo.hex = data; break; + case 0x1042: xfregs.texcoords[2].texmtxinfo.hex = data; break; + case 0x1043: xfregs.texcoords[3].texmtxinfo.hex = data; break; + case 0x1044: xfregs.texcoords[4].texmtxinfo.hex = data; break; + case 0x1045: xfregs.texcoords[5].texmtxinfo.hex = data; break; + case 0x1046: xfregs.texcoords[6].texmtxinfo.hex = data; break; + case 0x1047: xfregs.texcoords[7].texmtxinfo.hex = data; break; + + case 0x1048: + case 0x1049: + case 0x104a: + case 0x104b: + case 0x104c: + case 0x104d: + case 0x104e: + case 0x104f: + DEBUG_LOG("xf addr: %x=%x\n", address, data); + break; + case 0x1050: xfregs.texcoords[0].postmtxinfo.hex = data; break; + case 0x1051: xfregs.texcoords[1].postmtxinfo.hex = data; break; + case 0x1052: xfregs.texcoords[2].postmtxinfo.hex = data; break; + case 0x1053: xfregs.texcoords[3].postmtxinfo.hex = data; break; + case 0x1054: xfregs.texcoords[4].postmtxinfo.hex = data; break; + case 0x1055: xfregs.texcoords[5].postmtxinfo.hex = data; break; + case 0x1056: xfregs.texcoords[6].postmtxinfo.hex = data; break; + case 0x1057: xfregs.texcoords[7].postmtxinfo.hex = data; break; + + default: + DEBUG_LOG("xf addr: %x=%x\n", address, data); + break; + } + } + else if (address >= 0x4000) + { + // MessageBox(NULL, "1", "1", MB_OK); + //4010 __GXSetGenMode + } + } +} + +// TODO - verify that it is correct. Seems to work, though. +void LoadIndexedXF(u32 val, int array) +{ + int index = val >> 16; + int address = val & 0xFFF; //check mask + int size = ((val >> 12) & 0xF) + 1; + //load stuff from array to address in xf mem + + VertexManager::Flush(); + VertexShaderMngr::InvalidateXFRange(address, address+size); + //PRIM_LOG("xfmem iwrite: 0x%x-0x%x\n", address, address+size); + + for (int i = 0; i < size; i++) + xfmem[address + i] = Memory_Read_U32(arraybases[array] + arraystrides[array]*index + i*4); +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/XFB.cpp b/Source/Plugins/Plugin_VideoOGL/Src/XFB.cpp index 923eb4b78f..6127b745e4 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/XFB.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/XFB.cpp @@ -1,231 +1,231 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -// Preliminary non-working code. - -#include "Globals.h" -#include "GLUtil.h" -#include "MemoryUtil.h" -#include "Render.h" -#include "TextureMngr.h" -#include "VertexShaderManager.h" -#include "XFBConvert.h" -#include "TextureConverter.h" - -#define XFB_USE_SHADERS 1 - -enum { - XFB_WIDTH = 640, - XFB_HEIGHT = 480, // 528 is max height. - XFB_BUF_HEIGHT = 538, //480, - // TODO: figure out what to do with PAL -}; - - -#if XFB_USE_SHADERS - -static GLuint xfb_decoded_texture; - -void XFB_Init() -{ - glGenTextures(1, &xfb_decoded_texture); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfb_decoded_texture); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, XFB_WIDTH, XFB_BUF_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); -} - -void XFB_Shutdown() -{ - glDeleteTextures(1, &xfb_decoded_texture); -} - - -void XFB_Write(u8 *xfb_in_ram, const TRectangle& sourceRc, u32 dstWd, u32 dstHt) -{ - TRectangle renderSrcRc; - renderSrcRc.left = sourceRc.left; - renderSrcRc.right = sourceRc.right; - renderSrcRc.top = nBackbufferHeight - sourceRc.top; - renderSrcRc.bottom = nBackbufferHeight - sourceRc.bottom; - TextureConverter::EncodeToRam(Renderer::GetRenderTarget(), renderSrcRc, xfb_in_ram, dstWd, dstHt); -} - -void XFB_Draw(u8 *xfb_in_ram, u32 width, u32 height, s32 yOffset) -{ - TextureConverter::DecodeToTexture(xfb_in_ram, width, height, xfb_decoded_texture); - - OpenGL_Update(); // just updates the render window position and the backbuffer size - - Renderer::ResetGLState(); - - TextureMngr::EnableTexRECT(0); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfb_decoded_texture); - - glViewport(nXoff, nYoff, nBackbufferWidth, nBackbufferHeight); - GL_REPORT_ERRORD(); - - float w = (float)width; - float h = (float)height; - float yOff = (float)yOffset; - - glBegin(GL_QUADS); - glTexCoord2f(w, 0 - yOff); glVertex2f(1, -1); - glTexCoord2f(w, h - yOff); glVertex2f(1, 1); - glTexCoord2f(0, h - yOff); glVertex2f(-1, 1); - glTexCoord2f(0, 0 - yOff); glVertex2f(-1,-1); - glEnd(); - - TextureMngr::DisableStage(0); - - Renderer::SwapBuffers(); - - Renderer::RestoreGLState(); - GL_REPORT_ERRORD(); -} - -#else - -static GLuint xfb_texture; -static u8 *xfb_buffer = 0; -static u8 *efb_buffer = 0; -static GLuint s_xfbFrameBuffer = 0; -static GLuint s_xfbRenderBuffer = 0; - -void XFB_Init() -{ - // used to render XFB - xfb_buffer = new u8[XFB_WIDTH * XFB_BUF_HEIGHT * 4]; - memset(xfb_buffer, 0, XFB_WIDTH * XFB_BUF_HEIGHT * 4); - glGenTextures(1, &xfb_texture); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfb_texture); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, XFB_WIDTH, XFB_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_BYTE, xfb_buffer); - - // used to render EFB - glGenFramebuffersEXT( 1, &s_xfbFrameBuffer); - glGenRenderbuffersEXT(1, &s_xfbRenderBuffer); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_xfbRenderBuffer); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, nBackbufferWidth, nBackbufferHeight); - - // Ensure efb_buffer is aligned. - efb_buffer = (u8 *)AllocateMemoryPages(nBackbufferWidth * nBackbufferHeight * 4); -} - -void XFB_Shutdown() -{ - glDeleteFramebuffersEXT(1, &s_xfbFrameBuffer); - - glDeleteTextures(1, &xfb_texture); - xfb_texture = 0; - delete [] xfb_buffer; - xfb_buffer = 0; - FreeMemoryPages(efb_buffer, nBackbufferWidth * nBackbufferHeight * 4); -} - - -void XFB_Write(u8 *xfb_in_ram, const TRectangle& sourceRc, u32 dstWd, u32 dstHt) -{ - Renderer::SetRenderMode(Renderer::RM_Normal); - - Renderer::ResetGLState(); - - // switch to XFB frame buffer - Renderer::SetFramebuffer(s_xfbFrameBuffer); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_xfbRenderBuffer); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, s_xfbRenderBuffer); - GL_REPORT_ERRORD(); - - glViewport(nXoff, nYoff, nBackbufferWidth, nBackbufferHeight); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, Renderer::GetRenderTarget()); - TextureMngr::EnableTexRECT(0); - for (int i = 1; i < 8; ++i) - TextureMngr::DisableStage(i); - GL_REPORT_ERRORD(); - - glBegin(GL_QUADS); - glTexCoord2f(0, nBackbufferHeight); glVertex2f(-1,-1); - glTexCoord2f(0, 0); glVertex2f(-1,1); - glTexCoord2f(nBackbufferWidth, 0); glVertex2f(1,1); - glTexCoord2f(nBackbufferWidth, nBackbufferHeight); glVertex2f(1,-1); - glEnd(); - GL_REPORT_ERRORD(); - - int width = sourceRc.right - sourceRc.left; - int height = sourceRc.bottom - sourceRc.top; - glReadPixels(sourceRc.left, sourceRc.top, width, height, GL_RGBA, GL_UNSIGNED_BYTE, efb_buffer); - GL_REPORT_ERRORD(); - - Renderer::SetFramebuffer(0); - Renderer::RestoreGLState(); - VertexShaderMngr::SetViewportChanged(); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - TextureMngr::DisableStage(0); - - Renderer::RestoreGLState(); - GL_REPORT_ERRORD(); - - // TODO - use shader for conversion - ConvertToXFB((u32 *)xfb_in_ram, efb_buffer, dstWd, dstHt); -} - -void XFB_Draw(u8 *xfb_in_ram, u32 width, u32 height, s32 yOffset) -{ - OpenGL_Update(); // just updates the render window position and the backbuffer size - - Renderer::SetRenderMode(Renderer::RM_Normal); - - // render to the real buffer now - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer - glViewport(nXoff, nYoff, nBackbufferWidth, nBackbufferHeight); - - Renderer::ResetGLState(); - - // TODO - use shader for conversion - ConvertFromXFB((u32 *)xfb_buffer, xfb_in_ram, width, height); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfb_texture); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, xfb_buffer); - TextureMngr::EnableTexRECT(0); - for (int i = 1; i < 8; ++i) - TextureMngr::DisableStage(i); - - GL_REPORT_ERRORD(); - - glBegin(GL_QUADS); - glTexCoord2f(width, height + yOffset); glVertex2f(1,-1); - glTexCoord2f(width, 0 + yOffset); glVertex2f(1,1); - glTexCoord2f(0, 0 + yOffset); glVertex2f(-1,1); - glTexCoord2f(0, height + yOffset); glVertex2f(-1,-1); - glEnd(); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - TextureMngr::DisableStage(0); - - Renderer::SwapBuffers(); - - Renderer::RestoreGLState(); - GL_REPORT_ERRORD(); -} - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +// Preliminary non-working code. + +#include "Globals.h" +#include "GLUtil.h" +#include "MemoryUtil.h" +#include "Render.h" +#include "TextureMngr.h" +#include "VertexShaderManager.h" +#include "XFBConvert.h" +#include "TextureConverter.h" + +#define XFB_USE_SHADERS 1 + +enum { + XFB_WIDTH = 640, + XFB_HEIGHT = 480, // 528 is max height. + XFB_BUF_HEIGHT = 538, //480, + // TODO: figure out what to do with PAL +}; + + +#if XFB_USE_SHADERS + +static GLuint xfb_decoded_texture; + +void XFB_Init() +{ + glGenTextures(1, &xfb_decoded_texture); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfb_decoded_texture); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, XFB_WIDTH, XFB_BUF_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); +} + +void XFB_Shutdown() +{ + glDeleteTextures(1, &xfb_decoded_texture); +} + + +void XFB_Write(u8 *xfb_in_ram, const TRectangle& sourceRc, u32 dstWd, u32 dstHt) +{ + TRectangle renderSrcRc; + renderSrcRc.left = sourceRc.left; + renderSrcRc.right = sourceRc.right; + renderSrcRc.top = nBackbufferHeight - sourceRc.top; + renderSrcRc.bottom = nBackbufferHeight - sourceRc.bottom; + TextureConverter::EncodeToRam(Renderer::GetRenderTarget(), renderSrcRc, xfb_in_ram, dstWd, dstHt); +} + +void XFB_Draw(u8 *xfb_in_ram, u32 width, u32 height, s32 yOffset) +{ + TextureConverter::DecodeToTexture(xfb_in_ram, width, height, xfb_decoded_texture); + + OpenGL_Update(); // just updates the render window position and the backbuffer size + + Renderer::ResetGLState(); + + TextureMngr::EnableTexRECT(0); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfb_decoded_texture); + + glViewport(nXoff, nYoff, nBackbufferWidth, nBackbufferHeight); + GL_REPORT_ERRORD(); + + float w = (float)width; + float h = (float)height; + float yOff = (float)yOffset; + + glBegin(GL_QUADS); + glTexCoord2f(w, 0 - yOff); glVertex2f(1, -1); + glTexCoord2f(w, h - yOff); glVertex2f(1, 1); + glTexCoord2f(0, h - yOff); glVertex2f(-1, 1); + glTexCoord2f(0, 0 - yOff); glVertex2f(-1,-1); + glEnd(); + + TextureMngr::DisableStage(0); + + Renderer::SwapBuffers(); + + Renderer::RestoreGLState(); + GL_REPORT_ERRORD(); +} + +#else + +static GLuint xfb_texture; +static u8 *xfb_buffer = 0; +static u8 *efb_buffer = 0; +static GLuint s_xfbFrameBuffer = 0; +static GLuint s_xfbRenderBuffer = 0; + +void XFB_Init() +{ + // used to render XFB + xfb_buffer = new u8[XFB_WIDTH * XFB_BUF_HEIGHT * 4]; + memset(xfb_buffer, 0, XFB_WIDTH * XFB_BUF_HEIGHT * 4); + glGenTextures(1, &xfb_texture); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfb_texture); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, XFB_WIDTH, XFB_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_BYTE, xfb_buffer); + + // used to render EFB + glGenFramebuffersEXT( 1, &s_xfbFrameBuffer); + glGenRenderbuffersEXT(1, &s_xfbRenderBuffer); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_xfbRenderBuffer); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, nBackbufferWidth, nBackbufferHeight); + + // Ensure efb_buffer is aligned. + efb_buffer = (u8 *)AllocateMemoryPages(nBackbufferWidth * nBackbufferHeight * 4); +} + +void XFB_Shutdown() +{ + glDeleteFramebuffersEXT(1, &s_xfbFrameBuffer); + + glDeleteTextures(1, &xfb_texture); + xfb_texture = 0; + delete [] xfb_buffer; + xfb_buffer = 0; + FreeMemoryPages(efb_buffer, nBackbufferWidth * nBackbufferHeight * 4); +} + + +void XFB_Write(u8 *xfb_in_ram, const TRectangle& sourceRc, u32 dstWd, u32 dstHt) +{ + Renderer::SetRenderMode(Renderer::RM_Normal); + + Renderer::ResetGLState(); + + // switch to XFB frame buffer + Renderer::SetFramebuffer(s_xfbFrameBuffer); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_xfbRenderBuffer); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, s_xfbRenderBuffer); + GL_REPORT_ERRORD(); + + glViewport(nXoff, nYoff, nBackbufferWidth, nBackbufferHeight); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, Renderer::GetRenderTarget()); + TextureMngr::EnableTexRECT(0); + for (int i = 1; i < 8; ++i) + TextureMngr::DisableStage(i); + GL_REPORT_ERRORD(); + + glBegin(GL_QUADS); + glTexCoord2f(0, nBackbufferHeight); glVertex2f(-1,-1); + glTexCoord2f(0, 0); glVertex2f(-1,1); + glTexCoord2f(nBackbufferWidth, 0); glVertex2f(1,1); + glTexCoord2f(nBackbufferWidth, nBackbufferHeight); glVertex2f(1,-1); + glEnd(); + GL_REPORT_ERRORD(); + + int width = sourceRc.right - sourceRc.left; + int height = sourceRc.bottom - sourceRc.top; + glReadPixels(sourceRc.left, sourceRc.top, width, height, GL_RGBA, GL_UNSIGNED_BYTE, efb_buffer); + GL_REPORT_ERRORD(); + + Renderer::SetFramebuffer(0); + Renderer::RestoreGLState(); + VertexShaderMngr::SetViewportChanged(); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + TextureMngr::DisableStage(0); + + Renderer::RestoreGLState(); + GL_REPORT_ERRORD(); + + // TODO - use shader for conversion + ConvertToXFB((u32 *)xfb_in_ram, efb_buffer, dstWd, dstHt); +} + +void XFB_Draw(u8 *xfb_in_ram, u32 width, u32 height, s32 yOffset) +{ + OpenGL_Update(); // just updates the render window position and the backbuffer size + + Renderer::SetRenderMode(Renderer::RM_Normal); + + // render to the real buffer now + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer + glViewport(nXoff, nYoff, nBackbufferWidth, nBackbufferHeight); + + Renderer::ResetGLState(); + + // TODO - use shader for conversion + ConvertFromXFB((u32 *)xfb_buffer, xfb_in_ram, width, height); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfb_texture); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, xfb_buffer); + TextureMngr::EnableTexRECT(0); + for (int i = 1; i < 8; ++i) + TextureMngr::DisableStage(i); + + GL_REPORT_ERRORD(); + + glBegin(GL_QUADS); + glTexCoord2f(width, height + yOffset); glVertex2f(1,-1); + glTexCoord2f(width, 0 + yOffset); glVertex2f(1,1); + glTexCoord2f(0, 0 + yOffset); glVertex2f(-1,1); + glTexCoord2f(0, height + yOffset); glVertex2f(-1,-1); + glEnd(); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + TextureMngr::DisableStage(0); + + Renderer::SwapBuffers(); + + Renderer::RestoreGLState(); + GL_REPORT_ERRORD(); +} + #endif \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index 4bba72be15..d5218fda09 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -1,362 +1,362 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Globals.h" - -#ifdef _WIN32 -#include "OS/Win32.h" -#endif - -#if defined(USE_SDL) && USE_SDL -#include -#endif - -#if defined(HAVE_WX) && HAVE_WX -#include "GUI/ConfigDlg.h" -#endif - -#include "Config.h" -#include "LookUpTables.h" -#include "ImageWrite.h" -#include "Render.h" -#include "GLUtil.h" -#include "Fifo.h" -#include "OpcodeDecoding.h" -#include "TextureMngr.h" -#include "BPStructs.h" -#include "VertexLoader.h" -#include "VertexLoaderManager.h" -#include "VertexManager.h" -#include "PixelShaderManager.h" -#include "VertexShaderManager.h" -#include "XFB.h" -#include "XFBConvert.h" -#include "TextureConverter.h" - -#include "VideoState.h" -#if defined(HAVE_WX) && HAVE_WX -#include "Debugger/Debugger.h" // for the CDebugger class -#endif -SVideoInitialize g_VideoInitialize; - - -/* Create debugging window. There's currently a strange crash that occurs whe a game is loaded - if the OpenGL plugin was loaded before. I'll try to fix that. Currently you may have to - clsoe the window if it has auto started, and then restart it after the dll has loaded - for the purpose of the game. At that point there is no need to use the same dll instance - as the one that is rendering the game. However, that could be done. */ - -#if defined(HAVE_WX) && HAVE_WX -CDebugger* m_frame; -void DllDebugger(HWND _hParent, bool Show) -{ - if(m_frame && Show) // if we have created it, let us show it again - { - m_frame->DoShow(); - } - else if(!m_frame && Show) - { - m_frame = new CDebugger(NULL); - m_frame->Show(); - } - else if(m_frame && !Show) - { - m_frame->DoHide(); - } -} - -void DoDllDebugger() -{ - //m_frame = new CDebugger(NULL); - //m_frame->Show(); -} -#else -void DllDebugger(HWND _hParent) { } -void DoDllDebugger() { } -#endif - - -void GetDllInfo (PLUGIN_INFO* _PluginInfo) -{ - _PluginInfo->Version = 0x0100; - _PluginInfo->Type = PLUGIN_TYPE_VIDEO; -#ifdef DEBUGFAST - sprintf(_PluginInfo->Name, "Dolphin OpenGL (DebugFast)"); -#else -#ifndef _DEBUG - sprintf(_PluginInfo->Name, "Dolphin OpenGL"); -#else - sprintf(_PluginInfo->Name, "Dolphin OpenGL (Debug)"); -#endif -#endif -} - -void DllConfig(HWND _hParent) -{ -#if defined(_WIN32) - //wxWindow win; - //win.SetHWND(_hParent); - //ConfigDialog frame(&win); - //ConfigDialog frame(NULL); - - ConfigDialog *frame; - frame = new ConfigDialog(NULL); - - DWORD iModeNum = 0; - DEVMODE dmi; - ZeroMemory(&dmi, sizeof(dmi)); - dmi.dmSize = sizeof(dmi); - std::string resos[100]; - int i = 0; - - while (EnumDisplaySettings(NULL, iModeNum++, &dmi) != 0) - { - char szBuffer[100]; - sprintf(szBuffer,"%dx%d", dmi.dmPelsWidth, dmi.dmPelsHeight); - //making a string cause char*[] to char was a baaad idea - std::string strBuffer(szBuffer); - //create a check loop to check every pointer of resos to see if the res is added or not - int b = 0; - bool resFound = false; - while (b < i && !resFound) - { - //is the res already added? - resFound = (resos[b] == strBuffer); - b++; - } - if (!resFound) - //and add the res - { - resos[i] = strBuffer; - i++; - //frame.AddFSReso(szBuffer); - //frame.AddWindowReso(szBuffer); - frame->AddFSReso(szBuffer); - frame->AddWindowReso(szBuffer); - } - ZeroMemory(&dmi, sizeof(dmi)); - } - //frame.ShowModal(); - frame->ShowModal(); - //win.SetHWND(0); - -#elif defined(HAVE_WX) && HAVE_WX - ConfigDialog frame(NULL); - g_Config.Load(); - int glxMajorVersion, glxMinorVersion; - int vidModeMajorVersion, vidModeMinorVersion; - GLWin.dpy = XOpenDisplay(0); - glXQueryVersion(GLWin.dpy, &glxMajorVersion, &glxMinorVersion); - XF86VidModeQueryVersion(GLWin.dpy, &vidModeMajorVersion, &vidModeMinorVersion); - //Get all full screen resos for the config dialog - XF86VidModeModeInfo **modes = NULL; - int modeNum = 0; - int bestMode = 0; - - //set best mode to current - bestMode = 0; - XF86VidModeGetAllModeLines(GLWin.dpy, GLWin.screen, &modeNum, &modes); - int px = 0, py = 0; - if (modeNum > 0 && modes != NULL) - { - for (int i = 0; i < modeNum; i++) - { - if(px != modes[i]->hdisplay && py != modes[i]->vdisplay) - { - char temp[32]; - sprintf(temp,"%dx%d", modes[i]->hdisplay, modes[i]->vdisplay); - frame.AddFSReso(temp); - frame.AddWindowReso(temp);//Add same to Window ones, since they should be nearly all that's needed - px = modes[i]->hdisplay;//Used to remove repeating from different screen depths - py = modes[i]->vdisplay; - } - } - } - XFree(modes); - frame.ShowModal(); -#else - //TODO -#endif -} - -void Video_Initialize(SVideoInitialize* _pVideoInitialize) -{ - if (_pVideoInitialize == NULL) - return; - -#ifdef _WIN32 -// OpenConsole(); -#endif - - /* Dolphin currently crashes if the dll is loaded when a game is started so we clsoe the - debugger and open it again after loading */ - /* - if(m_frame) - { - m_frame->EndModal(0); wxEntryCleanup(); - }//use wxUninitialize() if you don't want GUI - */ - - frameCount = 0; - g_VideoInitialize = *_pVideoInitialize; - InitLUTs(); - InitXFBConvTables(); - g_Config.Load(); - - if (!OpenGL_Create(g_VideoInitialize, 640, 480)) { //640x480 will be the default if all else fails// - g_VideoInitialize.pLog("Renderer::Create failed\n", TRUE); - return; - } - _pVideoInitialize->pPeekMessages = g_VideoInitialize.pPeekMessages; - _pVideoInitialize->pUpdateFPSDisplay = g_VideoInitialize.pUpdateFPSDisplay; - _pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle; - - Renderer::AddMessage("Dolphin OpenGL Video Plugin" ,5000); -} - -void Video_DoState(unsigned char **ptr, int mode) { -#ifdef _WIN32 -// What is this code doing here? -// if (!wglMakeCurrent(hDC,hRC)) { -// PanicAlert("Can't Activate The GL Rendering Context for saving"); -// return; -// } -#elif defined(OSX64) - cocoaGLMakeCurrent(GLWin.cocoaCtx,GLWin.cocoaWin); -#else // Linux - glXMakeCurrent(GLWin.dpy, GLWin.win, GLWin.ctx); -#endif - - // Clear all caches that touch RAM - TextureMngr::Invalidate(); - // DisplayListManager::Invalidate(); - - VertexLoaderManager::MarkAllDirty(); - - PointerWrap p(ptr, mode); - VideoCommon_DoState(p); - - // Refresh state. - if (mode == PointerWrap::MODE_READ) - BPReload(); -} - -// This is called after Video_Initialize() from the Core -void Video_Prepare(void) -{ - OpenGL_MakeCurrent(); - if (!Renderer::Create2()) { - g_VideoInitialize.pLog("Renderer::Create2 failed\n", TRUE); - PanicAlert("Can't create opengl renderer. You might be missing some required opengl extensions, check the logs for more info"); - exit(1); - } - - TextureMngr::Init(); - - BPInit(); - VertexManager::Init(); - Fifo_Init(); // must be done before OpcodeDecoder_Init() - OpcodeDecoder_Init(); - VertexShaderMngr::Init(); - PixelShaderMngr::Init(); - GL_REPORT_ERRORD(); - VertexLoaderManager::Init(); - TextureConverter::Init(); -} - -void Video_Shutdown(void) -{ - TextureConverter::Shutdown(); - VertexLoaderManager::Shutdown(); - VertexShaderMngr::Shutdown(); - PixelShaderMngr::Shutdown(); - Fifo_Shutdown(); - VertexManager::Shutdown(); - TextureMngr::Shutdown(); - OpcodeDecoder_Shutdown(); - Renderer::Shutdown(); - OpenGL_Shutdown(); -} - -void Video_Stop(void) -{ - Fifo_Stop(); -} - -void Video_EnterLoop() -{ - Fifo_EnterLoop(g_VideoInitialize); -} - -void DebugLog(const char* _fmt, ...) -{ -#if defined(_DEBUG) || defined(DEBUGFAST) - - char* Msg = (char*)alloca(strlen(_fmt)+512); - va_list ap; - - va_start( ap, _fmt ); - vsnprintf( Msg, strlen(_fmt)+512, _fmt, ap ); - va_end( ap ); - - g_VideoInitialize.pLog(Msg, FALSE); -#endif -} - -bool ScreenShot(TCHAR *File) -{ - char str[64]; - int left = 200, top = 15; - sprintf(str, "Dolphin OpenGL"); - - Renderer::ResetGLState(); - Renderer::RenderText(str, left+1, top+1, 0xff000000); - Renderer::RenderText(str, left, top, 0xffc0ffff); - Renderer::RestoreGLState(); - - if (Renderer::SaveRenderTarget(File, 0)) { - char msg[255]; - sprintf(msg, "saved %s\n", File); - Renderer::AddMessage(msg, 500); - return true; - } - return false; -} -#if defined(OSX64) -unsigned int Video_Screenshot(TCHAR* _szFilename) -#else -BOOL Video_Screenshot(TCHAR* _szFilename) -#endif -{ - if (ScreenShot(_szFilename)) - return TRUE; - - return FALSE; -} - -void Video_UpdateXFB(u8* _pXFB, u32 _dwWidth, u32 _dwHeight, s32 _dwYOffset) -{ - if(g_Config.bUseXFB) - { - XFB_Draw(_pXFB, _dwWidth, _dwHeight, _dwYOffset); - } -} - -void Video_AddMessage(const char* pstr, u32 milliseconds) -{ - Renderer::AddMessage(pstr,milliseconds); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Globals.h" + +#ifdef _WIN32 +#include "OS/Win32.h" +#endif + +#if defined(USE_SDL) && USE_SDL +#include +#endif + +#if defined(HAVE_WX) && HAVE_WX +#include "GUI/ConfigDlg.h" +#endif + +#include "Config.h" +#include "LookUpTables.h" +#include "ImageWrite.h" +#include "Render.h" +#include "GLUtil.h" +#include "Fifo.h" +#include "OpcodeDecoding.h" +#include "TextureMngr.h" +#include "BPStructs.h" +#include "VertexLoader.h" +#include "VertexLoaderManager.h" +#include "VertexManager.h" +#include "PixelShaderManager.h" +#include "VertexShaderManager.h" +#include "XFB.h" +#include "XFBConvert.h" +#include "TextureConverter.h" + +#include "VideoState.h" +#if defined(HAVE_WX) && HAVE_WX +#include "Debugger/Debugger.h" // for the CDebugger class +#endif +SVideoInitialize g_VideoInitialize; + + +/* Create debugging window. There's currently a strange crash that occurs whe a game is loaded + if the OpenGL plugin was loaded before. I'll try to fix that. Currently you may have to + clsoe the window if it has auto started, and then restart it after the dll has loaded + for the purpose of the game. At that point there is no need to use the same dll instance + as the one that is rendering the game. However, that could be done. */ + +#if defined(HAVE_WX) && HAVE_WX +CDebugger* m_frame; +void DllDebugger(HWND _hParent, bool Show) +{ + if(m_frame && Show) // if we have created it, let us show it again + { + m_frame->DoShow(); + } + else if(!m_frame && Show) + { + m_frame = new CDebugger(NULL); + m_frame->Show(); + } + else if(m_frame && !Show) + { + m_frame->DoHide(); + } +} + +void DoDllDebugger() +{ + //m_frame = new CDebugger(NULL); + //m_frame->Show(); +} +#else +void DllDebugger(HWND _hParent) { } +void DoDllDebugger() { } +#endif + + +void GetDllInfo (PLUGIN_INFO* _PluginInfo) +{ + _PluginInfo->Version = 0x0100; + _PluginInfo->Type = PLUGIN_TYPE_VIDEO; +#ifdef DEBUGFAST + sprintf(_PluginInfo->Name, "Dolphin OpenGL (DebugFast)"); +#else +#ifndef _DEBUG + sprintf(_PluginInfo->Name, "Dolphin OpenGL"); +#else + sprintf(_PluginInfo->Name, "Dolphin OpenGL (Debug)"); +#endif +#endif +} + +void DllConfig(HWND _hParent) +{ +#if defined(_WIN32) + //wxWindow win; + //win.SetHWND(_hParent); + //ConfigDialog frame(&win); + //ConfigDialog frame(NULL); + + ConfigDialog *frame; + frame = new ConfigDialog(NULL); + + DWORD iModeNum = 0; + DEVMODE dmi; + ZeroMemory(&dmi, sizeof(dmi)); + dmi.dmSize = sizeof(dmi); + std::string resos[100]; + int i = 0; + + while (EnumDisplaySettings(NULL, iModeNum++, &dmi) != 0) + { + char szBuffer[100]; + sprintf(szBuffer,"%dx%d", dmi.dmPelsWidth, dmi.dmPelsHeight); + //making a string cause char*[] to char was a baaad idea + std::string strBuffer(szBuffer); + //create a check loop to check every pointer of resos to see if the res is added or not + int b = 0; + bool resFound = false; + while (b < i && !resFound) + { + //is the res already added? + resFound = (resos[b] == strBuffer); + b++; + } + if (!resFound) + //and add the res + { + resos[i] = strBuffer; + i++; + //frame.AddFSReso(szBuffer); + //frame.AddWindowReso(szBuffer); + frame->AddFSReso(szBuffer); + frame->AddWindowReso(szBuffer); + } + ZeroMemory(&dmi, sizeof(dmi)); + } + //frame.ShowModal(); + frame->ShowModal(); + //win.SetHWND(0); + +#elif defined(HAVE_WX) && HAVE_WX + ConfigDialog frame(NULL); + g_Config.Load(); + int glxMajorVersion, glxMinorVersion; + int vidModeMajorVersion, vidModeMinorVersion; + GLWin.dpy = XOpenDisplay(0); + glXQueryVersion(GLWin.dpy, &glxMajorVersion, &glxMinorVersion); + XF86VidModeQueryVersion(GLWin.dpy, &vidModeMajorVersion, &vidModeMinorVersion); + //Get all full screen resos for the config dialog + XF86VidModeModeInfo **modes = NULL; + int modeNum = 0; + int bestMode = 0; + + //set best mode to current + bestMode = 0; + XF86VidModeGetAllModeLines(GLWin.dpy, GLWin.screen, &modeNum, &modes); + int px = 0, py = 0; + if (modeNum > 0 && modes != NULL) + { + for (int i = 0; i < modeNum; i++) + { + if(px != modes[i]->hdisplay && py != modes[i]->vdisplay) + { + char temp[32]; + sprintf(temp,"%dx%d", modes[i]->hdisplay, modes[i]->vdisplay); + frame.AddFSReso(temp); + frame.AddWindowReso(temp);//Add same to Window ones, since they should be nearly all that's needed + px = modes[i]->hdisplay;//Used to remove repeating from different screen depths + py = modes[i]->vdisplay; + } + } + } + XFree(modes); + frame.ShowModal(); +#else + //TODO +#endif +} + +void Video_Initialize(SVideoInitialize* _pVideoInitialize) +{ + if (_pVideoInitialize == NULL) + return; + +#ifdef _WIN32 +// OpenConsole(); +#endif + + /* Dolphin currently crashes if the dll is loaded when a game is started so we clsoe the + debugger and open it again after loading */ + /* + if(m_frame) + { + m_frame->EndModal(0); wxEntryCleanup(); + }//use wxUninitialize() if you don't want GUI + */ + + frameCount = 0; + g_VideoInitialize = *_pVideoInitialize; + InitLUTs(); + InitXFBConvTables(); + g_Config.Load(); + + if (!OpenGL_Create(g_VideoInitialize, 640, 480)) { //640x480 will be the default if all else fails// + g_VideoInitialize.pLog("Renderer::Create failed\n", TRUE); + return; + } + _pVideoInitialize->pPeekMessages = g_VideoInitialize.pPeekMessages; + _pVideoInitialize->pUpdateFPSDisplay = g_VideoInitialize.pUpdateFPSDisplay; + _pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle; + + Renderer::AddMessage("Dolphin OpenGL Video Plugin" ,5000); +} + +void Video_DoState(unsigned char **ptr, int mode) { +#ifdef _WIN32 +// What is this code doing here? +// if (!wglMakeCurrent(hDC,hRC)) { +// PanicAlert("Can't Activate The GL Rendering Context for saving"); +// return; +// } +#elif defined(OSX64) + cocoaGLMakeCurrent(GLWin.cocoaCtx,GLWin.cocoaWin); +#else // Linux + glXMakeCurrent(GLWin.dpy, GLWin.win, GLWin.ctx); +#endif + + // Clear all caches that touch RAM + TextureMngr::Invalidate(); + // DisplayListManager::Invalidate(); + + VertexLoaderManager::MarkAllDirty(); + + PointerWrap p(ptr, mode); + VideoCommon_DoState(p); + + // Refresh state. + if (mode == PointerWrap::MODE_READ) + BPReload(); +} + +// This is called after Video_Initialize() from the Core +void Video_Prepare(void) +{ + OpenGL_MakeCurrent(); + if (!Renderer::Create2()) { + g_VideoInitialize.pLog("Renderer::Create2 failed\n", TRUE); + PanicAlert("Can't create opengl renderer. You might be missing some required opengl extensions, check the logs for more info"); + exit(1); + } + + TextureMngr::Init(); + + BPInit(); + VertexManager::Init(); + Fifo_Init(); // must be done before OpcodeDecoder_Init() + OpcodeDecoder_Init(); + VertexShaderMngr::Init(); + PixelShaderMngr::Init(); + GL_REPORT_ERRORD(); + VertexLoaderManager::Init(); + TextureConverter::Init(); +} + +void Video_Shutdown(void) +{ + TextureConverter::Shutdown(); + VertexLoaderManager::Shutdown(); + VertexShaderMngr::Shutdown(); + PixelShaderMngr::Shutdown(); + Fifo_Shutdown(); + VertexManager::Shutdown(); + TextureMngr::Shutdown(); + OpcodeDecoder_Shutdown(); + Renderer::Shutdown(); + OpenGL_Shutdown(); +} + +void Video_Stop(void) +{ + Fifo_Stop(); +} + +void Video_EnterLoop() +{ + Fifo_EnterLoop(g_VideoInitialize); +} + +void DebugLog(const char* _fmt, ...) +{ +#if defined(_DEBUG) || defined(DEBUGFAST) + + char* Msg = (char*)alloca(strlen(_fmt)+512); + va_list ap; + + va_start( ap, _fmt ); + vsnprintf( Msg, strlen(_fmt)+512, _fmt, ap ); + va_end( ap ); + + g_VideoInitialize.pLog(Msg, FALSE); +#endif +} + +bool ScreenShot(TCHAR *File) +{ + char str[64]; + int left = 200, top = 15; + sprintf(str, "Dolphin OpenGL"); + + Renderer::ResetGLState(); + Renderer::RenderText(str, left+1, top+1, 0xff000000); + Renderer::RenderText(str, left, top, 0xffc0ffff); + Renderer::RestoreGLState(); + + if (Renderer::SaveRenderTarget(File, 0)) { + char msg[255]; + sprintf(msg, "saved %s\n", File); + Renderer::AddMessage(msg, 500); + return true; + } + return false; +} +#if defined(OSX64) +unsigned int Video_Screenshot(TCHAR* _szFilename) +#else +BOOL Video_Screenshot(TCHAR* _szFilename) +#endif +{ + if (ScreenShot(_szFilename)) + return TRUE; + + return FALSE; +} + +void Video_UpdateXFB(u8* _pXFB, u32 _dwWidth, u32 _dwHeight, s32 _dwYOffset) +{ + if(g_Config.bUseXFB) + { + XFB_Draw(_pXFB, _dwWidth, _dwHeight, _dwYOffset); + } +} + +void Video_AddMessage(const char* pstr, u32 milliseconds) +{ + Renderer::AddMessage(pstr,milliseconds); +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/memcpy_amd.cpp b/Source/Plugins/Plugin_VideoOGL/Src/memcpy_amd.cpp index 8b3fc8f1e4..4bc3012e81 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/memcpy_amd.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/memcpy_amd.cpp @@ -1,473 +1,473 @@ -/****************************************************************************** - - Copyright (c) 2001 Advanced Micro Devices, Inc. - - LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED *AS IS* WITHOUT ANY - EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, - NONINFRINGEMENT OF THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY - PARTICULAR PURPOSE. IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY - DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, - BUSINESS INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR - INABILITY TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY - OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION OR LIMITATION - OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY - NOT APPLY TO YOU. - - AMD does not assume any responsibility for any errors which may appear in the - Materials nor any responsibility to support or update the Materials. AMD retains - the right to make changes to its test specifications at any time, without notice. - - NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any - further information, software, technical information, know-how, or show-how - available to you. - - So that all may benefit from your experience, please report any problems - or suggestions about this software to 3dsdk.support@amd.com - - AMD Developer Technologies, M/S 585 - Advanced Micro Devices, Inc. - 5900 E. Ben White Blvd. - Austin, TX 78741 - 3dsdk.support@amd.com -******************************************************************************/ - -#include - -/***************************************************************************** -MEMCPY_AMD.CPP -******************************************************************************/ - -// Very optimized memcpy() routine for AMD Athlon and Duron family. -// This code uses any of FOUR different basic copy methods, depending -// on the transfer size. -// NOTE: Since this code uses MOVNTQ (also known as "Non-Temporal MOV" or -// "Streaming Store"), and also uses the software prefetch instructions, -// be sure you're running on Athlon/Duron or other recent CPU before calling! - -#define TINY_BLOCK_COPY 64 // upper limit for movsd type copy -// The smallest copy uses the X86 "movsd" instruction, in an optimized -// form which is an "unrolled loop". - -#define IN_CACHE_COPY 2 * 1024 // upper limit for movq/movq copy w/SW prefetch -// Next is a copy that uses the MMX registers to copy 8 bytes at a time, -// also using the "unrolled loop" optimization. This code uses -// the software prefetch instruction to get the data into the cache. - -#define UNCACHED_COPY 4 * 1024 // upper limit for movq/movntq w/SW prefetch -// For larger blocks, which will spill beyond the cache, it's faster to -// use the Streaming Store instruction MOVNTQ. This write instruction -// bypasses the cache and writes straight to main memory. This code also -// uses the software prefetch instruction to pre-read the data. -// USE 64 * 1024 FOR THIS VALUE IF YOU'RE ALWAYS FILLING A "CLEAN CACHE" - -#define BLOCK_PREFETCH_COPY infinity // no limit for movq/movntq w/block prefetch -#define CACHEBLOCK 80h // number of 64-byte blocks (cache lines) for block prefetch -// For the largest size blocks, a special technique called Block Prefetch -// can be used to accelerate the read operations. Block Prefetch reads -// one address per cache line, for a series of cache lines, in a short loop. -// This is faster than using software prefetch. The technique is great for -// getting maximum read bandwidth, especially in DDR memory systems. - -//#include - -// Inline assembly syntax for use with Visual C++ -#ifdef _WIN32 -#include -#endif - -#if defined(_MSC_VER) && !defined(__x86_64__) && !defined(_M_X64) - -void * memcpy_amd(void *dest, const void *src, size_t n) -{ - __asm { - mov ecx, [n] ; number of bytes to copy - mov edi, [dest] ; destination - mov esi, [src] ; source - mov ebx, ecx ; keep a copy of count - - cld - cmp ecx, TINY_BLOCK_COPY - jb $memcpy_ic_3 ; tiny? skip mmx copy - - cmp ecx, 32*1024 ; do not align between 32k-64k because - jbe $memcpy_do_align ; it appears to be slower - cmp ecx, 64*1024 - jbe $memcpy_align_done -$memcpy_do_align: - mov ecx, 8 ; a trick that is faster than rep movsb... - sub ecx, edi ; align destination to qword - and ecx, 111b ; get the low bits - sub ebx, ecx ; update copy count - neg ecx ; set up to jump into the array - add ecx, offset $memcpy_align_done - jmp ecx ; jump to array of movsb''s - -align 4 - movsb - movsb - movsb - movsb - movsb - movsb - movsb - movsb - -$memcpy_align_done: ; destination is dword aligned - mov ecx, ebx ; number of bytes left to copy - shr ecx, 6 ; get 64-byte block count - jz $memcpy_ic_2 ; finish the last few bytes - - cmp ecx, IN_CACHE_COPY/64 ; too big 4 cache? use uncached copy - jae $memcpy_uc_test - -// This is small block copy that uses the MMX registers to copy 8 bytes -// at a time. It uses the "unrolled loop" optimization, and also uses -// the software prefetch instruction to get the data into the cache. -align 16 -$memcpy_ic_1: ; 64-byte block copies, in-cache copy - - prefetchnta [esi + (200*64/34+192)] ; start reading ahead - - movq mm0, [esi+0] ; read 64 bits - movq mm1, [esi+8] - movq [edi+0], mm0 ; write 64 bits - movq [edi+8], mm1 ; note: the normal movq writes the - movq mm2, [esi+16] ; data to cache; a cache line will be - movq mm3, [esi+24] ; allocated as needed, to store the data - movq [edi+16], mm2 - movq [edi+24], mm3 - movq mm0, [esi+32] - movq mm1, [esi+40] - movq [edi+32], mm0 - movq [edi+40], mm1 - movq mm2, [esi+48] - movq mm3, [esi+56] - movq [edi+48], mm2 - movq [edi+56], mm3 - - add esi, 64 ; update source pointer - add edi, 64 ; update destination pointer - dec ecx ; count down - jnz $memcpy_ic_1 ; last 64-byte block? - -$memcpy_ic_2: - mov ecx, ebx ; has valid low 6 bits of the byte count -$memcpy_ic_3: - shr ecx, 2 ; dword count - and ecx, 1111b ; only look at the "remainder" bits - neg ecx ; set up to jump into the array - add ecx, offset $memcpy_last_few - jmp ecx ; jump to array of movsd''s - -$memcpy_uc_test: - cmp ecx, UNCACHED_COPY/64 ; big enough? use block prefetch copy - jae $memcpy_bp_1 - -$memcpy_64_test: - or ecx, ecx ; tail end of block prefetch will jump here - jz $memcpy_ic_2 ; no more 64-byte blocks left - -// For larger blocks, which will spill beyond the cache, it's faster to -// use the Streaming Store instruction MOVNTQ. This write instruction -// bypasses the cache and writes straight to main memory. This code also -// uses the software prefetch instruction to pre-read the data. -align 16 -$memcpy_uc_1: ; 64-byte blocks, uncached copy - - prefetchnta [esi + (200*64/34+192)] ; start reading ahead - - movq mm0,[esi+0] ; read 64 bits - add edi,64 ; update destination pointer - movq mm1,[esi+8] - add esi,64 ; update source pointer - movq mm2,[esi-48] - movntq [edi-64], mm0 ; write 64 bits, bypassing the cache - movq mm0,[esi-40] ; note: movntq also prevents the CPU - movntq [edi-56], mm1 ; from READING the destination address - movq mm1,[esi-32] ; into the cache, only to be over-written - movntq [edi-48], mm2 ; so that also helps performance - movq mm2,[esi-24] - movntq [edi-40], mm0 - movq mm0,[esi-16] - movntq [edi-32], mm1 - movq mm1,[esi-8] - movntq [edi-24], mm2 - movntq [edi-16], mm0 - dec ecx - movntq [edi-8], mm1 - jnz $memcpy_uc_1 ; last 64-byte block? - - jmp $memcpy_ic_2 ; almost done - -// For the largest size blocks, a special technique called Block Prefetch -// can be used to accelerate the read operations. Block Prefetch reads -// one address per cache line, for a series of cache lines, in a short loop. -// This is faster than using software prefetch. The technique is great for -// getting maximum read bandwidth, especially in DDR memory systems. -$memcpy_bp_1: ; large blocks, block prefetch copy - - cmp ecx, CACHEBLOCK ; big enough to run another prefetch loop? - jl $memcpy_64_test ; no, back to regular uncached copy - - mov eax, CACHEBLOCK / 2 ; block prefetch loop, unrolled 2X - add esi, CACHEBLOCK * 64 ; move to the top of the block -align 16 -$memcpy_bp_2: - mov edx, [esi-64] ; grab one address per cache line - mov edx, [esi-128] ; grab one address per cache line - sub esi, 128 ; go reverse order to suppress HW prefetcher - dec eax ; count down the cache lines - jnz $memcpy_bp_2 ; keep grabbing more lines into cache - - mov eax, CACHEBLOCK ; now that it is in cache, do the copy -align 16 -$memcpy_bp_3: - movq mm0, [esi ] ; read 64 bits - movq mm1, [esi+ 8] - movq mm2, [esi+16] - movq mm3, [esi+24] - movq mm4, [esi+32] - movq mm5, [esi+40] - movq mm6, [esi+48] - movq mm7, [esi+56] - add esi, 64 ; update source pointer - movntq [edi ], mm0 ; write 64 bits, bypassing cache - movntq [edi+ 8], mm1 ; note: movntq also prevents the CPU - movntq [edi+16], mm2 ; from READING the destination address - movntq [edi+24], mm3 ; into the cache, only to be over-written, - movntq [edi+32], mm4 ; so that also helps performance - movntq [edi+40], mm5 - movntq [edi+48], mm6 - movntq [edi+56], mm7 - add edi, 64 ; update dest pointer - - dec eax ; count down - - jnz $memcpy_bp_3 ; keep copying - sub ecx, CACHEBLOCK ; update the 64-byte block count - jmp $memcpy_bp_1 ; keep processing chunks - -// The smallest copy uses the X86 "movsd" instruction, in an optimized -// form which is an "unrolled loop". Then it handles the last few bytes. -align 4 - movsd - movsd ; perform last 1-15 dword copies - movsd - movsd - movsd - movsd - movsd - movsd - movsd - movsd ; perform last 1-7 dword copies - movsd - movsd - movsd - movsd - movsd - movsd - -$memcpy_last_few: ; dword aligned from before movsd''s - mov ecx, ebx ; has valid low 2 bits of the byte count - and ecx, 11b ; the last few cows must come home - jz $memcpy_final ; no more, lets leave - rep movsb ; the last 1, 2, or 3 bytes - -$memcpy_final: - emms ; clean up the MMX state - sfence ; flush the write buffer - mov eax, [dest] ; ret value = destination pointer - - } -} - -// mmx memcmp implementation, size has to be a multiple of 8 -// returns 0 is equal, nonzero value if not equal -// ~10 times faster than standard memcmp -// (zerofrog) -unsigned char memcmp_mmx(const void* src1, const void* src2, int cmpsize) -{ - assert( (cmpsize&7) == 0 ); - - __asm { - push esi - mov ecx, cmpsize - mov edx, src1 - mov esi, src2 - - cmp ecx, 32 - jl Done4 - - // custom test first 8 to make sure things are ok - movq mm0, [esi] - movq mm1, [esi+8] - pcmpeqd mm0, [edx] - pcmpeqd mm1, [edx+8] - pand mm0, mm1 - movq mm2, [esi+16] - pmovmskb eax, mm0 - movq mm3, [esi+24] - - // check if eq - cmp eax, 0xff - je NextComp - mov eax, 1 - jmp End - -NextComp: - pcmpeqd mm2, [edx+16] - pcmpeqd mm3, [edx+24] - pand mm2, mm3 - pmovmskb eax, mm2 - - sub ecx, 32 - add esi, 32 - add edx, 32 - - // check if eq - cmp eax, 0xff - je ContinueTest - mov eax, 1 - jmp End - - cmp ecx, 64 - jl Done8 - -Cmp8: - movq mm0, [esi] - movq mm1, [esi+8] - movq mm2, [esi+16] - movq mm3, [esi+24] - movq mm4, [esi+32] - movq mm5, [esi+40] - movq mm6, [esi+48] - movq mm7, [esi+56] - pcmpeqd mm0, [edx] - pcmpeqd mm1, [edx+8] - pcmpeqd mm2, [edx+16] - pcmpeqd mm3, [edx+24] - pand mm0, mm1 - pcmpeqd mm4, [edx+32] - pand mm0, mm2 - pcmpeqd mm5, [edx+40] - pand mm0, mm3 - pcmpeqd mm6, [edx+48] - pand mm0, mm4 - pcmpeqd mm7, [edx+56] - pand mm0, mm5 - pand mm0, mm6 - pand mm0, mm7 - pmovmskb eax, mm0 - - // check if eq - cmp eax, 0xff - je Continue - mov eax, 1 - jmp End - -Continue: - sub ecx, 64 - add esi, 64 - add edx, 64 -ContinueTest: - cmp ecx, 64 - jge Cmp8 - -Done8: - test ecx, 0x20 - jz Done4 - movq mm0, [esi] - movq mm1, [esi+8] - movq mm2, [esi+16] - movq mm3, [esi+24] - pcmpeqd mm0, [edx] - pcmpeqd mm1, [edx+8] - pcmpeqd mm2, [edx+16] - pcmpeqd mm3, [edx+24] - pand mm0, mm1 - pand mm0, mm2 - pand mm0, mm3 - pmovmskb eax, mm0 - sub ecx, 32 - add esi, 32 - add edx, 32 - - // check if eq - cmp eax, 0xff - je Done4 - mov eax, 1 - jmp End - -Done4: - cmp ecx, 24 - jne Done2 - movq mm0, [esi] - movq mm1, [esi+8] - movq mm2, [esi+16] - pcmpeqd mm0, [edx] - pcmpeqd mm1, [edx+8] - pcmpeqd mm2, [edx+16] - pand mm0, mm1 - pand mm0, mm2 - pmovmskb eax, mm0 - - // check if eq - cmp eax, 0xff - setne al - jmp End - -Done2: - cmp ecx, 16 - jne Done1 - - movq mm0, [esi] - movq mm1, [esi+8] - pcmpeqd mm0, [edx] - pcmpeqd mm1, [edx+8] - pand mm0, mm1 - pmovmskb eax, mm0 - - // check if eq - cmp eax, 0xff - setne al - jmp End - -Done1: - cmp ecx, 8 - jne Done - - mov eax, [esi] - mov esi, [esi+4] - cmp eax, [edx] - je Next - mov eax, 1 - jmp End - -Next: - cmp esi, [edx+4] - setne al - jmp End - -Done: - xor eax, eax - -End: - pop esi - emms - } -} - -#else // _MSC_VER -// assume gcc or mingw or win x64 - -#include -#include - -void * memcpy_amd(void *dest, const void *src, size_t n) -{ -memcpy(dest, src, n); -return dest; -} - - -#endif +/****************************************************************************** + + Copyright (c) 2001 Advanced Micro Devices, Inc. + + LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED *AS IS* WITHOUT ANY + EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, + NONINFRINGEMENT OF THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY + PARTICULAR PURPOSE. IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY + DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, + BUSINESS INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR + INABILITY TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY + OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION OR LIMITATION + OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY + NOT APPLY TO YOU. + + AMD does not assume any responsibility for any errors which may appear in the + Materials nor any responsibility to support or update the Materials. AMD retains + the right to make changes to its test specifications at any time, without notice. + + NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any + further information, software, technical information, know-how, or show-how + available to you. + + So that all may benefit from your experience, please report any problems + or suggestions about this software to 3dsdk.support@amd.com + + AMD Developer Technologies, M/S 585 + Advanced Micro Devices, Inc. + 5900 E. Ben White Blvd. + Austin, TX 78741 + 3dsdk.support@amd.com +******************************************************************************/ + +#include + +/***************************************************************************** +MEMCPY_AMD.CPP +******************************************************************************/ + +// Very optimized memcpy() routine for AMD Athlon and Duron family. +// This code uses any of FOUR different basic copy methods, depending +// on the transfer size. +// NOTE: Since this code uses MOVNTQ (also known as "Non-Temporal MOV" or +// "Streaming Store"), and also uses the software prefetch instructions, +// be sure you're running on Athlon/Duron or other recent CPU before calling! + +#define TINY_BLOCK_COPY 64 // upper limit for movsd type copy +// The smallest copy uses the X86 "movsd" instruction, in an optimized +// form which is an "unrolled loop". + +#define IN_CACHE_COPY 2 * 1024 // upper limit for movq/movq copy w/SW prefetch +// Next is a copy that uses the MMX registers to copy 8 bytes at a time, +// also using the "unrolled loop" optimization. This code uses +// the software prefetch instruction to get the data into the cache. + +#define UNCACHED_COPY 4 * 1024 // upper limit for movq/movntq w/SW prefetch +// For larger blocks, which will spill beyond the cache, it's faster to +// use the Streaming Store instruction MOVNTQ. This write instruction +// bypasses the cache and writes straight to main memory. This code also +// uses the software prefetch instruction to pre-read the data. +// USE 64 * 1024 FOR THIS VALUE IF YOU'RE ALWAYS FILLING A "CLEAN CACHE" + +#define BLOCK_PREFETCH_COPY infinity // no limit for movq/movntq w/block prefetch +#define CACHEBLOCK 80h // number of 64-byte blocks (cache lines) for block prefetch +// For the largest size blocks, a special technique called Block Prefetch +// can be used to accelerate the read operations. Block Prefetch reads +// one address per cache line, for a series of cache lines, in a short loop. +// This is faster than using software prefetch. The technique is great for +// getting maximum read bandwidth, especially in DDR memory systems. + +//#include + +// Inline assembly syntax for use with Visual C++ +#ifdef _WIN32 +#include +#endif + +#if defined(_MSC_VER) && !defined(__x86_64__) && !defined(_M_X64) + +void * memcpy_amd(void *dest, const void *src, size_t n) +{ + __asm { + mov ecx, [n] ; number of bytes to copy + mov edi, [dest] ; destination + mov esi, [src] ; source + mov ebx, ecx ; keep a copy of count + + cld + cmp ecx, TINY_BLOCK_COPY + jb $memcpy_ic_3 ; tiny? skip mmx copy + + cmp ecx, 32*1024 ; do not align between 32k-64k because + jbe $memcpy_do_align ; it appears to be slower + cmp ecx, 64*1024 + jbe $memcpy_align_done +$memcpy_do_align: + mov ecx, 8 ; a trick that is faster than rep movsb... + sub ecx, edi ; align destination to qword + and ecx, 111b ; get the low bits + sub ebx, ecx ; update copy count + neg ecx ; set up to jump into the array + add ecx, offset $memcpy_align_done + jmp ecx ; jump to array of movsb''s + +align 4 + movsb + movsb + movsb + movsb + movsb + movsb + movsb + movsb + +$memcpy_align_done: ; destination is dword aligned + mov ecx, ebx ; number of bytes left to copy + shr ecx, 6 ; get 64-byte block count + jz $memcpy_ic_2 ; finish the last few bytes + + cmp ecx, IN_CACHE_COPY/64 ; too big 4 cache? use uncached copy + jae $memcpy_uc_test + +// This is small block copy that uses the MMX registers to copy 8 bytes +// at a time. It uses the "unrolled loop" optimization, and also uses +// the software prefetch instruction to get the data into the cache. +align 16 +$memcpy_ic_1: ; 64-byte block copies, in-cache copy + + prefetchnta [esi + (200*64/34+192)] ; start reading ahead + + movq mm0, [esi+0] ; read 64 bits + movq mm1, [esi+8] + movq [edi+0], mm0 ; write 64 bits + movq [edi+8], mm1 ; note: the normal movq writes the + movq mm2, [esi+16] ; data to cache; a cache line will be + movq mm3, [esi+24] ; allocated as needed, to store the data + movq [edi+16], mm2 + movq [edi+24], mm3 + movq mm0, [esi+32] + movq mm1, [esi+40] + movq [edi+32], mm0 + movq [edi+40], mm1 + movq mm2, [esi+48] + movq mm3, [esi+56] + movq [edi+48], mm2 + movq [edi+56], mm3 + + add esi, 64 ; update source pointer + add edi, 64 ; update destination pointer + dec ecx ; count down + jnz $memcpy_ic_1 ; last 64-byte block? + +$memcpy_ic_2: + mov ecx, ebx ; has valid low 6 bits of the byte count +$memcpy_ic_3: + shr ecx, 2 ; dword count + and ecx, 1111b ; only look at the "remainder" bits + neg ecx ; set up to jump into the array + add ecx, offset $memcpy_last_few + jmp ecx ; jump to array of movsd''s + +$memcpy_uc_test: + cmp ecx, UNCACHED_COPY/64 ; big enough? use block prefetch copy + jae $memcpy_bp_1 + +$memcpy_64_test: + or ecx, ecx ; tail end of block prefetch will jump here + jz $memcpy_ic_2 ; no more 64-byte blocks left + +// For larger blocks, which will spill beyond the cache, it's faster to +// use the Streaming Store instruction MOVNTQ. This write instruction +// bypasses the cache and writes straight to main memory. This code also +// uses the software prefetch instruction to pre-read the data. +align 16 +$memcpy_uc_1: ; 64-byte blocks, uncached copy + + prefetchnta [esi + (200*64/34+192)] ; start reading ahead + + movq mm0,[esi+0] ; read 64 bits + add edi,64 ; update destination pointer + movq mm1,[esi+8] + add esi,64 ; update source pointer + movq mm2,[esi-48] + movntq [edi-64], mm0 ; write 64 bits, bypassing the cache + movq mm0,[esi-40] ; note: movntq also prevents the CPU + movntq [edi-56], mm1 ; from READING the destination address + movq mm1,[esi-32] ; into the cache, only to be over-written + movntq [edi-48], mm2 ; so that also helps performance + movq mm2,[esi-24] + movntq [edi-40], mm0 + movq mm0,[esi-16] + movntq [edi-32], mm1 + movq mm1,[esi-8] + movntq [edi-24], mm2 + movntq [edi-16], mm0 + dec ecx + movntq [edi-8], mm1 + jnz $memcpy_uc_1 ; last 64-byte block? + + jmp $memcpy_ic_2 ; almost done + +// For the largest size blocks, a special technique called Block Prefetch +// can be used to accelerate the read operations. Block Prefetch reads +// one address per cache line, for a series of cache lines, in a short loop. +// This is faster than using software prefetch. The technique is great for +// getting maximum read bandwidth, especially in DDR memory systems. +$memcpy_bp_1: ; large blocks, block prefetch copy + + cmp ecx, CACHEBLOCK ; big enough to run another prefetch loop? + jl $memcpy_64_test ; no, back to regular uncached copy + + mov eax, CACHEBLOCK / 2 ; block prefetch loop, unrolled 2X + add esi, CACHEBLOCK * 64 ; move to the top of the block +align 16 +$memcpy_bp_2: + mov edx, [esi-64] ; grab one address per cache line + mov edx, [esi-128] ; grab one address per cache line + sub esi, 128 ; go reverse order to suppress HW prefetcher + dec eax ; count down the cache lines + jnz $memcpy_bp_2 ; keep grabbing more lines into cache + + mov eax, CACHEBLOCK ; now that it is in cache, do the copy +align 16 +$memcpy_bp_3: + movq mm0, [esi ] ; read 64 bits + movq mm1, [esi+ 8] + movq mm2, [esi+16] + movq mm3, [esi+24] + movq mm4, [esi+32] + movq mm5, [esi+40] + movq mm6, [esi+48] + movq mm7, [esi+56] + add esi, 64 ; update source pointer + movntq [edi ], mm0 ; write 64 bits, bypassing cache + movntq [edi+ 8], mm1 ; note: movntq also prevents the CPU + movntq [edi+16], mm2 ; from READING the destination address + movntq [edi+24], mm3 ; into the cache, only to be over-written, + movntq [edi+32], mm4 ; so that also helps performance + movntq [edi+40], mm5 + movntq [edi+48], mm6 + movntq [edi+56], mm7 + add edi, 64 ; update dest pointer + + dec eax ; count down + + jnz $memcpy_bp_3 ; keep copying + sub ecx, CACHEBLOCK ; update the 64-byte block count + jmp $memcpy_bp_1 ; keep processing chunks + +// The smallest copy uses the X86 "movsd" instruction, in an optimized +// form which is an "unrolled loop". Then it handles the last few bytes. +align 4 + movsd + movsd ; perform last 1-15 dword copies + movsd + movsd + movsd + movsd + movsd + movsd + movsd + movsd ; perform last 1-7 dword copies + movsd + movsd + movsd + movsd + movsd + movsd + +$memcpy_last_few: ; dword aligned from before movsd''s + mov ecx, ebx ; has valid low 2 bits of the byte count + and ecx, 11b ; the last few cows must come home + jz $memcpy_final ; no more, lets leave + rep movsb ; the last 1, 2, or 3 bytes + +$memcpy_final: + emms ; clean up the MMX state + sfence ; flush the write buffer + mov eax, [dest] ; ret value = destination pointer + + } +} + +// mmx memcmp implementation, size has to be a multiple of 8 +// returns 0 is equal, nonzero value if not equal +// ~10 times faster than standard memcmp +// (zerofrog) +unsigned char memcmp_mmx(const void* src1, const void* src2, int cmpsize) +{ + assert( (cmpsize&7) == 0 ); + + __asm { + push esi + mov ecx, cmpsize + mov edx, src1 + mov esi, src2 + + cmp ecx, 32 + jl Done4 + + // custom test first 8 to make sure things are ok + movq mm0, [esi] + movq mm1, [esi+8] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pand mm0, mm1 + movq mm2, [esi+16] + pmovmskb eax, mm0 + movq mm3, [esi+24] + + // check if eq + cmp eax, 0xff + je NextComp + mov eax, 1 + jmp End + +NextComp: + pcmpeqd mm2, [edx+16] + pcmpeqd mm3, [edx+24] + pand mm2, mm3 + pmovmskb eax, mm2 + + sub ecx, 32 + add esi, 32 + add edx, 32 + + // check if eq + cmp eax, 0xff + je ContinueTest + mov eax, 1 + jmp End + + cmp ecx, 64 + jl Done8 + +Cmp8: + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + movq mm4, [esi+32] + movq mm5, [esi+40] + movq mm6, [esi+48] + movq mm7, [esi+56] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pcmpeqd mm2, [edx+16] + pcmpeqd mm3, [edx+24] + pand mm0, mm1 + pcmpeqd mm4, [edx+32] + pand mm0, mm2 + pcmpeqd mm5, [edx+40] + pand mm0, mm3 + pcmpeqd mm6, [edx+48] + pand mm0, mm4 + pcmpeqd mm7, [edx+56] + pand mm0, mm5 + pand mm0, mm6 + pand mm0, mm7 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + je Continue + mov eax, 1 + jmp End + +Continue: + sub ecx, 64 + add esi, 64 + add edx, 64 +ContinueTest: + cmp ecx, 64 + jge Cmp8 + +Done8: + test ecx, 0x20 + jz Done4 + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pcmpeqd mm2, [edx+16] + pcmpeqd mm3, [edx+24] + pand mm0, mm1 + pand mm0, mm2 + pand mm0, mm3 + pmovmskb eax, mm0 + sub ecx, 32 + add esi, 32 + add edx, 32 + + // check if eq + cmp eax, 0xff + je Done4 + mov eax, 1 + jmp End + +Done4: + cmp ecx, 24 + jne Done2 + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pcmpeqd mm2, [edx+16] + pand mm0, mm1 + pand mm0, mm2 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + setne al + jmp End + +Done2: + cmp ecx, 16 + jne Done1 + + movq mm0, [esi] + movq mm1, [esi+8] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pand mm0, mm1 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + setne al + jmp End + +Done1: + cmp ecx, 8 + jne Done + + mov eax, [esi] + mov esi, [esi+4] + cmp eax, [edx] + je Next + mov eax, 1 + jmp End + +Next: + cmp esi, [edx+4] + setne al + jmp End + +Done: + xor eax, eax + +End: + pop esi + emms + } +} + +#else // _MSC_VER +// assume gcc or mingw or win x64 + +#include +#include + +void * memcpy_amd(void *dest, const void *src, size_t n) +{ +memcpy(dest, src, n); +return dest; +} + + +#endif diff --git a/Source/Plugins/Plugin_VideoOGL/Src/rasterfont.cpp b/Source/Plugins/Plugin_VideoOGL/Src/rasterfont.cpp index 422f00c126..c4d8b6ba40 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/rasterfont.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/rasterfont.cpp @@ -1,226 +1,226 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Globals.h" - -#ifdef _WIN32 -#include -#endif - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Globals.h" + +#ifdef _WIN32 +#include +#endif + #if defined(__APPLE__) - -#include - -#else - -#include - -#endif - -#include - -#include "rasterfont.h" -// globals - -GLubyte rasters[][13] = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36}, - {0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00, 0x00}, - {0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, 0x18}, - {0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8, 0x70}, - {0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c, 0x38}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c, 0x0e}, - {0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c}, - {0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30}, - {0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00}, - {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03}, - {0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, 0x3c}, - {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18}, - {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, 0x7e}, - {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, 0x7e}, - {0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c}, - {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff}, - {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, - {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 0xff}, - {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e}, - {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e}, - {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06}, - {0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60}, - {0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3, 0x7e}, - {0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18}, - {0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, - {0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, - {0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc}, - {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff}, - {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff}, - {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, - {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, - {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e}, - {0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06}, - {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3}, - {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}, - {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3}, - {0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3}, - {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e}, - {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, - {0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c}, - {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, - {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e}, - {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff}, - {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, - {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, - {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, - {0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3}, - {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3}, - {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff}, - {0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c}, - {0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60}, - {0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18}, - {0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x70}, - {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}, - {0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x03}, - {0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, 0x1e}, - {0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0}, - {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00}, - {0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x00}, - {0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0}, - {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78}, - {0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, - {0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00}, - {0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00}, - {0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00}, - {0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x0f}, - {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, - {0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18, 0xf0}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00} -}; - -RasterFont::RasterFont() -{ - // set GL modes - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - // create the raster font - fontOffset = glGenLists (128); - for (int i = 32; i < 127; i++) { - glNewList(i+fontOffset, GL_COMPILE); - glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i-32]); - glEndList(); - } -} - -RasterFont::~RasterFont() -{ - glDeleteLists(fontOffset, 128); -} - -void RasterFont::printString(const char *s, double x, double y, double z) -{ - // go to the right spot - glRasterPos3d(x, y, z); - - glPushAttrib (GL_LIST_BIT); - glListBase(fontOffset); - glCallLists((GLsizei)strlen(s), GL_UNSIGNED_BYTE, (GLubyte *) s); - glPopAttrib (); -} - -void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z) -{ - int length = (int)strlen(s); - int x = int(screen_width/2.0 - (length/2.0)*char_width); - - printString(s, x, y, z); -} - -void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight) -{ - double x=start_x; - double y=start_y; - - static char temp[1024]; - char* t = temp; - - while(*text) - { - if(*text=='\n') - { - *t=0; - printString(temp,x,y,z); - y-=char_height * 2.0f / bbHeight; - x=start_x; - t=temp; - } - else if(*text=='\r') - { - t=temp; - } - else if(*text=='\t') - { - //todo: add tabs every something like 4*char_width - *t=0; - - int cpos = strlen(temp); - - int newpos = (cpos+4)&(~3); - - - printString(temp,x,y,z); - - x =start_x + (char_width*newpos) * 2.0f / bbWidth; - - t=temp; - - *(t++)=' '; - } - else - { - *(t++)=*text; - } - text++; - } - if(t!=text) - { - *t=0; - printString(temp,x,y,z); - } + +#include + +#else + +#include + +#endif + +#include + +#include "rasterfont.h" +// globals + +GLubyte rasters[][13] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36}, + {0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00, 0x00}, + {0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, 0x18}, + {0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8, 0x70}, + {0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c, 0x38}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c, 0x0e}, + {0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c}, + {0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30}, + {0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00}, + {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03}, + {0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, 0x3c}, + {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, 0x7e}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, 0x7e}, + {0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, + {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e}, + {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06}, + {0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60}, + {0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3, 0x7e}, + {0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18}, + {0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, + {0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, + {0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff}, + {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, + {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e}, + {0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06}, + {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3}, + {0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e}, + {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, + {0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c}, + {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e}, + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, + {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, + {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, + {0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3}, + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff}, + {0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c}, + {0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60}, + {0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18}, + {0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x70}, + {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}, + {0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x03}, + {0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, 0x1e}, + {0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0}, + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00}, + {0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x00}, + {0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0}, + {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78}, + {0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, + {0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00}, + {0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00}, + {0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00}, + {0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x0f}, + {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, + {0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18, 0xf0}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00} +}; + +RasterFont::RasterFont() +{ + // set GL modes + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + // create the raster font + fontOffset = glGenLists (128); + for (int i = 32; i < 127; i++) { + glNewList(i+fontOffset, GL_COMPILE); + glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i-32]); + glEndList(); + } +} + +RasterFont::~RasterFont() +{ + glDeleteLists(fontOffset, 128); +} + +void RasterFont::printString(const char *s, double x, double y, double z) +{ + // go to the right spot + glRasterPos3d(x, y, z); + + glPushAttrib (GL_LIST_BIT); + glListBase(fontOffset); + glCallLists((GLsizei)strlen(s), GL_UNSIGNED_BYTE, (GLubyte *) s); + glPopAttrib (); +} + +void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z) +{ + int length = (int)strlen(s); + int x = int(screen_width/2.0 - (length/2.0)*char_width); + + printString(s, x, y, z); +} + +void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight) +{ + double x=start_x; + double y=start_y; + + static char temp[1024]; + char* t = temp; + + while(*text) + { + if(*text=='\n') + { + *t=0; + printString(temp,x,y,z); + y-=char_height * 2.0f / bbHeight; + x=start_x; + t=temp; + } + else if(*text=='\r') + { + t=temp; + } + else if(*text=='\t') + { + //todo: add tabs every something like 4*char_width + *t=0; + + int cpos = strlen(temp); + + int newpos = (cpos+4)&(~3); + + + printString(temp,x,y,z); + + x =start_x + (char_width*newpos) * 2.0f / bbWidth; + + t=temp; + + *(t++)=' '; + } + else + { + *(t++)=*text; + } + text++; + } + if(t!=text) + { + *t=0; + printString(temp,x,y,z); + } } diff --git a/Source/Plugins/Plugin_Wiimote/Src/Config.cpp b/Source/Plugins/Plugin_Wiimote/Src/Config.cpp index 64ad2a08ad..8a6ae7c715 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Config.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/Config.cpp @@ -1,55 +1,55 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -#include "Common.h" -#include "IniFile.h" -#include "Config.h" - -Config g_Config; - -Config::Config() -{ - memset(this, 0, sizeof(Config)); -} - -void Config::Load() -{ - std::string temp; - IniFile iniFile; - iniFile.Load(FULL_CONFIG_DIR "Wiimote.ini"); - - // get resolution - - iniFile.Get("Settings", "SidewaysDPad", &bSidewaysDPad, false); // Hardware - iniFile.Get("Settings", "WideScreen", &bWideScreen, false); - iniFile.Get("Settings", "NunchuckConnected", &bNunchuckConnected, false); - iniFile.Get("Settings", "ClassicControllerConnected", &bClassicControllerConnected, false); -} - -void Config::Save() -{ - IniFile iniFile; - iniFile.Load(FULL_CONFIG_DIR "Wiimote.ini"); - iniFile.Set("Settings", "SidewaysDPad", bSidewaysDPad); - iniFile.Set("Settings", "WideScreen", bWideScreen); - iniFile.Set("Settings", "NunchuckConnected", bNunchuckConnected); - iniFile.Set("Settings", "ClassicControllerConnected", bClassicControllerConnected); - - - iniFile.Save(FULL_CONFIG_DIR "Wiimote.ini"); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#include "Common.h" +#include "IniFile.h" +#include "Config.h" + +Config g_Config; + +Config::Config() +{ + memset(this, 0, sizeof(Config)); +} + +void Config::Load() +{ + std::string temp; + IniFile iniFile; + iniFile.Load(FULL_CONFIG_DIR "Wiimote.ini"); + + // get resolution + + iniFile.Get("Settings", "SidewaysDPad", &bSidewaysDPad, false); // Hardware + iniFile.Get("Settings", "WideScreen", &bWideScreen, false); + iniFile.Get("Settings", "NunchuckConnected", &bNunchuckConnected, false); + iniFile.Get("Settings", "ClassicControllerConnected", &bClassicControllerConnected, false); +} + +void Config::Save() +{ + IniFile iniFile; + iniFile.Load(FULL_CONFIG_DIR "Wiimote.ini"); + iniFile.Set("Settings", "SidewaysDPad", bSidewaysDPad); + iniFile.Set("Settings", "WideScreen", bWideScreen); + iniFile.Set("Settings", "NunchuckConnected", bNunchuckConnected); + iniFile.Set("Settings", "ClassicControllerConnected", bClassicControllerConnected); + + + iniFile.Save(FULL_CONFIG_DIR "Wiimote.ini"); +} diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp index a169b0896c..4b30f46e96 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp @@ -1,192 +1,192 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -//#include "Common.h" // for u16 -#include "ConfigDlg.h" -#include "Config.h" -#include "EmuSubroutines.h" // for WmRequestStatus - - -BEGIN_EVENT_TABLE(ConfigDialog,wxDialog) - EVT_CLOSE(ConfigDialog::OnClose) - EVT_BUTTON(ID_CLOSE, ConfigDialog::CloseClick) - EVT_BUTTON(ID_ABOUTOGL, ConfigDialog::AboutClick) - EVT_CHECKBOX(ID_SIDEWAYSDPAD, ConfigDialog::GeneralSettingsChanged) - EVT_CHECKBOX(ID_WIDESCREEN, ConfigDialog::GeneralSettingsChanged) - EVT_CHECKBOX(ID_NUNCHUCKCONNECTED, ConfigDialog::GeneralSettingsChanged) - EVT_CHECKBOX(ID_CLASSICCONTROLLERCONNECTED, ConfigDialog::GeneralSettingsChanged) -END_EVENT_TABLE() - -ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) -: wxDialog(parent, id, title, position, size, style) -{ - g_Config.Load(); - CreateGUIControls(); -} - -ConfigDialog::~ConfigDialog() -{ -} - -void ConfigDialog::CreateGUIControls() -{ - // Notebook - m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize); - m_PageEmu = new wxPanel(m_Notebook, ID_PAGEEMU, wxDefaultPosition, wxDefaultSize); - m_PageReal = new wxPanel(m_Notebook, ID_PAGEREAL, wxDefaultPosition, wxDefaultSize); - m_Notebook->AddPage(m_PageEmu, wxT("Emulated Wiimote")); - m_Notebook->AddPage(m_PageReal, wxT("Real Wiimote")); - - // Buttons - //m_About = new wxButton(this, ID_ABOUTOGL, wxT("About"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_Close = new wxButton(this, ID_CLOSE, wxT("Close"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - - // Put notebook and buttons in sizers - wxBoxSizer* sButtons; - sButtons = new wxBoxSizer(wxHORIZONTAL); - //sButtons->Add(m_About, 0, wxALL, 5); // there is no about - sButtons->AddStretchSpacer(); - sButtons->Add(m_Close, 0, wxALL, 5); - - wxBoxSizer* sMain; - sMain = new wxBoxSizer(wxVERTICAL); - sMain->Add(m_Notebook, 1, wxEXPAND|wxALL, 5); - sMain->Add(sButtons, 0, wxEXPAND, 5); - - - // General - sbBasic = new wxStaticBoxSizer(wxVERTICAL, m_PageEmu, wxT("Basic Settings")); - m_SidewaysDPad = new wxCheckBox(m_PageEmu, ID_SIDEWAYSDPAD, wxT("Sideways D-Pad"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_SidewaysDPad->SetValue(g_Config.bSidewaysDPad); - m_WideScreen = new wxCheckBox(m_PageEmu, ID_WIDESCREEN, wxT("WideScreen Mode (for correct aiming)"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_WideScreen->SetValue(g_Config.bWideScreen); - m_NunchuckConnected = new wxCheckBox(m_PageEmu, ID_NUNCHUCKCONNECTED, wxT("Nunchuck connected"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_NunchuckConnected->SetValue(g_Config.bNunchuckConnected); - m_ClassicControllerConnected = new wxCheckBox(m_PageEmu, ID_CLASSICCONTROLLERCONNECTED, wxT("Classic Controller connected"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_ClassicControllerConnected->SetValue(g_Config.bClassicControllerConnected); - - - // ---------------------------------------------------------------------- - // Set up sGeneral and sBasic - // Usage: The wxGBPosition() must have a column and row - // ---------------- - sGeneral = new wxBoxSizer(wxVERTICAL); - sBasic = new wxGridBagSizer(0, 0); - sBasic->Add(m_SidewaysDPad, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL, 5); - sBasic->Add(m_WideScreen, wxGBPosition(1, 0), wxGBSpan(1, 2), wxALL, 5); - sBasic->Add(m_NunchuckConnected, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL, 5); - sBasic->Add(m_ClassicControllerConnected, wxGBPosition(3, 0), wxGBSpan(1, 2), wxALL, 5); - sbBasic->Add(sBasic); - sGeneral->Add(sbBasic, 0, wxEXPAND|wxALL, 5); - - m_PageEmu->SetSizer(sGeneral); - sGeneral->Layout(); - - this->SetSizer(sMain); - this->Layout(); - // ---------------- - - - Fit(); - Center(); -} - -void ConfigDialog::OnClose(wxCloseEvent& WXUNUSED (event)) -{ - g_Config.Save(); - EndModal(0); -} - -void ConfigDialog::CloseClick(wxCommandEvent& WXUNUSED (event)) -{ - Close(); -} - -void ConfigDialog::AboutClick(wxCommandEvent& WXUNUSED (event)) -{ - -} - - -// =================================================== -/* Generate connect/disconnect status event */ -// ---------------- -void ConfigDialog::DoExtensionConnectedDisconnected() -{ - u8 DataFrame[8]; // make a blank report for it - wm_request_status *rs = (wm_request_status*)DataFrame; - - // Check if a game is running, in that case change the status - if(WiiMoteEmu::g_ReportingChannel > 0) - WiiMoteEmu::WmRequestStatus(WiiMoteEmu::g_ReportingChannel, rs); -} - - -// =================================================== -/* Change general Emulated Wii Remote settings */ -// ---------------- -void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event) -{ - switch (event.GetId()) - { - case ID_SIDEWAYSDPAD: - g_Config.bSidewaysDPad = m_SidewaysDPad->IsChecked(); - break; - - case ID_WIDESCREEN: - g_Config.bWideScreen = m_WideScreen->IsChecked(); - break; - - case ID_NUNCHUCKCONNECTED: - // Don't allow two extensions at the same time - if(m_ClassicControllerConnected->IsChecked()) - { - m_ClassicControllerConnected->SetValue(false); - g_Config.bClassicControllerConnected = false; - // Disconnect the extension so that the game recognize the change - DoExtensionConnectedDisconnected(); - } - - g_Config.bNunchuckConnected = m_NunchuckConnected->IsChecked(); - - // Generate connect/disconnect status event - memcpy(WiiMoteEmu::g_RegExt + 0x20, WiiMoteEmu::nunchuck_calibration, - sizeof(WiiMoteEmu::nunchuck_calibration)); - memcpy(WiiMoteEmu::g_RegExt + 0xfa, WiiMoteEmu::nunchuck_id, sizeof(WiiMoteEmu::nunchuck_id)); - DoExtensionConnectedDisconnected(); - break; - - case ID_CLASSICCONTROLLERCONNECTED: - // Don't allow two extensions at the same time - if(m_NunchuckConnected->IsChecked()) - { - m_NunchuckConnected->SetValue(false); - g_Config.bNunchuckConnected = false; - // Disconnect the extension so that the game recognize the change - DoExtensionConnectedDisconnected(); - } - - g_Config.bClassicControllerConnected = m_ClassicControllerConnected->IsChecked(); - - // Generate connect/disconnect status event - memcpy(WiiMoteEmu::g_RegExt + 0x20, WiiMoteEmu::classic_calibration, - sizeof(WiiMoteEmu::classic_calibration)); - memcpy(WiiMoteEmu::g_RegExt + 0xfa, WiiMoteEmu::classic_id, sizeof(WiiMoteEmu::classic_id)); - DoExtensionConnectedDisconnected(); - break; - } +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +//#include "Common.h" // for u16 +#include "ConfigDlg.h" +#include "Config.h" +#include "EmuSubroutines.h" // for WmRequestStatus + + +BEGIN_EVENT_TABLE(ConfigDialog,wxDialog) + EVT_CLOSE(ConfigDialog::OnClose) + EVT_BUTTON(ID_CLOSE, ConfigDialog::CloseClick) + EVT_BUTTON(ID_ABOUTOGL, ConfigDialog::AboutClick) + EVT_CHECKBOX(ID_SIDEWAYSDPAD, ConfigDialog::GeneralSettingsChanged) + EVT_CHECKBOX(ID_WIDESCREEN, ConfigDialog::GeneralSettingsChanged) + EVT_CHECKBOX(ID_NUNCHUCKCONNECTED, ConfigDialog::GeneralSettingsChanged) + EVT_CHECKBOX(ID_CLASSICCONTROLLERCONNECTED, ConfigDialog::GeneralSettingsChanged) +END_EVENT_TABLE() + +ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) +: wxDialog(parent, id, title, position, size, style) +{ + g_Config.Load(); + CreateGUIControls(); +} + +ConfigDialog::~ConfigDialog() +{ +} + +void ConfigDialog::CreateGUIControls() +{ + // Notebook + m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize); + m_PageEmu = new wxPanel(m_Notebook, ID_PAGEEMU, wxDefaultPosition, wxDefaultSize); + m_PageReal = new wxPanel(m_Notebook, ID_PAGEREAL, wxDefaultPosition, wxDefaultSize); + m_Notebook->AddPage(m_PageEmu, wxT("Emulated Wiimote")); + m_Notebook->AddPage(m_PageReal, wxT("Real Wiimote")); + + // Buttons + //m_About = new wxButton(this, ID_ABOUTOGL, wxT("About"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_Close = new wxButton(this, ID_CLOSE, wxT("Close"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + + // Put notebook and buttons in sizers + wxBoxSizer* sButtons; + sButtons = new wxBoxSizer(wxHORIZONTAL); + //sButtons->Add(m_About, 0, wxALL, 5); // there is no about + sButtons->AddStretchSpacer(); + sButtons->Add(m_Close, 0, wxALL, 5); + + wxBoxSizer* sMain; + sMain = new wxBoxSizer(wxVERTICAL); + sMain->Add(m_Notebook, 1, wxEXPAND|wxALL, 5); + sMain->Add(sButtons, 0, wxEXPAND, 5); + + + // General + sbBasic = new wxStaticBoxSizer(wxVERTICAL, m_PageEmu, wxT("Basic Settings")); + m_SidewaysDPad = new wxCheckBox(m_PageEmu, ID_SIDEWAYSDPAD, wxT("Sideways D-Pad"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_SidewaysDPad->SetValue(g_Config.bSidewaysDPad); + m_WideScreen = new wxCheckBox(m_PageEmu, ID_WIDESCREEN, wxT("WideScreen Mode (for correct aiming)"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_WideScreen->SetValue(g_Config.bWideScreen); + m_NunchuckConnected = new wxCheckBox(m_PageEmu, ID_NUNCHUCKCONNECTED, wxT("Nunchuck connected"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_NunchuckConnected->SetValue(g_Config.bNunchuckConnected); + m_ClassicControllerConnected = new wxCheckBox(m_PageEmu, ID_CLASSICCONTROLLERCONNECTED, wxT("Classic Controller connected"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_ClassicControllerConnected->SetValue(g_Config.bClassicControllerConnected); + + + // ---------------------------------------------------------------------- + // Set up sGeneral and sBasic + // Usage: The wxGBPosition() must have a column and row + // ---------------- + sGeneral = new wxBoxSizer(wxVERTICAL); + sBasic = new wxGridBagSizer(0, 0); + sBasic->Add(m_SidewaysDPad, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL, 5); + sBasic->Add(m_WideScreen, wxGBPosition(1, 0), wxGBSpan(1, 2), wxALL, 5); + sBasic->Add(m_NunchuckConnected, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL, 5); + sBasic->Add(m_ClassicControllerConnected, wxGBPosition(3, 0), wxGBSpan(1, 2), wxALL, 5); + sbBasic->Add(sBasic); + sGeneral->Add(sbBasic, 0, wxEXPAND|wxALL, 5); + + m_PageEmu->SetSizer(sGeneral); + sGeneral->Layout(); + + this->SetSizer(sMain); + this->Layout(); + // ---------------- + + + Fit(); + Center(); +} + +void ConfigDialog::OnClose(wxCloseEvent& WXUNUSED (event)) +{ + g_Config.Save(); + EndModal(0); +} + +void ConfigDialog::CloseClick(wxCommandEvent& WXUNUSED (event)) +{ + Close(); +} + +void ConfigDialog::AboutClick(wxCommandEvent& WXUNUSED (event)) +{ + +} + + +// =================================================== +/* Generate connect/disconnect status event */ +// ---------------- +void ConfigDialog::DoExtensionConnectedDisconnected() +{ + u8 DataFrame[8]; // make a blank report for it + wm_request_status *rs = (wm_request_status*)DataFrame; + + // Check if a game is running, in that case change the status + if(WiiMoteEmu::g_ReportingChannel > 0) + WiiMoteEmu::WmRequestStatus(WiiMoteEmu::g_ReportingChannel, rs); +} + + +// =================================================== +/* Change general Emulated Wii Remote settings */ +// ---------------- +void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event) +{ + switch (event.GetId()) + { + case ID_SIDEWAYSDPAD: + g_Config.bSidewaysDPad = m_SidewaysDPad->IsChecked(); + break; + + case ID_WIDESCREEN: + g_Config.bWideScreen = m_WideScreen->IsChecked(); + break; + + case ID_NUNCHUCKCONNECTED: + // Don't allow two extensions at the same time + if(m_ClassicControllerConnected->IsChecked()) + { + m_ClassicControllerConnected->SetValue(false); + g_Config.bClassicControllerConnected = false; + // Disconnect the extension so that the game recognize the change + DoExtensionConnectedDisconnected(); + } + + g_Config.bNunchuckConnected = m_NunchuckConnected->IsChecked(); + + // Generate connect/disconnect status event + memcpy(WiiMoteEmu::g_RegExt + 0x20, WiiMoteEmu::nunchuck_calibration, + sizeof(WiiMoteEmu::nunchuck_calibration)); + memcpy(WiiMoteEmu::g_RegExt + 0xfa, WiiMoteEmu::nunchuck_id, sizeof(WiiMoteEmu::nunchuck_id)); + DoExtensionConnectedDisconnected(); + break; + + case ID_CLASSICCONTROLLERCONNECTED: + // Don't allow two extensions at the same time + if(m_NunchuckConnected->IsChecked()) + { + m_NunchuckConnected->SetValue(false); + g_Config.bNunchuckConnected = false; + // Disconnect the extension so that the game recognize the change + DoExtensionConnectedDisconnected(); + } + + g_Config.bClassicControllerConnected = m_ClassicControllerConnected->IsChecked(); + + // Generate connect/disconnect status event + memcpy(WiiMoteEmu::g_RegExt + 0x20, WiiMoteEmu::classic_calibration, + sizeof(WiiMoteEmu::classic_calibration)); + memcpy(WiiMoteEmu::g_RegExt + 0xfa, WiiMoteEmu::classic_id, sizeof(WiiMoteEmu::classic_id)); + DoExtensionConnectedDisconnected(); + break; + } } \ No newline at end of file diff --git a/Source/Plugins/Plugin_Wiimote/Src/Console.cpp b/Source/Plugins/Plugin_Wiimote/Src/Console.cpp index fe0cc8c848..5ff05f281f 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Console.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/Console.cpp @@ -1,223 +1,223 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -// -------------------- -// Includes -#include -#include -#ifdef _WIN32 -#include -#endif - - -// -------------------- -// On and off -bool g_consoleEnable = true; -int gSaveFile = 0; -#define DEBUG_WIIMOTE - - -// -------------------- -// Settings -int nFiles = 1; - - -// -------------------- -// Create handles - -#ifdef DEBUG_WIIMOTE - FILE* __fStdOut[1]; // you have to update this manually, we can't place a nFiles in there -#endif -#ifdef _WIN32 - HANDLE __hStdOut = NULL; -#endif - - -// ======================================================================================= -/* Start console window - width and height is the size of console window, if you specify -fname, the output will also be written to this file. TODO: Close the file pointer when the app -is closed */ -// ------------- -void startConsoleWin(int width, int height, char* fname) -{ -#if defined(DEBUG_WIIMOTE) && defined(_WIN32) - - AllocConsole(); - - SetConsoleTitle(fname); - __hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); - - COORD co = {width,height}; - SetConsoleScreenBufferSize(__hStdOut, co); - - SMALL_RECT coo = {0,0,(width - 1),70}; // top, left, right, bottom - SetConsoleWindowInfo(__hStdOut, TRUE, &coo); - - // --------------------------------------------------------------------------------------- - // Write to a file - if(fname) - { - for(int i = 0; i < nFiles; i++) - { - // Edit the log file name - std::string FileEnding = ".log"; - std::string FileName = fname; - char buffer[33]; itoa(i, buffer, 10); // convert number to string - std::string FullFilename = (FileName + buffer + FileEnding); - __fStdOut[i] = fopen(FullFilename.c_str(), "w"); - } - } - // --------------- - -#endif -} - - -// --------------------------------------------------------------------------------------- -// File printf function -int aprintf(int a, char *fmt, ...) -{ -#if defined(DEBUG_WIIMOTE) && defined(_WIN32) - if(gSaveFile) - { - char s[500]; // WARNING: mind this value - va_list argptr; - int cnt; - - va_start(argptr, fmt); - cnt = vsnprintf(s, 500, fmt, argptr); // remember to update this value to - va_end(argptr); - - // --------------------------------------------------------------------------------------- - if(__fStdOut[a]) // TODO: make this work, we have to set all default values to NULL - //to make it work - fprintf(__fStdOut[a], s); - // ------------- - - return(cnt); - } - else - { - return 0; - } -#else - return 0; -#endif -} - - - -// --------------------------------------------------------------------------------------- -// Printf to screen function -int wprintf(const char *fmt, ...) -{ -#if defined(DEBUG_WIIMOTE) && defined(_WIN32) - char s[500]; // WARNING: mind this value - va_list argptr; - int cnt; - - va_start(argptr, fmt); - cnt = vsnprintf(s, 500, fmt, argptr); - va_end(argptr); - - DWORD cCharsWritten; - - // --------------------------------------------------------------------------------------- - if(__hStdOut) - { - WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL); - } - // ------------- - - return(cnt); -#else - return 0; -#endif -} - - -// --------------------------------------------------------------------------------------- -// Clear console screen -void ClearScreen() -{ -#if defined(_WIN32) - if(g_consoleEnable) - { - COORD coordScreen = { 0, 0 }; - DWORD cCharsWritten; - CONSOLE_SCREEN_BUFFER_INFO csbi; - DWORD dwConSize; - - HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - - GetConsoleScreenBufferInfo(hConsole, &csbi); - dwConSize = csbi.dwSize.X * csbi.dwSize.Y; - FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, - coordScreen, &cCharsWritten); - GetConsoleScreenBufferInfo(hConsole, &csbi); - FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, - coordScreen, &cCharsWritten); - SetConsoleCursorPosition(hConsole, coordScreen); - } -#endif -} - - -// --------------------------------------------------------------------------------------- -// Get window handle of console window to be able to resize it -#if defined(_WIN32) -HWND GetConsoleHwnd(void) -{ - - #define MY_BUFSIZE 1024 // Buffer size for console window titles. - HWND hwndFound; // This is what is returned to the caller. - char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated - // WindowTitle. - char pszOldWindowTitle[MY_BUFSIZE]; // Contains original - // WindowTitle. - - // Fetch current window title. - - GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE); - - // Format a "unique" NewWindowTitle. - - wsprintf(pszNewWindowTitle,"%d/%d", - GetTickCount(), - GetCurrentProcessId()); - - // Change current window title. - - SetConsoleTitle(pszNewWindowTitle); - - // Ensure window title has been updated. - - Sleep(40); - - // Look for NewWindowTitle. - - hwndFound = FindWindow(NULL, pszNewWindowTitle); - - // Restore original window title. - - SetConsoleTitle(pszOldWindowTitle); - - return(hwndFound); - -} -#endif // win32 +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +// -------------------- +// Includes +#include +#include +#ifdef _WIN32 +#include +#endif + + +// -------------------- +// On and off +bool g_consoleEnable = true; +int gSaveFile = 0; +#define DEBUG_WIIMOTE + + +// -------------------- +// Settings +int nFiles = 1; + + +// -------------------- +// Create handles + +#ifdef DEBUG_WIIMOTE + FILE* __fStdOut[1]; // you have to update this manually, we can't place a nFiles in there +#endif +#ifdef _WIN32 + HANDLE __hStdOut = NULL; +#endif + + +// ======================================================================================= +/* Start console window - width and height is the size of console window, if you specify +fname, the output will also be written to this file. TODO: Close the file pointer when the app +is closed */ +// ------------- +void startConsoleWin(int width, int height, char* fname) +{ +#if defined(DEBUG_WIIMOTE) && defined(_WIN32) + + AllocConsole(); + + SetConsoleTitle(fname); + __hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + + COORD co = {width,height}; + SetConsoleScreenBufferSize(__hStdOut, co); + + SMALL_RECT coo = {0,0,(width - 1),70}; // top, left, right, bottom + SetConsoleWindowInfo(__hStdOut, TRUE, &coo); + + // --------------------------------------------------------------------------------------- + // Write to a file + if(fname) + { + for(int i = 0; i < nFiles; i++) + { + // Edit the log file name + std::string FileEnding = ".log"; + std::string FileName = fname; + char buffer[33]; itoa(i, buffer, 10); // convert number to string + std::string FullFilename = (FileName + buffer + FileEnding); + __fStdOut[i] = fopen(FullFilename.c_str(), "w"); + } + } + // --------------- + +#endif +} + + +// --------------------------------------------------------------------------------------- +// File printf function +int aprintf(int a, char *fmt, ...) +{ +#if defined(DEBUG_WIIMOTE) && defined(_WIN32) + if(gSaveFile) + { + char s[500]; // WARNING: mind this value + va_list argptr; + int cnt; + + va_start(argptr, fmt); + cnt = vsnprintf(s, 500, fmt, argptr); // remember to update this value to + va_end(argptr); + + // --------------------------------------------------------------------------------------- + if(__fStdOut[a]) // TODO: make this work, we have to set all default values to NULL + //to make it work + fprintf(__fStdOut[a], s); + // ------------- + + return(cnt); + } + else + { + return 0; + } +#else + return 0; +#endif +} + + + +// --------------------------------------------------------------------------------------- +// Printf to screen function +int wprintf(const char *fmt, ...) +{ +#if defined(DEBUG_WIIMOTE) && defined(_WIN32) + char s[500]; // WARNING: mind this value + va_list argptr; + int cnt; + + va_start(argptr, fmt); + cnt = vsnprintf(s, 500, fmt, argptr); + va_end(argptr); + + DWORD cCharsWritten; + + // --------------------------------------------------------------------------------------- + if(__hStdOut) + { + WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL); + } + // ------------- + + return(cnt); +#else + return 0; +#endif +} + + +// --------------------------------------------------------------------------------------- +// Clear console screen +void ClearScreen() +{ +#if defined(_WIN32) + if(g_consoleEnable) + { + COORD coordScreen = { 0, 0 }; + DWORD cCharsWritten; + CONSOLE_SCREEN_BUFFER_INFO csbi; + DWORD dwConSize; + + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + + GetConsoleScreenBufferInfo(hConsole, &csbi); + dwConSize = csbi.dwSize.X * csbi.dwSize.Y; + FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, + coordScreen, &cCharsWritten); + GetConsoleScreenBufferInfo(hConsole, &csbi); + FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, + coordScreen, &cCharsWritten); + SetConsoleCursorPosition(hConsole, coordScreen); + } +#endif +} + + +// --------------------------------------------------------------------------------------- +// Get window handle of console window to be able to resize it +#if defined(_WIN32) +HWND GetConsoleHwnd(void) +{ + + #define MY_BUFSIZE 1024 // Buffer size for console window titles. + HWND hwndFound; // This is what is returned to the caller. + char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated + // WindowTitle. + char pszOldWindowTitle[MY_BUFSIZE]; // Contains original + // WindowTitle. + + // Fetch current window title. + + GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE); + + // Format a "unique" NewWindowTitle. + + wsprintf(pszNewWindowTitle,"%d/%d", + GetTickCount(), + GetCurrentProcessId()); + + // Change current window title. + + SetConsoleTitle(pszNewWindowTitle); + + // Ensure window title has been updated. + + Sleep(40); + + // Look for NewWindowTitle. + + hwndFound = FindWindow(NULL, pszNewWindowTitle); + + // Restore original window title. + + SetConsoleTitle(pszOldWindowTitle); + + return(hwndFound); + +} +#endif // win32 diff --git a/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp b/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp index 3c482983ce..b2ab217a8f 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp @@ -1,281 +1,281 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - - - -// =================================================== -/* Data reports guide. The different structures location in the Input reports. The ? in - the IR coordinates is the High coordinates that are four in one byte. */ -// ---------------- - -/* 0x33 - [c.left etc] [c.a etc] acc.x y z ir0.x y ? ir1.x y ? ir2.x y ? ir3.x y ? - - 0x37 - [c.left etc] [c.a etc] acc.x y z ir0.x1 y1 ? x2 y2 ir1.x1 y1 ? x2 y2 ext.jx jy ax ay az bt - - - The Data Report's path from here is - WII_IPC_HLE_WiiMote.cpp: - Callback_WiimoteInput() - CWII_IPC_HLE_WiiMote::SendL2capData() - WII_IPC_HLE_Device_usb.cpp: - CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLFrame() - at that point the message is queued and will be sent by the next - CWII_IPC_HLE_Device_usb_oh1_57e_305::Update() */ - -// ================ - - - - -#include "pluginspecs_wiimote.h" - -#include -#include -#include "Common.h" -#include "wiimote_hid.h" -#include "EmuMain.h" -#include "EmuSubroutines.h" -#include "EmuDefinitions.h" -#include "Encryption.h" // for extension encryption -#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd -#include "Config.h" // for g_Config - -extern SWiimoteInitialize g_WiimoteInitialize; -//extern void __Log(int log, const char *format, ...); -//extern void __Log(int log, int v, const char *format, ...); - - -namespace WiiMoteEmu -{ - -//****************************************************************************** -// Subroutines -//****************************************************************************** - - -void WmDataReporting(u16 _channelID, wm_data_reporting* dr) -{ - LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); - LOG(WII_IPC_WIIMOTE, " Set Data reporting mode"); - LOG(WII_IPC_WIIMOTE, " Rumble: %x", dr->rumble); - LOG(WII_IPC_WIIMOTE, " Continuous: %x", dr->continuous); - LOG(WII_IPC_WIIMOTE, " All The Time: %x (not only on data change)", dr->all_the_time); - LOG(WII_IPC_WIIMOTE, " Mode: 0x%02x", dr->mode); - wprintf("\nData reporting mode: 0x%02x", dr->mode); - wprintf("\nData reporting channel: 0x%04x\n", _channelID); - - - g_ReportingMode = dr->mode; - g_ReportingChannel = _channelID; - switch(dr->mode) { //see Wiimote_Update() - case WM_REPORT_CORE: - case WM_REPORT_CORE_ACCEL: - case WM_REPORT_CORE_ACCEL_IR12: - case WM_REPORT_CORE_ACCEL_EXT16: - case WM_REPORT_CORE_ACCEL_IR10_EXT6: - break; - default: - PanicAlert("Wiimote: Unknown reporting mode 0x%x", dr->mode); - } - - // WmSendAck(_channelID, WM_DATA_REPORTING); - - LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); -} - - - -// =================================================== -/* Case 0x30: Core Buttons */ -// ---------------- -void SendReportCore(u16 _channelID) -{ - u8 DataFrame[1024]; - u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE); - - wm_report_core* pReport = (wm_report_core*)(DataFrame + Offset); - Offset += sizeof(wm_report_core); - memset(pReport, 0, sizeof(wm_report_core)); - - FillReportInfo(pReport->c); - - LOGV(WII_IPC_WIIMOTE, 2, " SendReportCore()"); - - g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); -} - - -// =================================================== -/* 0x31: Core Buttons and Accelerometer */ -// ---------------- -void SendReportCoreAccel(u16 _channelID) -{ - u8 DataFrame[1024]; - u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE_ACCEL); - - wm_report_core_accel* pReport = (wm_report_core_accel*)(DataFrame + Offset); - Offset += sizeof(wm_report_core_accel); - memset(pReport, 0, sizeof(wm_report_core_accel)); - - FillReportInfo(pReport->c); - FillReportAcc(pReport->a); - - LOGV(WII_IPC_WIIMOTE, 2, " SendReportCoreAccel (0x31)"); - LOGV(WII_IPC_WIIMOTE, 2, " Channel: %04x", _channelID); - LOGV(WII_IPC_WIIMOTE, 2, " Offset: %08x", Offset); - - // Debugging -#ifdef _WIN32 - /*if(GetAsyncKeyState('V')) - { - std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0, 30); - wprintf("DataFrame: %s\n", Temp.c_str()); - }*/ -#endif - g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); -} - - -// =================================================== -/* Case 0x33: Core Buttons and Accelerometer with 12 IR bytes */ -// ---------------- -void SendReportCoreAccelIr12(u16 _channelID) { - u8 DataFrame[1024]; - u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE_ACCEL_IR12); - - wm_report_core_accel_ir12* pReport = (wm_report_core_accel_ir12*)(DataFrame + Offset); - Offset += sizeof(wm_report_core_accel_ir12); - memset(pReport, 0, sizeof(wm_report_core_accel_ir12)); - - FillReportInfo(pReport->c); - FillReportAcc(pReport->a); - - // We settle with emulating two objects, not all four - FillReportIR(pReport->ir[0], pReport->ir[1]); - - LOGV(WII_IPC_WIIMOTE, 2, " SendReportCoreAccelIr12()"); - LOGV(WII_IPC_WIIMOTE, 2, " Offset: %08x", Offset); - - // Debugging -#ifdef _WIN32 - /*if(GetAsyncKeyState('V')) - { - std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0, 30); - wprintf("DataFrame: %s\n", Temp.c_str()); - }*/ -#endif - g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); -} - - - - -// =================================================== -/* Case 0x35: Core Buttons and Accelerometer with 16 Extension Bytes */ -// ---------------- -void SendReportCoreAccelExt16(u16 _channelID) -{ - u8 DataFrame[1024]; - u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE_ACCEL_EXT16); - - wm_report_core_accel_ext16* pReport = (wm_report_core_accel_ext16*)(DataFrame + Offset); - Offset += sizeof(wm_report_core_accel_ext16); - memset(pReport, 0, sizeof(wm_report_core_accel_ext16)); - - // Make a classic extension struct - wm_classic_extension _ext; - memset(&_ext, 0, sizeof(wm_classic_extension)); - - FillReportInfo(pReport->c); - FillReportAcc(pReport->a); - - if(g_Config.bNunchuckConnected) - { - FillReportExtension(pReport->ext); - } - else if(g_Config.bClassicControllerConnected) - { - FillReportClassicExtension(_ext); - // Copy _ext to pReport->ext - memcpy(&pReport->ext, &_ext, sizeof(_ext)); - } - - LOGV(WII_IPC_WIIMOTE, 2, " SendReportCoreAccelExt16 (0x35)"); - LOGV(WII_IPC_WIIMOTE, 2, " Channel: %04x", _channelID); - LOGV(WII_IPC_WIIMOTE, 2, " Offset: %08x", Offset); - - // Debugging -#ifdef _WIN32 - /*if(GetAsyncKeyState('V')) - { - std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0, 30); - wprintf("DataFrame: %s\n", Temp.c_str()); - }*/ -#endif - g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); -} - - -// =================================================== -/* Case 0x37: Core Buttons and Accelerometer with 10 IR bytes and 6 Extension Bytes */ -// ---------------- -void SendReportCoreAccelIr10Ext(u16 _channelID) -{ - u8 DataFrame[1024]; - u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE_ACCEL_IR10_EXT6); - - wm_report_core_accel_ir10_ext6* pReport = (wm_report_core_accel_ir10_ext6*)(DataFrame + Offset); - Offset += sizeof(wm_report_core_accel_ir10_ext6); - memset(pReport, 0, sizeof(wm_report_core_accel_ir10_ext6)); - - // Make a classic extension struct - wm_classic_extension _ext; - memset(&_ext, 0, sizeof(wm_classic_extension)); - - FillReportInfo(pReport->c); - FillReportAcc(pReport->a); - FillReportIRBasic(pReport->ir[0], pReport->ir[1]); - - if(g_Config.bNunchuckConnected) - { - FillReportExtension(pReport->ext); - } - else if(g_Config.bClassicControllerConnected) - { - FillReportClassicExtension(_ext); - // Copy _ext to pReport->ext - memcpy(&pReport->ext, &_ext, sizeof(_ext)); - } - - LOGV(WII_IPC_WIIMOTE, 2, " SendReportCoreAccelIr10Ext()"); - - // Debugging -#ifdef _WIN32 - /*if(GetAsyncKeyState('V')) - { - std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0, 30); - wprintf("DataFrame: %s\n", Temp.c_str()); - }*/ -#endif - g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); -} - - -} // end of namespace +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + + + +// =================================================== +/* Data reports guide. The different structures location in the Input reports. The ? in + the IR coordinates is the High coordinates that are four in one byte. */ +// ---------------- + +/* 0x33 + [c.left etc] [c.a etc] acc.x y z ir0.x y ? ir1.x y ? ir2.x y ? ir3.x y ? + + 0x37 + [c.left etc] [c.a etc] acc.x y z ir0.x1 y1 ? x2 y2 ir1.x1 y1 ? x2 y2 ext.jx jy ax ay az bt + + + The Data Report's path from here is + WII_IPC_HLE_WiiMote.cpp: + Callback_WiimoteInput() + CWII_IPC_HLE_WiiMote::SendL2capData() + WII_IPC_HLE_Device_usb.cpp: + CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLFrame() + at that point the message is queued and will be sent by the next + CWII_IPC_HLE_Device_usb_oh1_57e_305::Update() */ + +// ================ + + + + +#include "pluginspecs_wiimote.h" + +#include +#include +#include "Common.h" +#include "wiimote_hid.h" +#include "EmuMain.h" +#include "EmuSubroutines.h" +#include "EmuDefinitions.h" +#include "Encryption.h" // for extension encryption +#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd +#include "Config.h" // for g_Config + +extern SWiimoteInitialize g_WiimoteInitialize; +//extern void __Log(int log, const char *format, ...); +//extern void __Log(int log, int v, const char *format, ...); + + +namespace WiiMoteEmu +{ + +//****************************************************************************** +// Subroutines +//****************************************************************************** + + +void WmDataReporting(u16 _channelID, wm_data_reporting* dr) +{ + LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); + LOG(WII_IPC_WIIMOTE, " Set Data reporting mode"); + LOG(WII_IPC_WIIMOTE, " Rumble: %x", dr->rumble); + LOG(WII_IPC_WIIMOTE, " Continuous: %x", dr->continuous); + LOG(WII_IPC_WIIMOTE, " All The Time: %x (not only on data change)", dr->all_the_time); + LOG(WII_IPC_WIIMOTE, " Mode: 0x%02x", dr->mode); + wprintf("\nData reporting mode: 0x%02x", dr->mode); + wprintf("\nData reporting channel: 0x%04x\n", _channelID); + + + g_ReportingMode = dr->mode; + g_ReportingChannel = _channelID; + switch(dr->mode) { //see Wiimote_Update() + case WM_REPORT_CORE: + case WM_REPORT_CORE_ACCEL: + case WM_REPORT_CORE_ACCEL_IR12: + case WM_REPORT_CORE_ACCEL_EXT16: + case WM_REPORT_CORE_ACCEL_IR10_EXT6: + break; + default: + PanicAlert("Wiimote: Unknown reporting mode 0x%x", dr->mode); + } + + // WmSendAck(_channelID, WM_DATA_REPORTING); + + LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); +} + + + +// =================================================== +/* Case 0x30: Core Buttons */ +// ---------------- +void SendReportCore(u16 _channelID) +{ + u8 DataFrame[1024]; + u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE); + + wm_report_core* pReport = (wm_report_core*)(DataFrame + Offset); + Offset += sizeof(wm_report_core); + memset(pReport, 0, sizeof(wm_report_core)); + + FillReportInfo(pReport->c); + + LOGV(WII_IPC_WIIMOTE, 2, " SendReportCore()"); + + g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); +} + + +// =================================================== +/* 0x31: Core Buttons and Accelerometer */ +// ---------------- +void SendReportCoreAccel(u16 _channelID) +{ + u8 DataFrame[1024]; + u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE_ACCEL); + + wm_report_core_accel* pReport = (wm_report_core_accel*)(DataFrame + Offset); + Offset += sizeof(wm_report_core_accel); + memset(pReport, 0, sizeof(wm_report_core_accel)); + + FillReportInfo(pReport->c); + FillReportAcc(pReport->a); + + LOGV(WII_IPC_WIIMOTE, 2, " SendReportCoreAccel (0x31)"); + LOGV(WII_IPC_WIIMOTE, 2, " Channel: %04x", _channelID); + LOGV(WII_IPC_WIIMOTE, 2, " Offset: %08x", Offset); + + // Debugging +#ifdef _WIN32 + /*if(GetAsyncKeyState('V')) + { + std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0, 30); + wprintf("DataFrame: %s\n", Temp.c_str()); + }*/ +#endif + g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); +} + + +// =================================================== +/* Case 0x33: Core Buttons and Accelerometer with 12 IR bytes */ +// ---------------- +void SendReportCoreAccelIr12(u16 _channelID) { + u8 DataFrame[1024]; + u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE_ACCEL_IR12); + + wm_report_core_accel_ir12* pReport = (wm_report_core_accel_ir12*)(DataFrame + Offset); + Offset += sizeof(wm_report_core_accel_ir12); + memset(pReport, 0, sizeof(wm_report_core_accel_ir12)); + + FillReportInfo(pReport->c); + FillReportAcc(pReport->a); + + // We settle with emulating two objects, not all four + FillReportIR(pReport->ir[0], pReport->ir[1]); + + LOGV(WII_IPC_WIIMOTE, 2, " SendReportCoreAccelIr12()"); + LOGV(WII_IPC_WIIMOTE, 2, " Offset: %08x", Offset); + + // Debugging +#ifdef _WIN32 + /*if(GetAsyncKeyState('V')) + { + std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0, 30); + wprintf("DataFrame: %s\n", Temp.c_str()); + }*/ +#endif + g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); +} + + + + +// =================================================== +/* Case 0x35: Core Buttons and Accelerometer with 16 Extension Bytes */ +// ---------------- +void SendReportCoreAccelExt16(u16 _channelID) +{ + u8 DataFrame[1024]; + u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE_ACCEL_EXT16); + + wm_report_core_accel_ext16* pReport = (wm_report_core_accel_ext16*)(DataFrame + Offset); + Offset += sizeof(wm_report_core_accel_ext16); + memset(pReport, 0, sizeof(wm_report_core_accel_ext16)); + + // Make a classic extension struct + wm_classic_extension _ext; + memset(&_ext, 0, sizeof(wm_classic_extension)); + + FillReportInfo(pReport->c); + FillReportAcc(pReport->a); + + if(g_Config.bNunchuckConnected) + { + FillReportExtension(pReport->ext); + } + else if(g_Config.bClassicControllerConnected) + { + FillReportClassicExtension(_ext); + // Copy _ext to pReport->ext + memcpy(&pReport->ext, &_ext, sizeof(_ext)); + } + + LOGV(WII_IPC_WIIMOTE, 2, " SendReportCoreAccelExt16 (0x35)"); + LOGV(WII_IPC_WIIMOTE, 2, " Channel: %04x", _channelID); + LOGV(WII_IPC_WIIMOTE, 2, " Offset: %08x", Offset); + + // Debugging +#ifdef _WIN32 + /*if(GetAsyncKeyState('V')) + { + std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0, 30); + wprintf("DataFrame: %s\n", Temp.c_str()); + }*/ +#endif + g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); +} + + +// =================================================== +/* Case 0x37: Core Buttons and Accelerometer with 10 IR bytes and 6 Extension Bytes */ +// ---------------- +void SendReportCoreAccelIr10Ext(u16 _channelID) +{ + u8 DataFrame[1024]; + u32 Offset = WriteWmReport(DataFrame, WM_REPORT_CORE_ACCEL_IR10_EXT6); + + wm_report_core_accel_ir10_ext6* pReport = (wm_report_core_accel_ir10_ext6*)(DataFrame + Offset); + Offset += sizeof(wm_report_core_accel_ir10_ext6); + memset(pReport, 0, sizeof(wm_report_core_accel_ir10_ext6)); + + // Make a classic extension struct + wm_classic_extension _ext; + memset(&_ext, 0, sizeof(wm_classic_extension)); + + FillReportInfo(pReport->c); + FillReportAcc(pReport->a); + FillReportIRBasic(pReport->ir[0], pReport->ir[1]); + + if(g_Config.bNunchuckConnected) + { + FillReportExtension(pReport->ext); + } + else if(g_Config.bClassicControllerConnected) + { + FillReportClassicExtension(_ext); + // Copy _ext to pReport->ext + memcpy(&pReport->ext, &_ext, sizeof(_ext)); + } + + LOGV(WII_IPC_WIIMOTE, 2, " SendReportCoreAccelIr10Ext()"); + + // Debugging +#ifdef _WIN32 + /*if(GetAsyncKeyState('V')) + { + std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0, 30); + wprintf("DataFrame: %s\n", Temp.c_str()); + }*/ +#endif + g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); +} + + +} // end of namespace diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp index 2e22af3865..c55dd7037c 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp @@ -1,57 +1,57 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifndef _EMU_DECLARATIONS_ -#define _EMU_DECLARATIONS_ - -#include "pluginspecs_wiimote.h" - -#include -#include -#include "Common.h" -#include "wiimote_hid.h" -#include "EmuDefinitions.h" -#include "Encryption.h" -#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd - -extern SWiimoteInitialize g_WiimoteInitialize; - -namespace WiiMoteEmu -{ - -//****************************************************************************** -// Definitions and variable declarations -//****************************************************************************** - -u8 g_Leds = 0x1; -u8 g_IR = 0x1; // 1 = on - -u8 g_Eeprom[WIIMOTE_EEPROM_SIZE]; - -u8 g_RegSpeaker[WIIMOTE_REG_SPEAKER_SIZE]; -u8 g_RegExt[WIIMOTE_REG_EXT_SIZE]; -u8 g_RegExtTmp[WIIMOTE_REG_EXT_SIZE]; -u8 g_RegIr[WIIMOTE_REG_IR_SIZE]; - -u8 g_ReportingMode; // the reporting mode and channel id -u16 g_ReportingChannel; - -wiimote_key g_ExtKey; // the extension encryption key - -} // namespace - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _EMU_DECLARATIONS_ +#define _EMU_DECLARATIONS_ + +#include "pluginspecs_wiimote.h" + +#include +#include +#include "Common.h" +#include "wiimote_hid.h" +#include "EmuDefinitions.h" +#include "Encryption.h" +#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd + +extern SWiimoteInitialize g_WiimoteInitialize; + +namespace WiiMoteEmu +{ + +//****************************************************************************** +// Definitions and variable declarations +//****************************************************************************** + +u8 g_Leds = 0x1; +u8 g_IR = 0x1; // 1 = on + +u8 g_Eeprom[WIIMOTE_EEPROM_SIZE]; + +u8 g_RegSpeaker[WIIMOTE_REG_SPEAKER_SIZE]; +u8 g_RegExt[WIIMOTE_REG_EXT_SIZE]; +u8 g_RegExtTmp[WIIMOTE_REG_EXT_SIZE]; +u8 g_RegIr[WIIMOTE_REG_IR_SIZE]; + +u8 g_ReportingMode; // the reporting mode and channel id +u16 g_ReportingChannel; + +wiimote_key g_ExtKey; // the extension encryption key + +} // namespace + #endif //_EMU_DECLARATIONS_ \ No newline at end of file diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp index 43b11059f3..3c25e3a325 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp @@ -1,510 +1,510 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -#include "pluginspecs_wiimote.h" - -#include -#include -#include "Common.h" -#include "wiimote_hid.h" -#include "EmuSubroutines.h" -#include "EmuDefinitions.h" -#include "EmuMain.h" -#include "Encryption.h" // for extension encryption -#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd -#include "Config.h" // for g_Config - -extern SWiimoteInitialize g_WiimoteInitialize; - - -namespace WiiMoteEmu -{ - -//****************************************************************************** -// Subroutines -//****************************************************************************** - - - -// =================================================== -/* Here we process the Output Reports that the Wii sends. Our response will be an Input Report - back to the Wii. Input and Output is from the Wii's perspective, Output means data to - the Wiimote (from the Wii), Input means data from the Wiimote. - - The call browser: - - 1. Wiimote_InterruptChannel > InterruptChannel > HidOutputReport - 2. Wiimote_ControlChannel > ControlChannel > HidOutputReport */ -// ---------------- -void HidOutputReport(u16 _channelID, wm_report* sr) { - LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); - - LOGV(WII_IPC_WIIMOTE, 0, "HidOutputReport (0x%02x)", sr->channel); - - switch(sr->channel) - { - case 0x10: - LOGV(WII_IPC_WIIMOTE, 0, "HidOutputReport: unknown sr->channel 0x10"); - break; - case WM_LEDS: // 0x11 - WmLeds(_channelID, (wm_leds*)sr->data); - break; - case WM_DATA_REPORTING: // 0x12 - WmDataReporting(_channelID, (wm_data_reporting*)sr->data); - break; - case WM_REQUEST_STATUS: // 0x15 - WmRequestStatus(_channelID, (wm_request_status*)sr->data); - break; - case WM_READ_DATA: // 0x17 - WmReadData(_channelID, (wm_read_data*)sr->data); - break; - case WM_IR_PIXEL_CLOCK: // 0x13 - case WM_IR_LOGIC: // 0x1a - LOGV(WII_IPC_WIIMOTE, 0, " IR Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]); - //wprintf("IR Enable/Disable 0x%02x: 0x%02x\n", sr->channel, sr->data[0]); - // Update the global value so that WmRequestStatus() knows it - if(sr->data[0] == 0x02) g_IR = 0; - else if(sr->data[0] == 0x06) g_IR = 1; - break; - case WM_WRITE_DATA: // 0x16 - WmWriteData(_channelID, (wm_write_data*)sr->data); - break; - case WM_SPEAKER_ENABLE: - LOGV(WII_IPC_WIIMOTE, 1, " WM Speaker Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]); - break; - case WM_SPEAKER_MUTE: - LOGV(WII_IPC_WIIMOTE, 1, " WM Mute Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]); - break; - default: - PanicAlert("HidOutputReport: Unknown channel 0x%02x", sr->channel); - return; - } - LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); -} - - -// =================================================== -/* Generate the right address for wm reports. */ -// ---------------- -int WriteWmReport(u8* dst, u8 channel) { - u32 Offset = 0; - hid_packet* pHidHeader = (hid_packet*)(dst + Offset); - Offset += sizeof(hid_packet); - pHidHeader->type = HID_TYPE_DATA; - pHidHeader->param = HID_PARAM_INPUT; - - wm_report* pReport = (wm_report*)(dst + Offset); - Offset += sizeof(wm_report); - pReport->channel = channel; - return Offset; -} - - -// =================================================== -/* LED (blue lights) report. */ -// ---------------- -void WmLeds(u16 _channelID, wm_leds* leds) { - LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); - LOG(WII_IPC_WIIMOTE, " Set LEDs"); - LOG(WII_IPC_WIIMOTE, " Leds: %x", leds->leds); - LOG(WII_IPC_WIIMOTE, " Rumble: %x", leds->rumble); - - g_Leds = leds->leds; - - LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); -} - - -// =================================================== -/* This will generate the 0x22 acknowledgment after all Input reports. It will - have the form a1 22 00 00 _reportID 00. The first two bytes are unknown but - 00 00 seems to work fine. */ -// ---------------- -void WmSendAck(u16 _channelID, u8 _reportID, u32 address) -{ - u8 DataFrame[1024]; - u32 Offset = 0; - - // Header - hid_packet* pHidHeader = (hid_packet*)(DataFrame + Offset); - pHidHeader->type = HID_TYPE_DATA; - pHidHeader->param = HID_PARAM_INPUT; - Offset += sizeof(hid_packet); - - wm_acknowledge* pData = (wm_acknowledge*)(DataFrame + Offset); - pData->Channel = WM_WRITE_DATA_REPLY; - pData->unk0 = 0; - pData->unk1 = 0; - pData->reportID = _reportID; - pData->errorID = 0; - Offset += sizeof(wm_acknowledge); - - LOGV(WII_IPC_WIIMOTE, 2, " WMSendAck()"); - LOGV(WII_IPC_WIIMOTE, 2, " Report ID: %02x", _reportID); - //std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0); - //LOGV(WII_IPC_WIIMOTE, 2, " Data: %s", Temp.c_str()); - - /* Debug. Write the report for extension registry writes. - if((_reportID == 0x16 || _reportID == 0x17) && ((address >> 16) & 0xfe) == 0xa4) - { - wprintf("\nWMSendAck Report ID: %02x Encryption: %02x\n", _reportID, g_RegExt[0xf0]); - wprintf("Data: %s\n", Temp.c_str()); - }*/ - - g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); -} - - -// =================================================== -/* Read data from Wiimote and Extensions registers. */ -// ---------------- -void WmReadData(u16 _channelID, wm_read_data* rd) -{ - LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); - u32 address = convert24bit(rd->address); - u16 size = convert16bit(rd->size); - std::string Temp; - LOG(WII_IPC_WIIMOTE, "Read data"); - LOG(WII_IPC_WIIMOTE, " Address space: %x", rd->space); - LOG(WII_IPC_WIIMOTE, " Address: 0x%06x", address); - LOG(WII_IPC_WIIMOTE, " Size: 0x%04x", size); - LOG(WII_IPC_WIIMOTE, " Rumble: %x", rd->rumble); - - //u32 _address = address; - - /* Now we determine what address space we are reading from. Space 0 is Eeprom and - space 1 and 2 is the registers. */ - if(rd->space == 0) - { - if (address + size > WIIMOTE_EEPROM_SIZE) - { - PanicAlert("WmReadData: address + size out of bounds!"); - return; - } - SendReadDataReply(_channelID, g_Eeprom+address, address, (u8)size); - } - else if(rd->space == WM_SPACE_REGS1 || rd->space == WM_SPACE_REGS2) - { - u8* block; - u32 blockSize; - switch((address >> 16) & 0xFE) - { - case 0xA2: - block = g_RegSpeaker; - blockSize = WIIMOTE_REG_SPEAKER_SIZE; - LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa2: g_RegSpeaker"); - //Temp = WiiMoteEmu::ArrayToString(g_RegSpeaker, size, (address & 0xffff)); - //LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str()); - break; - case 0xA4: - block = g_RegExt; - blockSize = WIIMOTE_REG_EXT_SIZE; - LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa4: Read ExtReg ****************************"); - //Temp = WiiMoteEmu::ArrayToString(g_RegExt, size, (address & 0xffff)); - //LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str()); - break; - case 0xB0: - block = g_RegIr; - blockSize = WIIMOTE_REG_IR_SIZE; - LOGV(WII_IPC_WIIMOTE, 0, " Case: 0xb0 g_RegIr"); - //Temp = WiiMoteEmu::ArrayToString(g_RegIr, size, (address & 0xffff)); - //LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str()); - break; - default: - PanicAlert("WmWriteData: bad register block!"); - return; - } - - - // ----------------------------------------- - // Encrypt data that is read from the Wiimote Extension Register - // ------------- - if(((address >> 16) & 0xfe) == 0xa4) - { - wprintf("\n\nWmReadData Address: %08x Offset: %08x Size: %i byte\n", - address, address & 0xffff, (u8)size); - - /* Debugging - u32 offset = address & 0xffff; - std::string Temp = WiiMoteEmu::ArrayToString(g_RegExt, size, offset); - wprintf("Unencrypted data:\n%s\n", Temp.c_str());*/ - - // Check if encrypted reads is on - if(g_RegExt[0xf0] == 0xaa) - { - // Copy g_RegExt to g_RegExtTmp - memcpy(g_RegExtTmp, g_RegExt, sizeof(g_RegExt)); - - // Copy the registry to a temporary space - memcpy(g_RegExtTmp, g_RegExt, sizeof(g_RegExt)); - - // Encrypt the read - wiimote_encrypt(&g_ExtKey, &g_RegExtTmp[address & 0xffff], (address & 0xffff), (u8)size); - - /* Debugging - wprintf("\nEncrypted data:\n"); - for (int i = 0; i < (u8)size; i++) - { - wprintf("%02x ", g_RegExtTmp[i + offset]); - if((i + 1) % 20 == 0) wprintf("\n"); - }*/ - - // Update the block that SendReadDataReply will eventually send to the Wii - block = g_RegExtTmp; - } - } - //--------- - - - address &= 0xFFFF; - if(address + size > blockSize) { - PanicAlert("WmReadData: address + size out of bounds!"); - return; - } - - // Let this function process the message and send it to the Wii - SendReadDataReply(_channelID, block+address, address, (u8)size); - - - } - else - { - PanicAlert("WmReadData: unimplemented parameters (size: %i, addr: 0x%x!", size, rd->space); - } - - // Acknowledge the 0x17 read, we will do this from InterruptChannel() - //WmSendAck(_channelID, WM_READ_DATA, _address); - - LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); -} - - - -// =================================================== -/* Write data to Wiimote and Extensions registers. */ -// ---------------- -void WmWriteData(u16 _channelID, wm_write_data* wd) -{ - LOGV(WII_IPC_WIIMOTE, 0, "========================================================"); - u32 address = convert24bit(wd->address); - LOG(WII_IPC_WIIMOTE, "Write data"); - LOG(WII_IPC_WIIMOTE, " Address space: %x", wd->space); - LOG(WII_IPC_WIIMOTE, " Address: 0x%06x", address); - LOG(WII_IPC_WIIMOTE, " Size: 0x%02x", wd->size); - LOG(WII_IPC_WIIMOTE, " Rumble: %x", wd->rumble); - //std::string Temp = WiiMoteEmu::ArrayToString(wd->data, wd->size); - //LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str()); - - // Write to EEPROM - if(wd->size <= 16 && wd->space == WM_SPACE_EEPROM) - { - if(address + wd->size > WIIMOTE_EEPROM_SIZE) { - PanicAlert("WmWriteData: address + size out of bounds!"); - return; - } - memcpy(g_Eeprom + address, wd->data, wd->size); - } - // Write to registers - else if(wd->size <= 16 && (wd->space == WM_SPACE_REGS1 || wd->space == WM_SPACE_REGS2)) - { - u8* block; - u32 blockSize; - switch((address >> 16) & 0xFE) - { - case 0xA2: - block = g_RegSpeaker; - blockSize = WIIMOTE_REG_SPEAKER_SIZE; - LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa2: g_RegSpeaker"); - break; - case 0xA4: - block = g_RegExt; // Extension Controller register - blockSize = WIIMOTE_REG_EXT_SIZE; - //LOGV(WII_IPC_WIIMOTE, 0, " *******************************************************"); - LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa4: ExtReg"); - //LOGV(WII_IPC_WIIMOTE, 0, " *******************************************************"); - wprintf("\n\nWmWriteData Size: %i Address: %08x Offset: %08x \n", - wd->size, address, (address & 0xffff)); - break; - case 0xB0: - block = g_RegIr; - blockSize = WIIMOTE_REG_IR_SIZE; - LOGV(WII_IPC_WIIMOTE, 0, " Case 0xb0: g_RegIr"); - break; - default: - PanicAlert("WmWriteData: bad register block!"); - return; - } - - - // Remove for example 0xa40000 from the address - address &= 0xFFFF; - - // Check if the address is within bounds - if(address + wd->size > blockSize) { - PanicAlert("WmWriteData: address + size out of bounds!"); - return; - } - - // Finally write the registers to the right structure - memcpy(block + address, wd->data, wd->size); - - - // ----------------------------------------- - // Generate key for the Wiimote Extension - // ------------- - if(blockSize == WIIMOTE_REG_EXT_SIZE) - { - /* Debugging. Write the data. - wprintf("Data: %s\n", Temp.c_str()); - wprintf("Current address: %08x\n", address); */ - - /* Run the key generation on all writes in the key area, it doesn't matter - that we send it parts of a key, only the last full key will have an - effect */ - if(address >= 0x40 && address <= 0x4c) - wiimote_gen_key(&g_ExtKey, &g_RegExt[0x40]); - } - // ------------- - - - } else { - PanicAlert("WmWriteData: unimplemented parameters!"); - } - - /* Just added for home brew... Isn't it enough that we call this from - InterruptChannel()? Or is there a separate route here that don't pass though - InterruptChannel()? */ - //WmSendAck(_channelID, WM_WRITE_DATA, _address); - LOGV(WII_IPC_WIIMOTE, 0, "=========================================================="); -} - - -// =================================================== -/* Here we produce the actual 0x21 Input report that we send to the Wii. The message - is divided into 16 bytes pieces and sent piece by piece. There will be five formatting - bytes at the begging of all reports. A common format is 00 00 f0 00 20, the 00 00 - means that no buttons are pressed, the f means 16 bytes in the message, the 0 - means no error, the 00 20 means that the message is at the 00 20 offest in the - registry that was read. */ -// ---------------- -void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size) -{ - LOGV(WII_IPC_WIIMOTE, 0, "========================================="); - int dataOffset = 0; - while (_Size > 0) - { - u8 DataFrame[1024]; - u32 Offset = WriteWmReport(DataFrame, WM_READ_DATA_REPLY); - - int copySize = _Size; - if (copySize > 16) - { - copySize = 16; - } - - wm_read_data_reply* pReply = (wm_read_data_reply*)(DataFrame + Offset); - Offset += sizeof(wm_read_data_reply); - pReply->buttons = 0; - pReply->error = 0; - pReply->size = (copySize - 1) & 0xF; - pReply->address = Common::swap16(_Address + dataOffset); - - - // Write a pice - memcpy(pReply->data + dataOffset, _Base, copySize); - - if(copySize < 16) // check if we have less than 16 bytes left to send - { - memset(pReply->data + copySize, 0, 16 - copySize); - } - dataOffset += copySize; - - - LOG(WII_IPC_WIIMOTE, " SendReadDataReply()"); - LOG(WII_IPC_WIIMOTE, " Buttons: 0x%04x", pReply->buttons); - LOG(WII_IPC_WIIMOTE, " Error: 0x%x", pReply->error); - LOG(WII_IPC_WIIMOTE, " Size: 0x%x", pReply->size); - LOG(WII_IPC_WIIMOTE, " Address: 0x%04x", pReply->address); - - // Send a piece - g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); - - _Size -= copySize; - } - - if (_Size != 0) - { - PanicAlert("WiiMote-Plugin: SendReadDataReply() failed"); - } - LOGV(WII_IPC_WIIMOTE, 0, "=========================================="); -} -// ================ - - -// =================================================== -/* Here we produce a status report to send to the Wii. We currently ignore the status - request rs and all its eventual instructions it may include (for example turn off - rumble or something else) and just send the status report. */ -// ---------------- -void WmRequestStatus(u16 _channelID, wm_request_status* rs) -{ - //PanicAlert("WmRequestStatus"); - LOGV(WII_IPC_WIIMOTE, 0, "================================================"); - LOGV(WII_IPC_WIIMOTE, 0, " Request Status"); - LOGV(WII_IPC_WIIMOTE, 0, " Rumble: %x", rs->rumble); - LOGV(WII_IPC_WIIMOTE, 0, " Channel: %04x", _channelID); - - //SendStatusReport(); - u8 DataFrame[1024]; - u32 Offset = WriteWmReport(DataFrame, WM_STATUS_REPORT); - - wm_status_report* pStatus = (wm_status_report*)(DataFrame + Offset); - Offset += sizeof(wm_status_report); - memset(pStatus, 0, sizeof(wm_status_report)); // fill the status report with zeroes - - // Status values - pStatus->battery_low = 0; // battery is okay - pStatus->leds = g_Leds; // current setting - pStatus->ir = g_IR; // current setting - - /* Battery levels in voltage - 0x00 - 0x32: level 1 - 0x33 - 0x43: level 2 - 0x33 - 0x54: level 3 - 0x55 - 0xff: level 4 */ - pStatus->battery = 0x5f; // fully charged - - // Read config value for this one - if(g_Config.bNunchuckConnected || g_Config.bClassicControllerConnected) - pStatus->extension = 1; - else - pStatus->extension = 0; - - LOGV(WII_IPC_WIIMOTE, 0, " Extension: %x", pStatus->extension); - LOGV(WII_IPC_WIIMOTE, 0, " SendStatusReport()"); - LOGV(WII_IPC_WIIMOTE, 0, " Flags: 0x%02x", pStatus->padding1[2]); - LOGV(WII_IPC_WIIMOTE, 0, " Battery: %d", pStatus->battery); - - //std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0); - //wprintf("Status Report: %s\n", Temp.c_str()); - - g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); - LOGV(WII_IPC_WIIMOTE, 0, "================================================="); -} - -} // end of namespace +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#include "pluginspecs_wiimote.h" + +#include +#include +#include "Common.h" +#include "wiimote_hid.h" +#include "EmuSubroutines.h" +#include "EmuDefinitions.h" +#include "EmuMain.h" +#include "Encryption.h" // for extension encryption +#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd +#include "Config.h" // for g_Config + +extern SWiimoteInitialize g_WiimoteInitialize; + + +namespace WiiMoteEmu +{ + +//****************************************************************************** +// Subroutines +//****************************************************************************** + + + +// =================================================== +/* Here we process the Output Reports that the Wii sends. Our response will be an Input Report + back to the Wii. Input and Output is from the Wii's perspective, Output means data to + the Wiimote (from the Wii), Input means data from the Wiimote. + + The call browser: + + 1. Wiimote_InterruptChannel > InterruptChannel > HidOutputReport + 2. Wiimote_ControlChannel > ControlChannel > HidOutputReport */ +// ---------------- +void HidOutputReport(u16 _channelID, wm_report* sr) { + LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); + + LOGV(WII_IPC_WIIMOTE, 0, "HidOutputReport (0x%02x)", sr->channel); + + switch(sr->channel) + { + case 0x10: + LOGV(WII_IPC_WIIMOTE, 0, "HidOutputReport: unknown sr->channel 0x10"); + break; + case WM_LEDS: // 0x11 + WmLeds(_channelID, (wm_leds*)sr->data); + break; + case WM_DATA_REPORTING: // 0x12 + WmDataReporting(_channelID, (wm_data_reporting*)sr->data); + break; + case WM_REQUEST_STATUS: // 0x15 + WmRequestStatus(_channelID, (wm_request_status*)sr->data); + break; + case WM_READ_DATA: // 0x17 + WmReadData(_channelID, (wm_read_data*)sr->data); + break; + case WM_IR_PIXEL_CLOCK: // 0x13 + case WM_IR_LOGIC: // 0x1a + LOGV(WII_IPC_WIIMOTE, 0, " IR Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]); + //wprintf("IR Enable/Disable 0x%02x: 0x%02x\n", sr->channel, sr->data[0]); + // Update the global value so that WmRequestStatus() knows it + if(sr->data[0] == 0x02) g_IR = 0; + else if(sr->data[0] == 0x06) g_IR = 1; + break; + case WM_WRITE_DATA: // 0x16 + WmWriteData(_channelID, (wm_write_data*)sr->data); + break; + case WM_SPEAKER_ENABLE: + LOGV(WII_IPC_WIIMOTE, 1, " WM Speaker Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]); + break; + case WM_SPEAKER_MUTE: + LOGV(WII_IPC_WIIMOTE, 1, " WM Mute Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]); + break; + default: + PanicAlert("HidOutputReport: Unknown channel 0x%02x", sr->channel); + return; + } + LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); +} + + +// =================================================== +/* Generate the right address for wm reports. */ +// ---------------- +int WriteWmReport(u8* dst, u8 channel) { + u32 Offset = 0; + hid_packet* pHidHeader = (hid_packet*)(dst + Offset); + Offset += sizeof(hid_packet); + pHidHeader->type = HID_TYPE_DATA; + pHidHeader->param = HID_PARAM_INPUT; + + wm_report* pReport = (wm_report*)(dst + Offset); + Offset += sizeof(wm_report); + pReport->channel = channel; + return Offset; +} + + +// =================================================== +/* LED (blue lights) report. */ +// ---------------- +void WmLeds(u16 _channelID, wm_leds* leds) { + LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); + LOG(WII_IPC_WIIMOTE, " Set LEDs"); + LOG(WII_IPC_WIIMOTE, " Leds: %x", leds->leds); + LOG(WII_IPC_WIIMOTE, " Rumble: %x", leds->rumble); + + g_Leds = leds->leds; + + LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); +} + + +// =================================================== +/* This will generate the 0x22 acknowledgment after all Input reports. It will + have the form a1 22 00 00 _reportID 00. The first two bytes are unknown but + 00 00 seems to work fine. */ +// ---------------- +void WmSendAck(u16 _channelID, u8 _reportID, u32 address) +{ + u8 DataFrame[1024]; + u32 Offset = 0; + + // Header + hid_packet* pHidHeader = (hid_packet*)(DataFrame + Offset); + pHidHeader->type = HID_TYPE_DATA; + pHidHeader->param = HID_PARAM_INPUT; + Offset += sizeof(hid_packet); + + wm_acknowledge* pData = (wm_acknowledge*)(DataFrame + Offset); + pData->Channel = WM_WRITE_DATA_REPLY; + pData->unk0 = 0; + pData->unk1 = 0; + pData->reportID = _reportID; + pData->errorID = 0; + Offset += sizeof(wm_acknowledge); + + LOGV(WII_IPC_WIIMOTE, 2, " WMSendAck()"); + LOGV(WII_IPC_WIIMOTE, 2, " Report ID: %02x", _reportID); + //std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0); + //LOGV(WII_IPC_WIIMOTE, 2, " Data: %s", Temp.c_str()); + + /* Debug. Write the report for extension registry writes. + if((_reportID == 0x16 || _reportID == 0x17) && ((address >> 16) & 0xfe) == 0xa4) + { + wprintf("\nWMSendAck Report ID: %02x Encryption: %02x\n", _reportID, g_RegExt[0xf0]); + wprintf("Data: %s\n", Temp.c_str()); + }*/ + + g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); +} + + +// =================================================== +/* Read data from Wiimote and Extensions registers. */ +// ---------------- +void WmReadData(u16 _channelID, wm_read_data* rd) +{ + LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); + u32 address = convert24bit(rd->address); + u16 size = convert16bit(rd->size); + std::string Temp; + LOG(WII_IPC_WIIMOTE, "Read data"); + LOG(WII_IPC_WIIMOTE, " Address space: %x", rd->space); + LOG(WII_IPC_WIIMOTE, " Address: 0x%06x", address); + LOG(WII_IPC_WIIMOTE, " Size: 0x%04x", size); + LOG(WII_IPC_WIIMOTE, " Rumble: %x", rd->rumble); + + //u32 _address = address; + + /* Now we determine what address space we are reading from. Space 0 is Eeprom and + space 1 and 2 is the registers. */ + if(rd->space == 0) + { + if (address + size > WIIMOTE_EEPROM_SIZE) + { + PanicAlert("WmReadData: address + size out of bounds!"); + return; + } + SendReadDataReply(_channelID, g_Eeprom+address, address, (u8)size); + } + else if(rd->space == WM_SPACE_REGS1 || rd->space == WM_SPACE_REGS2) + { + u8* block; + u32 blockSize; + switch((address >> 16) & 0xFE) + { + case 0xA2: + block = g_RegSpeaker; + blockSize = WIIMOTE_REG_SPEAKER_SIZE; + LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa2: g_RegSpeaker"); + //Temp = WiiMoteEmu::ArrayToString(g_RegSpeaker, size, (address & 0xffff)); + //LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str()); + break; + case 0xA4: + block = g_RegExt; + blockSize = WIIMOTE_REG_EXT_SIZE; + LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa4: Read ExtReg ****************************"); + //Temp = WiiMoteEmu::ArrayToString(g_RegExt, size, (address & 0xffff)); + //LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str()); + break; + case 0xB0: + block = g_RegIr; + blockSize = WIIMOTE_REG_IR_SIZE; + LOGV(WII_IPC_WIIMOTE, 0, " Case: 0xb0 g_RegIr"); + //Temp = WiiMoteEmu::ArrayToString(g_RegIr, size, (address & 0xffff)); + //LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str()); + break; + default: + PanicAlert("WmWriteData: bad register block!"); + return; + } + + + // ----------------------------------------- + // Encrypt data that is read from the Wiimote Extension Register + // ------------- + if(((address >> 16) & 0xfe) == 0xa4) + { + wprintf("\n\nWmReadData Address: %08x Offset: %08x Size: %i byte\n", + address, address & 0xffff, (u8)size); + + /* Debugging + u32 offset = address & 0xffff; + std::string Temp = WiiMoteEmu::ArrayToString(g_RegExt, size, offset); + wprintf("Unencrypted data:\n%s\n", Temp.c_str());*/ + + // Check if encrypted reads is on + if(g_RegExt[0xf0] == 0xaa) + { + // Copy g_RegExt to g_RegExtTmp + memcpy(g_RegExtTmp, g_RegExt, sizeof(g_RegExt)); + + // Copy the registry to a temporary space + memcpy(g_RegExtTmp, g_RegExt, sizeof(g_RegExt)); + + // Encrypt the read + wiimote_encrypt(&g_ExtKey, &g_RegExtTmp[address & 0xffff], (address & 0xffff), (u8)size); + + /* Debugging + wprintf("\nEncrypted data:\n"); + for (int i = 0; i < (u8)size; i++) + { + wprintf("%02x ", g_RegExtTmp[i + offset]); + if((i + 1) % 20 == 0) wprintf("\n"); + }*/ + + // Update the block that SendReadDataReply will eventually send to the Wii + block = g_RegExtTmp; + } + } + //--------- + + + address &= 0xFFFF; + if(address + size > blockSize) { + PanicAlert("WmReadData: address + size out of bounds!"); + return; + } + + // Let this function process the message and send it to the Wii + SendReadDataReply(_channelID, block+address, address, (u8)size); + + + } + else + { + PanicAlert("WmReadData: unimplemented parameters (size: %i, addr: 0x%x!", size, rd->space); + } + + // Acknowledge the 0x17 read, we will do this from InterruptChannel() + //WmSendAck(_channelID, WM_READ_DATA, _address); + + LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); +} + + + +// =================================================== +/* Write data to Wiimote and Extensions registers. */ +// ---------------- +void WmWriteData(u16 _channelID, wm_write_data* wd) +{ + LOGV(WII_IPC_WIIMOTE, 0, "========================================================"); + u32 address = convert24bit(wd->address); + LOG(WII_IPC_WIIMOTE, "Write data"); + LOG(WII_IPC_WIIMOTE, " Address space: %x", wd->space); + LOG(WII_IPC_WIIMOTE, " Address: 0x%06x", address); + LOG(WII_IPC_WIIMOTE, " Size: 0x%02x", wd->size); + LOG(WII_IPC_WIIMOTE, " Rumble: %x", wd->rumble); + //std::string Temp = WiiMoteEmu::ArrayToString(wd->data, wd->size); + //LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str()); + + // Write to EEPROM + if(wd->size <= 16 && wd->space == WM_SPACE_EEPROM) + { + if(address + wd->size > WIIMOTE_EEPROM_SIZE) { + PanicAlert("WmWriteData: address + size out of bounds!"); + return; + } + memcpy(g_Eeprom + address, wd->data, wd->size); + } + // Write to registers + else if(wd->size <= 16 && (wd->space == WM_SPACE_REGS1 || wd->space == WM_SPACE_REGS2)) + { + u8* block; + u32 blockSize; + switch((address >> 16) & 0xFE) + { + case 0xA2: + block = g_RegSpeaker; + blockSize = WIIMOTE_REG_SPEAKER_SIZE; + LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa2: g_RegSpeaker"); + break; + case 0xA4: + block = g_RegExt; // Extension Controller register + blockSize = WIIMOTE_REG_EXT_SIZE; + //LOGV(WII_IPC_WIIMOTE, 0, " *******************************************************"); + LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa4: ExtReg"); + //LOGV(WII_IPC_WIIMOTE, 0, " *******************************************************"); + wprintf("\n\nWmWriteData Size: %i Address: %08x Offset: %08x \n", + wd->size, address, (address & 0xffff)); + break; + case 0xB0: + block = g_RegIr; + blockSize = WIIMOTE_REG_IR_SIZE; + LOGV(WII_IPC_WIIMOTE, 0, " Case 0xb0: g_RegIr"); + break; + default: + PanicAlert("WmWriteData: bad register block!"); + return; + } + + + // Remove for example 0xa40000 from the address + address &= 0xFFFF; + + // Check if the address is within bounds + if(address + wd->size > blockSize) { + PanicAlert("WmWriteData: address + size out of bounds!"); + return; + } + + // Finally write the registers to the right structure + memcpy(block + address, wd->data, wd->size); + + + // ----------------------------------------- + // Generate key for the Wiimote Extension + // ------------- + if(blockSize == WIIMOTE_REG_EXT_SIZE) + { + /* Debugging. Write the data. + wprintf("Data: %s\n", Temp.c_str()); + wprintf("Current address: %08x\n", address); */ + + /* Run the key generation on all writes in the key area, it doesn't matter + that we send it parts of a key, only the last full key will have an + effect */ + if(address >= 0x40 && address <= 0x4c) + wiimote_gen_key(&g_ExtKey, &g_RegExt[0x40]); + } + // ------------- + + + } else { + PanicAlert("WmWriteData: unimplemented parameters!"); + } + + /* Just added for home brew... Isn't it enough that we call this from + InterruptChannel()? Or is there a separate route here that don't pass though + InterruptChannel()? */ + //WmSendAck(_channelID, WM_WRITE_DATA, _address); + LOGV(WII_IPC_WIIMOTE, 0, "=========================================================="); +} + + +// =================================================== +/* Here we produce the actual 0x21 Input report that we send to the Wii. The message + is divided into 16 bytes pieces and sent piece by piece. There will be five formatting + bytes at the begging of all reports. A common format is 00 00 f0 00 20, the 00 00 + means that no buttons are pressed, the f means 16 bytes in the message, the 0 + means no error, the 00 20 means that the message is at the 00 20 offest in the + registry that was read. */ +// ---------------- +void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size) +{ + LOGV(WII_IPC_WIIMOTE, 0, "========================================="); + int dataOffset = 0; + while (_Size > 0) + { + u8 DataFrame[1024]; + u32 Offset = WriteWmReport(DataFrame, WM_READ_DATA_REPLY); + + int copySize = _Size; + if (copySize > 16) + { + copySize = 16; + } + + wm_read_data_reply* pReply = (wm_read_data_reply*)(DataFrame + Offset); + Offset += sizeof(wm_read_data_reply); + pReply->buttons = 0; + pReply->error = 0; + pReply->size = (copySize - 1) & 0xF; + pReply->address = Common::swap16(_Address + dataOffset); + + + // Write a pice + memcpy(pReply->data + dataOffset, _Base, copySize); + + if(copySize < 16) // check if we have less than 16 bytes left to send + { + memset(pReply->data + copySize, 0, 16 - copySize); + } + dataOffset += copySize; + + + LOG(WII_IPC_WIIMOTE, " SendReadDataReply()"); + LOG(WII_IPC_WIIMOTE, " Buttons: 0x%04x", pReply->buttons); + LOG(WII_IPC_WIIMOTE, " Error: 0x%x", pReply->error); + LOG(WII_IPC_WIIMOTE, " Size: 0x%x", pReply->size); + LOG(WII_IPC_WIIMOTE, " Address: 0x%04x", pReply->address); + + // Send a piece + g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); + + _Size -= copySize; + } + + if (_Size != 0) + { + PanicAlert("WiiMote-Plugin: SendReadDataReply() failed"); + } + LOGV(WII_IPC_WIIMOTE, 0, "=========================================="); +} +// ================ + + +// =================================================== +/* Here we produce a status report to send to the Wii. We currently ignore the status + request rs and all its eventual instructions it may include (for example turn off + rumble or something else) and just send the status report. */ +// ---------------- +void WmRequestStatus(u16 _channelID, wm_request_status* rs) +{ + //PanicAlert("WmRequestStatus"); + LOGV(WII_IPC_WIIMOTE, 0, "================================================"); + LOGV(WII_IPC_WIIMOTE, 0, " Request Status"); + LOGV(WII_IPC_WIIMOTE, 0, " Rumble: %x", rs->rumble); + LOGV(WII_IPC_WIIMOTE, 0, " Channel: %04x", _channelID); + + //SendStatusReport(); + u8 DataFrame[1024]; + u32 Offset = WriteWmReport(DataFrame, WM_STATUS_REPORT); + + wm_status_report* pStatus = (wm_status_report*)(DataFrame + Offset); + Offset += sizeof(wm_status_report); + memset(pStatus, 0, sizeof(wm_status_report)); // fill the status report with zeroes + + // Status values + pStatus->battery_low = 0; // battery is okay + pStatus->leds = g_Leds; // current setting + pStatus->ir = g_IR; // current setting + + /* Battery levels in voltage + 0x00 - 0x32: level 1 + 0x33 - 0x43: level 2 + 0x33 - 0x54: level 3 + 0x55 - 0xff: level 4 */ + pStatus->battery = 0x5f; // fully charged + + // Read config value for this one + if(g_Config.bNunchuckConnected || g_Config.bClassicControllerConnected) + pStatus->extension = 1; + else + pStatus->extension = 0; + + LOGV(WII_IPC_WIIMOTE, 0, " Extension: %x", pStatus->extension); + LOGV(WII_IPC_WIIMOTE, 0, " SendStatusReport()"); + LOGV(WII_IPC_WIIMOTE, 0, " Flags: 0x%02x", pStatus->padding1[2]); + LOGV(WII_IPC_WIIMOTE, 0, " Battery: %d", pStatus->battery); + + //std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0); + //wprintf("Status Report: %s\n", Temp.c_str()); + + g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); + LOGV(WII_IPC_WIIMOTE, 0, "================================================="); +} + +} // end of namespace diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp index 5587532f52..73dc048025 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp @@ -1,297 +1,297 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - - - -// =================================================== -/* HID reports access guide. */ -// ---------------- - -/* 0x10 - 0x1a Output EmuMain.cpp: HidOutputReport() - 0x10 - 0x14: General - 0x15: Status report request from the Wii - 0x16 and 0x17: Write and read memory or registers - 0x19 and 0x1a: General - 0x20 - 0x22 Input EmuMain.cpp: HidOutputReport() to the destination - 0x15 leads to a 0x20 Input report - 0x17 leads to a 0x21 Input report - 0x10 - 0x1a leads to a 0x22 Input report - 0x30 - 0x3f Input This file: Update() */ - -// ================ - - - -#include "pluginspecs_wiimote.h" - -#include -#include -#include "Common.h" -#include "wiimote_hid.h" -#include "EmuSubroutines.h" -#include "EmuDefinitions.h" -#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd -#include "Config.h" // for g_Config - -extern SWiimoteInitialize g_WiimoteInitialize; - -namespace WiiMoteEmu -{ - - -//****************************************************************************** -// Subroutine declarations -//****************************************************************************** - -u32 convert24bit(const u8* src) { - return (src[0] << 16) | (src[1] << 8) | src[2]; -} - -u16 convert16bit(const u8* src) { - return (src[0] << 8) | src[1]; -} - - -// =================================================== -/* Calibrate the mouse position to the emulation window. */ -// ---------------- -void GetMousePos(float& x, float& y) -{ -#ifdef _WIN32 - POINT point; - - GetCursorPos(&point); - ScreenToClient(g_WiimoteInitialize.hWnd, &point); - - RECT Rect; - GetClientRect(g_WiimoteInitialize.hWnd, &Rect); - - int width = Rect.right - Rect.left; - int height = Rect.bottom - Rect.top; - - x = point.x / (float)width; - y = point.y / (float)height; -#else - // TODO fix on linux - x = 0.5f; - y = 0.5f; -#endif -} - - -// =================================================== -/* Homebrew encryption for 0x00000000 encryption keys. */ -// ---------------- -void CryptBuffer(u8* _buffer, u8 _size) -{ - for (int i=0; i<_size; i++) - { - _buffer[i] = ((_buffer[i] - 0x17) ^ 0x17) & 0xFF; - } -} - -void WriteCrypted16(u8* _baseBlock, u16 _address, u16 _value) -{ - u16 cryptedValue = _value; - CryptBuffer((u8*)&cryptedValue, sizeof(u16)); - - *(u16*)(_baseBlock + _address) = cryptedValue; - //PanicAlert("Converted %04x to %04x", _value, cryptedValue); -} -// ================ - - -// =================================================== -/* Write initial values to Eeprom and registers. */ -// ---------------- -void Initialize() -{ - memset(g_Eeprom, 0, WIIMOTE_EEPROM_SIZE); - memcpy(g_Eeprom, EepromData_0, sizeof(EepromData_0)); - memcpy(g_Eeprom + 0x16D0, EepromData_16D0, sizeof(EepromData_16D0)); - - g_ReportingMode = 0; - - - /* Extension data for homebrew applications that use the 0x00000000 key. This - writes 0x0000 in encrypted form (0xfefe) to 0xfe in the extension register. */ - //WriteCrypted16(g_RegExt, 0xfe, 0x0000); // Fully inserted Nunchuk - - - // Copy extension id and calibration to its register - if(g_Config.bNunchuckConnected) - { - memcpy(g_RegExt + 0x20, nunchuck_calibration, sizeof(nunchuck_calibration)); - memcpy(g_RegExt + 0xfa, nunchuck_id, sizeof(nunchuck_id)); - } - else if(g_Config.bClassicControllerConnected) - { - memcpy(g_RegExt + 0x20, classic_calibration, sizeof(classic_calibration)); - memcpy(g_RegExt + 0xfa, classic_id, sizeof(classic_id)); - } - - -// g_RegExt[0xfd] = 0x1e; -// g_RegExt[0xfc] = 0x9a; -} -// ================ - - -void DoState(void* ptr, int mode) -{ - //TODO: implement -} - -void Shutdown(void) -{ -} - - -// =================================================== -/* This function produce Wiimote Input, i.e. reports from the Wiimote in response - to Output from the Wii. */ -// ---------------- -void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size) -{ - LOGV(WII_IPC_WIIMOTE, 3, "============================================================="); - const u8* data = (const u8*)_pData; - - // Debugging. Dump raw data. - { - LOGV(WII_IPC_WIIMOTE, 3, "Wiimote_Input"); - std::string Temp; - for (u32 j=0; j<_Size; j++) - { - char Buffer[128]; - sprintf(Buffer, "%02x ", data[j]); - Temp.append(Buffer); - } - LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str()); - } - hid_packet* hidp = (hid_packet*) data; - - switch(hidp->type) - { - case HID_TYPE_DATA: - { - switch(hidp->param) - { - case HID_PARAM_OUTPUT: - { - wm_report* sr = (wm_report*)hidp->data; - - HidOutputReport(_channelID, sr); - - /* This is the 0x22 answer to all Inputs. In most games it didn't matter - if it was written before or after HidOutputReport(), but Wii Sports - and Mario Galaxy would stop working if it was placed before - HidOutputReport(). */ - wm_write_data *wd = (wm_write_data*)sr->data; - u32 address = convert24bit(wd->address); - WmSendAck(_channelID, sr->channel, address); - } - break; - - default: - PanicAlert("HidInput: HID_TYPE_DATA - param 0x%02x", hidp->type, hidp->param); - break; - } - } - break; - - default: - PanicAlert("HidInput: Unknown type 0x%02x and param 0x%02x", hidp->type, hidp->param); - break; - } - LOGV(WII_IPC_WIIMOTE, 3, "============================================================="); -} - - -void ControlChannel(u16 _channelID, const void* _pData, u32 _Size) -{ - const u8* data = (const u8*)_pData; - // dump raw data - { - LOG(WII_IPC_WIIMOTE, "Wiimote_ControlChannel"); - std::string Temp; - for (u32 j=0; j<_Size; j++) - { - char Buffer[128]; - sprintf(Buffer, "%02x ", data[j]); - Temp.append(Buffer); - } - LOG(WII_IPC_WIIMOTE, " Data: %s", Temp.c_str()); - } - - hid_packet* hidp = (hid_packet*) data; - switch(hidp->type) - { - case HID_TYPE_HANDSHAKE: - if (hidp->param == HID_PARAM_INPUT) - { - PanicAlert("HID_TYPE_HANDSHAKE - HID_PARAM_INPUT"); - } - else - { - PanicAlert("HID_TYPE_HANDSHAKE - HID_PARAM_OUTPUT"); - } - break; - - case HID_TYPE_SET_REPORT: - if (hidp->param == HID_PARAM_INPUT) - { - PanicAlert("HID_TYPE_SET_REPORT input"); - } - else - { - HidOutputReport(_channelID, (wm_report*)hidp->data); - - //return handshake - u8 handshake = 0; - g_WiimoteInitialize.pWiimoteInput(_channelID, &handshake, 1); - } - break; - - case HID_TYPE_DATA: - PanicAlert("HID_TYPE_DATA %s", hidp->type, hidp->param == HID_PARAM_INPUT ? "input" : "output"); - break; - - default: - PanicAlert("HidControlChanel: Unknown type %x and param %x", hidp->type, hidp->param); - break; - } - -} - -void Update() -{ - //LOG(WII_IPC_WIIMOTE, "Wiimote_Update"); - - switch(g_ReportingMode) { - case 0: - break; - case WM_REPORT_CORE: SendReportCore(g_ReportingChannel); break; - case WM_REPORT_CORE_ACCEL: SendReportCoreAccel(g_ReportingChannel); break; - case WM_REPORT_CORE_ACCEL_IR12: SendReportCoreAccelIr12(g_ReportingChannel);break; - case WM_REPORT_CORE_ACCEL_EXT16: SendReportCoreAccelExt16(g_ReportingChannel);break; - case WM_REPORT_CORE_ACCEL_IR10_EXT6: SendReportCoreAccelIr10Ext(g_ReportingChannel);break; - } - // g_ReportingMode = 0; -} - -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + + + +// =================================================== +/* HID reports access guide. */ +// ---------------- + +/* 0x10 - 0x1a Output EmuMain.cpp: HidOutputReport() + 0x10 - 0x14: General + 0x15: Status report request from the Wii + 0x16 and 0x17: Write and read memory or registers + 0x19 and 0x1a: General + 0x20 - 0x22 Input EmuMain.cpp: HidOutputReport() to the destination + 0x15 leads to a 0x20 Input report + 0x17 leads to a 0x21 Input report + 0x10 - 0x1a leads to a 0x22 Input report + 0x30 - 0x3f Input This file: Update() */ + +// ================ + + + +#include "pluginspecs_wiimote.h" + +#include +#include +#include "Common.h" +#include "wiimote_hid.h" +#include "EmuSubroutines.h" +#include "EmuDefinitions.h" +#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd +#include "Config.h" // for g_Config + +extern SWiimoteInitialize g_WiimoteInitialize; + +namespace WiiMoteEmu +{ + + +//****************************************************************************** +// Subroutine declarations +//****************************************************************************** + +u32 convert24bit(const u8* src) { + return (src[0] << 16) | (src[1] << 8) | src[2]; +} + +u16 convert16bit(const u8* src) { + return (src[0] << 8) | src[1]; +} + + +// =================================================== +/* Calibrate the mouse position to the emulation window. */ +// ---------------- +void GetMousePos(float& x, float& y) +{ +#ifdef _WIN32 + POINT point; + + GetCursorPos(&point); + ScreenToClient(g_WiimoteInitialize.hWnd, &point); + + RECT Rect; + GetClientRect(g_WiimoteInitialize.hWnd, &Rect); + + int width = Rect.right - Rect.left; + int height = Rect.bottom - Rect.top; + + x = point.x / (float)width; + y = point.y / (float)height; +#else + // TODO fix on linux + x = 0.5f; + y = 0.5f; +#endif +} + + +// =================================================== +/* Homebrew encryption for 0x00000000 encryption keys. */ +// ---------------- +void CryptBuffer(u8* _buffer, u8 _size) +{ + for (int i=0; i<_size; i++) + { + _buffer[i] = ((_buffer[i] - 0x17) ^ 0x17) & 0xFF; + } +} + +void WriteCrypted16(u8* _baseBlock, u16 _address, u16 _value) +{ + u16 cryptedValue = _value; + CryptBuffer((u8*)&cryptedValue, sizeof(u16)); + + *(u16*)(_baseBlock + _address) = cryptedValue; + //PanicAlert("Converted %04x to %04x", _value, cryptedValue); +} +// ================ + + +// =================================================== +/* Write initial values to Eeprom and registers. */ +// ---------------- +void Initialize() +{ + memset(g_Eeprom, 0, WIIMOTE_EEPROM_SIZE); + memcpy(g_Eeprom, EepromData_0, sizeof(EepromData_0)); + memcpy(g_Eeprom + 0x16D0, EepromData_16D0, sizeof(EepromData_16D0)); + + g_ReportingMode = 0; + + + /* Extension data for homebrew applications that use the 0x00000000 key. This + writes 0x0000 in encrypted form (0xfefe) to 0xfe in the extension register. */ + //WriteCrypted16(g_RegExt, 0xfe, 0x0000); // Fully inserted Nunchuk + + + // Copy extension id and calibration to its register + if(g_Config.bNunchuckConnected) + { + memcpy(g_RegExt + 0x20, nunchuck_calibration, sizeof(nunchuck_calibration)); + memcpy(g_RegExt + 0xfa, nunchuck_id, sizeof(nunchuck_id)); + } + else if(g_Config.bClassicControllerConnected) + { + memcpy(g_RegExt + 0x20, classic_calibration, sizeof(classic_calibration)); + memcpy(g_RegExt + 0xfa, classic_id, sizeof(classic_id)); + } + + +// g_RegExt[0xfd] = 0x1e; +// g_RegExt[0xfc] = 0x9a; +} +// ================ + + +void DoState(void* ptr, int mode) +{ + //TODO: implement +} + +void Shutdown(void) +{ +} + + +// =================================================== +/* This function produce Wiimote Input, i.e. reports from the Wiimote in response + to Output from the Wii. */ +// ---------------- +void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size) +{ + LOGV(WII_IPC_WIIMOTE, 3, "============================================================="); + const u8* data = (const u8*)_pData; + + // Debugging. Dump raw data. + { + LOGV(WII_IPC_WIIMOTE, 3, "Wiimote_Input"); + std::string Temp; + for (u32 j=0; j<_Size; j++) + { + char Buffer[128]; + sprintf(Buffer, "%02x ", data[j]); + Temp.append(Buffer); + } + LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str()); + } + hid_packet* hidp = (hid_packet*) data; + + switch(hidp->type) + { + case HID_TYPE_DATA: + { + switch(hidp->param) + { + case HID_PARAM_OUTPUT: + { + wm_report* sr = (wm_report*)hidp->data; + + HidOutputReport(_channelID, sr); + + /* This is the 0x22 answer to all Inputs. In most games it didn't matter + if it was written before or after HidOutputReport(), but Wii Sports + and Mario Galaxy would stop working if it was placed before + HidOutputReport(). */ + wm_write_data *wd = (wm_write_data*)sr->data; + u32 address = convert24bit(wd->address); + WmSendAck(_channelID, sr->channel, address); + } + break; + + default: + PanicAlert("HidInput: HID_TYPE_DATA - param 0x%02x", hidp->type, hidp->param); + break; + } + } + break; + + default: + PanicAlert("HidInput: Unknown type 0x%02x and param 0x%02x", hidp->type, hidp->param); + break; + } + LOGV(WII_IPC_WIIMOTE, 3, "============================================================="); +} + + +void ControlChannel(u16 _channelID, const void* _pData, u32 _Size) +{ + const u8* data = (const u8*)_pData; + // dump raw data + { + LOG(WII_IPC_WIIMOTE, "Wiimote_ControlChannel"); + std::string Temp; + for (u32 j=0; j<_Size; j++) + { + char Buffer[128]; + sprintf(Buffer, "%02x ", data[j]); + Temp.append(Buffer); + } + LOG(WII_IPC_WIIMOTE, " Data: %s", Temp.c_str()); + } + + hid_packet* hidp = (hid_packet*) data; + switch(hidp->type) + { + case HID_TYPE_HANDSHAKE: + if (hidp->param == HID_PARAM_INPUT) + { + PanicAlert("HID_TYPE_HANDSHAKE - HID_PARAM_INPUT"); + } + else + { + PanicAlert("HID_TYPE_HANDSHAKE - HID_PARAM_OUTPUT"); + } + break; + + case HID_TYPE_SET_REPORT: + if (hidp->param == HID_PARAM_INPUT) + { + PanicAlert("HID_TYPE_SET_REPORT input"); + } + else + { + HidOutputReport(_channelID, (wm_report*)hidp->data); + + //return handshake + u8 handshake = 0; + g_WiimoteInitialize.pWiimoteInput(_channelID, &handshake, 1); + } + break; + + case HID_TYPE_DATA: + PanicAlert("HID_TYPE_DATA %s", hidp->type, hidp->param == HID_PARAM_INPUT ? "input" : "output"); + break; + + default: + PanicAlert("HidControlChanel: Unknown type %x and param %x", hidp->type, hidp->param); + break; + } + +} + +void Update() +{ + //LOG(WII_IPC_WIIMOTE, "Wiimote_Update"); + + switch(g_ReportingMode) { + case 0: + break; + case WM_REPORT_CORE: SendReportCore(g_ReportingChannel); break; + case WM_REPORT_CORE_ACCEL: SendReportCoreAccel(g_ReportingChannel); break; + case WM_REPORT_CORE_ACCEL_IR12: SendReportCoreAccelIr12(g_ReportingChannel);break; + case WM_REPORT_CORE_ACCEL_EXT16: SendReportCoreAccelExt16(g_ReportingChannel);break; + case WM_REPORT_CORE_ACCEL_IR10_EXT6: SendReportCoreAccelIr10Ext(g_ReportingChannel);break; + } + // g_ReportingMode = 0; +} + +} diff --git a/Source/Plugins/Plugin_Wiimote/Src/Encryption.cpp b/Source/Plugins/Plugin_Wiimote/Src/Encryption.cpp index 5967f05029..72b531bf43 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Encryption.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/Encryption.cpp @@ -1,297 +1,297 @@ -// Copyright (C) 2003-2008 Dolphin Project. -// Copyright (C) Hector Martin "marcan" (hector@marcansoft.com) - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -#include "pluginspecs_wiimote.h" -#include "Common.h" -#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd -#include "Encryption.h" - - -u8 ans_tbl[7][6] = { - {0xA8,0x77,0xA6,0xE0,0xF7,0x43}, - {0x5A,0x35,0x85,0xE2,0x72,0x97}, - {0x8F,0xB7,0x1A,0x62,0x87,0x38}, - { 0xD,0x67,0xC7,0xBE,0x4F,0x3E}, - {0x20,0x76,0x37,0x8F,0x68,0xB7}, - {0xA9,0x26,0x3F,0x2B,0x10,0xE3}, - {0x30,0x7E,0x90, 0xE,0x85, 0xA}, -}; - -u8 tsbox[256] = { - 0x70,0x51, 3,0x86,0x40, 0xD,0x4F,0xEB,0x3E,0xCC,0xD1,0x87,0x35,0xBD,0xF5, 0xB, - 0x5E,0xD0,0xF8,0xF2,0xD5,0xE2,0x6C,0x31, 0xC,0xAD,0xFC,0x21,0xC3,0x78,0xC1, 6, - 0xC2,0x4C,0x55,0xE6,0x4A,0x34,0x48,0x11,0x1E,0xDA,0xE7,0x1A,0x84,0xA0,0x96,0xA7, - 0xE3,0x7F,0xAF,0x63,0x9C,0xFA,0x23,0x5B,0x79,0xC8,0x9E,0xBA,0xB2,0xC9,0x22,0x12, - 0x4B,0xB3,0xA1,0xB6,0x32,0x49,0xA2,0xE1,0x89,0x39,0x10,0x66,0xC5, 7,0x8F,0x54, - 0xEA,0x91,0xCA,0x3F,0xF9,0x19,0xF0,0xD7,0x46,0xBC,0x28,0x1B,0x61,0xE8,0x2F,0x6A, - 0xAE,0x9D,0xF6,0x4E, 9,0x14,0x77,0x4D,0xDB,0x1F,0x2E,0x7B,0x7C,0xF1,0x43,0xA3, - 0,0xB8,0x13,0x8C,0x85,0xB9,0x29,0x75,0x88,0xFD,0xD2,0x56,0x1C,0x50,0x97,0x41, - 0xE5,0x3B,0x60,0xB5,0xC0,0x64,0xEE,0x98,0xD6,0x2D,0x25,0xA4,0xAA,0xCD,0x7D,0xA8, - 0x83,0xC6,0xAB,0xBE,0x44,0x99,0x26,0x3C,0xCE,0x9F,0xBF,0xD3,0xCB,0x76,0x7A,0x7E, - 0x82, 1,0x8A,0x9A,0x80,0x1D, 0xE,0xB0,0x5C,0xD4,0x38,0x62,0xF4,0x30,0xE0,0x8E, - 0x53,0xB7, 2,0x57,0xAC,0xA6,0x52, 0xA,0x6D,0x92,0x65,0x17,0x24,0x33,0x45,0x72, - 0x74,0xB1,0xB4,0xF7,0x5D,0xED,0x2C,0xFF,0x47,0x37,0x5A,0x90,0xBB,0xDF,0x2A,0x16, - 0x59,0x95,0xD9,0xC4,0x27,0x67,0x73,0xC7,0x68,0xFE,0xA5,0xDD,0x6B,0x5F,0x93,0xD8, - 0xEC, 5,0x3A,0x8D,0x6E,0xFB,0x3D,0xA9,0x69,0x36,0xF3,0x94,0xDE,0xEF,0x15,0x6F, - 0x8B,0x9B, 8, 0xF,0xDC,0x81,0x18,0x20, 4,0xE4,0x71,0xCF,0xE9,0x2B,0x42,0x58, -}; - -u8 sboxes[8][256] = { - { - 1,0xA0,0xA9,0x62,0xD6,0x3F,0x85,0xA7,0xB6,0xD4,0xFA,0x15,0x66,0x17, 9,0xBD, - 0x5D,0x14,0x34,0x26,0x59,0x72,0x91,0x54, 6,0x4F,0xF8,0xB0,0x5B,0x74,0x93,0x99, - 0x8C,0xF2,0x45,0xCD,0xEA,0x4E,0xAD,0x10,0x4A,0xE5,0xCA,0xEE,0xDF,0xC6,0x6F,0x9F, - 0x88,0x8E, 2,0xCC, 8,0xA8,0x77,0x94,0x6D,0x21,0xB1,0x28,0xE4,0x39,0x79,0x96, - 0x60,0x71,0x81,0x16,0x2E,0xE6,0x78,0xB9,0xC4,0x46,0x9A,0x42,0xAE,0xB7,0x7C,0x43, - 0xB3,0x22,0x1A,0x86,0xC2,0x32,0x3D,0x2D,0x9C,0xD2,0x29,0xE9,0x63,0x9B,0xD1,0x31, - 0x38,0x5E,0x1E,0x36,0x41,0xBB, 3,0x18,0x2B,0x3E,0xBF,0x68,0x61,0xFC,0x52,0xC0, - 0xDE,0xE0, 0xA,0x58,0x13,0x5A, 0,0xBE,0x1C,0x90, 0xE,0x53,0x12,0xFD,0xE2,0x6E, - 0xBA,0xCE,0x24,0x27,0x44,0x7F,0x87,0xA3,0xA1,0xD5,0x50,0x40,0xE3,0xF9,0x83,0xF7, - 0xC7,0xA2,0x35,0xC8,0xDB,0x19,0xAB,0x2F,0x11,0x25,0xED,0x33,0x9E,0x55,0xE1,0x48, - 0xAF,0x73,0x84,0xDA,0x2A,0xAA,0x51,0xEB,0x9D,0x95,0xB2,0xCB,0xE7,0x70,0x80,0xFE, - 0x4C,0x65, 4,0xEF,0xC5,0xF1,0xC3,0x3A,0xB4,0xF5,0x5F,0x23,0x89,0xDD,0x30,0xA5, - 0x8B,0xD3,0xF6,0xDC,0x4D,0x64,0xD7,0xF0,0x8F,0xEC,0x56,0x37,0x5C,0xA4, 0xD, 7, - 0x76,0x8A,0x2C, 0xB,0xB5,0xD8,0xC1,0x1F,0xE8,0x3B,0xF4,0x4B,0x1B,0x47,0x6C,0x49, - 0x67,0x7B,0x92,0xCF,0x75,0x7E,0x20,0xD9,0x7D,0x3C,0x97,0x7A,0xD0, 5,0x6B, 0xF, - 0x1D,0xFB,0x82,0x98,0x57,0x8D,0xF3,0x6A,0xBC,0xAC,0xC9,0xA6,0xFF,0xB8,0x69, 0xC, - }, - { - 0x4C,0x4D,0x72, 7,0x5A,0x49,0x33,0x8D,0xA2,0xAB,0x46,0x3D,0x63, 0xD,0xA0,0x97, - 0xFF,0xF0,0xF5,0xFA,0xC0,0xE9,0xDB,0x62,0xE4,0xE1,0x74,0x43,0xDC,0x86,0x18,0x29, - 0x37,0xF4, 6,0xE2,0xED,0x6F,0x90,0x48,0x1E,0x2D,0x1D,0xEA,0x73,0x94,0x54,0xDF, - 0x25,0xF6,0x47,0x27,0xD9,0x11,0x77,0xC9,0x84,0x1C,0x5B,0x5C,0x51,0x81,0xA6,0x22, - 0x3E,0x24,0x96,0xC8,0x8A,0xEC,0x82,0x7C, 9,0xB8,0x45,0x4A,0x57,0xBB,0x2F,0x50, - 0x75,0x8E,0x61,0x70,0x8C,0x6C,0xAF,0xD0,0xFD,0xB4,0x1B,0xAE,0xDE,0xFE,0x3B,0xB5, - 0x36,0xBD,0x55, 1, 0xE,0x9C,0x41,0x56,0x5F,0xB3,0x26, 3,0x83,0xBA,0x13,0x4B, - 0xCA,0xC5, 0xA,0xF8,0x60,0xA5,0xB9,0xC7,0xC3,0x98,0x32,0xFB,0x12,0xF9,0xA7,0x92, - 0xAA,0x68,0xF3,0x78,0x7E, 5,0x20,0x21, 2,0xE8,0xBF,0xF2,0xB0,0x59,0x8F,0xD2, - 0xCB,0x87,0x65,0x15,0xF1,0x1A,0xB2,0x30,0xAD,0xEE,0x58,0xA3,0x8B,0x66,0x1F,0x2C, - 0xD7,0x5D,0x19,0x85,0xA8,0xE6,0xD3,0x6B,0xA1, 0xC,0x91,0x93,0x6A,0x5E, 0xB,0x79, - 0xE3,0xDD, 0,0x4F,0x3C,0x89,0x6E,0x71,0x69,0xA9,0xAC,0x40,0xE5,0x99,0x28,0xC6, - 0x31,0x4E,0x7A,0xCD, 8,0x9E,0x7D,0xEF,0x17,0xFC,0x88,0xD8,0xA4,0x6D,0x44,0x95, - 0xD1,0xB7,0xD4,0x9B,0xBE,0x2A,0x34,0x64,0x2B,0xCF,0x2E,0xEB,0x38,0xCE,0x23,0xE0, - 0x3A,0x3F,0xF7,0x7B,0x9F,0x10,0x53,0xBC,0x52,0x67,0x16,0xE7,0x80,0x76, 4,0xC4, - 0xB6,0xC1,0xC2,0x7F,0x9A,0xDA,0xD5,0x39,0x42,0x14,0x9D,0xB1, 0xF,0x35,0xD6,0xCC, - }, - { - 0xB9,0xDA,0x38, 0xC,0xA2,0x9C, 9,0x1F, 6,0xB1,0xB6,0xFD,0x1A,0x69,0x23,0x30, - 0xC4,0xDE, 1,0xD1,0xF4,0x58,0x29,0x37,0x1C,0x7D,0xD5,0xBF,0xFF,0xBD,0xC8,0xC9, - 0xCF,0x65,0xBE,0x7B,0x78,0x97,0x98,0x67, 8,0xB3,0x26,0x57,0xF7,0xFA,0x40,0xAD, - 0x8E,0x75,0xA6,0x7C,0xDB,0x91,0x8B,0x51,0x99,0xD4,0x17,0x7A,0x90,0x8D,0xCE,0x63, - 0xCB,0x4E,0xA0,0xAB,0x18,0x3A,0x5B,0x50,0x7F,0x21,0x74,0xC1,0xBB,0xB8,0xB7,0xBA, - 0xB,0x35,0x95,0x31,0x59,0x9A,0x4D, 4, 7,0x1E,0x5A,0x76,0x13,0xF3,0x71,0x83, - 0xD0,0x86, 3,0xA8,0x39,0x42,0xAA,0x28,0xE6,0xE4,0xD8,0x5D,0xD3,0xD0,0x6E,0x6F, - 0x96,0xFB,0x5E,0xBC,0x56,0xC2,0x5F,0x85,0x9B,0xE7,0xAF,0xD2,0x3B,0x84,0x6A,0xA7, - 0x53,0xC5,0x44,0x49,0xA5,0xF9,0x36,0x72,0x3D,0x2C,0xD9,0x1B,0xA1,0xF5,0x4F,0x93, - 0x9D,0x68,0x47,0x41,0x16,0xCA,0x2A,0x4C,0xA3,0x87,0xD6,0xE5,0x19,0x2E,0x77,0x15, - 0x6D,0x70,0xC0,0xDF,0xB2, 0,0x46,0xED,0xC6,0x6C,0x43,0x60,0x92,0x2D,0xA9,0x22, - 0x45,0x8F,0x34,0x55,0xAE,0xA4, 0xA,0x66,0x32,0xE0,0xDC, 2,0xAC,0xE8,0x20,0x8C, - 0x89,0x62,0x4A,0xFE,0xEE,0xC3,0xE3,0x3C,0xF1,0x79, 5,0xE9,0xF6,0x27,0x33,0xCC, - 0xF2,0x9E,0x11,0x81,0x7E,0x80,0x10,0x8A,0x82,0x9F,0x48, 0xD,0xD7,0xB4,0xFC,0x2F, - 0xB5,0xC7,0xDD,0x88,0x14,0x6B,0x2B,0x54,0xEA,0x1D,0x94,0x5C,0xB0,0xEF,0x12,0x24, - 0xCD,0xEB,0xE1,0xE2,0x64,0x73,0x3F, 0xE,0x52,0x61,0x25,0x3E,0xF8, 0xF,0x4B,0xEC, - }, - { - 0xC0, 0,0x30,0xF6, 2,0x49,0x3D,0x10,0x6E,0x20,0xC9,0xA6,0x2F,0xFE,0x2C,0x2B, - 0x75,0x2E,0x45,0x26,0xAB,0x48,0xA9,0x80,0xFC, 4,0xCC,0xD3,0xB5,0xBA,0xA3,0x38, - 0x31,0x7D, 1,0xD9,0xA7,0x7B,0x96,0xB6,0x63,0x69,0x4E,0xF7,0xDE,0xE0,0x78,0xCA, - 0x50,0xAA,0x41,0x91,0x65,0x88,0xE4,0x21,0x85,0xDA,0x3A,0x27,0xBE,0x1C,0x3E,0x42, - 0x5E,0x17,0x52,0x7F,0x1F,0x89,0x24,0x6F,0x8F,0x5C,0x67,0x74, 0xE,0x12,0x87,0x8D, - 0xE9,0x34,0xED,0x73,0xC4,0xF8,0x61,0x5B, 5,0xDF,0x59,0x4C,0x97,0x79,0x83,0x18, - 0xA4,0x55,0x95,0xEB,0xBD,0x53,0xF5,0xF1,0x57,0x66,0x46,0x9F,0xB2,0x81, 9,0x51, - 0x86,0x22,0x16,0xDD,0x23,0x93,0x76,0x29,0xC2,0xD7,0x1D,0xD4,0xBF,0x36,0x3F,0xEA, - 0x4B,0x11,0x32,0xB9,0x62,0x54,0x60,0xD6,0x6D,0x43,0x9A, 0xD,0x92,0x9C,0xB0,0xEF, - 0x58,0x6C,0x9D,0x77,0x2D,0x70,0xFA,0xF3,0xB3, 0xB,0xE2,0x40,0x7E,0xF4,0x8A,0xE5, - 0x8C,0x3C,0x56,0x71,0xD1,0x64,0xE1,0x82, 0xA,0xCB,0x13,0x15,0x90,0xEC, 3,0x99, - 0xAF,0x14,0x5D, 0xF,0x33,0x4A,0x94,0xA5,0xA8,0x35,0x1B,0xE3,0x6A,0xC6,0x28,0xFF, - 0x4D,0xE7,0x25,0x84,0xAC, 8,0xAE,0xC5,0xA2,0x2A,0xB8,0x37, 0xC,0x7A,0xA0,0xC3, - 0xCE,0xAD, 6,0x1A,0x9E,0x8B,0xFB,0xD5,0xD0,0xC1,0x1E,0xD0,0xB4,0x9B,0xB1,0x44, - 0xF2,0x47,0xC7,0x68,0xCF,0x72,0xBB,0x4F,0x5A,0xF9,0xDC,0x6B,0xDB,0xD2,0xE8,0x7C, - 0xC8,0xEE,0x98,0xA1,0xE6,0xD8,0x39, 7,0x5F,0xFD,0x8E,0x19,0xB7,0x3B,0xBC,0xCD, - }, - { - 0x7C,0xE3,0x81,0x73,0xB2,0x11,0xBF,0x6F,0x20,0x98,0xFE,0x75,0x96,0xEF,0x6C,0xDA, - 0x50,0xE1, 9,0x72,0x54,0x45,0xBA,0x34,0x80,0x5B,0xED,0x3E,0x53,0x2C,0x87,0xA4, - 0x57,0xF3,0x33,0x3F,0x3C,0xB7,0x67,0xB4,0xA3,0x25,0x60,0x4F, 7,0x6B,0x1B,0x47, - 0x15, 0xF,0xE4, 0xA,0xEA,0xD1,0x32,0x78,0x36,0x49,0x8D,0x4B,0xD2,0xBC,0xA5,0xDC, - 0x1D, 0xD,0x4D,0xCD,0x9A,0x82,0x5F,0xFC,0x94,0x65,0xBE,0xE2,0xF4,0xC9,0x1E,0x44, - 0xCB,0x9E, 0xC,0x64,0x71,0x26,0x63,0xB3,0x14,0xE8,0x40,0x70,0x8A, 0xE,0x19,0x42, - 0x6D,0xAC,0x88,0x10,0x5C,0xDF,0x41,0xA9,0xAD,0xE5,0xFB,0x74,0xCC,0xD5, 6,0x8E, - 0x59,0x86,0xCE,0x1F,0x3D,0x76,0xE0,0x8F,0xB9,0x77,0x27,0x7B,0xA6,0xD8,0x29,0xD3, - 0xEC,0xB8,0x13,0xF7,0xFA,0xC3,0x51,0x6A,0xDE,0x4A,0x5A,0xEB,0xC2,0x8B,0x23,0x48, - 0x92,0xCF,0x62,0xA8,0x99,0xF8,0xD0,0x2E,0x85,0x61,0x43,0xC8,0xBD,0xF0, 5,0x93, - 0xCA,0x4E,0xF1,0x7D,0x30,0xFD,0xC4,0x69,0x66,0x2F, 8,0xB1,0x52,0xF9,0x21,0xE6, - 0x7A,0x2B,0xDD,0x39,0x84,0xFF,0xC0,0x91,0xD6,0x37,0xD4,0x7F,0x2D,0x9B,0x5D,0xA1, - 0x3B,0x6E,0xB5,0xC5,0x46, 4,0xF5,0x90,0xEE,0x7E,0x83,0x1C, 3,0x56,0xB6,0xAA, - 0,0x17, 1,0x35,0x55,0x79, 0xB,0x12,0xBB,0x1A,0x31,0xE7, 2,0x28,0x16,0xC1, - 0xF6,0xA2,0xDB,0x18,0x9C,0x89,0x68,0x38,0x97,0xAB,0xC7,0x2A,0xD7,0x3A,0xF2,0xC6, - 0x24,0x4C,0xB0,0x58,0xA0,0x22,0x5E,0x9D,0xD9,0xA7,0xE9,0xAE,0xAF,0x8C,0x95,0x9F, - }, - { - 0x28,0xB7,0x20,0xD7,0xB0,0x30,0xC3, 9,0x19,0xC0,0x67,0xD6, 0,0x3C,0x7E,0xE7, - 0xE9,0xF4, 8,0x5A,0xF8,0xB8,0x2E, 5,0xA6,0x25,0x9E,0x5C,0xD8,0x15, 0xD,0xE1, - 0xF6,0x11,0x54,0x6B,0xCD,0x21,0x46,0x66,0x5E,0x84,0xAD, 6,0x38,0x29,0x44,0xC5, - 0xA2,0xCE,0xF1,0xAA,0xC1,0x40,0x71,0x86,0xB5,0xEF,0xFC,0x36,0xA8,0xCB, 0xA,0x48, - 0x27,0x45,0x64,0xA3,0xAF,0x8C,0xB2,0xC6,0x9F, 7,0x89,0xDC,0x17,0xD3,0x49,0x79, - 0xFB,0xFE,0x1D,0xD0,0xB9,0x88,0x43,0x52,0xBC, 1,0x78,0x2B,0x7D,0x94,0xC7, 0xE, - 0xDE,0xA5,0xD5,0x9B,0xCC,0xF7,0x61,0x7A,0xC2,0x74,0x81,0x39, 3,0xAB,0x96,0xA0, - 0x37,0xBD,0x2D,0x72,0x75,0x3F,0xC9,0xD4,0x8E,0x6F,0xF9,0x8D,0xED,0x62,0xDB,0x1C, - 0xDF, 4,0xAC,0x1B,0x6C,0x14,0x4B,0x63,0xD0,0xBF,0xB4,0x82,0xEC,0x7B,0x1A,0x59, - 0x92,0xD2,0x10,0x60,0xB6,0x3D,0x5F,0xE6,0x80,0x6E,0x70,0xC4,0xF2,0x35,0xD9,0x7C, - 0xEE,0xE5,0x41,0xA4,0x5B,0x50,0xDD,0xBB,0x4C,0xF3,0x1F,0x9D,0x5D,0x57,0x55,0x51, - 0x97,0xE3,0x58,0x42,0x4D,0x9C,0x73,0xBA,0xC8,0x77,0x31,0x69,0x26,0xAE,0xEA,0x8A, - 0xDA,0x22,0xB3,0x87,0x56,0xFA,0x93, 0xB,0x34,0x16,0x33,0xE8,0xE4,0x53,0xBE,0xA9, - 0xB1,0x3A,0x3E,0xF5,0x90,0x6A,0xCF,0x3B,0x12,0xFD,0x8F,0x9A,0xA7,0x47,0x91,0x99, - 0xEB, 0xF,0x24,0xFF,0x23,0x18,0x85,0x4E,0x7F, 0xC,0xE0,0xA1,0xD2,0xD1,0x2C,0x2A, - 0x4A, 2,0x4F,0x1E,0x95,0x68,0x8B,0x98,0x83,0x6D,0x76,0xCA,0x65,0x32,0x13,0x2F, - }, - { - 0xC3,0x82,0x9A,0xA4,0xBA,0x81,0x60,0x37,0x34,0x35,0xFC,0x80,0xA8,0x51,0x65,0x67, - 0xED,0x30,0x5F,0x10,0xD3,0x4A,0x27,0x2F,0x13,0xB9,0x2A,0xD2,0xCC,0xE1,0xEF,0xAE, - 0xEB,0xBE,0xF4,0xBD,0xCF,0x43,0xB3,0xC5,0x88,0x84,0xB7,0xDD,0x39,0x40,0xCE,0x48, - 0x6D,0x9B,0x72,0x61,0x7E,0xE7,0xA1,0x4E,0x53,0x2E,0x77,0x3B,0xE2,0xC9,0x36,0x22, - 0x1B,0x6E,0x73,0xB1, 3,0xB2,0x4C,0x87,0xA9,0xD4,0x4D, 0xF,0xD8,0x15,0x6C,0xAA, - 0x18,0xF6,0x49,0x57,0x5D,0xFB,0x7A,0x14,0x94,0x63,0xA0,0x11,0xB0,0x9E,0xDE, 5, - 0x46,0xC8,0xEE,0x47,0xDB,0xDC,0x24,0x89,0x9C,0x91,0x97,0x29,0xE9,0x7B,0xC1, 7, - 0x1E,0xB8,0xFD,0xFE,0xAC,0xC6,0x62,0x98,0x4F,0xF1,0x79,0xE0,0xE8,0x6B,0x78,0x56, - 0xB6,0x8D, 4,0x50,0x86,0xCA,0x6F,0x20,0xE6,0xEA,0xE5,0x76,0x17,0x1C,0x74,0x7F, - 0xBC, 0xD,0x2C,0x85,0xF7,0x66,0x96,0xE4,0x8B,0x75,0x3F,0x4B,0xD9,0x38,0xAF,0x7C, - 0xDA, 0xB,0x83,0x2D,0x31,0x32,0xA2,0xF5,0x1D,0x59,0x41,0x45,0xBF,0x3C,0x1F,0xF8, - 0xF9,0x8A,0xD0,0x16,0x25,0x69,0x12,0x99,0x9D,0x21,0x95,0xAB, 1,0xA6,0xD7,0xB5, - 0xC0,0x7D,0xFF,0x58, 0xE,0x3A,0x92,0xD1,0x55,0xE3, 8,0x9F,0xD6,0x3E,0x52,0x8E, - 0xFA,0xA3,0xC7, 2,0xCD,0xDF,0x8F,0x64,0x19,0x8C,0xF3,0xA7, 0xC,0x5E, 0xA,0x6A, - 9,0xF0,0x93,0x5B,0x42,0xC2, 6,0x23,0xEC,0x71,0xAD,0xB4,0xCB,0xBB,0x70,0x28, - 0xD5,0x1A,0x5C,0x33,0x68,0x5A, 0,0x44,0x90,0xA5,0xC4,0x26,0x3D,0x2B,0xF2,0x54, - }, - { - 0x96,0xAD,0xDA,0x1F,0xED,0x33,0xE1,0x81,0x69, 8, 0xD, 0xA,0xDB,0x35,0x77,0x9A, - 0x64,0xD1,0xFC,0x78,0xAA,0x1B,0xD0,0x67,0xA0,0xDD,0xFA,0x6C,0x63,0x71, 5,0x84, - 0x17,0x6A,0x89,0x4F,0x66,0x7F,0xC6,0x50,0x55,0x92,0x6F,0xBD,0xE7,0xD2,0x40,0x72, - 0x8D,0xBB,0xEC, 6,0x42,0x8A,0xE4,0x88,0x9D,0x7E,0x7A,0x82,0x27,0x13,0x41,0x1A, - 0xAF,0xC8,0xA4,0x76,0xB4,0xC2,0xFE,0x6D,0x1C,0xD9,0x61,0x30,0xB3,0x7C,0xEA,0xF7, - 0x29, 0xF,0xF2,0x3B,0x51,0xC1,0xDE,0x5F,0xE5,0x2A,0x2F,0x99, 0xB,0x5D,0xA3,0x2B, - 0x4A,0xAB,0x95,0xA5,0xD3,0x58,0x56,0xEE,0x28,0x31, 0,0xCC,0x15,0x46,0xCA,0xE6, - 0x86,0x38,0x3C,0x65,0xF5,0xE3,0x9F,0xD6,0x5B, 9,0x49,0x83,0x70,0x2D,0x53,0xA9, - 0x7D,0xE2,0xC4,0xAC,0x8E,0x5E,0xB8,0x25,0xF4,0xB9,0x57,0xF3,0xF1,0x68,0x47,0xB2, - 0xA2,0x59,0x20,0xCE,0x34,0x79,0x5C,0x90, 0xE,0x1E,0xBE,0xD5,0x22,0x23,0xB1,0xC9, - 0x18,0x62,0x16,0x2E,0x91,0x3E, 7,0x8F,0xD8,0x3F,0x93,0x3D,0xD4,0x9B,0xDF,0x85, - 0x21,0xFB,0x11,0x74,0x97,0xC7,0xD7,0xDC,0x4C,0x19,0x45,0x98,0xE9,0x43, 2,0x4B, - 0xBC,0xC3, 4,0x9C,0x6B,0xF0,0x75,0x52,0xA7,0x26,0xF6,0xC5,0xBA,0xCF,0xB0,0xB7, - 0xAE,0x5A,0xA1,0xBF, 3,0x8B,0x80,0x12,0x6E, 0xC,0xEB,0xF9,0xC0,0x44,0x24,0xEF, - 0x10,0xF8,0xA8,0x8C,0xE8,0x7B,0xFF,0x9E,0x2C,0xCD,0x60,0x36,0x87,0xB5,0x94,0xA6, - 0x54,0x73,0x3A,0x14,0x4E, 1,0x1D,0xB6,0xFD,0x37,0x48,0x4D,0x39,0xCB,0xE0,0x32, - } -}; - - -static inline u8 ror8(u8 a, u8 b) { - return (a>>b) | ((a<<(8-b))&0xff); -} - - -void genkey(u8 *rand, u8 idx, u8 *key) -{ - u8 *ans = ans_tbl[idx]; - u8 t0[10]; - int i; - - for(i=0;i<10;i++) - t0[i] = tsbox[rand[i]]; - - key[0] = ((ror8((ans[0]^t0[5]),(t0[2]%8)) - t0[9]) ^ t0[4]); - key[1] = ((ror8((ans[1]^t0[1]),(t0[0]%8)) - t0[5]) ^ t0[7]); - key[2] = ((ror8((ans[2]^t0[6]),(t0[8]%8)) - t0[2]) ^ t0[0]); - key[3] = ((ror8((ans[3]^t0[4]),(t0[7]%8)) - t0[3]) ^ t0[2]); - key[4] = ((ror8((ans[4]^t0[1]),(t0[6]%8)) - t0[3]) ^ t0[4]); - key[5] = ((ror8((ans[5]^t0[7]),(t0[8]%8)) - t0[5]) ^ t0[9]); -} - - -void gentabs(u8 *rand, u8 *key, u8 idx, u8 *ft, u8 *sb) -{ - ft[0] = sboxes[idx][key[4]] ^ sboxes[(idx+1)%8][rand[3]]; - ft[1] = sboxes[idx][key[2]] ^ sboxes[(idx+1)%8][rand[5]]; - ft[2] = sboxes[idx][key[5]] ^ sboxes[(idx+1)%8][rand[7]]; - ft[3] = sboxes[idx][key[0]] ^ sboxes[(idx+1)%8][rand[2]]; - ft[4] = sboxes[idx][key[1]] ^ sboxes[(idx+1)%8][rand[4]]; - ft[5] = sboxes[idx][key[3]] ^ sboxes[(idx+1)%8][rand[9]]; - ft[6] = sboxes[idx][rand[0]] ^ sboxes[(idx+1)%8][rand[6]]; - ft[7] = sboxes[idx][rand[1]] ^ sboxes[(idx+1)%8][rand[8]]; - - sb[0] = sboxes[idx][key[0]] ^ sboxes[(idx+1)%8][rand[1]]; - sb[1] = sboxes[idx][key[5]] ^ sboxes[(idx+1)%8][rand[4]]; - sb[2] = sboxes[idx][key[3]] ^ sboxes[(idx+1)%8][rand[0]]; - sb[3] = sboxes[idx][key[2]] ^ sboxes[(idx+1)%8][rand[9]]; - sb[4] = sboxes[idx][key[4]] ^ sboxes[(idx+1)%8][rand[7]]; - sb[5] = sboxes[idx][key[1]] ^ sboxes[(idx+1)%8][rand[8]]; - sb[6] = sboxes[idx][rand[3]] ^ sboxes[(idx+1)%8][rand[5]]; - sb[7] = sboxes[idx][rand[2]] ^ sboxes[(idx+1)%8][rand[6]]; -} - - - - -// =================================================== -/* Generate key from the 0x40-0x4c data in g_RegExt */ -// ---------------- -void wiimote_gen_key(wiimote_key *key, u8 *keydata) -{ - u8 rand[10]; - u8 skey[6]; - u8 testkey[6]; - int idx; - - for(int i=0;i<10;i++) - rand[9-i] = keydata[i]; - for(int i=0;i<6;i++) - skey[5-i] = keydata[i+10]; - - wprintf("rand: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", rand[0], rand[1], rand[2], rand[3], rand[4], rand[5], rand[6], rand[7], rand[8], rand[9]); - wprintf("key: %02x %02x %02x %02x %02x %02x\n", skey[0], skey[1], skey[2], skey[3], skey[4], skey[5]); - - for(idx=0;idx<7;idx++) - { - genkey(rand, idx, testkey); - if(!memcmp(testkey,skey,6)) - break; - } - // default case is idx = 7 which is valid (homebrew uses it for the 0x17 case) - wprintf("idx: %d\n", idx); - - gentabs(rand, skey, idx, key->ft, key->sb); - - wprintf("ft: %02x %02x %02x %02x %02x %02x %02x %02x\n", key->ft[0], key->ft[1], key->ft[2], key->ft[3], key->ft[4], key->ft[5], key->ft[6], key->ft[7]); - wprintf("sb: %02x %02x %02x %02x %02x %02x %02x %02x\n", key->sb[0], key->sb[1], key->sb[2], key->sb[3], key->sb[4], key->sb[5], key->sb[6], key->sb[7]); - - // for homebrew, ft and sb are all 0x97 which is equivalent to 0x17 -} - - -// =================================================== -/* Encrypt data */ -// ---------------- -void wiimote_encrypt(wiimote_key *key, u8 *data, int addr, u8 len) -{ - for(int i = 0; i < len; i++, addr++) - { - //wprintf("data[%i] from %02x ", i, data[i]); - data[i] = (data[i] - key->ft[addr%8]) ^ key->sb[addr%8]; - //wprintf("to %02x\n", data[i]); - } -} +// Copyright (C) 2003-2008 Dolphin Project. +// Copyright (C) Hector Martin "marcan" (hector@marcansoft.com) + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#include "pluginspecs_wiimote.h" +#include "Common.h" +#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd +#include "Encryption.h" + + +u8 ans_tbl[7][6] = { + {0xA8,0x77,0xA6,0xE0,0xF7,0x43}, + {0x5A,0x35,0x85,0xE2,0x72,0x97}, + {0x8F,0xB7,0x1A,0x62,0x87,0x38}, + { 0xD,0x67,0xC7,0xBE,0x4F,0x3E}, + {0x20,0x76,0x37,0x8F,0x68,0xB7}, + {0xA9,0x26,0x3F,0x2B,0x10,0xE3}, + {0x30,0x7E,0x90, 0xE,0x85, 0xA}, +}; + +u8 tsbox[256] = { + 0x70,0x51, 3,0x86,0x40, 0xD,0x4F,0xEB,0x3E,0xCC,0xD1,0x87,0x35,0xBD,0xF5, 0xB, + 0x5E,0xD0,0xF8,0xF2,0xD5,0xE2,0x6C,0x31, 0xC,0xAD,0xFC,0x21,0xC3,0x78,0xC1, 6, + 0xC2,0x4C,0x55,0xE6,0x4A,0x34,0x48,0x11,0x1E,0xDA,0xE7,0x1A,0x84,0xA0,0x96,0xA7, + 0xE3,0x7F,0xAF,0x63,0x9C,0xFA,0x23,0x5B,0x79,0xC8,0x9E,0xBA,0xB2,0xC9,0x22,0x12, + 0x4B,0xB3,0xA1,0xB6,0x32,0x49,0xA2,0xE1,0x89,0x39,0x10,0x66,0xC5, 7,0x8F,0x54, + 0xEA,0x91,0xCA,0x3F,0xF9,0x19,0xF0,0xD7,0x46,0xBC,0x28,0x1B,0x61,0xE8,0x2F,0x6A, + 0xAE,0x9D,0xF6,0x4E, 9,0x14,0x77,0x4D,0xDB,0x1F,0x2E,0x7B,0x7C,0xF1,0x43,0xA3, + 0,0xB8,0x13,0x8C,0x85,0xB9,0x29,0x75,0x88,0xFD,0xD2,0x56,0x1C,0x50,0x97,0x41, + 0xE5,0x3B,0x60,0xB5,0xC0,0x64,0xEE,0x98,0xD6,0x2D,0x25,0xA4,0xAA,0xCD,0x7D,0xA8, + 0x83,0xC6,0xAB,0xBE,0x44,0x99,0x26,0x3C,0xCE,0x9F,0xBF,0xD3,0xCB,0x76,0x7A,0x7E, + 0x82, 1,0x8A,0x9A,0x80,0x1D, 0xE,0xB0,0x5C,0xD4,0x38,0x62,0xF4,0x30,0xE0,0x8E, + 0x53,0xB7, 2,0x57,0xAC,0xA6,0x52, 0xA,0x6D,0x92,0x65,0x17,0x24,0x33,0x45,0x72, + 0x74,0xB1,0xB4,0xF7,0x5D,0xED,0x2C,0xFF,0x47,0x37,0x5A,0x90,0xBB,0xDF,0x2A,0x16, + 0x59,0x95,0xD9,0xC4,0x27,0x67,0x73,0xC7,0x68,0xFE,0xA5,0xDD,0x6B,0x5F,0x93,0xD8, + 0xEC, 5,0x3A,0x8D,0x6E,0xFB,0x3D,0xA9,0x69,0x36,0xF3,0x94,0xDE,0xEF,0x15,0x6F, + 0x8B,0x9B, 8, 0xF,0xDC,0x81,0x18,0x20, 4,0xE4,0x71,0xCF,0xE9,0x2B,0x42,0x58, +}; + +u8 sboxes[8][256] = { + { + 1,0xA0,0xA9,0x62,0xD6,0x3F,0x85,0xA7,0xB6,0xD4,0xFA,0x15,0x66,0x17, 9,0xBD, + 0x5D,0x14,0x34,0x26,0x59,0x72,0x91,0x54, 6,0x4F,0xF8,0xB0,0x5B,0x74,0x93,0x99, + 0x8C,0xF2,0x45,0xCD,0xEA,0x4E,0xAD,0x10,0x4A,0xE5,0xCA,0xEE,0xDF,0xC6,0x6F,0x9F, + 0x88,0x8E, 2,0xCC, 8,0xA8,0x77,0x94,0x6D,0x21,0xB1,0x28,0xE4,0x39,0x79,0x96, + 0x60,0x71,0x81,0x16,0x2E,0xE6,0x78,0xB9,0xC4,0x46,0x9A,0x42,0xAE,0xB7,0x7C,0x43, + 0xB3,0x22,0x1A,0x86,0xC2,0x32,0x3D,0x2D,0x9C,0xD2,0x29,0xE9,0x63,0x9B,0xD1,0x31, + 0x38,0x5E,0x1E,0x36,0x41,0xBB, 3,0x18,0x2B,0x3E,0xBF,0x68,0x61,0xFC,0x52,0xC0, + 0xDE,0xE0, 0xA,0x58,0x13,0x5A, 0,0xBE,0x1C,0x90, 0xE,0x53,0x12,0xFD,0xE2,0x6E, + 0xBA,0xCE,0x24,0x27,0x44,0x7F,0x87,0xA3,0xA1,0xD5,0x50,0x40,0xE3,0xF9,0x83,0xF7, + 0xC7,0xA2,0x35,0xC8,0xDB,0x19,0xAB,0x2F,0x11,0x25,0xED,0x33,0x9E,0x55,0xE1,0x48, + 0xAF,0x73,0x84,0xDA,0x2A,0xAA,0x51,0xEB,0x9D,0x95,0xB2,0xCB,0xE7,0x70,0x80,0xFE, + 0x4C,0x65, 4,0xEF,0xC5,0xF1,0xC3,0x3A,0xB4,0xF5,0x5F,0x23,0x89,0xDD,0x30,0xA5, + 0x8B,0xD3,0xF6,0xDC,0x4D,0x64,0xD7,0xF0,0x8F,0xEC,0x56,0x37,0x5C,0xA4, 0xD, 7, + 0x76,0x8A,0x2C, 0xB,0xB5,0xD8,0xC1,0x1F,0xE8,0x3B,0xF4,0x4B,0x1B,0x47,0x6C,0x49, + 0x67,0x7B,0x92,0xCF,0x75,0x7E,0x20,0xD9,0x7D,0x3C,0x97,0x7A,0xD0, 5,0x6B, 0xF, + 0x1D,0xFB,0x82,0x98,0x57,0x8D,0xF3,0x6A,0xBC,0xAC,0xC9,0xA6,0xFF,0xB8,0x69, 0xC, + }, + { + 0x4C,0x4D,0x72, 7,0x5A,0x49,0x33,0x8D,0xA2,0xAB,0x46,0x3D,0x63, 0xD,0xA0,0x97, + 0xFF,0xF0,0xF5,0xFA,0xC0,0xE9,0xDB,0x62,0xE4,0xE1,0x74,0x43,0xDC,0x86,0x18,0x29, + 0x37,0xF4, 6,0xE2,0xED,0x6F,0x90,0x48,0x1E,0x2D,0x1D,0xEA,0x73,0x94,0x54,0xDF, + 0x25,0xF6,0x47,0x27,0xD9,0x11,0x77,0xC9,0x84,0x1C,0x5B,0x5C,0x51,0x81,0xA6,0x22, + 0x3E,0x24,0x96,0xC8,0x8A,0xEC,0x82,0x7C, 9,0xB8,0x45,0x4A,0x57,0xBB,0x2F,0x50, + 0x75,0x8E,0x61,0x70,0x8C,0x6C,0xAF,0xD0,0xFD,0xB4,0x1B,0xAE,0xDE,0xFE,0x3B,0xB5, + 0x36,0xBD,0x55, 1, 0xE,0x9C,0x41,0x56,0x5F,0xB3,0x26, 3,0x83,0xBA,0x13,0x4B, + 0xCA,0xC5, 0xA,0xF8,0x60,0xA5,0xB9,0xC7,0xC3,0x98,0x32,0xFB,0x12,0xF9,0xA7,0x92, + 0xAA,0x68,0xF3,0x78,0x7E, 5,0x20,0x21, 2,0xE8,0xBF,0xF2,0xB0,0x59,0x8F,0xD2, + 0xCB,0x87,0x65,0x15,0xF1,0x1A,0xB2,0x30,0xAD,0xEE,0x58,0xA3,0x8B,0x66,0x1F,0x2C, + 0xD7,0x5D,0x19,0x85,0xA8,0xE6,0xD3,0x6B,0xA1, 0xC,0x91,0x93,0x6A,0x5E, 0xB,0x79, + 0xE3,0xDD, 0,0x4F,0x3C,0x89,0x6E,0x71,0x69,0xA9,0xAC,0x40,0xE5,0x99,0x28,0xC6, + 0x31,0x4E,0x7A,0xCD, 8,0x9E,0x7D,0xEF,0x17,0xFC,0x88,0xD8,0xA4,0x6D,0x44,0x95, + 0xD1,0xB7,0xD4,0x9B,0xBE,0x2A,0x34,0x64,0x2B,0xCF,0x2E,0xEB,0x38,0xCE,0x23,0xE0, + 0x3A,0x3F,0xF7,0x7B,0x9F,0x10,0x53,0xBC,0x52,0x67,0x16,0xE7,0x80,0x76, 4,0xC4, + 0xB6,0xC1,0xC2,0x7F,0x9A,0xDA,0xD5,0x39,0x42,0x14,0x9D,0xB1, 0xF,0x35,0xD6,0xCC, + }, + { + 0xB9,0xDA,0x38, 0xC,0xA2,0x9C, 9,0x1F, 6,0xB1,0xB6,0xFD,0x1A,0x69,0x23,0x30, + 0xC4,0xDE, 1,0xD1,0xF4,0x58,0x29,0x37,0x1C,0x7D,0xD5,0xBF,0xFF,0xBD,0xC8,0xC9, + 0xCF,0x65,0xBE,0x7B,0x78,0x97,0x98,0x67, 8,0xB3,0x26,0x57,0xF7,0xFA,0x40,0xAD, + 0x8E,0x75,0xA6,0x7C,0xDB,0x91,0x8B,0x51,0x99,0xD4,0x17,0x7A,0x90,0x8D,0xCE,0x63, + 0xCB,0x4E,0xA0,0xAB,0x18,0x3A,0x5B,0x50,0x7F,0x21,0x74,0xC1,0xBB,0xB8,0xB7,0xBA, + 0xB,0x35,0x95,0x31,0x59,0x9A,0x4D, 4, 7,0x1E,0x5A,0x76,0x13,0xF3,0x71,0x83, + 0xD0,0x86, 3,0xA8,0x39,0x42,0xAA,0x28,0xE6,0xE4,0xD8,0x5D,0xD3,0xD0,0x6E,0x6F, + 0x96,0xFB,0x5E,0xBC,0x56,0xC2,0x5F,0x85,0x9B,0xE7,0xAF,0xD2,0x3B,0x84,0x6A,0xA7, + 0x53,0xC5,0x44,0x49,0xA5,0xF9,0x36,0x72,0x3D,0x2C,0xD9,0x1B,0xA1,0xF5,0x4F,0x93, + 0x9D,0x68,0x47,0x41,0x16,0xCA,0x2A,0x4C,0xA3,0x87,0xD6,0xE5,0x19,0x2E,0x77,0x15, + 0x6D,0x70,0xC0,0xDF,0xB2, 0,0x46,0xED,0xC6,0x6C,0x43,0x60,0x92,0x2D,0xA9,0x22, + 0x45,0x8F,0x34,0x55,0xAE,0xA4, 0xA,0x66,0x32,0xE0,0xDC, 2,0xAC,0xE8,0x20,0x8C, + 0x89,0x62,0x4A,0xFE,0xEE,0xC3,0xE3,0x3C,0xF1,0x79, 5,0xE9,0xF6,0x27,0x33,0xCC, + 0xF2,0x9E,0x11,0x81,0x7E,0x80,0x10,0x8A,0x82,0x9F,0x48, 0xD,0xD7,0xB4,0xFC,0x2F, + 0xB5,0xC7,0xDD,0x88,0x14,0x6B,0x2B,0x54,0xEA,0x1D,0x94,0x5C,0xB0,0xEF,0x12,0x24, + 0xCD,0xEB,0xE1,0xE2,0x64,0x73,0x3F, 0xE,0x52,0x61,0x25,0x3E,0xF8, 0xF,0x4B,0xEC, + }, + { + 0xC0, 0,0x30,0xF6, 2,0x49,0x3D,0x10,0x6E,0x20,0xC9,0xA6,0x2F,0xFE,0x2C,0x2B, + 0x75,0x2E,0x45,0x26,0xAB,0x48,0xA9,0x80,0xFC, 4,0xCC,0xD3,0xB5,0xBA,0xA3,0x38, + 0x31,0x7D, 1,0xD9,0xA7,0x7B,0x96,0xB6,0x63,0x69,0x4E,0xF7,0xDE,0xE0,0x78,0xCA, + 0x50,0xAA,0x41,0x91,0x65,0x88,0xE4,0x21,0x85,0xDA,0x3A,0x27,0xBE,0x1C,0x3E,0x42, + 0x5E,0x17,0x52,0x7F,0x1F,0x89,0x24,0x6F,0x8F,0x5C,0x67,0x74, 0xE,0x12,0x87,0x8D, + 0xE9,0x34,0xED,0x73,0xC4,0xF8,0x61,0x5B, 5,0xDF,0x59,0x4C,0x97,0x79,0x83,0x18, + 0xA4,0x55,0x95,0xEB,0xBD,0x53,0xF5,0xF1,0x57,0x66,0x46,0x9F,0xB2,0x81, 9,0x51, + 0x86,0x22,0x16,0xDD,0x23,0x93,0x76,0x29,0xC2,0xD7,0x1D,0xD4,0xBF,0x36,0x3F,0xEA, + 0x4B,0x11,0x32,0xB9,0x62,0x54,0x60,0xD6,0x6D,0x43,0x9A, 0xD,0x92,0x9C,0xB0,0xEF, + 0x58,0x6C,0x9D,0x77,0x2D,0x70,0xFA,0xF3,0xB3, 0xB,0xE2,0x40,0x7E,0xF4,0x8A,0xE5, + 0x8C,0x3C,0x56,0x71,0xD1,0x64,0xE1,0x82, 0xA,0xCB,0x13,0x15,0x90,0xEC, 3,0x99, + 0xAF,0x14,0x5D, 0xF,0x33,0x4A,0x94,0xA5,0xA8,0x35,0x1B,0xE3,0x6A,0xC6,0x28,0xFF, + 0x4D,0xE7,0x25,0x84,0xAC, 8,0xAE,0xC5,0xA2,0x2A,0xB8,0x37, 0xC,0x7A,0xA0,0xC3, + 0xCE,0xAD, 6,0x1A,0x9E,0x8B,0xFB,0xD5,0xD0,0xC1,0x1E,0xD0,0xB4,0x9B,0xB1,0x44, + 0xF2,0x47,0xC7,0x68,0xCF,0x72,0xBB,0x4F,0x5A,0xF9,0xDC,0x6B,0xDB,0xD2,0xE8,0x7C, + 0xC8,0xEE,0x98,0xA1,0xE6,0xD8,0x39, 7,0x5F,0xFD,0x8E,0x19,0xB7,0x3B,0xBC,0xCD, + }, + { + 0x7C,0xE3,0x81,0x73,0xB2,0x11,0xBF,0x6F,0x20,0x98,0xFE,0x75,0x96,0xEF,0x6C,0xDA, + 0x50,0xE1, 9,0x72,0x54,0x45,0xBA,0x34,0x80,0x5B,0xED,0x3E,0x53,0x2C,0x87,0xA4, + 0x57,0xF3,0x33,0x3F,0x3C,0xB7,0x67,0xB4,0xA3,0x25,0x60,0x4F, 7,0x6B,0x1B,0x47, + 0x15, 0xF,0xE4, 0xA,0xEA,0xD1,0x32,0x78,0x36,0x49,0x8D,0x4B,0xD2,0xBC,0xA5,0xDC, + 0x1D, 0xD,0x4D,0xCD,0x9A,0x82,0x5F,0xFC,0x94,0x65,0xBE,0xE2,0xF4,0xC9,0x1E,0x44, + 0xCB,0x9E, 0xC,0x64,0x71,0x26,0x63,0xB3,0x14,0xE8,0x40,0x70,0x8A, 0xE,0x19,0x42, + 0x6D,0xAC,0x88,0x10,0x5C,0xDF,0x41,0xA9,0xAD,0xE5,0xFB,0x74,0xCC,0xD5, 6,0x8E, + 0x59,0x86,0xCE,0x1F,0x3D,0x76,0xE0,0x8F,0xB9,0x77,0x27,0x7B,0xA6,0xD8,0x29,0xD3, + 0xEC,0xB8,0x13,0xF7,0xFA,0xC3,0x51,0x6A,0xDE,0x4A,0x5A,0xEB,0xC2,0x8B,0x23,0x48, + 0x92,0xCF,0x62,0xA8,0x99,0xF8,0xD0,0x2E,0x85,0x61,0x43,0xC8,0xBD,0xF0, 5,0x93, + 0xCA,0x4E,0xF1,0x7D,0x30,0xFD,0xC4,0x69,0x66,0x2F, 8,0xB1,0x52,0xF9,0x21,0xE6, + 0x7A,0x2B,0xDD,0x39,0x84,0xFF,0xC0,0x91,0xD6,0x37,0xD4,0x7F,0x2D,0x9B,0x5D,0xA1, + 0x3B,0x6E,0xB5,0xC5,0x46, 4,0xF5,0x90,0xEE,0x7E,0x83,0x1C, 3,0x56,0xB6,0xAA, + 0,0x17, 1,0x35,0x55,0x79, 0xB,0x12,0xBB,0x1A,0x31,0xE7, 2,0x28,0x16,0xC1, + 0xF6,0xA2,0xDB,0x18,0x9C,0x89,0x68,0x38,0x97,0xAB,0xC7,0x2A,0xD7,0x3A,0xF2,0xC6, + 0x24,0x4C,0xB0,0x58,0xA0,0x22,0x5E,0x9D,0xD9,0xA7,0xE9,0xAE,0xAF,0x8C,0x95,0x9F, + }, + { + 0x28,0xB7,0x20,0xD7,0xB0,0x30,0xC3, 9,0x19,0xC0,0x67,0xD6, 0,0x3C,0x7E,0xE7, + 0xE9,0xF4, 8,0x5A,0xF8,0xB8,0x2E, 5,0xA6,0x25,0x9E,0x5C,0xD8,0x15, 0xD,0xE1, + 0xF6,0x11,0x54,0x6B,0xCD,0x21,0x46,0x66,0x5E,0x84,0xAD, 6,0x38,0x29,0x44,0xC5, + 0xA2,0xCE,0xF1,0xAA,0xC1,0x40,0x71,0x86,0xB5,0xEF,0xFC,0x36,0xA8,0xCB, 0xA,0x48, + 0x27,0x45,0x64,0xA3,0xAF,0x8C,0xB2,0xC6,0x9F, 7,0x89,0xDC,0x17,0xD3,0x49,0x79, + 0xFB,0xFE,0x1D,0xD0,0xB9,0x88,0x43,0x52,0xBC, 1,0x78,0x2B,0x7D,0x94,0xC7, 0xE, + 0xDE,0xA5,0xD5,0x9B,0xCC,0xF7,0x61,0x7A,0xC2,0x74,0x81,0x39, 3,0xAB,0x96,0xA0, + 0x37,0xBD,0x2D,0x72,0x75,0x3F,0xC9,0xD4,0x8E,0x6F,0xF9,0x8D,0xED,0x62,0xDB,0x1C, + 0xDF, 4,0xAC,0x1B,0x6C,0x14,0x4B,0x63,0xD0,0xBF,0xB4,0x82,0xEC,0x7B,0x1A,0x59, + 0x92,0xD2,0x10,0x60,0xB6,0x3D,0x5F,0xE6,0x80,0x6E,0x70,0xC4,0xF2,0x35,0xD9,0x7C, + 0xEE,0xE5,0x41,0xA4,0x5B,0x50,0xDD,0xBB,0x4C,0xF3,0x1F,0x9D,0x5D,0x57,0x55,0x51, + 0x97,0xE3,0x58,0x42,0x4D,0x9C,0x73,0xBA,0xC8,0x77,0x31,0x69,0x26,0xAE,0xEA,0x8A, + 0xDA,0x22,0xB3,0x87,0x56,0xFA,0x93, 0xB,0x34,0x16,0x33,0xE8,0xE4,0x53,0xBE,0xA9, + 0xB1,0x3A,0x3E,0xF5,0x90,0x6A,0xCF,0x3B,0x12,0xFD,0x8F,0x9A,0xA7,0x47,0x91,0x99, + 0xEB, 0xF,0x24,0xFF,0x23,0x18,0x85,0x4E,0x7F, 0xC,0xE0,0xA1,0xD2,0xD1,0x2C,0x2A, + 0x4A, 2,0x4F,0x1E,0x95,0x68,0x8B,0x98,0x83,0x6D,0x76,0xCA,0x65,0x32,0x13,0x2F, + }, + { + 0xC3,0x82,0x9A,0xA4,0xBA,0x81,0x60,0x37,0x34,0x35,0xFC,0x80,0xA8,0x51,0x65,0x67, + 0xED,0x30,0x5F,0x10,0xD3,0x4A,0x27,0x2F,0x13,0xB9,0x2A,0xD2,0xCC,0xE1,0xEF,0xAE, + 0xEB,0xBE,0xF4,0xBD,0xCF,0x43,0xB3,0xC5,0x88,0x84,0xB7,0xDD,0x39,0x40,0xCE,0x48, + 0x6D,0x9B,0x72,0x61,0x7E,0xE7,0xA1,0x4E,0x53,0x2E,0x77,0x3B,0xE2,0xC9,0x36,0x22, + 0x1B,0x6E,0x73,0xB1, 3,0xB2,0x4C,0x87,0xA9,0xD4,0x4D, 0xF,0xD8,0x15,0x6C,0xAA, + 0x18,0xF6,0x49,0x57,0x5D,0xFB,0x7A,0x14,0x94,0x63,0xA0,0x11,0xB0,0x9E,0xDE, 5, + 0x46,0xC8,0xEE,0x47,0xDB,0xDC,0x24,0x89,0x9C,0x91,0x97,0x29,0xE9,0x7B,0xC1, 7, + 0x1E,0xB8,0xFD,0xFE,0xAC,0xC6,0x62,0x98,0x4F,0xF1,0x79,0xE0,0xE8,0x6B,0x78,0x56, + 0xB6,0x8D, 4,0x50,0x86,0xCA,0x6F,0x20,0xE6,0xEA,0xE5,0x76,0x17,0x1C,0x74,0x7F, + 0xBC, 0xD,0x2C,0x85,0xF7,0x66,0x96,0xE4,0x8B,0x75,0x3F,0x4B,0xD9,0x38,0xAF,0x7C, + 0xDA, 0xB,0x83,0x2D,0x31,0x32,0xA2,0xF5,0x1D,0x59,0x41,0x45,0xBF,0x3C,0x1F,0xF8, + 0xF9,0x8A,0xD0,0x16,0x25,0x69,0x12,0x99,0x9D,0x21,0x95,0xAB, 1,0xA6,0xD7,0xB5, + 0xC0,0x7D,0xFF,0x58, 0xE,0x3A,0x92,0xD1,0x55,0xE3, 8,0x9F,0xD6,0x3E,0x52,0x8E, + 0xFA,0xA3,0xC7, 2,0xCD,0xDF,0x8F,0x64,0x19,0x8C,0xF3,0xA7, 0xC,0x5E, 0xA,0x6A, + 9,0xF0,0x93,0x5B,0x42,0xC2, 6,0x23,0xEC,0x71,0xAD,0xB4,0xCB,0xBB,0x70,0x28, + 0xD5,0x1A,0x5C,0x33,0x68,0x5A, 0,0x44,0x90,0xA5,0xC4,0x26,0x3D,0x2B,0xF2,0x54, + }, + { + 0x96,0xAD,0xDA,0x1F,0xED,0x33,0xE1,0x81,0x69, 8, 0xD, 0xA,0xDB,0x35,0x77,0x9A, + 0x64,0xD1,0xFC,0x78,0xAA,0x1B,0xD0,0x67,0xA0,0xDD,0xFA,0x6C,0x63,0x71, 5,0x84, + 0x17,0x6A,0x89,0x4F,0x66,0x7F,0xC6,0x50,0x55,0x92,0x6F,0xBD,0xE7,0xD2,0x40,0x72, + 0x8D,0xBB,0xEC, 6,0x42,0x8A,0xE4,0x88,0x9D,0x7E,0x7A,0x82,0x27,0x13,0x41,0x1A, + 0xAF,0xC8,0xA4,0x76,0xB4,0xC2,0xFE,0x6D,0x1C,0xD9,0x61,0x30,0xB3,0x7C,0xEA,0xF7, + 0x29, 0xF,0xF2,0x3B,0x51,0xC1,0xDE,0x5F,0xE5,0x2A,0x2F,0x99, 0xB,0x5D,0xA3,0x2B, + 0x4A,0xAB,0x95,0xA5,0xD3,0x58,0x56,0xEE,0x28,0x31, 0,0xCC,0x15,0x46,0xCA,0xE6, + 0x86,0x38,0x3C,0x65,0xF5,0xE3,0x9F,0xD6,0x5B, 9,0x49,0x83,0x70,0x2D,0x53,0xA9, + 0x7D,0xE2,0xC4,0xAC,0x8E,0x5E,0xB8,0x25,0xF4,0xB9,0x57,0xF3,0xF1,0x68,0x47,0xB2, + 0xA2,0x59,0x20,0xCE,0x34,0x79,0x5C,0x90, 0xE,0x1E,0xBE,0xD5,0x22,0x23,0xB1,0xC9, + 0x18,0x62,0x16,0x2E,0x91,0x3E, 7,0x8F,0xD8,0x3F,0x93,0x3D,0xD4,0x9B,0xDF,0x85, + 0x21,0xFB,0x11,0x74,0x97,0xC7,0xD7,0xDC,0x4C,0x19,0x45,0x98,0xE9,0x43, 2,0x4B, + 0xBC,0xC3, 4,0x9C,0x6B,0xF0,0x75,0x52,0xA7,0x26,0xF6,0xC5,0xBA,0xCF,0xB0,0xB7, + 0xAE,0x5A,0xA1,0xBF, 3,0x8B,0x80,0x12,0x6E, 0xC,0xEB,0xF9,0xC0,0x44,0x24,0xEF, + 0x10,0xF8,0xA8,0x8C,0xE8,0x7B,0xFF,0x9E,0x2C,0xCD,0x60,0x36,0x87,0xB5,0x94,0xA6, + 0x54,0x73,0x3A,0x14,0x4E, 1,0x1D,0xB6,0xFD,0x37,0x48,0x4D,0x39,0xCB,0xE0,0x32, + } +}; + + +static inline u8 ror8(u8 a, u8 b) { + return (a>>b) | ((a<<(8-b))&0xff); +} + + +void genkey(u8 *rand, u8 idx, u8 *key) +{ + u8 *ans = ans_tbl[idx]; + u8 t0[10]; + int i; + + for(i=0;i<10;i++) + t0[i] = tsbox[rand[i]]; + + key[0] = ((ror8((ans[0]^t0[5]),(t0[2]%8)) - t0[9]) ^ t0[4]); + key[1] = ((ror8((ans[1]^t0[1]),(t0[0]%8)) - t0[5]) ^ t0[7]); + key[2] = ((ror8((ans[2]^t0[6]),(t0[8]%8)) - t0[2]) ^ t0[0]); + key[3] = ((ror8((ans[3]^t0[4]),(t0[7]%8)) - t0[3]) ^ t0[2]); + key[4] = ((ror8((ans[4]^t0[1]),(t0[6]%8)) - t0[3]) ^ t0[4]); + key[5] = ((ror8((ans[5]^t0[7]),(t0[8]%8)) - t0[5]) ^ t0[9]); +} + + +void gentabs(u8 *rand, u8 *key, u8 idx, u8 *ft, u8 *sb) +{ + ft[0] = sboxes[idx][key[4]] ^ sboxes[(idx+1)%8][rand[3]]; + ft[1] = sboxes[idx][key[2]] ^ sboxes[(idx+1)%8][rand[5]]; + ft[2] = sboxes[idx][key[5]] ^ sboxes[(idx+1)%8][rand[7]]; + ft[3] = sboxes[idx][key[0]] ^ sboxes[(idx+1)%8][rand[2]]; + ft[4] = sboxes[idx][key[1]] ^ sboxes[(idx+1)%8][rand[4]]; + ft[5] = sboxes[idx][key[3]] ^ sboxes[(idx+1)%8][rand[9]]; + ft[6] = sboxes[idx][rand[0]] ^ sboxes[(idx+1)%8][rand[6]]; + ft[7] = sboxes[idx][rand[1]] ^ sboxes[(idx+1)%8][rand[8]]; + + sb[0] = sboxes[idx][key[0]] ^ sboxes[(idx+1)%8][rand[1]]; + sb[1] = sboxes[idx][key[5]] ^ sboxes[(idx+1)%8][rand[4]]; + sb[2] = sboxes[idx][key[3]] ^ sboxes[(idx+1)%8][rand[0]]; + sb[3] = sboxes[idx][key[2]] ^ sboxes[(idx+1)%8][rand[9]]; + sb[4] = sboxes[idx][key[4]] ^ sboxes[(idx+1)%8][rand[7]]; + sb[5] = sboxes[idx][key[1]] ^ sboxes[(idx+1)%8][rand[8]]; + sb[6] = sboxes[idx][rand[3]] ^ sboxes[(idx+1)%8][rand[5]]; + sb[7] = sboxes[idx][rand[2]] ^ sboxes[(idx+1)%8][rand[6]]; +} + + + + +// =================================================== +/* Generate key from the 0x40-0x4c data in g_RegExt */ +// ---------------- +void wiimote_gen_key(wiimote_key *key, u8 *keydata) +{ + u8 rand[10]; + u8 skey[6]; + u8 testkey[6]; + int idx; + + for(int i=0;i<10;i++) + rand[9-i] = keydata[i]; + for(int i=0;i<6;i++) + skey[5-i] = keydata[i+10]; + + wprintf("rand: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", rand[0], rand[1], rand[2], rand[3], rand[4], rand[5], rand[6], rand[7], rand[8], rand[9]); + wprintf("key: %02x %02x %02x %02x %02x %02x\n", skey[0], skey[1], skey[2], skey[3], skey[4], skey[5]); + + for(idx=0;idx<7;idx++) + { + genkey(rand, idx, testkey); + if(!memcmp(testkey,skey,6)) + break; + } + // default case is idx = 7 which is valid (homebrew uses it for the 0x17 case) + wprintf("idx: %d\n", idx); + + gentabs(rand, skey, idx, key->ft, key->sb); + + wprintf("ft: %02x %02x %02x %02x %02x %02x %02x %02x\n", key->ft[0], key->ft[1], key->ft[2], key->ft[3], key->ft[4], key->ft[5], key->ft[6], key->ft[7]); + wprintf("sb: %02x %02x %02x %02x %02x %02x %02x %02x\n", key->sb[0], key->sb[1], key->sb[2], key->sb[3], key->sb[4], key->sb[5], key->sb[6], key->sb[7]); + + // for homebrew, ft and sb are all 0x97 which is equivalent to 0x17 +} + + +// =================================================== +/* Encrypt data */ +// ---------------- +void wiimote_encrypt(wiimote_key *key, u8 *data, int addr, u8 len) +{ + for(int i = 0; i < len; i++, addr++) + { + //wprintf("data[%i] from %02x ", i, data[i]); + data[i] = (data[i] - key->ft[addr%8]) ^ key->sb[addr%8]; + //wprintf("to %02x\n", data[i]); + } +} diff --git a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp index db6f5e5843..42df0bac50 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp @@ -1,711 +1,711 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -#include - -#include "pluginspecs_wiimote.h" - -#include -#include -#include "Common.h" -#include "wiimote_hid.h" -#include "EmuSubroutines.h" -#include "EmuDefinitions.h" -#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd -#include "Config.h" // for g_Config - -extern SWiimoteInitialize g_WiimoteInitialize; - - -namespace WiiMoteEmu -{ - -//****************************************************************************** -// Subroutines -//****************************************************************************** - - -// =================================================== -/* Debugging. Read out an u8 array. */ -// ---------------- -std::string ArrayToString(const u8 *data, u32 size, u32 offset, int line_len) -{ - //const u8* _data = (const u8*)data; - std::string Temp; - for (u32 i = 0; i < size; i++) - { - char Buffer[128]; - sprintf(Buffer, "%02x ", data[i + offset]); - if((i + 1) % line_len == 0) Temp.append("\n"); // break long lines - Temp.append(Buffer); - } - return Temp; -} -// ================ - - -void FillReportInfo(wm_core& _core) -{ - memset(&_core, 0x00, sizeof(wm_core)); - -#ifdef _WIN32 - // allow both mouse buttons and keyboard to press a and b - if(GetAsyncKeyState(VK_LBUTTON) ? 1 : 0 || GetAsyncKeyState('A') ? 1 : 0) - _core.a = 1; - - if(GetAsyncKeyState(VK_RBUTTON) ? 1 : 0 || GetAsyncKeyState('B') ? 1 : 0) - _core.b = 1; - - _core.one = GetAsyncKeyState('1') ? 1 : 0; - _core.two = GetAsyncKeyState('2') ? 1 : 0; - _core.plus = GetAsyncKeyState('P') ? 1 : 0; - _core.minus = GetAsyncKeyState('M') ? 1 : 0; - _core.home = GetAsyncKeyState('H') ? 1 : 0; - - - /* Sideways controls (for example for Wario Land) was not enabled automatically - so I have to use this function. I'm not sure how it works on the actual Wii. - */ - if(g_Config.bSidewaysDPad) - { - _core.left = GetAsyncKeyState(VK_DOWN) ? 1 : 0; - _core.up = GetAsyncKeyState(VK_LEFT) ? 1 : 0; - _core.right = GetAsyncKeyState(VK_UP) ? 1 : 0; - _core.down = GetAsyncKeyState(VK_RIGHT) ? 1 : 0; - } - else - { - _core.left = GetAsyncKeyState(VK_LEFT) ? 1 : 0; - _core.up = GetAsyncKeyState(VK_UP) ? 1 : 0; - _core.right = GetAsyncKeyState(VK_RIGHT) ? 1 : 0; - _core.down = GetAsyncKeyState(VK_DOWN) ? 1 : 0; - } -#else - // TODO: fill in -#endif -} - -// ----------------------------- -/* Global declarations for FillReportAcc. The accelerometer x, y and z values range from - 0x00 to 0xff with the default netural values being [y = 0x84, x = 0x84, z = 0x9f] - according to a source. The extremes are 0x00 for (-) and 0xff for (+). It's important - that all values are not 0x80, the the mouse pointer can disappear from the screen - permanently then, until z is adjusted back. */ -// ---------- -// the variables are global so they can be changed during debugging -//int A = 0, B = 128, C = 64; // for debugging -//int a = 1, b = 1, c = 2, d = -2; // for debugging -//int consoleDisplay = 0; - -int X = 0x84, Y = 0x84, Z = 0x9f; // neutral values -u8 x = X, y = Y, z = Z; -int shake = -1, yhistsize = 15; // for the shake function -std::vector yhist(15); // for the tilt function - -void FillReportAcc(wm_accel& _acc) -{ -#ifdef _WIN32 - // ----------------------------- - // Wiimote to Gamepad translations - // ---------- - // Tilting Wiimote (Wario Land aiming, Mario Kart steering) : For some reason 150 and 40 - // seemed like decent starting values. - if(GetAsyncKeyState('3')) - { - //if(a < 128) // for debugging - if(y < 250) - { - y += 4; // aim left - //a += c; // debugging values - //y = A + a; // aim left - } - } - else if(GetAsyncKeyState('4')) - { - // if(b < 128) // for debugging - if(y > 5) - { - y -= 4; // aim right - //b -= d; // debugging values - //y = B + b; - } - } - - - /* Single shake of Wiimote while holding it sideways (Wario Land pound ground) - if(GetAsyncKeyState('S')) - z = 0; - else - z = Z;*/ - - if(GetAsyncKeyState('S')) - { - z = 0; - y = 0; - shake = 2; - } - else if(shake == 2) - { - z = 128; - y = 0; - shake = 1; - } - else if(shake == 1) - { - z = Z; - y = Y; - shake = -1; - } - else // the default Y and Z if nothing is pressed - { - z = Z; - } - // ---------- - - - // ----------------------------- - // For tilting: add new value and move all back - // ---------- - bool ypressed = false; - - yhist[yhist.size() - 1] = ( - GetAsyncKeyState('3') ? true : false - || GetAsyncKeyState('4') ? true : false - || shake > 0 - ); - if(yhistsize > yhist.size()) yhistsize = yhist.size(); - for (int i = 1; i < yhistsize; i++) - { - yhist[i-1] = yhist[i]; - if(yhist[i]) ypressed = true; - } - - if(!ypressed) // y was not pressed a single time - { - y = Y; // this is the default value that will occur most of the time - //a = 0; // for debugging - //b = 0; - } - else if(!GetAsyncKeyState('3') && !GetAsyncKeyState('4')) - { - // perhaps start dropping acceleration back? - } - // ---------- - - - // Write values - _acc.x = X; - _acc.y = y; - _acc.z = z; - - - // ---------------------------- - // Debugging for translating Wiimote to Keyboard (or Gamepad) - // ---------- - /* - - // Toogle console display - if(GetAsyncKeyState('U')) - { - if(consoleDisplay < 2) - consoleDisplay ++; - else - consoleDisplay = 0; - } - - if(GetAsyncKeyState('5')) - A-=1; - else if(GetAsyncKeyState('6')) - A+=1; - if(GetAsyncKeyState('7')) - B-=1; - else if(GetAsyncKeyState('8')) - B+=1; - if(GetAsyncKeyState('9')) - C-=1; - else if(GetAsyncKeyState('0')) - C+=1; - - else if(GetAsyncKeyState(VK_NUMPAD3)) - d-=1; - else if(GetAsyncKeyState(VK_NUMPAD6)) - d+=1; - else if(GetAsyncKeyState(VK_ADD)) - yhistsize-=1; - else if(GetAsyncKeyState(VK_SUBTRACT)) - yhistsize+=1; - - - if(GetAsyncKeyState(VK_INSERT)) - AX-=1; - else if(GetAsyncKeyState(VK_DELETE)) - AX+=1; - else if(GetAsyncKeyState(VK_HOME)) - AY-=1; - else if(GetAsyncKeyState(VK_END)) - AY+=1; - else if(GetAsyncKeyState(VK_SHIFT)) - AZ-=1; - else if(GetAsyncKeyState(VK_CONTROL)) - AZ+=1; - - if(GetAsyncKeyState(VK_NUMPAD1)) - X+=1; - else if(GetAsyncKeyState(VK_NUMPAD2)) - X-=1; - if(GetAsyncKeyState(VK_NUMPAD4)) - Y+=1; - else if(GetAsyncKeyState(VK_NUMPAD5)) - Y-=1; - if(GetAsyncKeyState(VK_NUMPAD7)) - Z+=1; - else if(GetAsyncKeyState(VK_NUMPAD8)) - Z-=1; - - - //if(consoleDisplay == 0) - wprintf("x: %03i | y: %03i | z: %03i | A:%i B:%i C:%i a:%i b:%i c:%i d:%i X:%i Y:%i Z:%i\n", - _acc.x, _acc.y, _acc.z, - A, B, C, - a, b, c, d, - X, Y, Z - ); - wprintf("x: %03i | y: %03i | z: %03i | X:%i Y:%i Z:%i | AX:%i AY:%i AZ:%i \n", - _acc.x, _acc.y, _acc.z, - X, Y, Z, - AX, AY, AZ - );*/ -#else - // TODO port to linux -#endif -} - - -void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1) -{ - -/* DESCRIPTION: The calibration is controlled by these values, their absolute value and - the relative distance between between them control the calibration. WideScreen mode - has its own settings. */ - int Top, Left, Right, Bottom, SensorBarRadius; - if(g_Config.bWideScreen) - { - Top = wTOP; Left = wLEFT; Right = wRIGHT; - Bottom = wBOTTOM; SensorBarRadius = wSENSOR_BAR_RADIUS; - } - else - { - Top = TOP; Left = LEFT; Right = RIGHT; - Bottom = BOTTOM; SensorBarRadius = SENSOR_BAR_RADIUS; - } - - // Fill with 0xff if empty - memset(&_ir0, 0xFF, sizeof(wm_ir_extended)); - memset(&_ir1, 0xFF, sizeof(wm_ir_extended)); - - float MouseX, MouseY; - GetMousePos(MouseX, MouseY); - - int y0 = Top + (MouseY * (Bottom - Top)); - int y1 = Top + (MouseY * (Bottom - Top)); - - int x0 = Left + (MouseX * (Right - Left)) - SensorBarRadius; - int x1 = Left + (MouseX * (Right - Left)) + SensorBarRadius; - - x0 = 1023 - x0; - _ir0.x = x0 & 0xFF; - _ir0.y = y0 & 0xFF; - _ir0.size = 10; - _ir0.xHi = x0 >> 8; - _ir0.yHi = y0 >> 8; - - x1 = 1023 - x1; - _ir1.x = x1 & 0xFF; - _ir1.y = y1 & 0xFF; - _ir1.size = 10; - _ir1.xHi = x1 >> 8; - _ir1.yHi = y1 >> 8; - - - // ---------------------------- - // Debugging for calibration - // ---------- - /* - if(GetAsyncKeyState(VK_NUMPAD1)) - Right +=1; - else if(GetAsyncKeyState(VK_NUMPAD2)) - Right -=1; - if(GetAsyncKeyState(VK_NUMPAD4)) - Left +=1; - else if(GetAsyncKeyState(VK_NUMPAD5)) - Left -=1; - if(GetAsyncKeyState(VK_NUMPAD7)) - Top += 1; - else if(GetAsyncKeyState(VK_NUMPAD8)) - Top -= 1; - if(GetAsyncKeyState(VK_NUMPAD6)) - Bottom += 1; - else if(GetAsyncKeyState(VK_NUMPAD3)) - Bottom -= 1; - if(GetAsyncKeyState(VK_INSERT)) - SensorBarRadius += 1; - else if(GetAsyncKeyState(VK_DELETE)) - SensorBarRadius -= 1; - - //ClearScreen(); - //if(consoleDisplay == 1) - wprintf("x0:%03i x1:%03i y0:%03i y1:%03i irx0:%03i y0:%03i x1:%03i y1:%03i | T:%i L:%i R:%i B:%i S:%i\n", - x0, x1, y0, y1, _ir0.x, _ir0.y, _ir1.x, _ir1.y, Top, Left, Right, Bottom, SensorBarRadius - ); - wprintf("\n"); - wprintf("ir0.x:%02x xHi:%02x ir1.x:%02x xHi:%02x | ir0.y:%02x yHi:%02x ir1.y:%02x yHi:%02x | 1.s:%02x 2:%02x\n", - _ir0.x, _ir0.xHi, _ir1.x, _ir1.xHi, - _ir0.y, _ir0.yHi, _ir1.y, _ir1.yHi, - _ir0.size, _ir1.size - );*/ -} - - -void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1) -{ - /* See description above */ - int Top, Left, Right, Bottom, SensorBarRadius; - - if(g_Config.bWideScreen) - { - Top = wTOP; Left = wLEFT; Right = wRIGHT; - Bottom = wBOTTOM; SensorBarRadius = wSENSOR_BAR_RADIUS; - } - else - { - Top = TOP; Left = LEFT; Right = RIGHT; - Bottom = BOTTOM; SensorBarRadius = SENSOR_BAR_RADIUS; - } - - // Fill with 0xff if empty - memset(&_ir0, 0xff, sizeof(wm_ir_basic)); - memset(&_ir1, 0xff, sizeof(wm_ir_basic)); - - float MouseX, MouseY; - GetMousePos(MouseX, MouseY); - - int y1 = Top + (MouseY * (Bottom - Top)); - int y2 = Top + (MouseY * (Bottom - Top)); - - int x1 = Left + (MouseX * (Right - Left)) - SensorBarRadius; - int x2 = Left + (MouseX * (Right - Left)) + SensorBarRadius; - - /* As with the extented report we settle with emulating two out of four - possible objects */ - x1 = 1023 - x1; - _ir0.x1 = x1 & 0xff; - _ir0.y1 = y1 & 0xff; - _ir0.x1Hi = (x1 >> 8); // we are dealing with 2 bit values here - _ir0.y1Hi = (y1 >> 8); - - x2 = 1023 - x2; - _ir0.x2 = x2 & 0xff; - _ir0.y2 = y2 & 0xff; - _ir0.x2Hi = (x2 >> 8); - _ir0.y2Hi = (y2 >> 8); - - // I don't understand't the & 0x03, should we do that? - //_ir1.x1Hi = (x1 >> 8) & 0x3; - //_ir1.y1Hi = (y1 >> 8) & 0x3; - - // ---------------------------- - // Debugging for calibration - // ---------- - /* - if(GetAsyncKeyState(VK_NUMPAD1)) - Right +=1; - else if(GetAsyncKeyState(VK_NUMPAD2)) - Right -=1; - if(GetAsyncKeyState(VK_NUMPAD4)) - Left +=1; - else if(GetAsyncKeyState(VK_NUMPAD5)) - Left -=1; - if(GetAsyncKeyState(VK_NUMPAD7)) - Top += 1; - else if(GetAsyncKeyState(VK_NUMPAD8)) - Top -= 1; - if(GetAsyncKeyState(VK_NUMPAD6)) - Bottom += 1; - else if(GetAsyncKeyState(VK_NUMPAD3)) - Bottom -= 1; - if(GetAsyncKeyState(VK_INSERT)) - SensorBarRadius += 1; - else if(GetAsyncKeyState(VK_DELETE)) - SensorBarRadius -= 1; - - //ClearScreen(); - //if(consoleDisplay == 1) - - wprintf("x1:%03i x2:%03i y1:%03i y2:%03i irx1:%02x y1:%02x x2:%02x y2:%02x | T:%i L:%i R:%i B:%i S:%i\n", - x1, x2, y1, y2, _ir0.x1, _ir0.y1, _ir1.x2, _ir1.y2, Top, Left, Right, Bottom, SensorBarRadius - ); - wprintf("\n"); - wprintf("ir0.x1:%02x x1h:%02x x2:%02x x2h:%02x | ir0.y1:%02x y1h:%02x y2:%02x y2h:%02x | ir1.x1:%02x x1h:%02x x2:%02x x2h:%02x | ir1.y1:%02x y1h:%02x y2:%02x y2h:%02x\n", - _ir0.x1, _ir0.x1Hi, _ir0.x2, _ir0.x2Hi, - _ir0.y1, _ir0.y1Hi, _ir0.y2, _ir0.y2Hi, - _ir1.x1, _ir1.x1Hi, _ir1.x2, _ir1.x2Hi, - _ir1.y1, _ir1.y1Hi, _ir1.y2, _ir1.y2Hi - );*/ -} - - -// =================================================== -/* Generate the 6 byte extension report, encrypted. The bytes are JX JY AX AY AZ BT. */ -// ---------------- -void FillReportExtension(wm_extension& _ext) -{ - - /* These are the default neutral values for the nunchuck accelerometer according - to a source. */ - _ext.ax = 0x80; - _ext.ay = 0x80; - _ext.az = 0xb3; - - - _ext.jx = 0x80; // these are the default values unless we use them - _ext.jy = 0x80; - _ext.bt = 0x03; // 0x03 means no button pressed, the button is zero active - - -#ifdef _WIN32 - /* We use a 192 range (32 to 224) that match our calibration values in - nunchuck_calibration */ - if(GetAsyncKeyState(VK_NUMPAD4)) // left - _ext.jx = 0x20; - - if(GetAsyncKeyState(VK_NUMPAD8)) - _ext.jy = 0xe0; - - if(GetAsyncKeyState(VK_NUMPAD6)) // right - _ext.jx = 0xe0; - - if(GetAsyncKeyState(VK_NUMPAD5)) - _ext.jy = 0x20; - - - if(GetAsyncKeyState('C')) - _ext.bt = 0x01; - - if(GetAsyncKeyState('Z')) - _ext.bt = 0x02; - - if(GetAsyncKeyState('C') && GetAsyncKeyState('Z')) - _ext.bt = 0x00; -#else - // TODO linux port -#endif - - // Clear g_RegExtTmp by copying zeroes to it - memset(g_RegExtTmp, 0, sizeof(g_RegExtTmp)); - - /* Write the nunchuck inputs to it. We begin writing at 0x08, but it could also be - 0x00, the important thing is that we begin at an address evenly divisible - by 0x08 */ - memcpy(g_RegExtTmp + 0x08, &_ext, sizeof(_ext)); - - // Encrypt it - wiimote_encrypt(&g_ExtKey, &g_RegExtTmp[0x08], 0x08, sizeof(_ext)); - - // Write it back - memcpy(&_ext, &g_RegExtTmp[0x08], sizeof(_ext)); -} - - -// =================================================== -/* Generate the 6 byte extension report for the Classic Controller, encrypted. - The bytes are ... */ -// ---------------- -void FillReportClassicExtension(wm_classic_extension& _ext) -{ - - /* These are the default neutral values for the analog triggers and sticks */ - u8 Rx = 0x80, Ry = 0x80, Lx = 0x80, Ly = 0x80, lT = 0x80, rT = 0x80; - - _ext.b1.padding = 0x01; // 0x01 means not pressed - _ext.b1.bRT = 0x01; - _ext.b1.bP = 0x01; - _ext.b1.bH = 0x01; - _ext.b1.bM = 0x01; - _ext.b1.bLT = 0x01; - _ext.b1.bdD = 0x01; - _ext.b1.bdR = 0x01; - - _ext.b2.bdU = 0x01; - _ext.b2.bdL = 0x01; - _ext.b2.bZR = 0x01; - _ext.b2.bX = 0x01; - _ext.b2.bA = 0x01; - _ext.b2.bY = 0x01; - _ext.b2.bB = 0x01; - _ext.b2.bZL = 0x01; - - // -------------------------------------- - /* Left and right analog sticks - - u8 Lx : 6; // byte 0 - u8 Rx : 2; - u8 Ly : 6; // byte 1 - u8 Rx2 : 2; - u8 Ry : 5; // byte 2 - u8 lT : 2; - u8 Rx3 : 1; - u8 rT : 5; // byte 3 - u8 lT2 : 3; - */ -#ifdef _WIN32 - /* We use a 200 range (28 to 228) for the left analog stick and a 176 range - (40 to 216) for the right analog stick to match our calibration values - in classic_calibration */ - if(GetAsyncKeyState('J')) // left analog left - Lx = 0x1c; - if(GetAsyncKeyState('I')) // up - Ly = 0xe4; - if(GetAsyncKeyState('L')) // right - Lx = 0xe4; - if(GetAsyncKeyState('K')) // down - Ly = 0x1c; - - if(GetAsyncKeyState('D')) // right analog left - Rx = 0x28; - if(GetAsyncKeyState('R')) // up - Ry = 0xd8; - if(GetAsyncKeyState('G')) // right - Rx = 0xd8; - if(GetAsyncKeyState('F')) // down - Ry = 0x28; - - _ext.Lx = (Lx >> 2); - _ext.Ly = (Ly >> 2); - _ext.Rx = (Rx >> 3); // this may be wrong - _ext.Rx2 = (Rx >> 5); - _ext.Rx3 = (Rx >> 7); - _ext.Ry = (Ry >> 2); - - _ext.lT = (Ry >> 2); - _ext.lT2 = (Ry >> 3); - _ext.rT = (Ry >> 4); - // -------------- - - - - - // -------------------------------------- - /* D-Pad - - u8 b1; - 0: - 6: bdD - 7: bdR - - u8 b2; - 0: bdU - 1: bdL - */ - if(GetAsyncKeyState(VK_NUMPAD4)) // left - _ext.b2.bdL = 0x00; - - if(GetAsyncKeyState(VK_NUMPAD8)) // up - _ext.b2.bdU = 0x00; - - if(GetAsyncKeyState(VK_NUMPAD6)) // right - _ext.b1.bdR = 0x00; - - if(GetAsyncKeyState(VK_NUMPAD5)) // down - _ext.b1.bdD = 0x00; - // -------------- - - - // -------------------------------------- - /* Buttons - u8 b1; - 0: - 6: - - 7: - - - u8 b2; - 0: - - 1: - - 2: bZr - 3: bX - 4: bA - 5: bY - 6: bB - 7: bZl - */ - if(GetAsyncKeyState('Z')) - _ext.b2.bA = 0x00; - - if(GetAsyncKeyState('C')) - _ext.b2.bB = 0x00; - - if(GetAsyncKeyState('Y')) - _ext.b2.bY = 0x00; - - if(GetAsyncKeyState('X')) - _ext.b2.bX = 0x00; - - if(GetAsyncKeyState('O')) // O instead of P - _ext.b1.bP = 0x00; - - if(GetAsyncKeyState('N')) // N instead of M - _ext.b1.bM = 0x00; - - if(GetAsyncKeyState('U')) // Home button - _ext.b1.bH = 0x00; - - if(GetAsyncKeyState('7')) // digital left trigger - _ext.b1.bLT = 0x00; - - if(GetAsyncKeyState('8')) - _ext.b2.bZL = 0x00; - - if(GetAsyncKeyState('9')) - _ext.b2.bZR = 0x00; - - if(GetAsyncKeyState('0')) // digital right trigger - _ext.b1.bRT = 0x00; - - // All buttons pressed - //if(GetAsyncKeyState('C') && GetAsyncKeyState('Z')) - // { _ext.b2.bA = 0x01; _ext.b2.bB = 0x01; } - // -------------- -#else - // TODO linux port -#endif - - - // Clear g_RegExtTmp by copying zeroes to it - memset(g_RegExtTmp, 0, sizeof(g_RegExtTmp)); - - /* Write the nunchuck inputs to it. We begin writing at 0x08, see comment above. */ - memcpy(g_RegExtTmp + 0x08, &_ext, sizeof(_ext)); - - // Encrypt it - wiimote_encrypt(&g_ExtKey, &g_RegExtTmp[0x08], 0x08, 0x06); - - // Write it back - memcpy(&_ext, &g_RegExtTmp[0x08], sizeof(_ext)); -} - - -} // end of namespace +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#include + +#include "pluginspecs_wiimote.h" + +#include +#include +#include "Common.h" +#include "wiimote_hid.h" +#include "EmuSubroutines.h" +#include "EmuDefinitions.h" +#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd +#include "Config.h" // for g_Config + +extern SWiimoteInitialize g_WiimoteInitialize; + + +namespace WiiMoteEmu +{ + +//****************************************************************************** +// Subroutines +//****************************************************************************** + + +// =================================================== +/* Debugging. Read out an u8 array. */ +// ---------------- +std::string ArrayToString(const u8 *data, u32 size, u32 offset, int line_len) +{ + //const u8* _data = (const u8*)data; + std::string Temp; + for (u32 i = 0; i < size; i++) + { + char Buffer[128]; + sprintf(Buffer, "%02x ", data[i + offset]); + if((i + 1) % line_len == 0) Temp.append("\n"); // break long lines + Temp.append(Buffer); + } + return Temp; +} +// ================ + + +void FillReportInfo(wm_core& _core) +{ + memset(&_core, 0x00, sizeof(wm_core)); + +#ifdef _WIN32 + // allow both mouse buttons and keyboard to press a and b + if(GetAsyncKeyState(VK_LBUTTON) ? 1 : 0 || GetAsyncKeyState('A') ? 1 : 0) + _core.a = 1; + + if(GetAsyncKeyState(VK_RBUTTON) ? 1 : 0 || GetAsyncKeyState('B') ? 1 : 0) + _core.b = 1; + + _core.one = GetAsyncKeyState('1') ? 1 : 0; + _core.two = GetAsyncKeyState('2') ? 1 : 0; + _core.plus = GetAsyncKeyState('P') ? 1 : 0; + _core.minus = GetAsyncKeyState('M') ? 1 : 0; + _core.home = GetAsyncKeyState('H') ? 1 : 0; + + + /* Sideways controls (for example for Wario Land) was not enabled automatically + so I have to use this function. I'm not sure how it works on the actual Wii. + */ + if(g_Config.bSidewaysDPad) + { + _core.left = GetAsyncKeyState(VK_DOWN) ? 1 : 0; + _core.up = GetAsyncKeyState(VK_LEFT) ? 1 : 0; + _core.right = GetAsyncKeyState(VK_UP) ? 1 : 0; + _core.down = GetAsyncKeyState(VK_RIGHT) ? 1 : 0; + } + else + { + _core.left = GetAsyncKeyState(VK_LEFT) ? 1 : 0; + _core.up = GetAsyncKeyState(VK_UP) ? 1 : 0; + _core.right = GetAsyncKeyState(VK_RIGHT) ? 1 : 0; + _core.down = GetAsyncKeyState(VK_DOWN) ? 1 : 0; + } +#else + // TODO: fill in +#endif +} + +// ----------------------------- +/* Global declarations for FillReportAcc. The accelerometer x, y and z values range from + 0x00 to 0xff with the default netural values being [y = 0x84, x = 0x84, z = 0x9f] + according to a source. The extremes are 0x00 for (-) and 0xff for (+). It's important + that all values are not 0x80, the the mouse pointer can disappear from the screen + permanently then, until z is adjusted back. */ +// ---------- +// the variables are global so they can be changed during debugging +//int A = 0, B = 128, C = 64; // for debugging +//int a = 1, b = 1, c = 2, d = -2; // for debugging +//int consoleDisplay = 0; + +int X = 0x84, Y = 0x84, Z = 0x9f; // neutral values +u8 x = X, y = Y, z = Z; +int shake = -1, yhistsize = 15; // for the shake function +std::vector yhist(15); // for the tilt function + +void FillReportAcc(wm_accel& _acc) +{ +#ifdef _WIN32 + // ----------------------------- + // Wiimote to Gamepad translations + // ---------- + // Tilting Wiimote (Wario Land aiming, Mario Kart steering) : For some reason 150 and 40 + // seemed like decent starting values. + if(GetAsyncKeyState('3')) + { + //if(a < 128) // for debugging + if(y < 250) + { + y += 4; // aim left + //a += c; // debugging values + //y = A + a; // aim left + } + } + else if(GetAsyncKeyState('4')) + { + // if(b < 128) // for debugging + if(y > 5) + { + y -= 4; // aim right + //b -= d; // debugging values + //y = B + b; + } + } + + + /* Single shake of Wiimote while holding it sideways (Wario Land pound ground) + if(GetAsyncKeyState('S')) + z = 0; + else + z = Z;*/ + + if(GetAsyncKeyState('S')) + { + z = 0; + y = 0; + shake = 2; + } + else if(shake == 2) + { + z = 128; + y = 0; + shake = 1; + } + else if(shake == 1) + { + z = Z; + y = Y; + shake = -1; + } + else // the default Y and Z if nothing is pressed + { + z = Z; + } + // ---------- + + + // ----------------------------- + // For tilting: add new value and move all back + // ---------- + bool ypressed = false; + + yhist[yhist.size() - 1] = ( + GetAsyncKeyState('3') ? true : false + || GetAsyncKeyState('4') ? true : false + || shake > 0 + ); + if(yhistsize > yhist.size()) yhistsize = yhist.size(); + for (int i = 1; i < yhistsize; i++) + { + yhist[i-1] = yhist[i]; + if(yhist[i]) ypressed = true; + } + + if(!ypressed) // y was not pressed a single time + { + y = Y; // this is the default value that will occur most of the time + //a = 0; // for debugging + //b = 0; + } + else if(!GetAsyncKeyState('3') && !GetAsyncKeyState('4')) + { + // perhaps start dropping acceleration back? + } + // ---------- + + + // Write values + _acc.x = X; + _acc.y = y; + _acc.z = z; + + + // ---------------------------- + // Debugging for translating Wiimote to Keyboard (or Gamepad) + // ---------- + /* + + // Toogle console display + if(GetAsyncKeyState('U')) + { + if(consoleDisplay < 2) + consoleDisplay ++; + else + consoleDisplay = 0; + } + + if(GetAsyncKeyState('5')) + A-=1; + else if(GetAsyncKeyState('6')) + A+=1; + if(GetAsyncKeyState('7')) + B-=1; + else if(GetAsyncKeyState('8')) + B+=1; + if(GetAsyncKeyState('9')) + C-=1; + else if(GetAsyncKeyState('0')) + C+=1; + + else if(GetAsyncKeyState(VK_NUMPAD3)) + d-=1; + else if(GetAsyncKeyState(VK_NUMPAD6)) + d+=1; + else if(GetAsyncKeyState(VK_ADD)) + yhistsize-=1; + else if(GetAsyncKeyState(VK_SUBTRACT)) + yhistsize+=1; + + + if(GetAsyncKeyState(VK_INSERT)) + AX-=1; + else if(GetAsyncKeyState(VK_DELETE)) + AX+=1; + else if(GetAsyncKeyState(VK_HOME)) + AY-=1; + else if(GetAsyncKeyState(VK_END)) + AY+=1; + else if(GetAsyncKeyState(VK_SHIFT)) + AZ-=1; + else if(GetAsyncKeyState(VK_CONTROL)) + AZ+=1; + + if(GetAsyncKeyState(VK_NUMPAD1)) + X+=1; + else if(GetAsyncKeyState(VK_NUMPAD2)) + X-=1; + if(GetAsyncKeyState(VK_NUMPAD4)) + Y+=1; + else if(GetAsyncKeyState(VK_NUMPAD5)) + Y-=1; + if(GetAsyncKeyState(VK_NUMPAD7)) + Z+=1; + else if(GetAsyncKeyState(VK_NUMPAD8)) + Z-=1; + + + //if(consoleDisplay == 0) + wprintf("x: %03i | y: %03i | z: %03i | A:%i B:%i C:%i a:%i b:%i c:%i d:%i X:%i Y:%i Z:%i\n", + _acc.x, _acc.y, _acc.z, + A, B, C, + a, b, c, d, + X, Y, Z + ); + wprintf("x: %03i | y: %03i | z: %03i | X:%i Y:%i Z:%i | AX:%i AY:%i AZ:%i \n", + _acc.x, _acc.y, _acc.z, + X, Y, Z, + AX, AY, AZ + );*/ +#else + // TODO port to linux +#endif +} + + +void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1) +{ + +/* DESCRIPTION: The calibration is controlled by these values, their absolute value and + the relative distance between between them control the calibration. WideScreen mode + has its own settings. */ + int Top, Left, Right, Bottom, SensorBarRadius; + if(g_Config.bWideScreen) + { + Top = wTOP; Left = wLEFT; Right = wRIGHT; + Bottom = wBOTTOM; SensorBarRadius = wSENSOR_BAR_RADIUS; + } + else + { + Top = TOP; Left = LEFT; Right = RIGHT; + Bottom = BOTTOM; SensorBarRadius = SENSOR_BAR_RADIUS; + } + + // Fill with 0xff if empty + memset(&_ir0, 0xFF, sizeof(wm_ir_extended)); + memset(&_ir1, 0xFF, sizeof(wm_ir_extended)); + + float MouseX, MouseY; + GetMousePos(MouseX, MouseY); + + int y0 = Top + (MouseY * (Bottom - Top)); + int y1 = Top + (MouseY * (Bottom - Top)); + + int x0 = Left + (MouseX * (Right - Left)) - SensorBarRadius; + int x1 = Left + (MouseX * (Right - Left)) + SensorBarRadius; + + x0 = 1023 - x0; + _ir0.x = x0 & 0xFF; + _ir0.y = y0 & 0xFF; + _ir0.size = 10; + _ir0.xHi = x0 >> 8; + _ir0.yHi = y0 >> 8; + + x1 = 1023 - x1; + _ir1.x = x1 & 0xFF; + _ir1.y = y1 & 0xFF; + _ir1.size = 10; + _ir1.xHi = x1 >> 8; + _ir1.yHi = y1 >> 8; + + + // ---------------------------- + // Debugging for calibration + // ---------- + /* + if(GetAsyncKeyState(VK_NUMPAD1)) + Right +=1; + else if(GetAsyncKeyState(VK_NUMPAD2)) + Right -=1; + if(GetAsyncKeyState(VK_NUMPAD4)) + Left +=1; + else if(GetAsyncKeyState(VK_NUMPAD5)) + Left -=1; + if(GetAsyncKeyState(VK_NUMPAD7)) + Top += 1; + else if(GetAsyncKeyState(VK_NUMPAD8)) + Top -= 1; + if(GetAsyncKeyState(VK_NUMPAD6)) + Bottom += 1; + else if(GetAsyncKeyState(VK_NUMPAD3)) + Bottom -= 1; + if(GetAsyncKeyState(VK_INSERT)) + SensorBarRadius += 1; + else if(GetAsyncKeyState(VK_DELETE)) + SensorBarRadius -= 1; + + //ClearScreen(); + //if(consoleDisplay == 1) + wprintf("x0:%03i x1:%03i y0:%03i y1:%03i irx0:%03i y0:%03i x1:%03i y1:%03i | T:%i L:%i R:%i B:%i S:%i\n", + x0, x1, y0, y1, _ir0.x, _ir0.y, _ir1.x, _ir1.y, Top, Left, Right, Bottom, SensorBarRadius + ); + wprintf("\n"); + wprintf("ir0.x:%02x xHi:%02x ir1.x:%02x xHi:%02x | ir0.y:%02x yHi:%02x ir1.y:%02x yHi:%02x | 1.s:%02x 2:%02x\n", + _ir0.x, _ir0.xHi, _ir1.x, _ir1.xHi, + _ir0.y, _ir0.yHi, _ir1.y, _ir1.yHi, + _ir0.size, _ir1.size + );*/ +} + + +void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1) +{ + /* See description above */ + int Top, Left, Right, Bottom, SensorBarRadius; + + if(g_Config.bWideScreen) + { + Top = wTOP; Left = wLEFT; Right = wRIGHT; + Bottom = wBOTTOM; SensorBarRadius = wSENSOR_BAR_RADIUS; + } + else + { + Top = TOP; Left = LEFT; Right = RIGHT; + Bottom = BOTTOM; SensorBarRadius = SENSOR_BAR_RADIUS; + } + + // Fill with 0xff if empty + memset(&_ir0, 0xff, sizeof(wm_ir_basic)); + memset(&_ir1, 0xff, sizeof(wm_ir_basic)); + + float MouseX, MouseY; + GetMousePos(MouseX, MouseY); + + int y1 = Top + (MouseY * (Bottom - Top)); + int y2 = Top + (MouseY * (Bottom - Top)); + + int x1 = Left + (MouseX * (Right - Left)) - SensorBarRadius; + int x2 = Left + (MouseX * (Right - Left)) + SensorBarRadius; + + /* As with the extented report we settle with emulating two out of four + possible objects */ + x1 = 1023 - x1; + _ir0.x1 = x1 & 0xff; + _ir0.y1 = y1 & 0xff; + _ir0.x1Hi = (x1 >> 8); // we are dealing with 2 bit values here + _ir0.y1Hi = (y1 >> 8); + + x2 = 1023 - x2; + _ir0.x2 = x2 & 0xff; + _ir0.y2 = y2 & 0xff; + _ir0.x2Hi = (x2 >> 8); + _ir0.y2Hi = (y2 >> 8); + + // I don't understand't the & 0x03, should we do that? + //_ir1.x1Hi = (x1 >> 8) & 0x3; + //_ir1.y1Hi = (y1 >> 8) & 0x3; + + // ---------------------------- + // Debugging for calibration + // ---------- + /* + if(GetAsyncKeyState(VK_NUMPAD1)) + Right +=1; + else if(GetAsyncKeyState(VK_NUMPAD2)) + Right -=1; + if(GetAsyncKeyState(VK_NUMPAD4)) + Left +=1; + else if(GetAsyncKeyState(VK_NUMPAD5)) + Left -=1; + if(GetAsyncKeyState(VK_NUMPAD7)) + Top += 1; + else if(GetAsyncKeyState(VK_NUMPAD8)) + Top -= 1; + if(GetAsyncKeyState(VK_NUMPAD6)) + Bottom += 1; + else if(GetAsyncKeyState(VK_NUMPAD3)) + Bottom -= 1; + if(GetAsyncKeyState(VK_INSERT)) + SensorBarRadius += 1; + else if(GetAsyncKeyState(VK_DELETE)) + SensorBarRadius -= 1; + + //ClearScreen(); + //if(consoleDisplay == 1) + + wprintf("x1:%03i x2:%03i y1:%03i y2:%03i irx1:%02x y1:%02x x2:%02x y2:%02x | T:%i L:%i R:%i B:%i S:%i\n", + x1, x2, y1, y2, _ir0.x1, _ir0.y1, _ir1.x2, _ir1.y2, Top, Left, Right, Bottom, SensorBarRadius + ); + wprintf("\n"); + wprintf("ir0.x1:%02x x1h:%02x x2:%02x x2h:%02x | ir0.y1:%02x y1h:%02x y2:%02x y2h:%02x | ir1.x1:%02x x1h:%02x x2:%02x x2h:%02x | ir1.y1:%02x y1h:%02x y2:%02x y2h:%02x\n", + _ir0.x1, _ir0.x1Hi, _ir0.x2, _ir0.x2Hi, + _ir0.y1, _ir0.y1Hi, _ir0.y2, _ir0.y2Hi, + _ir1.x1, _ir1.x1Hi, _ir1.x2, _ir1.x2Hi, + _ir1.y1, _ir1.y1Hi, _ir1.y2, _ir1.y2Hi + );*/ +} + + +// =================================================== +/* Generate the 6 byte extension report, encrypted. The bytes are JX JY AX AY AZ BT. */ +// ---------------- +void FillReportExtension(wm_extension& _ext) +{ + + /* These are the default neutral values for the nunchuck accelerometer according + to a source. */ + _ext.ax = 0x80; + _ext.ay = 0x80; + _ext.az = 0xb3; + + + _ext.jx = 0x80; // these are the default values unless we use them + _ext.jy = 0x80; + _ext.bt = 0x03; // 0x03 means no button pressed, the button is zero active + + +#ifdef _WIN32 + /* We use a 192 range (32 to 224) that match our calibration values in + nunchuck_calibration */ + if(GetAsyncKeyState(VK_NUMPAD4)) // left + _ext.jx = 0x20; + + if(GetAsyncKeyState(VK_NUMPAD8)) + _ext.jy = 0xe0; + + if(GetAsyncKeyState(VK_NUMPAD6)) // right + _ext.jx = 0xe0; + + if(GetAsyncKeyState(VK_NUMPAD5)) + _ext.jy = 0x20; + + + if(GetAsyncKeyState('C')) + _ext.bt = 0x01; + + if(GetAsyncKeyState('Z')) + _ext.bt = 0x02; + + if(GetAsyncKeyState('C') && GetAsyncKeyState('Z')) + _ext.bt = 0x00; +#else + // TODO linux port +#endif + + // Clear g_RegExtTmp by copying zeroes to it + memset(g_RegExtTmp, 0, sizeof(g_RegExtTmp)); + + /* Write the nunchuck inputs to it. We begin writing at 0x08, but it could also be + 0x00, the important thing is that we begin at an address evenly divisible + by 0x08 */ + memcpy(g_RegExtTmp + 0x08, &_ext, sizeof(_ext)); + + // Encrypt it + wiimote_encrypt(&g_ExtKey, &g_RegExtTmp[0x08], 0x08, sizeof(_ext)); + + // Write it back + memcpy(&_ext, &g_RegExtTmp[0x08], sizeof(_ext)); +} + + +// =================================================== +/* Generate the 6 byte extension report for the Classic Controller, encrypted. + The bytes are ... */ +// ---------------- +void FillReportClassicExtension(wm_classic_extension& _ext) +{ + + /* These are the default neutral values for the analog triggers and sticks */ + u8 Rx = 0x80, Ry = 0x80, Lx = 0x80, Ly = 0x80, lT = 0x80, rT = 0x80; + + _ext.b1.padding = 0x01; // 0x01 means not pressed + _ext.b1.bRT = 0x01; + _ext.b1.bP = 0x01; + _ext.b1.bH = 0x01; + _ext.b1.bM = 0x01; + _ext.b1.bLT = 0x01; + _ext.b1.bdD = 0x01; + _ext.b1.bdR = 0x01; + + _ext.b2.bdU = 0x01; + _ext.b2.bdL = 0x01; + _ext.b2.bZR = 0x01; + _ext.b2.bX = 0x01; + _ext.b2.bA = 0x01; + _ext.b2.bY = 0x01; + _ext.b2.bB = 0x01; + _ext.b2.bZL = 0x01; + + // -------------------------------------- + /* Left and right analog sticks + + u8 Lx : 6; // byte 0 + u8 Rx : 2; + u8 Ly : 6; // byte 1 + u8 Rx2 : 2; + u8 Ry : 5; // byte 2 + u8 lT : 2; + u8 Rx3 : 1; + u8 rT : 5; // byte 3 + u8 lT2 : 3; + */ +#ifdef _WIN32 + /* We use a 200 range (28 to 228) for the left analog stick and a 176 range + (40 to 216) for the right analog stick to match our calibration values + in classic_calibration */ + if(GetAsyncKeyState('J')) // left analog left + Lx = 0x1c; + if(GetAsyncKeyState('I')) // up + Ly = 0xe4; + if(GetAsyncKeyState('L')) // right + Lx = 0xe4; + if(GetAsyncKeyState('K')) // down + Ly = 0x1c; + + if(GetAsyncKeyState('D')) // right analog left + Rx = 0x28; + if(GetAsyncKeyState('R')) // up + Ry = 0xd8; + if(GetAsyncKeyState('G')) // right + Rx = 0xd8; + if(GetAsyncKeyState('F')) // down + Ry = 0x28; + + _ext.Lx = (Lx >> 2); + _ext.Ly = (Ly >> 2); + _ext.Rx = (Rx >> 3); // this may be wrong + _ext.Rx2 = (Rx >> 5); + _ext.Rx3 = (Rx >> 7); + _ext.Ry = (Ry >> 2); + + _ext.lT = (Ry >> 2); + _ext.lT2 = (Ry >> 3); + _ext.rT = (Ry >> 4); + // -------------- + + + + + // -------------------------------------- + /* D-Pad + + u8 b1; + 0: + 6: bdD + 7: bdR + + u8 b2; + 0: bdU + 1: bdL + */ + if(GetAsyncKeyState(VK_NUMPAD4)) // left + _ext.b2.bdL = 0x00; + + if(GetAsyncKeyState(VK_NUMPAD8)) // up + _ext.b2.bdU = 0x00; + + if(GetAsyncKeyState(VK_NUMPAD6)) // right + _ext.b1.bdR = 0x00; + + if(GetAsyncKeyState(VK_NUMPAD5)) // down + _ext.b1.bdD = 0x00; + // -------------- + + + // -------------------------------------- + /* Buttons + u8 b1; + 0: + 6: - + 7: - + + u8 b2; + 0: - + 1: - + 2: bZr + 3: bX + 4: bA + 5: bY + 6: bB + 7: bZl + */ + if(GetAsyncKeyState('Z')) + _ext.b2.bA = 0x00; + + if(GetAsyncKeyState('C')) + _ext.b2.bB = 0x00; + + if(GetAsyncKeyState('Y')) + _ext.b2.bY = 0x00; + + if(GetAsyncKeyState('X')) + _ext.b2.bX = 0x00; + + if(GetAsyncKeyState('O')) // O instead of P + _ext.b1.bP = 0x00; + + if(GetAsyncKeyState('N')) // N instead of M + _ext.b1.bM = 0x00; + + if(GetAsyncKeyState('U')) // Home button + _ext.b1.bH = 0x00; + + if(GetAsyncKeyState('7')) // digital left trigger + _ext.b1.bLT = 0x00; + + if(GetAsyncKeyState('8')) + _ext.b2.bZL = 0x00; + + if(GetAsyncKeyState('9')) + _ext.b2.bZR = 0x00; + + if(GetAsyncKeyState('0')) // digital right trigger + _ext.b1.bRT = 0x00; + + // All buttons pressed + //if(GetAsyncKeyState('C') && GetAsyncKeyState('Z')) + // { _ext.b2.bA = 0x01; _ext.b2.bB = 0x01; } + // -------------- +#else + // TODO linux port +#endif + + + // Clear g_RegExtTmp by copying zeroes to it + memset(g_RegExtTmp, 0, sizeof(g_RegExtTmp)); + + /* Write the nunchuck inputs to it. We begin writing at 0x08, see comment above. */ + memcpy(g_RegExtTmp + 0x08, &_ext, sizeof(_ext)); + + // Encrypt it + wiimote_encrypt(&g_ExtKey, &g_RegExtTmp[0x08], 0x08, 0x06); + + // Write it back + memcpy(&_ext, &g_RegExtTmp[0x08], sizeof(_ext)); +} + + +} // end of namespace diff --git a/Source/Plugins/Plugin_Wiimote/Src/main.cpp b/Source/Plugins/Plugin_Wiimote/Src/main.cpp index 250a587918..e5140c5ba5 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/main.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/main.cpp @@ -1,260 +1,260 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -#include "Common.h" -#include "Config.h" -#include "StringUtil.h" - -#if defined(HAVE_WX) && HAVE_WX -#include -#include "ConfigDlg.h" -#endif - -#include "pluginspecs_wiimote.h" - -#include "EmuMain.h" - -#if HAVE_WIIUSE -#include "wiimote_real.h" -#endif - -#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd - -SWiimoteInitialize g_WiimoteInitialize; - -bool g_UseRealWiiMote = false; - -HINSTANCE g_hInstance; - -class wxDLLApp : public wxApp -{ - bool OnInit() - { - return true; - } -}; -IMPLEMENT_APP_NO_MAIN(wxDLLApp) - -WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst); - -#ifdef _WIN32 -BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle - DWORD dwReason, // reason called - LPVOID lpvReserved) // reserved -{ - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - { //use wxInitialize() if you don't want GUI instead of the following 12 lines - wxSetInstance((HINSTANCE)hinstDLL); - int argc = 0; - char **argv = NULL; - wxEntryStart(argc, argv); - if ( !wxTheApp || !wxTheApp->CallOnInit() ) - return FALSE; - } - break; - - case DLL_PROCESS_DETACH: - wxEntryCleanup(); //use wxUninitialize() if you don't want GUI - break; - default: - break; - } - - g_hInstance = hinstDLL; - return TRUE; -} -#endif -//****************************************************************************** -// Exports -//****************************************************************************** -extern "C" void GetDllInfo (PLUGIN_INFO* _PluginInfo) -{ - _PluginInfo->Version = 0x0100; - _PluginInfo->Type = PLUGIN_TYPE_WIIMOTE; -#ifdef DEBUGFAST - sprintf(_PluginInfo->Name, "Wiimote Plug-in (DebugFast)"); -#else -#ifndef _DEBUG - sprintf(_PluginInfo->Name, "Wiimote Plug-in"); -#else - sprintf(_PluginInfo->Name, "Wiimote Plug-in (Debug)"); -#endif -#endif -} - - -extern "C" void DllAbout(HWND _hParent) -{ -#if defined(HAVE_WX) && HAVE_WX - wxAboutDialogInfo info; - info.SetName(_T("Wiimote plug-in")); - info.AddDeveloper(_T("masken (masken3@gmail.com)")); - info.SetDescription(_T("Wiimote plug-in")); - wxAboutBox(info); -#endif -} - -extern "C" void DllConfig(HWND _hParent) -{ - wxWindow win; -#ifdef _WIN32 - win.SetHWND(_hParent); -#endif - ConfigDialog frame(&win); - frame.ShowModal(); -#ifdef _WIN32 - win.SetHWND(0); -#endif -} - -extern "C" void Wiimote_Initialize(SWiimoteInitialize _WiimoteInitialize) -{ - g_WiimoteInitialize = _WiimoteInitialize; - - /* We will run WiiMoteReal::Initialize() even if we are not using a real wiimote, - we will initiate wiiuse.dll, but we will return before creating a new thread - for it in that case */ -#if HAVE_WIIUSE - g_UseRealWiiMote = WiiMoteReal::Initialize() > 0; -#endif - g_Config.Load(); // load config settings - - WiiMoteEmu::Initialize(); - - // Debugging window - /*startConsoleWin(100, 750, "Wiimote"); // give room for 20 rows - wprintf("Wiimote console opened\n"); - - // move window, TODO: make this - //MoveWindow(GetConsoleHwnd(), 0,400, 100*8,10*14, true); // small window - MoveWindow(GetConsoleHwnd(), 400,0, 100*8,70*14, true); // big window*/ -} - - -extern "C" void Wiimote_DoState(void* ptr, int mode) -{ -#if HAVE_WIIUSE - WiiMoteReal::DoState(ptr, mode); -#endif - WiiMoteEmu::DoState(ptr, mode); -} - -extern "C" void Wiimote_Shutdown(void) -{ -#if HAVE_WIIUSE - WiiMoteReal::Shutdown(); -#endif - WiiMoteEmu::Shutdown(); -} - -// =================================================== -/* This function produce Wiimote Input (reports from the Wiimote) in response - to Output from the Wii. It's called from WII_IPC_HLE_WiiMote.cpp. */ -// ---------------- -extern "C" void Wiimote_InterruptChannel(u16 _channelID, const void* _pData, u32 _Size) -{ - LOGV(WII_IPC_WIIMOTE, 3, "============================================================="); - const u8* data = (const u8*)_pData; - - // Debugging - { - LOGV(WII_IPC_WIIMOTE, 3, "Wiimote_Input"); - LOGV(WII_IPC_WIIMOTE, 3, " Channel ID: %04x", _channelID); - std::string Temp = WiiMoteEmu::ArrayToString(data, _Size); - LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str()); - } - - if (! g_UseRealWiiMote) - WiiMoteEmu::InterruptChannel(_channelID, _pData, _Size); -#if HAVE_WIIUSE - else - WiiMoteReal::InterruptChannel(_channelID, _pData, _Size); -#endif - - LOGV(WII_IPC_WIIMOTE, 3, "============================================================="); -} - -extern "C" void Wiimote_ControlChannel(u16 _channelID, const void* _pData, u32 _Size) -{ - LOGV(WII_IPC_WIIMOTE, 3, "============================================================="); - const u8* data = (const u8*)_pData; - - // Debugging - { - LOGV(WII_IPC_WIIMOTE, 3, "Wiimote_ControlChannel"); - std::string Temp = WiiMoteEmu::ArrayToString(data, _Size); - LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str()); - } - - - if (! g_UseRealWiiMote) - WiiMoteEmu::ControlChannel(_channelID, _pData, _Size); -#if HAVE_WIIUSE - else - WiiMoteReal::ControlChannel(_channelID, _pData, _Size); -#endif - - LOGV(WII_IPC_WIIMOTE, 3, "============================================================="); -} - -extern "C" void Wiimote_Update() -{ - if (! g_UseRealWiiMote) - WiiMoteEmu::Update(); -#if HAVE_WIIUSE - else - WiiMoteReal::Update(); -#endif -} - -extern "C" unsigned int Wiimote_GetAttachedControllers() -{ - return 1; -} - - -// =================================================== -/* Logging functions. */ -// ---------------- -void __Log(int log, const char *_fmt, ...) -{ - char Msg[512]; - va_list ap; - - va_start( ap, _fmt ); - vsprintf( Msg, _fmt, ap ); - va_end( ap ); - - g_WiimoteInitialize.pLog(Msg, 0); -} - - -void __Logv(int log, int v, const char *_fmt, ...) -{ - char Msg[512]; - va_list ap; - - va_start( ap, _fmt ); - vsprintf( Msg, _fmt, ap ); - va_end( ap ); - - g_WiimoteInitialize.pLog(Msg, v); -} -// ================ +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#include "Common.h" +#include "Config.h" +#include "StringUtil.h" + +#if defined(HAVE_WX) && HAVE_WX +#include +#include "ConfigDlg.h" +#endif + +#include "pluginspecs_wiimote.h" + +#include "EmuMain.h" + +#if HAVE_WIIUSE +#include "wiimote_real.h" +#endif + +#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd + +SWiimoteInitialize g_WiimoteInitialize; + +bool g_UseRealWiiMote = false; + +HINSTANCE g_hInstance; + +class wxDLLApp : public wxApp +{ + bool OnInit() + { + return true; + } +}; +IMPLEMENT_APP_NO_MAIN(wxDLLApp) + +WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst); + +#ifdef _WIN32 +BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle + DWORD dwReason, // reason called + LPVOID lpvReserved) // reserved +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + { //use wxInitialize() if you don't want GUI instead of the following 12 lines + wxSetInstance((HINSTANCE)hinstDLL); + int argc = 0; + char **argv = NULL; + wxEntryStart(argc, argv); + if ( !wxTheApp || !wxTheApp->CallOnInit() ) + return FALSE; + } + break; + + case DLL_PROCESS_DETACH: + wxEntryCleanup(); //use wxUninitialize() if you don't want GUI + break; + default: + break; + } + + g_hInstance = hinstDLL; + return TRUE; +} +#endif +//****************************************************************************** +// Exports +//****************************************************************************** +extern "C" void GetDllInfo (PLUGIN_INFO* _PluginInfo) +{ + _PluginInfo->Version = 0x0100; + _PluginInfo->Type = PLUGIN_TYPE_WIIMOTE; +#ifdef DEBUGFAST + sprintf(_PluginInfo->Name, "Wiimote Plug-in (DebugFast)"); +#else +#ifndef _DEBUG + sprintf(_PluginInfo->Name, "Wiimote Plug-in"); +#else + sprintf(_PluginInfo->Name, "Wiimote Plug-in (Debug)"); +#endif +#endif +} + + +extern "C" void DllAbout(HWND _hParent) +{ +#if defined(HAVE_WX) && HAVE_WX + wxAboutDialogInfo info; + info.SetName(_T("Wiimote plug-in")); + info.AddDeveloper(_T("masken (masken3@gmail.com)")); + info.SetDescription(_T("Wiimote plug-in")); + wxAboutBox(info); +#endif +} + +extern "C" void DllConfig(HWND _hParent) +{ + wxWindow win; +#ifdef _WIN32 + win.SetHWND(_hParent); +#endif + ConfigDialog frame(&win); + frame.ShowModal(); +#ifdef _WIN32 + win.SetHWND(0); +#endif +} + +extern "C" void Wiimote_Initialize(SWiimoteInitialize _WiimoteInitialize) +{ + g_WiimoteInitialize = _WiimoteInitialize; + + /* We will run WiiMoteReal::Initialize() even if we are not using a real wiimote, + we will initiate wiiuse.dll, but we will return before creating a new thread + for it in that case */ +#if HAVE_WIIUSE + g_UseRealWiiMote = WiiMoteReal::Initialize() > 0; +#endif + g_Config.Load(); // load config settings + + WiiMoteEmu::Initialize(); + + // Debugging window + /*startConsoleWin(100, 750, "Wiimote"); // give room for 20 rows + wprintf("Wiimote console opened\n"); + + // move window, TODO: make this + //MoveWindow(GetConsoleHwnd(), 0,400, 100*8,10*14, true); // small window + MoveWindow(GetConsoleHwnd(), 400,0, 100*8,70*14, true); // big window*/ +} + + +extern "C" void Wiimote_DoState(void* ptr, int mode) +{ +#if HAVE_WIIUSE + WiiMoteReal::DoState(ptr, mode); +#endif + WiiMoteEmu::DoState(ptr, mode); +} + +extern "C" void Wiimote_Shutdown(void) +{ +#if HAVE_WIIUSE + WiiMoteReal::Shutdown(); +#endif + WiiMoteEmu::Shutdown(); +} + +// =================================================== +/* This function produce Wiimote Input (reports from the Wiimote) in response + to Output from the Wii. It's called from WII_IPC_HLE_WiiMote.cpp. */ +// ---------------- +extern "C" void Wiimote_InterruptChannel(u16 _channelID, const void* _pData, u32 _Size) +{ + LOGV(WII_IPC_WIIMOTE, 3, "============================================================="); + const u8* data = (const u8*)_pData; + + // Debugging + { + LOGV(WII_IPC_WIIMOTE, 3, "Wiimote_Input"); + LOGV(WII_IPC_WIIMOTE, 3, " Channel ID: %04x", _channelID); + std::string Temp = WiiMoteEmu::ArrayToString(data, _Size); + LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str()); + } + + if (! g_UseRealWiiMote) + WiiMoteEmu::InterruptChannel(_channelID, _pData, _Size); +#if HAVE_WIIUSE + else + WiiMoteReal::InterruptChannel(_channelID, _pData, _Size); +#endif + + LOGV(WII_IPC_WIIMOTE, 3, "============================================================="); +} + +extern "C" void Wiimote_ControlChannel(u16 _channelID, const void* _pData, u32 _Size) +{ + LOGV(WII_IPC_WIIMOTE, 3, "============================================================="); + const u8* data = (const u8*)_pData; + + // Debugging + { + LOGV(WII_IPC_WIIMOTE, 3, "Wiimote_ControlChannel"); + std::string Temp = WiiMoteEmu::ArrayToString(data, _Size); + LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str()); + } + + + if (! g_UseRealWiiMote) + WiiMoteEmu::ControlChannel(_channelID, _pData, _Size); +#if HAVE_WIIUSE + else + WiiMoteReal::ControlChannel(_channelID, _pData, _Size); +#endif + + LOGV(WII_IPC_WIIMOTE, 3, "============================================================="); +} + +extern "C" void Wiimote_Update() +{ + if (! g_UseRealWiiMote) + WiiMoteEmu::Update(); +#if HAVE_WIIUSE + else + WiiMoteReal::Update(); +#endif +} + +extern "C" unsigned int Wiimote_GetAttachedControllers() +{ + return 1; +} + + +// =================================================== +/* Logging functions. */ +// ---------------- +void __Log(int log, const char *_fmt, ...) +{ + char Msg[512]; + va_list ap; + + va_start( ap, _fmt ); + vsprintf( Msg, _fmt, ap ); + va_end( ap ); + + g_WiimoteInitialize.pLog(Msg, 0); +} + + +void __Logv(int log, int v, const char *_fmt, ...) +{ + char Msg[512]; + va_list ap; + + va_start( ap, _fmt ); + vsprintf( Msg, _fmt, ap ); + va_end( ap ); + + g_WiimoteInitialize.pLog(Msg, v); +} +// ================ diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp index 1b8e4c48b9..20a8a2a7da 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp @@ -1,292 +1,292 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "pluginspecs_wiimote.h" - -#include "wiiuse.h" -#include - -#include "Common.h" -#include "Thread.h" - -#include "wiimote_hid.h" -#include "EmuMain.h" - - -extern SWiimoteInitialize g_WiimoteInitialize; -//extern void __Log(int log, const char *format, ...); -//extern void __Log(int log, int v, const char *format, ...); - - -namespace WiiMoteReal -{ -#define MAX_WIIMOTES 1 - -//****************************************************************************** -// Forwarding -//****************************************************************************** - - class CWiiMote; -#ifdef _WIN32 - DWORD WINAPI ReadWiimote_ThreadFunc(void* arg); -#else - void* ReadWiimote_ThreadFunc(void* arg); -#endif -//****************************************************************************** -// Variable declarations -//****************************************************************************** - - wiimote_t** g_WiiMotesFromWiiUse = NULL; - Common::Thread* g_pReadThread = NULL; - int g_NumberOfWiiMotes; - CWiiMote* g_WiiMotes[MAX_WIIMOTES]; - bool g_Shutdown = false; - -//****************************************************************************** -// Probably this class should be in its own file -//****************************************************************************** - - class CWiiMote - { - public: - - CWiiMote(u8 _WiimoteNumber, wiimote_t* _pWiimote) - : m_WiimoteNumber(_WiimoteNumber) - , m_channelID(0) - , m_pWiiMote(_pWiimote) - , m_pCriticalSection(NULL) - , m_LastReportValid(false) - { - m_pCriticalSection = new Common::CriticalSection(); - - wiiuse_set_leds(m_pWiiMote, WIIMOTE_LED_4); - -#ifdef _WIN32 - // F|RES: i dunno if we really need this - CancelIo(m_pWiiMote->dev_handle); -#endif - } - - virtual ~CWiiMote() - { - delete m_pCriticalSection; - }; - - // send raw HID data from the core to wiimote - void SendData(u16 _channelID, const u8* _pData, u32 _Size) - { - m_channelID = _channelID; - - m_pCriticalSection->Enter(); - { - SEvent WriteEvent; - memcpy(WriteEvent.m_PayLoad, _pData+1, _Size-1); - m_EventWriteQueue.push(WriteEvent); - } - m_pCriticalSection->Leave(); - } - - // read data from wiimote (but don't send it to the core, just filter - // and queue) - void ReadData() - { - m_pCriticalSection->Enter(); - - if (!m_EventWriteQueue.empty()) - { - SEvent& rEvent = m_EventWriteQueue.front(); - wiiuse_io_write(m_pWiiMote, (byte*)rEvent.m_PayLoad, MAX_PAYLOAD); - m_EventWriteQueue.pop(); - } - - m_pCriticalSection->Leave(); - - if (wiiuse_io_read(m_pWiiMote)) - { - const byte* pBuffer = m_pWiiMote->event_buf; - - // check if we have a channel (connection) if so save the - // data... - if (m_channelID > 0) - { - m_pCriticalSection->Enter(); - - // filter out reports - if (pBuffer[0] >= 0x30) - { - memcpy(m_LastReport.m_PayLoad, pBuffer, - MAX_PAYLOAD); - m_LastReportValid = true; - } - else - { - SEvent ImportantEvent; - memcpy(ImportantEvent.m_PayLoad, pBuffer, - MAX_PAYLOAD); - m_EventReadQueue.push(ImportantEvent); - } - - m_pCriticalSection->Leave(); - } - } - }; - - // send queued data to the core - void Update() - { - m_pCriticalSection->Enter(); - - if (m_EventReadQueue.empty()) - { - if (m_LastReportValid) - SendEvent(m_LastReport); - } - else - { - SendEvent(m_EventReadQueue.front()); - m_EventReadQueue.pop(); - } - - m_pCriticalSection->Leave(); - }; - - private: - - struct SEvent - { - SEvent() - { - memset(m_PayLoad, 0, MAX_PAYLOAD); - } - byte m_PayLoad[MAX_PAYLOAD]; - }; - typedef std::queue CEventQueue; - - u8 m_WiimoteNumber; // just for debugging - u16 m_channelID; - wiimote_t* m_pWiiMote; - - Common::CriticalSection* m_pCriticalSection; - CEventQueue m_EventReadQueue; - CEventQueue m_EventWriteQueue; - bool m_LastReportValid; - SEvent m_LastReport; - - void SendEvent(SEvent& _rEvent) - { - // we don't have an answer channel - if (m_channelID == 0) - return; - - // check event buffer; - u8 Buffer[1024]; - u32 Offset = 0; - hid_packet* pHidHeader = (hid_packet*)(Buffer + Offset); - Offset += sizeof(hid_packet); - pHidHeader->type = HID_TYPE_DATA; - pHidHeader->param = HID_PARAM_INPUT; - - memcpy(&Buffer[Offset], _rEvent.m_PayLoad, MAX_PAYLOAD); - Offset += MAX_PAYLOAD; - - g_WiimoteInitialize.pWiimoteInput(m_channelID, Buffer, Offset); - } - }; - -//****************************************************************************** -// Function Definitions -//****************************************************************************** - - int Initialize() - { - memset(g_WiiMotes, 0, sizeof(CWiiMote*) * MAX_WIIMOTES); - g_WiiMotesFromWiiUse = wiiuse_init(MAX_WIIMOTES); - g_NumberOfWiiMotes = wiiuse_find(g_WiiMotesFromWiiUse, MAX_WIIMOTES, 5); - - for (int i=0; i 0) - g_pReadThread = new Common::Thread(ReadWiimote_ThreadFunc, NULL); - - return g_NumberOfWiiMotes; - } - - void DoState(void* ptr, int mode) - {} - - void Shutdown(void) - { - g_Shutdown = true; - - // stop the thread - if (g_pReadThread != NULL) - { - g_pReadThread->WaitForDeath(); - delete g_pReadThread; - g_pReadThread = NULL; - } - - // delete the wiimotes - for (int i=0; iSendData(_channelID, (const u8*)_pData, _Size); - } - - void ControlChannel(u16 _channelID, const void* _pData, u32 _Size) - { - g_WiiMotes[0]->SendData(_channelID, (const u8*)_pData, _Size); - } - - void Update() - { - for (int i=0; iUpdate(); - } - } - -#ifdef _WIN32 - DWORD WINAPI ReadWiimote_ThreadFunc(void* arg) -#else - void *ReadWiimote_ThreadFunc(void* arg) -#endif - { - while (!g_Shutdown) - { - for (int i=0; iReadData(); - } - } - return 0; - } - -}; // end of namespace - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "pluginspecs_wiimote.h" + +#include "wiiuse.h" +#include + +#include "Common.h" +#include "Thread.h" + +#include "wiimote_hid.h" +#include "EmuMain.h" + + +extern SWiimoteInitialize g_WiimoteInitialize; +//extern void __Log(int log, const char *format, ...); +//extern void __Log(int log, int v, const char *format, ...); + + +namespace WiiMoteReal +{ +#define MAX_WIIMOTES 1 + +//****************************************************************************** +// Forwarding +//****************************************************************************** + + class CWiiMote; +#ifdef _WIN32 + DWORD WINAPI ReadWiimote_ThreadFunc(void* arg); +#else + void* ReadWiimote_ThreadFunc(void* arg); +#endif +//****************************************************************************** +// Variable declarations +//****************************************************************************** + + wiimote_t** g_WiiMotesFromWiiUse = NULL; + Common::Thread* g_pReadThread = NULL; + int g_NumberOfWiiMotes; + CWiiMote* g_WiiMotes[MAX_WIIMOTES]; + bool g_Shutdown = false; + +//****************************************************************************** +// Probably this class should be in its own file +//****************************************************************************** + + class CWiiMote + { + public: + + CWiiMote(u8 _WiimoteNumber, wiimote_t* _pWiimote) + : m_WiimoteNumber(_WiimoteNumber) + , m_channelID(0) + , m_pWiiMote(_pWiimote) + , m_pCriticalSection(NULL) + , m_LastReportValid(false) + { + m_pCriticalSection = new Common::CriticalSection(); + + wiiuse_set_leds(m_pWiiMote, WIIMOTE_LED_4); + +#ifdef _WIN32 + // F|RES: i dunno if we really need this + CancelIo(m_pWiiMote->dev_handle); +#endif + } + + virtual ~CWiiMote() + { + delete m_pCriticalSection; + }; + + // send raw HID data from the core to wiimote + void SendData(u16 _channelID, const u8* _pData, u32 _Size) + { + m_channelID = _channelID; + + m_pCriticalSection->Enter(); + { + SEvent WriteEvent; + memcpy(WriteEvent.m_PayLoad, _pData+1, _Size-1); + m_EventWriteQueue.push(WriteEvent); + } + m_pCriticalSection->Leave(); + } + + // read data from wiimote (but don't send it to the core, just filter + // and queue) + void ReadData() + { + m_pCriticalSection->Enter(); + + if (!m_EventWriteQueue.empty()) + { + SEvent& rEvent = m_EventWriteQueue.front(); + wiiuse_io_write(m_pWiiMote, (byte*)rEvent.m_PayLoad, MAX_PAYLOAD); + m_EventWriteQueue.pop(); + } + + m_pCriticalSection->Leave(); + + if (wiiuse_io_read(m_pWiiMote)) + { + const byte* pBuffer = m_pWiiMote->event_buf; + + // check if we have a channel (connection) if so save the + // data... + if (m_channelID > 0) + { + m_pCriticalSection->Enter(); + + // filter out reports + if (pBuffer[0] >= 0x30) + { + memcpy(m_LastReport.m_PayLoad, pBuffer, + MAX_PAYLOAD); + m_LastReportValid = true; + } + else + { + SEvent ImportantEvent; + memcpy(ImportantEvent.m_PayLoad, pBuffer, + MAX_PAYLOAD); + m_EventReadQueue.push(ImportantEvent); + } + + m_pCriticalSection->Leave(); + } + } + }; + + // send queued data to the core + void Update() + { + m_pCriticalSection->Enter(); + + if (m_EventReadQueue.empty()) + { + if (m_LastReportValid) + SendEvent(m_LastReport); + } + else + { + SendEvent(m_EventReadQueue.front()); + m_EventReadQueue.pop(); + } + + m_pCriticalSection->Leave(); + }; + + private: + + struct SEvent + { + SEvent() + { + memset(m_PayLoad, 0, MAX_PAYLOAD); + } + byte m_PayLoad[MAX_PAYLOAD]; + }; + typedef std::queue CEventQueue; + + u8 m_WiimoteNumber; // just for debugging + u16 m_channelID; + wiimote_t* m_pWiiMote; + + Common::CriticalSection* m_pCriticalSection; + CEventQueue m_EventReadQueue; + CEventQueue m_EventWriteQueue; + bool m_LastReportValid; + SEvent m_LastReport; + + void SendEvent(SEvent& _rEvent) + { + // we don't have an answer channel + if (m_channelID == 0) + return; + + // check event buffer; + u8 Buffer[1024]; + u32 Offset = 0; + hid_packet* pHidHeader = (hid_packet*)(Buffer + Offset); + Offset += sizeof(hid_packet); + pHidHeader->type = HID_TYPE_DATA; + pHidHeader->param = HID_PARAM_INPUT; + + memcpy(&Buffer[Offset], _rEvent.m_PayLoad, MAX_PAYLOAD); + Offset += MAX_PAYLOAD; + + g_WiimoteInitialize.pWiimoteInput(m_channelID, Buffer, Offset); + } + }; + +//****************************************************************************** +// Function Definitions +//****************************************************************************** + + int Initialize() + { + memset(g_WiiMotes, 0, sizeof(CWiiMote*) * MAX_WIIMOTES); + g_WiiMotesFromWiiUse = wiiuse_init(MAX_WIIMOTES); + g_NumberOfWiiMotes = wiiuse_find(g_WiiMotesFromWiiUse, MAX_WIIMOTES, 5); + + for (int i=0; i 0) + g_pReadThread = new Common::Thread(ReadWiimote_ThreadFunc, NULL); + + return g_NumberOfWiiMotes; + } + + void DoState(void* ptr, int mode) + {} + + void Shutdown(void) + { + g_Shutdown = true; + + // stop the thread + if (g_pReadThread != NULL) + { + g_pReadThread->WaitForDeath(); + delete g_pReadThread; + g_pReadThread = NULL; + } + + // delete the wiimotes + for (int i=0; iSendData(_channelID, (const u8*)_pData, _Size); + } + + void ControlChannel(u16 _channelID, const void* _pData, u32 _Size) + { + g_WiiMotes[0]->SendData(_channelID, (const u8*)_pData, _Size); + } + + void Update() + { + for (int i=0; iUpdate(); + } + } + +#ifdef _WIN32 + DWORD WINAPI ReadWiimote_ThreadFunc(void* arg) +#else + void *ReadWiimote_ThreadFunc(void* arg) +#endif + { + while (!g_Shutdown) + { + for (int i=0; iReadData(); + } + } + return 0; + } + +}; // end of namespace + diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/AboutBox.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/AboutBox.cpp index 667b2675d2..e55e42ca2c 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/AboutBox.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/AboutBox.cpp @@ -1,92 +1,92 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// Project description -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -// Name: nJoy -// Description: A Dolphin Compatible Input Plugin -// -// Author: Falcon4ever (nJoy@falcon4ever.com) -// Site: www.multigesture.net -// Copyright (C) 2003-2008 Dolphin Project. -// -////////////////////////////////////////////////////////////////////////////////////////// -// -// Licensetype: GNU General Public License (GPL) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. -// -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ -// -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ -// -////////////////////////////////////////////////////////////////////////////////////////// - -#include "AboutBox.h" -#include "../nJoy.h" -#include "Images/njoy.xpm" - - -BEGIN_EVENT_TABLE(AboutBox,wxDialog) - EVT_CLOSE(AboutBox::OnClose) - EVT_BUTTON(ID_OK, AboutBox::OKClick) -END_EVENT_TABLE() - -AboutBox::AboutBox(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) -: wxDialog(parent, id, title, position, size, style) -{ - CreateGUIControls(); -} - -AboutBox::~AboutBox() -{ - // empty -} - -void AboutBox::CreateGUIControls() -{ - SetTitle(wxT("About: nJoy Input Plugin")); - SetIcon(wxNullIcon); - //SetSize(8,8,200,399); - SetClientSize(200,376); - Center(); - -#ifndef _WIN32 - // Force a 8pt font so that it looks more or less "correct" regardless of the default font setting - wxFont f(8,wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL); - SetFont(f); -#endif - - m_thankyoutext = new wxStaticText(this, ID_THANKYOU, wxT(THANKYOU), wxPoint(18,196), wxDefaultSize, 0, wxT(THANKYOU)); - m_thankyoutext->Wrap(167); - m_specialthanks = new wxStaticText(this, ID_SPECIALTHANKS, wxT("F|RES and ector."), wxPoint(18,153), wxDefaultSize, 0, wxT("F|RES and ector.")); - m_pluginversion = new wxStaticText(this, ID_PLUGINVERSION, wxT("nJoy v"INPUT_VERSION" by Falcon4ever\n" "Release: "RELDAY"/"RELMONTH"/"RELYEAR"\n" "www.multigesture.net"), wxPoint(18,80), wxDefaultSize, 0, wxT("nJoy v"INPUT_VERSION" by Falcon4ever\n" "Release: "RELDAY"/"RELMONTH"/"RELYEAR"\n" "www.multigesture.net")); - m_OK = new wxButton(this, ID_OK, wxT("OK"), wxPoint(116,343), wxSize(75,25), 0, wxDefaultValidator, wxT("OK")); - m_version = new wxStaticText(this, ID_STATUSV, wxT("PUBLIC RELEASE"), wxPoint(14,349), wxDefaultSize, 0, wxT("PUBLIC RELEASE")); - m_thankyougroup = new wxStaticBox(this, IDG_THANKYOU, wxT("Greetings to:"), wxPoint(10,180), wxSize(180,160)); - m_specialthanksgroup = new wxStaticBox(this, IDG_SPECIALTHANKS, wxT("Special thanks to:"), wxPoint(10,135), wxSize(180,39)); - m_pluginversiongroup = new wxStaticBox(this, IDG_PLUGINVERSION, wxT("Plugin info:"), wxPoint(10,61), wxSize(180,68)); - - wxBitmap WxStaticBitmap1_BITMAP(AboutBox_WxStaticBitmap1_XPM); - m_njoylogo = new wxStaticBitmap(this, ID_AWESOMEPICTURE, WxStaticBitmap1_BITMAP, wxPoint(-1,-2), wxSize(200,60)); -} - -void AboutBox::OnClose(wxCloseEvent& /*event*/) -{ - EndModal(0); -} - -void AboutBox::OKClick(wxCommandEvent& event) -{ - if (event.GetId() == ID_OK) - { - Close(); - } -} +////////////////////////////////////////////////////////////////////////////////////////// +// Project description +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +// Name: nJoy +// Description: A Dolphin Compatible Input Plugin +// +// Author: Falcon4ever (nJoy@falcon4ever.com) +// Site: www.multigesture.net +// Copyright (C) 2003-2008 Dolphin Project. +// +////////////////////////////////////////////////////////////////////////////////////////// +// +// Licensetype: GNU General Public License (GPL) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. +// +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ +// +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +// +////////////////////////////////////////////////////////////////////////////////////////// + +#include "AboutBox.h" +#include "../nJoy.h" +#include "Images/njoy.xpm" + + +BEGIN_EVENT_TABLE(AboutBox,wxDialog) + EVT_CLOSE(AboutBox::OnClose) + EVT_BUTTON(ID_OK, AboutBox::OKClick) +END_EVENT_TABLE() + +AboutBox::AboutBox(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) +: wxDialog(parent, id, title, position, size, style) +{ + CreateGUIControls(); +} + +AboutBox::~AboutBox() +{ + // empty +} + +void AboutBox::CreateGUIControls() +{ + SetTitle(wxT("About: nJoy Input Plugin")); + SetIcon(wxNullIcon); + //SetSize(8,8,200,399); + SetClientSize(200,376); + Center(); + +#ifndef _WIN32 + // Force a 8pt font so that it looks more or less "correct" regardless of the default font setting + wxFont f(8,wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL); + SetFont(f); +#endif + + m_thankyoutext = new wxStaticText(this, ID_THANKYOU, wxT(THANKYOU), wxPoint(18,196), wxDefaultSize, 0, wxT(THANKYOU)); + m_thankyoutext->Wrap(167); + m_specialthanks = new wxStaticText(this, ID_SPECIALTHANKS, wxT("F|RES and ector."), wxPoint(18,153), wxDefaultSize, 0, wxT("F|RES and ector.")); + m_pluginversion = new wxStaticText(this, ID_PLUGINVERSION, wxT("nJoy v"INPUT_VERSION" by Falcon4ever\n" "Release: "RELDAY"/"RELMONTH"/"RELYEAR"\n" "www.multigesture.net"), wxPoint(18,80), wxDefaultSize, 0, wxT("nJoy v"INPUT_VERSION" by Falcon4ever\n" "Release: "RELDAY"/"RELMONTH"/"RELYEAR"\n" "www.multigesture.net")); + m_OK = new wxButton(this, ID_OK, wxT("OK"), wxPoint(116,343), wxSize(75,25), 0, wxDefaultValidator, wxT("OK")); + m_version = new wxStaticText(this, ID_STATUSV, wxT("PUBLIC RELEASE"), wxPoint(14,349), wxDefaultSize, 0, wxT("PUBLIC RELEASE")); + m_thankyougroup = new wxStaticBox(this, IDG_THANKYOU, wxT("Greetings to:"), wxPoint(10,180), wxSize(180,160)); + m_specialthanksgroup = new wxStaticBox(this, IDG_SPECIALTHANKS, wxT("Special thanks to:"), wxPoint(10,135), wxSize(180,39)); + m_pluginversiongroup = new wxStaticBox(this, IDG_PLUGINVERSION, wxT("Plugin info:"), wxPoint(10,61), wxSize(180,68)); + + wxBitmap WxStaticBitmap1_BITMAP(AboutBox_WxStaticBitmap1_XPM); + m_njoylogo = new wxStaticBitmap(this, ID_AWESOMEPICTURE, WxStaticBitmap1_BITMAP, wxPoint(-1,-2), wxSize(200,60)); +} + +void AboutBox::OnClose(wxCloseEvent& /*event*/) +{ + EndModal(0); +} + +void AboutBox::OKClick(wxCommandEvent& event) +{ + if (event.GetId() == ID_OK) + { + Close(); + } +} diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.cpp index 4bdb8cd001..47c3d28517 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.cpp @@ -1,774 +1,774 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// Project description -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -// Name: nJoy -// Description: A Dolphin Compatible Input Plugin -// -// Author: Falcon4ever (nJoy@falcon4ever.com) -// Site: www.multigesture.net -// Copyright (C) 2003-2008 Dolphin Project. -// -////////////////////////////////////////////////////////////////////////////////////////// -// -// Licensetype: GNU General Public License (GPL) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. -// -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ -// -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ -// -////////////////////////////////////////////////////////////////////////////////////////// - -#include "ConfigBox.h" -#include "../nJoy.h" -#include "Images/controller.xpm" - -extern CONTROLLER_INFO *joyinfo; -extern CONTROLLER_MAPPING joysticks[4]; -extern bool emulator_running; - -static const char* ControllerType[] = -{ - "Joystick (default)", - "Joystick (no hat)", -// "Joytstick (xbox360)", // Shoulder buttons -> axis -// "Keyboard" // Not supported yet, sorry F|RES ;( ... -}; - -BEGIN_EVENT_TABLE(ConfigBox,wxDialog) - EVT_CLOSE(ConfigBox::OnClose) - EVT_BUTTON(ID_ABOUT, ConfigBox::AboutClick) - EVT_BUTTON(ID_OK, ConfigBox::OKClick) - EVT_BUTTON(ID_CANCEL, ConfigBox::CancelClick) - EVT_COMBOBOX(IDC_JOYNAME, ConfigBox::ChangeJoystick) - EVT_COMBOBOX(IDC_CONTROLTYPE, ConfigBox::ChangeControllertype) - EVT_NOTEBOOK_PAGE_CHANGED(ID_NOTEBOOK, ConfigBox::NotebookPageChanged) - - EVT_BUTTON(IDB_SHOULDER_L, ConfigBox::GetButtons) - EVT_BUTTON(IDB_SHOULDER_R, ConfigBox::GetButtons) - EVT_BUTTON(IDB_BUTTON_A, ConfigBox::GetButtons) - EVT_BUTTON(IDB_BUTTON_B, ConfigBox::GetButtons) - EVT_BUTTON(IDB_BUTTON_X, ConfigBox::GetButtons) - EVT_BUTTON(IDB_BUTTON_Y, ConfigBox::GetButtons) - EVT_BUTTON(IDB_BUTTON_Z, ConfigBox::GetButtons) - EVT_BUTTON(IDB_BUTTONSTART, ConfigBox::GetButtons) - EVT_BUTTON(IDB_BUTTONHALFPRESS, ConfigBox::GetButtons) - EVT_BUTTON(IDB_DPAD_UP, ConfigBox::GetButtons) - EVT_BUTTON(IDB_DPAD_DOWN, ConfigBox::GetButtons) - EVT_BUTTON(IDB_DPAD_LEFT, ConfigBox::GetButtons) - EVT_BUTTON(IDB_DPAD_RIGHT, ConfigBox::GetButtons) - - EVT_BUTTON(IDB_ANALOG_MAIN_X, ConfigBox::GetAxis) - EVT_BUTTON(IDB_ANALOG_MAIN_Y, ConfigBox::GetAxis) - EVT_BUTTON(IDB_ANALOG_SUB_X, ConfigBox::GetAxis) - EVT_BUTTON(IDB_ANALOG_SUB_Y, ConfigBox::GetAxis) -END_EVENT_TABLE() - -ConfigBox::ConfigBox(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) -: wxDialog(parent, id, title, position, size, style) -{ - notebookpage = 0; - CreateGUIControls(); -} - -ConfigBox::~ConfigBox() -{ - // empty -} - -// Warning: horrible code below proceed at own risk! -void ConfigBox::CreateGUIControls() -{ - #ifndef _DEBUG - SetTitle(wxT("Configure: nJoy v"INPUT_VERSION" Input Plugin")); - #else - SetTitle(wxT("Configure: nJoy v"INPUT_VERSION" (Debug) Input Plugin")); - #endif - - SetIcon(wxNullIcon); - SetClientSize(637, 527); - Center(); - -#ifndef _WIN32 - // Force a 8pt font so that it looks more or less "correct" regardless of the default font setting - wxFont f(8,wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL); - SetFont(f); -#endif - - // Buttons - m_About = new wxButton(this, ID_ABOUT, wxT("About"), wxPoint(5, 497), wxSize(75, 25), 0, wxDefaultValidator, wxT("About")); - m_OK = new wxButton(this, ID_OK, wxT("OK"), wxPoint(475, 497), wxSize(75, 25), 0, wxDefaultValidator, wxT("OK")); - m_Cancel = new wxButton(this, ID_CANCEL, wxT("Cancel"), wxPoint(556, 497), wxSize(75, 25), 0, wxDefaultValidator, wxT("Cancel")); - - // Notebook - m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxPoint(6, 7),wxSize(625, 484)); - - // Controller pages - m_Controller[0] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE1, wxPoint(0, 0), wxSize(600, 400)); - m_Notebook->AddPage(m_Controller[0], wxT("Controller 1")); - m_Controller[1] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE2, wxPoint(0, 0), wxSize(600, 400)); - m_Notebook->AddPage(m_Controller[1], wxT("Controller 2")); - m_Controller[2] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE3, wxPoint(0, 0), wxSize(600, 400)); - m_Notebook->AddPage(m_Controller[2], wxT("Controller 3")); - m_Controller[3] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE4, wxPoint(0, 0), wxSize(600, 400)); - m_Notebook->AddPage(m_Controller[3], wxT("Controller 4")); - - // Add controls - wxArrayString arrayStringFor_Joyname; - wxArrayString arrayStringFor_Controltype; - wxArrayString arrayStringFor_Deadzone; - - // Search for devices and add the to the device list - if(Search_Devices()) - { - for(int x = 0; x < SDL_NumJoysticks(); x++) - { - arrayStringFor_Joyname.Add(wxString::FromAscii(joyinfo[x].Name)); - } - } - else - { - arrayStringFor_Joyname.Add(wxString::FromAscii("No Joystick detected!")); - } - - arrayStringFor_Controltype.Add(wxString::FromAscii(ControllerType[CTL_TYPE_JOYSTICK])); - arrayStringFor_Controltype.Add(wxString::FromAscii(ControllerType[CTL_TYPE_JOYSTICK_NO_HAT])); - // arrayStringFor_Controltype.Add(wxString::FromAscii(ControllerType[CTL_TYPE_JOYSTICK_XBOX360])); - // arrayStringFor_Controltype.Add(wxString::FromAscii(ControllerType[CTL_TYPE_KEYBOARD])); - - char buffer [8]; - for(int x = 1; x <= 100; x++) - { - sprintf (buffer, "%d %%", x); - arrayStringFor_Deadzone.Add(wxString::FromAscii(buffer)); - } - - wxBitmap WxStaticBitmap1_BITMAP(ConfigBox_WxStaticBitmap1_XPM); - - for(int i=0; i<4 ;i++) - { - - // Groups - m_gJoyname[i] = new wxStaticBox(m_Controller[i], IDG_JOYSTICK, wxT("Controller:"), wxPoint(5, 11), wxSize(608, 46)); - - #ifdef _WIN32 - m_Joyattach[i] = new wxCheckBox(m_Controller[i], IDC_JOYATTACH, wxT("Controller attached"), wxPoint(495, 26), wxSize(109, 25), 0, wxDefaultValidator, wxT("Controller attached")); - m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, wxEmptyString, wxPoint(12, 29), wxSize(476, 21), arrayStringFor_Joyname, 0, wxDefaultValidator, wxT("m_Joyname")); - m_gExtrasettings[i] = new wxStaticBox(m_Controller[i], IDG_EXTRASETTINGS, wxT("Extra settings:"), wxPoint(104, 385), wxSize(155, 69)); - m_Deadzone[i] = new wxComboBox(m_Controller[i], IDC_DEADZONE, wxEmptyString, wxPoint(167, 400), wxSize(59, 21), arrayStringFor_Deadzone, 0, wxDefaultValidator, wxT("m_Deadzone")); - m_gControllertype[i] = new wxStaticBox(m_Controller[i], IDG_CONTROLLERTYPE, wxT("Controller type:"), wxPoint(359, 383), wxSize(143, 44)); - m_Controltype[i] = new wxComboBox(m_Controller[i], IDC_CONTROLTYPE, wxEmptyString, wxPoint(366, 401), wxSize(131, 21), arrayStringFor_Controltype, 0, wxDefaultValidator, wxT("m_Controltype")); - #else - m_Joyattach[i] = new wxCheckBox(m_Controller[i], IDC_JOYATTACH, wxT("Controller attached"), wxPoint(470, 26), wxSize(140, 25), 0, wxDefaultValidator, wxT("Controller attached")); - m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, wxEmptyString, wxPoint(10, 25), wxSize(450, 25), arrayStringFor_Joyname, 0, wxDefaultValidator, wxT("m_Joyname")); - m_gExtrasettings[i] = new wxStaticBox(m_Controller[i], IDG_EXTRASETTINGS, wxT("Extra settings:"), wxPoint(100, 385), wxSize(155, 65)); - m_Deadzone[i] = new wxComboBox(m_Controller[i], IDC_DEADZONE, wxEmptyString, wxPoint(167, 398), wxSize(80, 25), arrayStringFor_Deadzone, 0, wxDefaultValidator, wxT("m_Deadzone")); - m_gControllertype[i] = new wxStaticBox(m_Controller[i], IDG_CONTROLLERTYPE, wxT("Controller type:"), wxPoint(359, 383), wxSize(160, 44)); - m_Controltype[i] = new wxComboBox(m_Controller[i], IDC_CONTROLTYPE, wxEmptyString, wxPoint(364, 396), wxSize(150, 25), arrayStringFor_Controltype, 0, wxDefaultValidator, wxT("m_Controltype")); - #endif - - // GUI left side buttons - m_JoyShoulderL[i] = new wxTextCtrl(m_Controller[i], ID_SHOULDER_L, wxT("0"), wxPoint(6, 80), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyShoulderL[i]->Enable(false); - m_JoyAnalogMainX[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_MAIN_X, wxT("0"), wxPoint(6, 218), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyAnalogMainX[i]->Enable(false); - m_JoyAnalogMainY[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_MAIN_Y, wxT("0"), wxPoint(6, 255), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyAnalogMainY[i]->Enable(false); - m_JoyDpadUp[i] = new wxTextCtrl(m_Controller[i], ID_DPAD_UP, wxT("0"), wxPoint(6, 296), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyDpadUp[i]->Enable(false); - m_JoyDpadDown[i] = new wxTextCtrl(m_Controller[i], ID_DPAD_DOWN, wxT("0"), wxPoint(6, 333), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyDpadDown[i]->Enable(false); - m_JoyDpadLeft[i] = new wxTextCtrl(m_Controller[i], ID_DPAD_LEFT, wxT("0"), wxPoint(6, 369), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyDpadLeft[i]->Enable(false); - m_JoyDpadRight[i] = new wxTextCtrl(m_Controller[i], ID_DPAD_RIGHT, wxT("0"), wxPoint(6, 406), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyDpadRight[i]->Enable(false); - m_bJoyShoulderL[i] = new wxButton(m_Controller[i], IDB_SHOULDER_L, wxEmptyString, wxPoint(70, 82), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyAnalogMainX[i] = new wxButton(m_Controller[i], IDB_ANALOG_MAIN_X, wxEmptyString, wxPoint(70, 220), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyAnalogMainY[i] = new wxButton(m_Controller[i], IDB_ANALOG_MAIN_Y, wxEmptyString, wxPoint(70, 257), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyDpadUp[i] = new wxButton(m_Controller[i], IDB_DPAD_UP, wxEmptyString, wxPoint(70, 298), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyDpadDown[i] = new wxButton(m_Controller[i], IDB_DPAD_DOWN, wxEmptyString, wxPoint(70, 335), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyDpadLeft[i] = new wxButton(m_Controller[i], IDB_DPAD_LEFT, wxEmptyString, wxPoint(70, 371), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyDpadRight[i] = new wxButton(m_Controller[i], IDB_DPAD_RIGHT, wxEmptyString, wxPoint(70, 408), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - - m_textMainX[i] = new wxStaticText(m_Controller[i], IDT_ANALOG_MAIN_X, wxT("X-axis"), wxPoint(6, 204), wxDefaultSize, 0, wxT("X-axis")); - m_textMainY[i] = new wxStaticText(m_Controller[i], IDT_ANALOG_MAIN_Y, wxT("Y-axis"), wxPoint(6, 241), wxDefaultSize, 0, wxT("Y-axis")); - m_textDpadUp[i] = new wxStaticText(m_Controller[i], IDT_DPAD_UP, wxT("Up"), wxPoint(6, 282), wxDefaultSize, 0, wxT("Up")); - m_textDpadDown[i] = new wxStaticText(m_Controller[i], IDT_DPAD_DOWN, wxT("Down"), wxPoint(6, 319), wxDefaultSize, 0, wxT("Down")); - m_textDpadLeft[i] = new wxStaticText(m_Controller[i], IDT_DPAD_LEFT, wxT("Left"), wxPoint(6, 354), wxDefaultSize, 0, wxT("Left")); - m_textDpadRight[i] = new wxStaticText(m_Controller[i], IDT_DPAD_RIGHT, wxT("Right"), wxPoint(6, 391), wxDefaultSize, 0, wxT("Right")); - - // GUI right side buttons - m_JoyShoulderR[i] = new wxTextCtrl(m_Controller[i], ID_SHOULDER_R, wxT("0"), wxPoint(552, 106), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyShoulderR[i]->Enable(false); - m_JoyButtonA[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_A, wxT("0"), wxPoint(552, 280), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyButtonA[i]->Enable(false); - m_JoyButtonB[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_B, wxT("0"), wxPoint(552, 80), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyButtonB[i]->Enable(false); - m_JoyButtonX[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_X, wxT("0"), wxPoint(552, 242), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyButtonX[i]->Enable(false); - m_JoyButtonY[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_Y, wxT("0"), wxPoint(552, 171), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyButtonY[i]->Enable(false); - m_JoyButtonZ[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_Z, wxT("0"), wxPoint(552, 145), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyButtonZ[i]->Enable(false); - m_JoyAnalogSubX[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_SUB_X, wxT("0"), wxPoint(552, 351), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyAnalogSubX[i]->Enable(false); - m_JoyAnalogSubY[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_SUB_Y, wxT("0"), wxPoint(552, 388), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyAnalogSubY[i]->Enable(false); - m_bJoyShoulderR[i] = new wxButton(m_Controller[i], IDB_SHOULDER_R, wxEmptyString, wxPoint(526, 108), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyButtonA[i] = new wxButton(m_Controller[i], IDB_BUTTON_A, wxEmptyString, wxPoint(526, 282), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyButtonB[i] = new wxButton(m_Controller[i], IDB_BUTTON_B, wxEmptyString, wxPoint(526, 82), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyButtonX[i] = new wxButton(m_Controller[i], IDB_BUTTON_X, wxEmptyString, wxPoint(526, 244), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyButtonY[i] = new wxButton(m_Controller[i], IDB_BUTTON_Y, wxEmptyString, wxPoint(526, 173), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyButtonZ[i] = new wxButton(m_Controller[i], IDB_BUTTON_Z, wxEmptyString, wxPoint(526, 147), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyAnalogSubX[i] = new wxButton(m_Controller[i], IDB_ANALOG_SUB_X, wxEmptyString, wxPoint(526, 353), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyAnalogSubY[i] = new wxButton(m_Controller[i], IDB_ANALOG_SUB_Y, wxEmptyString, wxPoint(526, 390), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - - m_textSubX[i] = new wxStaticText(m_Controller[i], IDT_ANALOG_SUB_X, wxT("X-axis"), wxPoint(552, 336), wxDefaultSize, 0, wxT("X-axis")); - m_textSubY[i] = new wxStaticText(m_Controller[i], IDT_ANALOG_SUB_Y, wxT("Y-axis"), wxPoint(552, 373), wxDefaultSize, 0, wxT("Y-axis")); - - // GUI center button - m_JoyButtonStart[i] = new wxTextCtrl(m_Controller[i], ID_BUTTONSTART, wxT("0"), wxPoint(278, 403), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyButtonStart[i]->Enable(false); - m_JoyButtonHalfpress[i] = new wxTextCtrl(m_Controller[i], ID_BUTTONHALFPRESS, wxT("0"), wxPoint(167, 424), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyButtonHalfpress[i]->Enable(false); - m_bJoyButtonStart[i] = new wxButton(m_Controller[i], IDB_BUTTONSTART, wxEmptyString, wxPoint(297, 385), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyButtonHalfpress[i] = new wxButton(m_Controller[i], IDB_BUTTONHALFPRESS, wxEmptyString, wxPoint(231, 426), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - - #ifdef _WIN32 - m_textDeadzone[i] = new wxStaticText(m_Controller[i], IDT_DEADZONE, wxT("Deadzone"), wxPoint(116, 404), wxDefaultSize, 0, wxT("Deadzone")); - m_textHalfpress[i] = new wxStaticText(m_Controller[i], IDT_BUTTONHALFPRESS, wxT("Half press"), wxPoint(116, 428), wxDefaultSize, 0, wxT("Half press")); - m_textWebsite[i] = new wxStaticText(m_Controller[i], IDT_WEBSITE, wxT("www.multigesture.net"), wxPoint(500, 438), wxDefaultSize, 0, wxT("www.multigesture.net")); - #else - m_textDeadzone[i] = new wxStaticText(m_Controller[i], IDT_DEADZONE, wxT("Deadzone"), wxPoint(105, 404), wxDefaultSize, 0, wxT("Deadzone")); - m_textHalfpress[i] = new wxStaticText(m_Controller[i], IDT_BUTTONHALFPRESS, wxT("Half press"), wxPoint(105, 428), wxDefaultSize, 0, wxT("Half press")); - m_textWebsite[i] = new wxStaticText(m_Controller[i], IDT_WEBSITE, wxT("www.multigesture.net"), wxPoint(480, 438), wxDefaultSize, 0, wxT("www.multigesture.net")); - #endif - - // TODO: Controller image - // Placeholder instead of bitmap - // m_PlaceholderBMP[i] = new wxTextCtrl(m_Controller[i], ID_CONTROLLERPICTURE, wxT("BITMAP HERE PLZ KTHX!"), wxPoint(98, 75), wxSize(423, 306), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("BITMAP HERE PLZ KTHX!")); - // m_PlaceholderBMP[i]->Enable(false); - - // You can enable the bitmap here: - // But it loads überslow on init... (only in windows, linux seems to load it fast!) - // AAaaand the XPM file (256 colours) looks crappier than the real bitmap... so maybe we can find a way to use a bitmap? - m_controllerimage[i] = new wxStaticBitmap(m_Controller[i], ID_CONTROLLERPICTURE, WxStaticBitmap1_BITMAP, wxPoint(98, 75), wxSize(421,304)); - - if(emulator_running) - { - m_Joyname[i]->Enable(false); - m_Joyattach[i]->Enable(false); - m_Controltype[i]->Enable(false); - } - - SetControllerAll(i); - } -} - -void ConfigBox::OnClose(wxCloseEvent& /*event*/) -{ - EndModal(0); -} - -void ConfigBox::AboutClick(wxCommandEvent& event) -{ -// Call about dialog -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -#ifdef _WIN32 - wxWindow win; - win.SetHWND((WXHWND)this->GetHWND()); - win.Enable(false); - - AboutBox frame(&win); - frame.ShowModal(); - - win.Enable(true); - win.SetHWND(0); -#else - AboutBox frame(NULL); - frame.ShowModal(); -#endif -} - -void ConfigBox::OKClick(wxCommandEvent& event) -{ - if (event.GetId() == ID_OK) - { - for(int i=0; i<4 ;i++) - GetControllerAll(i); - SaveConfig(); // save settings - LoadConfig(); // reload settings - Close(); - } -} - -void ConfigBox::CancelClick(wxCommandEvent& event) -{ - if (event.GetId() == ID_CANCEL) - { - LoadConfig(); // reload settings - Close(); - } -} - -// Set dialog items -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void ConfigBox::SetControllerAll(int controller) -{ - // http://wiki.wxwidgets.org/Converting_everything_to_and_from_wxString - wxString tmp; - - m_Joyname[controller]->SetSelection(joysticks[controller].ID); - - tmp << joysticks[controller].buttons[CTL_L_SHOULDER]; m_JoyShoulderL[controller]->SetValue(tmp); tmp.clear(); - tmp << joysticks[controller].buttons[CTL_R_SHOULDER]; m_JoyShoulderR[controller]->SetValue(tmp); tmp.clear(); - - tmp << joysticks[controller].buttons[CTL_A_BUTTON]; m_JoyButtonA[controller]->SetValue(tmp); tmp.clear(); - tmp << joysticks[controller].buttons[CTL_B_BUTTON]; m_JoyButtonB[controller]->SetValue(tmp); tmp.clear(); - tmp << joysticks[controller].buttons[CTL_X_BUTTON]; m_JoyButtonX[controller]->SetValue(tmp); tmp.clear(); - tmp << joysticks[controller].buttons[CTL_Y_BUTTON]; m_JoyButtonY[controller]->SetValue(tmp); tmp.clear(); - tmp << joysticks[controller].buttons[CTL_Z_TRIGGER]; m_JoyButtonZ[controller]->SetValue(tmp); tmp.clear(); - - tmp << joysticks[controller].buttons[CTL_START]; m_JoyButtonStart[controller]->SetValue(tmp); tmp.clear(); - tmp << joysticks[controller].halfpress; m_JoyButtonHalfpress[controller]->SetValue(tmp); tmp.clear(); - - tmp << joysticks[controller].axis[CTL_MAIN_X]; m_JoyAnalogMainX[controller]->SetValue(tmp); tmp.clear(); - tmp << joysticks[controller].axis[CTL_MAIN_Y]; m_JoyAnalogMainY[controller]->SetValue(tmp); tmp.clear(); - tmp << joysticks[controller].axis[CTL_SUB_X]; m_JoyAnalogSubX[controller]->SetValue(tmp); tmp.clear(); - tmp << joysticks[controller].axis[CTL_SUB_Y]; m_JoyAnalogSubY[controller]->SetValue(tmp); tmp.clear(); - - if(joysticks[controller].enabled) - m_Joyattach[controller]->SetValue(TRUE); - else - m_Joyattach[controller]->SetValue(FALSE); - - m_Controltype[controller]->SetSelection(joysticks[controller].controllertype); - m_Deadzone[controller]->SetSelection(joysticks[controller].deadzone); - - UpdateVisibleItems(controller); - - if(joysticks[controller].controllertype == CTL_TYPE_JOYSTICK) - { - tmp << joysticks[controller].dpad; m_JoyDpadUp[controller]->SetValue(tmp); tmp.clear(); - } - else - { - tmp << joysticks[controller].dpad2[CTL_D_PAD_UP]; m_JoyDpadUp[controller]->SetValue(tmp); tmp.clear(); - tmp << joysticks[controller].dpad2[CTL_D_PAD_DOWN]; m_JoyDpadDown[controller]->SetValue(tmp); tmp.clear(); - tmp << joysticks[controller].dpad2[CTL_D_PAD_LEFT]; m_JoyDpadLeft[controller]->SetValue(tmp); tmp.clear(); - tmp << joysticks[controller].dpad2[CTL_D_PAD_RIGHT]; m_JoyDpadRight[controller]->SetValue(tmp); tmp.clear(); - } -} - -// Get dialog items -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void ConfigBox::GetControllerAll(int controller) -{ - wxString tmp; - long value; - - joysticks[controller].ID = m_Joyname[controller]->GetSelection(); - - m_JoyShoulderL[controller]->GetValue().ToLong(&value); joysticks[controller].buttons[CTL_L_SHOULDER] = value; tmp.clear(); - m_JoyShoulderR[controller]->GetValue().ToLong(&value); joysticks[controller].buttons[CTL_R_SHOULDER] = value; tmp.clear(); - - m_JoyButtonA[controller]->GetValue().ToLong(&value); joysticks[controller].buttons[CTL_A_BUTTON] = value; tmp.clear(); - m_JoyButtonB[controller]->GetValue().ToLong(&value); joysticks[controller].buttons[CTL_B_BUTTON] = value; tmp.clear(); - m_JoyButtonX[controller]->GetValue().ToLong(&value); joysticks[controller].buttons[CTL_X_BUTTON] = value; tmp.clear(); - m_JoyButtonY[controller]->GetValue().ToLong(&value); joysticks[controller].buttons[CTL_Y_BUTTON] = value; tmp.clear(); - m_JoyButtonZ[controller]->GetValue().ToLong(&value); joysticks[controller].buttons[CTL_Z_TRIGGER] = value; tmp.clear(); - m_JoyButtonStart[controller]->GetValue().ToLong(&value); joysticks[controller].buttons[CTL_START] = value; tmp.clear(); - - m_JoyButtonHalfpress[controller]->GetValue().ToLong(&value); joysticks[controller].halfpress = value; tmp.clear(); - - if(joysticks[controller].controllertype == CTL_TYPE_JOYSTICK) - { - m_JoyDpadUp[controller]->GetValue().ToLong(&value); joysticks[controller].dpad = value; tmp.clear(); - } - else - { - m_JoyDpadUp[controller]->GetValue().ToLong(&value); joysticks[controller].dpad2[CTL_D_PAD_UP] = value; tmp.clear(); - m_JoyDpadDown[controller]->GetValue().ToLong(&value); joysticks[controller].dpad2[CTL_D_PAD_DOWN] = value; tmp.clear(); - m_JoyDpadLeft[controller]->GetValue().ToLong(&value); joysticks[controller].dpad2[CTL_D_PAD_LEFT] = value; tmp.clear(); - m_JoyDpadRight[controller]->GetValue().ToLong(&value); joysticks[controller].dpad2[CTL_D_PAD_RIGHT] = value; tmp.clear(); - } - - m_JoyAnalogMainX[controller]->GetValue().ToLong(&value); joysticks[controller].axis[CTL_MAIN_X] = value; tmp.clear(); - m_JoyAnalogMainY[controller]->GetValue().ToLong(&value); joysticks[controller].axis[CTL_MAIN_Y] = value; tmp.clear(); - m_JoyAnalogSubX[controller]->GetValue().ToLong(&value); joysticks[controller].axis[CTL_SUB_X] = value; tmp.clear(); - m_JoyAnalogSubY[controller]->GetValue().ToLong(&value); joysticks[controller].axis[CTL_SUB_Y] = value; tmp.clear(); - - joysticks[controller].enabled = m_Joyattach[controller]->GetValue(); - - joysticks[controller].controllertype = m_Controltype[controller]->GetSelection(); - joysticks[controller].deadzone = m_Deadzone[controller]->GetSelection(); -} - -void ConfigBox::UpdateVisibleItems(int controller) -{ - if(joysticks[controller].controllertype) - { - m_JoyDpadDown[controller]->Show(TRUE); - m_JoyDpadLeft[controller]->Show(TRUE); - m_JoyDpadRight[controller]->Show(TRUE); - - m_bJoyDpadDown[controller]->Show(TRUE); - m_bJoyDpadLeft[controller]->Show(TRUE); - m_bJoyDpadRight[controller]->Show(TRUE); - - m_textDpadUp[controller]->Show(TRUE); - m_textDpadDown[controller]->Show(TRUE); - m_textDpadLeft[controller]->Show(TRUE); - m_textDpadRight[controller]->Show(TRUE); - } - else - { - m_JoyDpadDown[controller]->Show(FALSE); - m_JoyDpadLeft[controller]->Show(FALSE); - m_JoyDpadRight[controller]->Show(FALSE); - - m_bJoyDpadDown[controller]->Show(FALSE); - m_bJoyDpadLeft[controller]->Show(FALSE); - m_bJoyDpadRight[controller]->Show(FALSE); - - m_textDpadUp[controller]->Show(FALSE); - m_textDpadDown[controller]->Show(FALSE); - m_textDpadLeft[controller]->Show(FALSE); - m_textDpadRight[controller]->Show(FALSE); - } -} - -void ConfigBox::ChangeJoystick(wxCommandEvent& event) -{ - joysticks[0].ID = m_Joyname[0]->GetSelection(); - joysticks[1].ID = m_Joyname[1]->GetSelection(); - joysticks[2].ID = m_Joyname[2]->GetSelection(); - joysticks[3].ID = m_Joyname[3]->GetSelection(); -} - -void ConfigBox::ChangeControllertype(wxCommandEvent& event) -{ - joysticks[0].controllertype = m_Controltype[0]->GetSelection(); - joysticks[1].controllertype = m_Controltype[1]->GetSelection(); - joysticks[2].controllertype = m_Controltype[2]->GetSelection(); - joysticks[3].controllertype = m_Controltype[3]->GetSelection(); - - for(int i=0; i<4 ;i++) - UpdateVisibleItems(i); -} - -void ConfigBox::NotebookPageChanged(wxNotebookEvent& event) -{ - notebookpage = event.GetSelection(); -} - -void ConfigBox::SetButtonText(int id, char text[128]) -{ - int controller = notebookpage; - - switch(id) - { - case IDB_SHOULDER_L: - { - m_JoyShoulderL[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_SHOULDER_R: - { - m_JoyShoulderR[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_BUTTON_A: - { - m_JoyButtonA[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_BUTTON_B: - { - m_JoyButtonB[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_BUTTON_X: - { - m_JoyButtonX[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_BUTTON_Y: - { - m_JoyButtonY[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_BUTTON_Z: - { - m_JoyButtonZ[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_BUTTONSTART: - { - m_JoyButtonStart[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_BUTTONHALFPRESS: - { - m_JoyButtonHalfpress[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_DPAD_UP: - { - m_JoyDpadUp[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_DPAD_DOWN: - { - m_JoyDpadDown[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_DPAD_LEFT: - { - m_JoyDpadLeft[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_DPAD_RIGHT: - { - m_JoyDpadRight[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_ANALOG_MAIN_X: - { - m_JoyAnalogMainX[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_ANALOG_MAIN_Y: - { - m_JoyAnalogMainY[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_ANALOG_SUB_X: - { - m_JoyAnalogSubX[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_ANALOG_SUB_Y: - { - m_JoyAnalogSubY[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - default: - break; - } -} - -// Wait for button press -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void ConfigBox::GetButtons(wxCommandEvent& event) -{ - int ID = event.GetId(); - int controller = notebookpage; - - // DPAD type check! - if(ID == IDB_DPAD_UP) - if(joysticks[controller].controllertype == 0) - { - GetHats(ID); - return; - } - - SDL_Joystick *joy = SDL_JoystickOpen(joysticks[controller].ID); - - char format[128]; - int buttons = SDL_JoystickNumButtons(joy); - bool waiting = true; - bool succeed = false; - int pressed = 0; - - int counter1 = 0; - int counter2 = 10; - - sprintf(format, "[%d]", counter2); - SetButtonText(ID, format); - wxWindow::Update(); // win only? doesnt seem to work in linux... - - while(waiting) - { - SDL_JoystickUpdate(); - for(int b = 0; b < buttons; b++) - { - if(SDL_JoystickGetButton(joy, b)) - { - pressed = b; - waiting = false; - succeed = true; - break; - } - } - - counter1++; - if(counter1==100) - { - counter1=0; - counter2--; - - sprintf(format, "[%d]", counter2); - SetButtonText(ID, format); - wxWindow::Update(); // win only? doesnt seem to work in linux... - - if(counter2<0) - waiting = false; - } - SLEEP(10); - } - - sprintf(format, "%d", succeed ? pressed : -1); - SetButtonText(ID, format); - - if(SDL_JoystickOpened(joysticks[controller].ID)) - SDL_JoystickClose(joy); -} - -// Wait for D-Pad -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void ConfigBox::GetHats(int ID) -{ - int controller = notebookpage; - - SDL_Joystick *joy; - joy=SDL_JoystickOpen(joysticks[controller].ID); - - char format[128]; - int hats = SDL_JoystickNumHats(joy); - bool waiting = true; - bool succeed = false; - int pressed = 0; - - int counter1 = 0; - int counter2 = 10; - - sprintf(format, "[%d]", counter2); - SetButtonText(ID, format); - wxWindow::Update(); // win only? doesnt seem to work in linux... - - while(waiting) - { - SDL_JoystickUpdate(); - for(int b = 0; b < hats; b++) - { - if(SDL_JoystickGetHat(joy, b)) - { - pressed = b; - waiting = false; - succeed = true; - break; - } - } - - counter1++; - if(counter1==100) - { - counter1=0; - counter2--; - - sprintf(format, "[%d]", counter2); - SetButtonText(ID, format); - wxWindow::Update(); // win only? doesnt seem to work in linux... - - if(counter2<0) - waiting = false; - } - SLEEP(10); - } - - sprintf(format, "%d", succeed ? pressed : -1); - SetButtonText(ID, format); - - if(SDL_JoystickOpened(joysticks[controller].ID)) - SDL_JoystickClose(joy); -} - -// Wait for Analog -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void ConfigBox::GetAxis(wxCommandEvent& event) -{ - int ID = event.GetId(); - int controller = notebookpage; - - SDL_Joystick *joy; - joy=SDL_JoystickOpen(joysticks[controller].ID); - - char format[128]; - int axes = SDL_JoystickNumAxes(joy); - bool waiting = true; - bool succeed = false; - int pressed = 0; - Sint16 value; - - int counter1 = 0; - int counter2 = 10; - - sprintf(format, "[%d]", counter2); - SetButtonText(ID, format); - wxWindow::Update(); // win only? doesnt seem to work in linux... - - while(waiting) - { - SDL_JoystickUpdate(); - for(int b = 0; b < axes; b++) - { - value = SDL_JoystickGetAxis(joy, b); - if(value < -10000 || value > 10000) - { - pressed = b; - waiting = false; - succeed = true; - break; - } - } - - counter1++; - if(counter1==100) - { - counter1=0; - counter2--; - - sprintf(format, "[%d]", counter2); - SetButtonText(ID, format); - wxWindow::Update(); // win only? doesnt seem to work in linux... - - if(counter2<0) - waiting = false; - } - SLEEP(10); - } - - sprintf(format, "%d", succeed ? pressed : -1); - SetButtonText(ID, format); - - if(SDL_JoystickOpened(joysticks[controller].ID)) - SDL_JoystickClose(joy); -} +////////////////////////////////////////////////////////////////////////////////////////// +// Project description +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +// Name: nJoy +// Description: A Dolphin Compatible Input Plugin +// +// Author: Falcon4ever (nJoy@falcon4ever.com) +// Site: www.multigesture.net +// Copyright (C) 2003-2008 Dolphin Project. +// +////////////////////////////////////////////////////////////////////////////////////////// +// +// Licensetype: GNU General Public License (GPL) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. +// +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ +// +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +// +////////////////////////////////////////////////////////////////////////////////////////// + +#include "ConfigBox.h" +#include "../nJoy.h" +#include "Images/controller.xpm" + +extern CONTROLLER_INFO *joyinfo; +extern CONTROLLER_MAPPING joysticks[4]; +extern bool emulator_running; + +static const char* ControllerType[] = +{ + "Joystick (default)", + "Joystick (no hat)", +// "Joytstick (xbox360)", // Shoulder buttons -> axis +// "Keyboard" // Not supported yet, sorry F|RES ;( ... +}; + +BEGIN_EVENT_TABLE(ConfigBox,wxDialog) + EVT_CLOSE(ConfigBox::OnClose) + EVT_BUTTON(ID_ABOUT, ConfigBox::AboutClick) + EVT_BUTTON(ID_OK, ConfigBox::OKClick) + EVT_BUTTON(ID_CANCEL, ConfigBox::CancelClick) + EVT_COMBOBOX(IDC_JOYNAME, ConfigBox::ChangeJoystick) + EVT_COMBOBOX(IDC_CONTROLTYPE, ConfigBox::ChangeControllertype) + EVT_NOTEBOOK_PAGE_CHANGED(ID_NOTEBOOK, ConfigBox::NotebookPageChanged) + + EVT_BUTTON(IDB_SHOULDER_L, ConfigBox::GetButtons) + EVT_BUTTON(IDB_SHOULDER_R, ConfigBox::GetButtons) + EVT_BUTTON(IDB_BUTTON_A, ConfigBox::GetButtons) + EVT_BUTTON(IDB_BUTTON_B, ConfigBox::GetButtons) + EVT_BUTTON(IDB_BUTTON_X, ConfigBox::GetButtons) + EVT_BUTTON(IDB_BUTTON_Y, ConfigBox::GetButtons) + EVT_BUTTON(IDB_BUTTON_Z, ConfigBox::GetButtons) + EVT_BUTTON(IDB_BUTTONSTART, ConfigBox::GetButtons) + EVT_BUTTON(IDB_BUTTONHALFPRESS, ConfigBox::GetButtons) + EVT_BUTTON(IDB_DPAD_UP, ConfigBox::GetButtons) + EVT_BUTTON(IDB_DPAD_DOWN, ConfigBox::GetButtons) + EVT_BUTTON(IDB_DPAD_LEFT, ConfigBox::GetButtons) + EVT_BUTTON(IDB_DPAD_RIGHT, ConfigBox::GetButtons) + + EVT_BUTTON(IDB_ANALOG_MAIN_X, ConfigBox::GetAxis) + EVT_BUTTON(IDB_ANALOG_MAIN_Y, ConfigBox::GetAxis) + EVT_BUTTON(IDB_ANALOG_SUB_X, ConfigBox::GetAxis) + EVT_BUTTON(IDB_ANALOG_SUB_Y, ConfigBox::GetAxis) +END_EVENT_TABLE() + +ConfigBox::ConfigBox(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) +: wxDialog(parent, id, title, position, size, style) +{ + notebookpage = 0; + CreateGUIControls(); +} + +ConfigBox::~ConfigBox() +{ + // empty +} + +// Warning: horrible code below proceed at own risk! +void ConfigBox::CreateGUIControls() +{ + #ifndef _DEBUG + SetTitle(wxT("Configure: nJoy v"INPUT_VERSION" Input Plugin")); + #else + SetTitle(wxT("Configure: nJoy v"INPUT_VERSION" (Debug) Input Plugin")); + #endif + + SetIcon(wxNullIcon); + SetClientSize(637, 527); + Center(); + +#ifndef _WIN32 + // Force a 8pt font so that it looks more or less "correct" regardless of the default font setting + wxFont f(8,wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL); + SetFont(f); +#endif + + // Buttons + m_About = new wxButton(this, ID_ABOUT, wxT("About"), wxPoint(5, 497), wxSize(75, 25), 0, wxDefaultValidator, wxT("About")); + m_OK = new wxButton(this, ID_OK, wxT("OK"), wxPoint(475, 497), wxSize(75, 25), 0, wxDefaultValidator, wxT("OK")); + m_Cancel = new wxButton(this, ID_CANCEL, wxT("Cancel"), wxPoint(556, 497), wxSize(75, 25), 0, wxDefaultValidator, wxT("Cancel")); + + // Notebook + m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxPoint(6, 7),wxSize(625, 484)); + + // Controller pages + m_Controller[0] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE1, wxPoint(0, 0), wxSize(600, 400)); + m_Notebook->AddPage(m_Controller[0], wxT("Controller 1")); + m_Controller[1] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE2, wxPoint(0, 0), wxSize(600, 400)); + m_Notebook->AddPage(m_Controller[1], wxT("Controller 2")); + m_Controller[2] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE3, wxPoint(0, 0), wxSize(600, 400)); + m_Notebook->AddPage(m_Controller[2], wxT("Controller 3")); + m_Controller[3] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE4, wxPoint(0, 0), wxSize(600, 400)); + m_Notebook->AddPage(m_Controller[3], wxT("Controller 4")); + + // Add controls + wxArrayString arrayStringFor_Joyname; + wxArrayString arrayStringFor_Controltype; + wxArrayString arrayStringFor_Deadzone; + + // Search for devices and add the to the device list + if(Search_Devices()) + { + for(int x = 0; x < SDL_NumJoysticks(); x++) + { + arrayStringFor_Joyname.Add(wxString::FromAscii(joyinfo[x].Name)); + } + } + else + { + arrayStringFor_Joyname.Add(wxString::FromAscii("No Joystick detected!")); + } + + arrayStringFor_Controltype.Add(wxString::FromAscii(ControllerType[CTL_TYPE_JOYSTICK])); + arrayStringFor_Controltype.Add(wxString::FromAscii(ControllerType[CTL_TYPE_JOYSTICK_NO_HAT])); + // arrayStringFor_Controltype.Add(wxString::FromAscii(ControllerType[CTL_TYPE_JOYSTICK_XBOX360])); + // arrayStringFor_Controltype.Add(wxString::FromAscii(ControllerType[CTL_TYPE_KEYBOARD])); + + char buffer [8]; + for(int x = 1; x <= 100; x++) + { + sprintf (buffer, "%d %%", x); + arrayStringFor_Deadzone.Add(wxString::FromAscii(buffer)); + } + + wxBitmap WxStaticBitmap1_BITMAP(ConfigBox_WxStaticBitmap1_XPM); + + for(int i=0; i<4 ;i++) + { + + // Groups + m_gJoyname[i] = new wxStaticBox(m_Controller[i], IDG_JOYSTICK, wxT("Controller:"), wxPoint(5, 11), wxSize(608, 46)); + + #ifdef _WIN32 + m_Joyattach[i] = new wxCheckBox(m_Controller[i], IDC_JOYATTACH, wxT("Controller attached"), wxPoint(495, 26), wxSize(109, 25), 0, wxDefaultValidator, wxT("Controller attached")); + m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, wxEmptyString, wxPoint(12, 29), wxSize(476, 21), arrayStringFor_Joyname, 0, wxDefaultValidator, wxT("m_Joyname")); + m_gExtrasettings[i] = new wxStaticBox(m_Controller[i], IDG_EXTRASETTINGS, wxT("Extra settings:"), wxPoint(104, 385), wxSize(155, 69)); + m_Deadzone[i] = new wxComboBox(m_Controller[i], IDC_DEADZONE, wxEmptyString, wxPoint(167, 400), wxSize(59, 21), arrayStringFor_Deadzone, 0, wxDefaultValidator, wxT("m_Deadzone")); + m_gControllertype[i] = new wxStaticBox(m_Controller[i], IDG_CONTROLLERTYPE, wxT("Controller type:"), wxPoint(359, 383), wxSize(143, 44)); + m_Controltype[i] = new wxComboBox(m_Controller[i], IDC_CONTROLTYPE, wxEmptyString, wxPoint(366, 401), wxSize(131, 21), arrayStringFor_Controltype, 0, wxDefaultValidator, wxT("m_Controltype")); + #else + m_Joyattach[i] = new wxCheckBox(m_Controller[i], IDC_JOYATTACH, wxT("Controller attached"), wxPoint(470, 26), wxSize(140, 25), 0, wxDefaultValidator, wxT("Controller attached")); + m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, wxEmptyString, wxPoint(10, 25), wxSize(450, 25), arrayStringFor_Joyname, 0, wxDefaultValidator, wxT("m_Joyname")); + m_gExtrasettings[i] = new wxStaticBox(m_Controller[i], IDG_EXTRASETTINGS, wxT("Extra settings:"), wxPoint(100, 385), wxSize(155, 65)); + m_Deadzone[i] = new wxComboBox(m_Controller[i], IDC_DEADZONE, wxEmptyString, wxPoint(167, 398), wxSize(80, 25), arrayStringFor_Deadzone, 0, wxDefaultValidator, wxT("m_Deadzone")); + m_gControllertype[i] = new wxStaticBox(m_Controller[i], IDG_CONTROLLERTYPE, wxT("Controller type:"), wxPoint(359, 383), wxSize(160, 44)); + m_Controltype[i] = new wxComboBox(m_Controller[i], IDC_CONTROLTYPE, wxEmptyString, wxPoint(364, 396), wxSize(150, 25), arrayStringFor_Controltype, 0, wxDefaultValidator, wxT("m_Controltype")); + #endif + + // GUI left side buttons + m_JoyShoulderL[i] = new wxTextCtrl(m_Controller[i], ID_SHOULDER_L, wxT("0"), wxPoint(6, 80), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyShoulderL[i]->Enable(false); + m_JoyAnalogMainX[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_MAIN_X, wxT("0"), wxPoint(6, 218), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyAnalogMainX[i]->Enable(false); + m_JoyAnalogMainY[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_MAIN_Y, wxT("0"), wxPoint(6, 255), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyAnalogMainY[i]->Enable(false); + m_JoyDpadUp[i] = new wxTextCtrl(m_Controller[i], ID_DPAD_UP, wxT("0"), wxPoint(6, 296), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyDpadUp[i]->Enable(false); + m_JoyDpadDown[i] = new wxTextCtrl(m_Controller[i], ID_DPAD_DOWN, wxT("0"), wxPoint(6, 333), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyDpadDown[i]->Enable(false); + m_JoyDpadLeft[i] = new wxTextCtrl(m_Controller[i], ID_DPAD_LEFT, wxT("0"), wxPoint(6, 369), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyDpadLeft[i]->Enable(false); + m_JoyDpadRight[i] = new wxTextCtrl(m_Controller[i], ID_DPAD_RIGHT, wxT("0"), wxPoint(6, 406), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyDpadRight[i]->Enable(false); + m_bJoyShoulderL[i] = new wxButton(m_Controller[i], IDB_SHOULDER_L, wxEmptyString, wxPoint(70, 82), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyAnalogMainX[i] = new wxButton(m_Controller[i], IDB_ANALOG_MAIN_X, wxEmptyString, wxPoint(70, 220), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyAnalogMainY[i] = new wxButton(m_Controller[i], IDB_ANALOG_MAIN_Y, wxEmptyString, wxPoint(70, 257), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyDpadUp[i] = new wxButton(m_Controller[i], IDB_DPAD_UP, wxEmptyString, wxPoint(70, 298), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyDpadDown[i] = new wxButton(m_Controller[i], IDB_DPAD_DOWN, wxEmptyString, wxPoint(70, 335), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyDpadLeft[i] = new wxButton(m_Controller[i], IDB_DPAD_LEFT, wxEmptyString, wxPoint(70, 371), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyDpadRight[i] = new wxButton(m_Controller[i], IDB_DPAD_RIGHT, wxEmptyString, wxPoint(70, 408), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + + m_textMainX[i] = new wxStaticText(m_Controller[i], IDT_ANALOG_MAIN_X, wxT("X-axis"), wxPoint(6, 204), wxDefaultSize, 0, wxT("X-axis")); + m_textMainY[i] = new wxStaticText(m_Controller[i], IDT_ANALOG_MAIN_Y, wxT("Y-axis"), wxPoint(6, 241), wxDefaultSize, 0, wxT("Y-axis")); + m_textDpadUp[i] = new wxStaticText(m_Controller[i], IDT_DPAD_UP, wxT("Up"), wxPoint(6, 282), wxDefaultSize, 0, wxT("Up")); + m_textDpadDown[i] = new wxStaticText(m_Controller[i], IDT_DPAD_DOWN, wxT("Down"), wxPoint(6, 319), wxDefaultSize, 0, wxT("Down")); + m_textDpadLeft[i] = new wxStaticText(m_Controller[i], IDT_DPAD_LEFT, wxT("Left"), wxPoint(6, 354), wxDefaultSize, 0, wxT("Left")); + m_textDpadRight[i] = new wxStaticText(m_Controller[i], IDT_DPAD_RIGHT, wxT("Right"), wxPoint(6, 391), wxDefaultSize, 0, wxT("Right")); + + // GUI right side buttons + m_JoyShoulderR[i] = new wxTextCtrl(m_Controller[i], ID_SHOULDER_R, wxT("0"), wxPoint(552, 106), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyShoulderR[i]->Enable(false); + m_JoyButtonA[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_A, wxT("0"), wxPoint(552, 280), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyButtonA[i]->Enable(false); + m_JoyButtonB[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_B, wxT("0"), wxPoint(552, 80), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyButtonB[i]->Enable(false); + m_JoyButtonX[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_X, wxT("0"), wxPoint(552, 242), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyButtonX[i]->Enable(false); + m_JoyButtonY[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_Y, wxT("0"), wxPoint(552, 171), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyButtonY[i]->Enable(false); + m_JoyButtonZ[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_Z, wxT("0"), wxPoint(552, 145), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyButtonZ[i]->Enable(false); + m_JoyAnalogSubX[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_SUB_X, wxT("0"), wxPoint(552, 351), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyAnalogSubX[i]->Enable(false); + m_JoyAnalogSubY[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_SUB_Y, wxT("0"), wxPoint(552, 388), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyAnalogSubY[i]->Enable(false); + m_bJoyShoulderR[i] = new wxButton(m_Controller[i], IDB_SHOULDER_R, wxEmptyString, wxPoint(526, 108), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyButtonA[i] = new wxButton(m_Controller[i], IDB_BUTTON_A, wxEmptyString, wxPoint(526, 282), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyButtonB[i] = new wxButton(m_Controller[i], IDB_BUTTON_B, wxEmptyString, wxPoint(526, 82), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyButtonX[i] = new wxButton(m_Controller[i], IDB_BUTTON_X, wxEmptyString, wxPoint(526, 244), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyButtonY[i] = new wxButton(m_Controller[i], IDB_BUTTON_Y, wxEmptyString, wxPoint(526, 173), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyButtonZ[i] = new wxButton(m_Controller[i], IDB_BUTTON_Z, wxEmptyString, wxPoint(526, 147), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyAnalogSubX[i] = new wxButton(m_Controller[i], IDB_ANALOG_SUB_X, wxEmptyString, wxPoint(526, 353), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyAnalogSubY[i] = new wxButton(m_Controller[i], IDB_ANALOG_SUB_Y, wxEmptyString, wxPoint(526, 390), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + + m_textSubX[i] = new wxStaticText(m_Controller[i], IDT_ANALOG_SUB_X, wxT("X-axis"), wxPoint(552, 336), wxDefaultSize, 0, wxT("X-axis")); + m_textSubY[i] = new wxStaticText(m_Controller[i], IDT_ANALOG_SUB_Y, wxT("Y-axis"), wxPoint(552, 373), wxDefaultSize, 0, wxT("Y-axis")); + + // GUI center button + m_JoyButtonStart[i] = new wxTextCtrl(m_Controller[i], ID_BUTTONSTART, wxT("0"), wxPoint(278, 403), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyButtonStart[i]->Enable(false); + m_JoyButtonHalfpress[i] = new wxTextCtrl(m_Controller[i], ID_BUTTONHALFPRESS, wxT("0"), wxPoint(167, 424), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyButtonHalfpress[i]->Enable(false); + m_bJoyButtonStart[i] = new wxButton(m_Controller[i], IDB_BUTTONSTART, wxEmptyString, wxPoint(297, 385), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyButtonHalfpress[i] = new wxButton(m_Controller[i], IDB_BUTTONHALFPRESS, wxEmptyString, wxPoint(231, 426), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + + #ifdef _WIN32 + m_textDeadzone[i] = new wxStaticText(m_Controller[i], IDT_DEADZONE, wxT("Deadzone"), wxPoint(116, 404), wxDefaultSize, 0, wxT("Deadzone")); + m_textHalfpress[i] = new wxStaticText(m_Controller[i], IDT_BUTTONHALFPRESS, wxT("Half press"), wxPoint(116, 428), wxDefaultSize, 0, wxT("Half press")); + m_textWebsite[i] = new wxStaticText(m_Controller[i], IDT_WEBSITE, wxT("www.multigesture.net"), wxPoint(500, 438), wxDefaultSize, 0, wxT("www.multigesture.net")); + #else + m_textDeadzone[i] = new wxStaticText(m_Controller[i], IDT_DEADZONE, wxT("Deadzone"), wxPoint(105, 404), wxDefaultSize, 0, wxT("Deadzone")); + m_textHalfpress[i] = new wxStaticText(m_Controller[i], IDT_BUTTONHALFPRESS, wxT("Half press"), wxPoint(105, 428), wxDefaultSize, 0, wxT("Half press")); + m_textWebsite[i] = new wxStaticText(m_Controller[i], IDT_WEBSITE, wxT("www.multigesture.net"), wxPoint(480, 438), wxDefaultSize, 0, wxT("www.multigesture.net")); + #endif + + // TODO: Controller image + // Placeholder instead of bitmap + // m_PlaceholderBMP[i] = new wxTextCtrl(m_Controller[i], ID_CONTROLLERPICTURE, wxT("BITMAP HERE PLZ KTHX!"), wxPoint(98, 75), wxSize(423, 306), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("BITMAP HERE PLZ KTHX!")); + // m_PlaceholderBMP[i]->Enable(false); + + // You can enable the bitmap here: + // But it loads überslow on init... (only in windows, linux seems to load it fast!) + // AAaaand the XPM file (256 colours) looks crappier than the real bitmap... so maybe we can find a way to use a bitmap? + m_controllerimage[i] = new wxStaticBitmap(m_Controller[i], ID_CONTROLLERPICTURE, WxStaticBitmap1_BITMAP, wxPoint(98, 75), wxSize(421,304)); + + if(emulator_running) + { + m_Joyname[i]->Enable(false); + m_Joyattach[i]->Enable(false); + m_Controltype[i]->Enable(false); + } + + SetControllerAll(i); + } +} + +void ConfigBox::OnClose(wxCloseEvent& /*event*/) +{ + EndModal(0); +} + +void ConfigBox::AboutClick(wxCommandEvent& event) +{ +// Call about dialog +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +#ifdef _WIN32 + wxWindow win; + win.SetHWND((WXHWND)this->GetHWND()); + win.Enable(false); + + AboutBox frame(&win); + frame.ShowModal(); + + win.Enable(true); + win.SetHWND(0); +#else + AboutBox frame(NULL); + frame.ShowModal(); +#endif +} + +void ConfigBox::OKClick(wxCommandEvent& event) +{ + if (event.GetId() == ID_OK) + { + for(int i=0; i<4 ;i++) + GetControllerAll(i); + SaveConfig(); // save settings + LoadConfig(); // reload settings + Close(); + } +} + +void ConfigBox::CancelClick(wxCommandEvent& event) +{ + if (event.GetId() == ID_CANCEL) + { + LoadConfig(); // reload settings + Close(); + } +} + +// Set dialog items +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void ConfigBox::SetControllerAll(int controller) +{ + // http://wiki.wxwidgets.org/Converting_everything_to_and_from_wxString + wxString tmp; + + m_Joyname[controller]->SetSelection(joysticks[controller].ID); + + tmp << joysticks[controller].buttons[CTL_L_SHOULDER]; m_JoyShoulderL[controller]->SetValue(tmp); tmp.clear(); + tmp << joysticks[controller].buttons[CTL_R_SHOULDER]; m_JoyShoulderR[controller]->SetValue(tmp); tmp.clear(); + + tmp << joysticks[controller].buttons[CTL_A_BUTTON]; m_JoyButtonA[controller]->SetValue(tmp); tmp.clear(); + tmp << joysticks[controller].buttons[CTL_B_BUTTON]; m_JoyButtonB[controller]->SetValue(tmp); tmp.clear(); + tmp << joysticks[controller].buttons[CTL_X_BUTTON]; m_JoyButtonX[controller]->SetValue(tmp); tmp.clear(); + tmp << joysticks[controller].buttons[CTL_Y_BUTTON]; m_JoyButtonY[controller]->SetValue(tmp); tmp.clear(); + tmp << joysticks[controller].buttons[CTL_Z_TRIGGER]; m_JoyButtonZ[controller]->SetValue(tmp); tmp.clear(); + + tmp << joysticks[controller].buttons[CTL_START]; m_JoyButtonStart[controller]->SetValue(tmp); tmp.clear(); + tmp << joysticks[controller].halfpress; m_JoyButtonHalfpress[controller]->SetValue(tmp); tmp.clear(); + + tmp << joysticks[controller].axis[CTL_MAIN_X]; m_JoyAnalogMainX[controller]->SetValue(tmp); tmp.clear(); + tmp << joysticks[controller].axis[CTL_MAIN_Y]; m_JoyAnalogMainY[controller]->SetValue(tmp); tmp.clear(); + tmp << joysticks[controller].axis[CTL_SUB_X]; m_JoyAnalogSubX[controller]->SetValue(tmp); tmp.clear(); + tmp << joysticks[controller].axis[CTL_SUB_Y]; m_JoyAnalogSubY[controller]->SetValue(tmp); tmp.clear(); + + if(joysticks[controller].enabled) + m_Joyattach[controller]->SetValue(TRUE); + else + m_Joyattach[controller]->SetValue(FALSE); + + m_Controltype[controller]->SetSelection(joysticks[controller].controllertype); + m_Deadzone[controller]->SetSelection(joysticks[controller].deadzone); + + UpdateVisibleItems(controller); + + if(joysticks[controller].controllertype == CTL_TYPE_JOYSTICK) + { + tmp << joysticks[controller].dpad; m_JoyDpadUp[controller]->SetValue(tmp); tmp.clear(); + } + else + { + tmp << joysticks[controller].dpad2[CTL_D_PAD_UP]; m_JoyDpadUp[controller]->SetValue(tmp); tmp.clear(); + tmp << joysticks[controller].dpad2[CTL_D_PAD_DOWN]; m_JoyDpadDown[controller]->SetValue(tmp); tmp.clear(); + tmp << joysticks[controller].dpad2[CTL_D_PAD_LEFT]; m_JoyDpadLeft[controller]->SetValue(tmp); tmp.clear(); + tmp << joysticks[controller].dpad2[CTL_D_PAD_RIGHT]; m_JoyDpadRight[controller]->SetValue(tmp); tmp.clear(); + } +} + +// Get dialog items +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void ConfigBox::GetControllerAll(int controller) +{ + wxString tmp; + long value; + + joysticks[controller].ID = m_Joyname[controller]->GetSelection(); + + m_JoyShoulderL[controller]->GetValue().ToLong(&value); joysticks[controller].buttons[CTL_L_SHOULDER] = value; tmp.clear(); + m_JoyShoulderR[controller]->GetValue().ToLong(&value); joysticks[controller].buttons[CTL_R_SHOULDER] = value; tmp.clear(); + + m_JoyButtonA[controller]->GetValue().ToLong(&value); joysticks[controller].buttons[CTL_A_BUTTON] = value; tmp.clear(); + m_JoyButtonB[controller]->GetValue().ToLong(&value); joysticks[controller].buttons[CTL_B_BUTTON] = value; tmp.clear(); + m_JoyButtonX[controller]->GetValue().ToLong(&value); joysticks[controller].buttons[CTL_X_BUTTON] = value; tmp.clear(); + m_JoyButtonY[controller]->GetValue().ToLong(&value); joysticks[controller].buttons[CTL_Y_BUTTON] = value; tmp.clear(); + m_JoyButtonZ[controller]->GetValue().ToLong(&value); joysticks[controller].buttons[CTL_Z_TRIGGER] = value; tmp.clear(); + m_JoyButtonStart[controller]->GetValue().ToLong(&value); joysticks[controller].buttons[CTL_START] = value; tmp.clear(); + + m_JoyButtonHalfpress[controller]->GetValue().ToLong(&value); joysticks[controller].halfpress = value; tmp.clear(); + + if(joysticks[controller].controllertype == CTL_TYPE_JOYSTICK) + { + m_JoyDpadUp[controller]->GetValue().ToLong(&value); joysticks[controller].dpad = value; tmp.clear(); + } + else + { + m_JoyDpadUp[controller]->GetValue().ToLong(&value); joysticks[controller].dpad2[CTL_D_PAD_UP] = value; tmp.clear(); + m_JoyDpadDown[controller]->GetValue().ToLong(&value); joysticks[controller].dpad2[CTL_D_PAD_DOWN] = value; tmp.clear(); + m_JoyDpadLeft[controller]->GetValue().ToLong(&value); joysticks[controller].dpad2[CTL_D_PAD_LEFT] = value; tmp.clear(); + m_JoyDpadRight[controller]->GetValue().ToLong(&value); joysticks[controller].dpad2[CTL_D_PAD_RIGHT] = value; tmp.clear(); + } + + m_JoyAnalogMainX[controller]->GetValue().ToLong(&value); joysticks[controller].axis[CTL_MAIN_X] = value; tmp.clear(); + m_JoyAnalogMainY[controller]->GetValue().ToLong(&value); joysticks[controller].axis[CTL_MAIN_Y] = value; tmp.clear(); + m_JoyAnalogSubX[controller]->GetValue().ToLong(&value); joysticks[controller].axis[CTL_SUB_X] = value; tmp.clear(); + m_JoyAnalogSubY[controller]->GetValue().ToLong(&value); joysticks[controller].axis[CTL_SUB_Y] = value; tmp.clear(); + + joysticks[controller].enabled = m_Joyattach[controller]->GetValue(); + + joysticks[controller].controllertype = m_Controltype[controller]->GetSelection(); + joysticks[controller].deadzone = m_Deadzone[controller]->GetSelection(); +} + +void ConfigBox::UpdateVisibleItems(int controller) +{ + if(joysticks[controller].controllertype) + { + m_JoyDpadDown[controller]->Show(TRUE); + m_JoyDpadLeft[controller]->Show(TRUE); + m_JoyDpadRight[controller]->Show(TRUE); + + m_bJoyDpadDown[controller]->Show(TRUE); + m_bJoyDpadLeft[controller]->Show(TRUE); + m_bJoyDpadRight[controller]->Show(TRUE); + + m_textDpadUp[controller]->Show(TRUE); + m_textDpadDown[controller]->Show(TRUE); + m_textDpadLeft[controller]->Show(TRUE); + m_textDpadRight[controller]->Show(TRUE); + } + else + { + m_JoyDpadDown[controller]->Show(FALSE); + m_JoyDpadLeft[controller]->Show(FALSE); + m_JoyDpadRight[controller]->Show(FALSE); + + m_bJoyDpadDown[controller]->Show(FALSE); + m_bJoyDpadLeft[controller]->Show(FALSE); + m_bJoyDpadRight[controller]->Show(FALSE); + + m_textDpadUp[controller]->Show(FALSE); + m_textDpadDown[controller]->Show(FALSE); + m_textDpadLeft[controller]->Show(FALSE); + m_textDpadRight[controller]->Show(FALSE); + } +} + +void ConfigBox::ChangeJoystick(wxCommandEvent& event) +{ + joysticks[0].ID = m_Joyname[0]->GetSelection(); + joysticks[1].ID = m_Joyname[1]->GetSelection(); + joysticks[2].ID = m_Joyname[2]->GetSelection(); + joysticks[3].ID = m_Joyname[3]->GetSelection(); +} + +void ConfigBox::ChangeControllertype(wxCommandEvent& event) +{ + joysticks[0].controllertype = m_Controltype[0]->GetSelection(); + joysticks[1].controllertype = m_Controltype[1]->GetSelection(); + joysticks[2].controllertype = m_Controltype[2]->GetSelection(); + joysticks[3].controllertype = m_Controltype[3]->GetSelection(); + + for(int i=0; i<4 ;i++) + UpdateVisibleItems(i); +} + +void ConfigBox::NotebookPageChanged(wxNotebookEvent& event) +{ + notebookpage = event.GetSelection(); +} + +void ConfigBox::SetButtonText(int id, char text[128]) +{ + int controller = notebookpage; + + switch(id) + { + case IDB_SHOULDER_L: + { + m_JoyShoulderL[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_SHOULDER_R: + { + m_JoyShoulderR[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_BUTTON_A: + { + m_JoyButtonA[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_BUTTON_B: + { + m_JoyButtonB[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_BUTTON_X: + { + m_JoyButtonX[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_BUTTON_Y: + { + m_JoyButtonY[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_BUTTON_Z: + { + m_JoyButtonZ[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_BUTTONSTART: + { + m_JoyButtonStart[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_BUTTONHALFPRESS: + { + m_JoyButtonHalfpress[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_DPAD_UP: + { + m_JoyDpadUp[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_DPAD_DOWN: + { + m_JoyDpadDown[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_DPAD_LEFT: + { + m_JoyDpadLeft[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_DPAD_RIGHT: + { + m_JoyDpadRight[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_ANALOG_MAIN_X: + { + m_JoyAnalogMainX[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_ANALOG_MAIN_Y: + { + m_JoyAnalogMainY[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_ANALOG_SUB_X: + { + m_JoyAnalogSubX[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_ANALOG_SUB_Y: + { + m_JoyAnalogSubY[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + default: + break; + } +} + +// Wait for button press +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void ConfigBox::GetButtons(wxCommandEvent& event) +{ + int ID = event.GetId(); + int controller = notebookpage; + + // DPAD type check! + if(ID == IDB_DPAD_UP) + if(joysticks[controller].controllertype == 0) + { + GetHats(ID); + return; + } + + SDL_Joystick *joy = SDL_JoystickOpen(joysticks[controller].ID); + + char format[128]; + int buttons = SDL_JoystickNumButtons(joy); + bool waiting = true; + bool succeed = false; + int pressed = 0; + + int counter1 = 0; + int counter2 = 10; + + sprintf(format, "[%d]", counter2); + SetButtonText(ID, format); + wxWindow::Update(); // win only? doesnt seem to work in linux... + + while(waiting) + { + SDL_JoystickUpdate(); + for(int b = 0; b < buttons; b++) + { + if(SDL_JoystickGetButton(joy, b)) + { + pressed = b; + waiting = false; + succeed = true; + break; + } + } + + counter1++; + if(counter1==100) + { + counter1=0; + counter2--; + + sprintf(format, "[%d]", counter2); + SetButtonText(ID, format); + wxWindow::Update(); // win only? doesnt seem to work in linux... + + if(counter2<0) + waiting = false; + } + SLEEP(10); + } + + sprintf(format, "%d", succeed ? pressed : -1); + SetButtonText(ID, format); + + if(SDL_JoystickOpened(joysticks[controller].ID)) + SDL_JoystickClose(joy); +} + +// Wait for D-Pad +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void ConfigBox::GetHats(int ID) +{ + int controller = notebookpage; + + SDL_Joystick *joy; + joy=SDL_JoystickOpen(joysticks[controller].ID); + + char format[128]; + int hats = SDL_JoystickNumHats(joy); + bool waiting = true; + bool succeed = false; + int pressed = 0; + + int counter1 = 0; + int counter2 = 10; + + sprintf(format, "[%d]", counter2); + SetButtonText(ID, format); + wxWindow::Update(); // win only? doesnt seem to work in linux... + + while(waiting) + { + SDL_JoystickUpdate(); + for(int b = 0; b < hats; b++) + { + if(SDL_JoystickGetHat(joy, b)) + { + pressed = b; + waiting = false; + succeed = true; + break; + } + } + + counter1++; + if(counter1==100) + { + counter1=0; + counter2--; + + sprintf(format, "[%d]", counter2); + SetButtonText(ID, format); + wxWindow::Update(); // win only? doesnt seem to work in linux... + + if(counter2<0) + waiting = false; + } + SLEEP(10); + } + + sprintf(format, "%d", succeed ? pressed : -1); + SetButtonText(ID, format); + + if(SDL_JoystickOpened(joysticks[controller].ID)) + SDL_JoystickClose(joy); +} + +// Wait for Analog +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void ConfigBox::GetAxis(wxCommandEvent& event) +{ + int ID = event.GetId(); + int controller = notebookpage; + + SDL_Joystick *joy; + joy=SDL_JoystickOpen(joysticks[controller].ID); + + char format[128]; + int axes = SDL_JoystickNumAxes(joy); + bool waiting = true; + bool succeed = false; + int pressed = 0; + Sint16 value; + + int counter1 = 0; + int counter2 = 10; + + sprintf(format, "[%d]", counter2); + SetButtonText(ID, format); + wxWindow::Update(); // win only? doesnt seem to work in linux... + + while(waiting) + { + SDL_JoystickUpdate(); + for(int b = 0; b < axes; b++) + { + value = SDL_JoystickGetAxis(joy, b); + if(value < -10000 || value > 10000) + { + pressed = b; + waiting = false; + succeed = true; + break; + } + } + + counter1++; + if(counter1==100) + { + counter1=0; + counter2--; + + sprintf(format, "[%d]", counter2); + SetButtonText(ID, format); + wxWindow::Update(); // win only? doesnt seem to work in linux... + + if(counter2<0) + waiting = false; + } + SLEEP(10); + } + + sprintf(format, "%d", succeed ? pressed : -1); + SetButtonText(ID, format); + + if(SDL_JoystickOpened(joysticks[controller].ID)) + SDL_JoystickClose(joy); +} diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp index 84036b0adf..f92075f594 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp @@ -1,912 +1,912 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// Project description -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -// Name: nJoy -// Description: A Dolphin Compatible Input Plugin -// -// Author: Falcon4ever (nJoy@falcon4ever.com) -// Site: www.multigesture.net -// Copyright (C) 2003-2008 Dolphin Project. -// -////////////////////////////////////////////////////////////////////////////////////////// -// -// Licensetype: GNU General Public License (GPL) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. -// -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ -// -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ -// -////////////////////////////////////////////////////////////////////////////////////////// - -#include "nJoy.h" - -////////////////////////////////////////////////////////////////////////////////////////// -// Variables -// ŻŻŻŻŻŻŻŻŻ - -FILE *pFile; -HINSTANCE nJoy_hInst = NULL; -CONTROLLER_INFO *joyinfo = 0; -CONTROLLER_STATE joystate[4]; -CONTROLLER_MAPPING joysticks[4]; -bool emulator_running = FALSE; - -// Handle to window -HWND m_hWnd; - -#ifdef USE_RUMBLE_DINPUT_HACK -bool g_rumbleEnable = FALSE; -#endif - -// Rumble in windows -#ifdef _WIN32 - -#ifdef USE_RUMBLE_DINPUT_HACK -LPDIRECTINPUT8 g_pDI = NULL; -LPDIRECTINPUTDEVICE8 g_pDevice = NULL; -LPDIRECTINPUTEFFECT g_pEffect = NULL; - -DWORD g_dwNumForceFeedbackAxis = 0; -INT g_nXForce = 0; -INT g_nYForce = 0; - -#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } - -HRESULT InitDirectInput(HWND hDlg); -VOID FreeDirectInput(); -BOOL CALLBACK EnumFFDevicesCallback(const DIDEVICEINSTANCE* pInst, VOID* pContext); -BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext); -HRESULT SetDeviceForcesXY(); -#endif - -#elif defined(__linux__) - int fd; - char device_file_name[64]; - struct ff_effect effect; - bool CanRumble = false; -#endif - -////////////////////////////////////////////////////////////////////////////////////////// -// wxWidgets -// ŻŻŻŻŻŻŻŻŻ -class wxDLLApp : public wxApp -{ - bool OnInit() - { - return true; - } -}; - -IMPLEMENT_APP_NO_MAIN(wxDLLApp) -WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst); - -////////////////////////////////////////////////////////////////////////////////////////// -// DllMain -// ŻŻŻŻŻŻŻ -#ifdef _WIN32 -BOOL APIENTRY DllMain( HINSTANCE hinstDLL, // DLL module handle - DWORD dwReason, // reason called - LPVOID lpvReserved) // reserved -{ - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - { - //use wxInitialize() if you don't want GUI instead of the following 12 lines - wxSetInstance((HINSTANCE)hinstDLL); - int argc = 0; - char **argv = NULL; - wxEntryStart(argc, argv); - - if ( !wxTheApp || !wxTheApp->CallOnInit() ) - return FALSE; - } - break; - - case DLL_PROCESS_DETACH: - wxEntryCleanup(); //use wxUninitialize() if you don't want GUI - break; - - default: - break; - } - - nJoy_hInst = hinstDLL; - return TRUE; -} -#endif - -////////////////////////////////////////////////////////////////////////////////////////// -// Input Plugin Functions (from spec's) -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ - -// Get properties of plugin -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void GetDllInfo(PLUGIN_INFO* _PluginInfo) -{ - _PluginInfo->Version = 0x0100; - _PluginInfo->Type = PLUGIN_TYPE_PAD; - -#ifdef DEBUGFAST - sprintf(_PluginInfo->Name, "nJoy v"INPUT_VERSION" (DebugFast) by Falcon4ever"); -#else -#ifndef _DEBUG - sprintf(_PluginInfo->Name, "nJoy v"INPUT_VERSION " by Falcon4ever"); -#else - sprintf(_PluginInfo->Name, "nJoy v"INPUT_VERSION" (Debug) by Falcon4ever"); -#endif -#endif -} - -// Call config dialog -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void DllConfig(HWND _hParent) -{ - #ifdef _WIN32 - if(SDL_Init(SDL_INIT_JOYSTICK ) < 0) - { - MessageBox(NULL, SDL_GetError(), "Could not initialize SDL!", MB_ICONERROR); - return; - } - - LoadConfig(); // load settings +////////////////////////////////////////////////////////////////////////////////////////// +// Project description +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +// Name: nJoy +// Description: A Dolphin Compatible Input Plugin +// +// Author: Falcon4ever (nJoy@falcon4ever.com) +// Site: www.multigesture.net +// Copyright (C) 2003-2008 Dolphin Project. +// +////////////////////////////////////////////////////////////////////////////////////////// +// +// Licensetype: GNU General Public License (GPL) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. +// +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ +// +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +// +////////////////////////////////////////////////////////////////////////////////////////// + +#include "nJoy.h" + +////////////////////////////////////////////////////////////////////////////////////////// +// Variables +// ŻŻŻŻŻŻŻŻŻ + +FILE *pFile; +HINSTANCE nJoy_hInst = NULL; +CONTROLLER_INFO *joyinfo = 0; +CONTROLLER_STATE joystate[4]; +CONTROLLER_MAPPING joysticks[4]; +bool emulator_running = FALSE; + +// Handle to window +HWND m_hWnd; + +#ifdef USE_RUMBLE_DINPUT_HACK +bool g_rumbleEnable = FALSE; +#endif + +// Rumble in windows +#ifdef _WIN32 + +#ifdef USE_RUMBLE_DINPUT_HACK +LPDIRECTINPUT8 g_pDI = NULL; +LPDIRECTINPUTDEVICE8 g_pDevice = NULL; +LPDIRECTINPUTEFFECT g_pEffect = NULL; + +DWORD g_dwNumForceFeedbackAxis = 0; +INT g_nXForce = 0; +INT g_nYForce = 0; + +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + +HRESULT InitDirectInput(HWND hDlg); +VOID FreeDirectInput(); +BOOL CALLBACK EnumFFDevicesCallback(const DIDEVICEINSTANCE* pInst, VOID* pContext); +BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext); +HRESULT SetDeviceForcesXY(); +#endif + +#elif defined(__linux__) + int fd; + char device_file_name[64]; + struct ff_effect effect; + bool CanRumble = false; +#endif + +////////////////////////////////////////////////////////////////////////////////////////// +// wxWidgets +// ŻŻŻŻŻŻŻŻŻ +class wxDLLApp : public wxApp +{ + bool OnInit() + { + return true; + } +}; + +IMPLEMENT_APP_NO_MAIN(wxDLLApp) +WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst); + +////////////////////////////////////////////////////////////////////////////////////////// +// DllMain +// ŻŻŻŻŻŻŻ +#ifdef _WIN32 +BOOL APIENTRY DllMain( HINSTANCE hinstDLL, // DLL module handle + DWORD dwReason, // reason called + LPVOID lpvReserved) // reserved +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + { + //use wxInitialize() if you don't want GUI instead of the following 12 lines + wxSetInstance((HINSTANCE)hinstDLL); + int argc = 0; + char **argv = NULL; + wxEntryStart(argc, argv); + + if ( !wxTheApp || !wxTheApp->CallOnInit() ) + return FALSE; + } + break; + + case DLL_PROCESS_DETACH: + wxEntryCleanup(); //use wxUninitialize() if you don't want GUI + break; + + default: + break; + } + + nJoy_hInst = hinstDLL; + return TRUE; +} +#endif + +////////////////////////////////////////////////////////////////////////////////////////// +// Input Plugin Functions (from spec's) +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ + +// Get properties of plugin +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void GetDllInfo(PLUGIN_INFO* _PluginInfo) +{ + _PluginInfo->Version = 0x0100; + _PluginInfo->Type = PLUGIN_TYPE_PAD; + +#ifdef DEBUGFAST + sprintf(_PluginInfo->Name, "nJoy v"INPUT_VERSION" (DebugFast) by Falcon4ever"); +#else +#ifndef _DEBUG + sprintf(_PluginInfo->Name, "nJoy v"INPUT_VERSION " by Falcon4ever"); +#else + sprintf(_PluginInfo->Name, "nJoy v"INPUT_VERSION" (Debug) by Falcon4ever"); +#endif +#endif +} + +// Call config dialog +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void DllConfig(HWND _hParent) +{ + #ifdef _WIN32 + if(SDL_Init(SDL_INIT_JOYSTICK ) < 0) + { + MessageBox(NULL, SDL_GetError(), "Could not initialize SDL!", MB_ICONERROR); + return; + } + + LoadConfig(); // load settings wxWindow win; win.SetHWND(_hParent); ConfigBox frame(&win); frame.ShowModal(); - win.SetHWND(0); - - #else - if(SDL_Init(SDL_INIT_JOYSTICK ) < 0) - { - printf("Could not initialize SDL! (%s)\n", SDL_GetError()); - return; - } - - LoadConfig(); // load settings - - ConfigBox frame(NULL); - frame.ShowModal(); - #endif -} - -// Init PAD (start emulation) -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void PAD_Initialize(SPADInitialize _PADInitialize) -{ - emulator_running = TRUE; - #ifdef _DEBUG - DEBUG_INIT(); - #endif - - if(SDL_Init(SDL_INIT_JOYSTICK ) < 0) - { - #ifdef _WIN32 - MessageBox(NULL, SDL_GetError(), "Could not initialize SDL!", MB_ICONERROR); - #else - printf("Could not initialize SDL! (%s)\n", SDL_GetError()); - #endif - return; - } - - #ifdef _WIN32 - m_hWnd = (HWND)_PADInitialize.hWnd; - #endif - - LoadConfig(); // Load joystick mapping - - if(joysticks[0].enabled) - joystate[0].joy = SDL_JoystickOpen(joysticks[0].ID); - if(joysticks[1].enabled) - joystate[1].joy = SDL_JoystickOpen(joysticks[1].ID); - if(joysticks[2].enabled) - joystate[2].joy = SDL_JoystickOpen(joysticks[2].ID); - if(joysticks[3].enabled) - joystate[3].joy = SDL_JoystickOpen(joysticks[3].ID); -} - -// Shutdown PAD (stop emulation) -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void PAD_Shutdown() -{ - if(joysticks[0].enabled) - SDL_JoystickClose(joystate[0].joy); - if(joysticks[1].enabled) - SDL_JoystickClose(joystate[1].joy); - if(joysticks[2].enabled) - SDL_JoystickClose(joystate[2].joy); - if(joysticks[3].enabled) - SDL_JoystickClose(joystate[3].joy); - - SDL_Quit(); - - #ifdef _DEBUG - DEBUG_QUIT(); - #endif - - delete [] joyinfo; - - emulator_running = FALSE; - - #ifdef _WIN32 - #ifdef USE_RUMBLE_DINPUT_HACK - FreeDirectInput(); - #endif - #elif defined(__linux__) - close(fd); - #endif -} - -// Set PAD status -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) -{ - if(!joysticks[_numPAD].enabled) - return; - - // clear pad status - memset(_pPADStatus, 0, sizeof(SPADStatus)); - - // get pad status - GetJoyState(_numPAD); - - // Reset! - int base = 0x80; - _pPADStatus->stickY = base; - _pPADStatus->stickX = base; - _pPADStatus->substickX = base; - _pPADStatus->substickY = base; - _pPADStatus->button |= PAD_USE_ORIGIN; - - // Set analog controllers - // Set Deadzones perhaps out of function - int deadzone = (int)(((float)(128.00/100.00)) * (float)(joysticks[_numPAD].deadzone+1)); - int deadzone2 = (int)(((float)(-128.00/100.00)) * (float)(joysticks[_numPAD].deadzone+1)); - - // Adjust range - // The value returned by SDL_JoystickGetAxis is a signed integer (-32768 to 32768) - // The value used for the gamecube controller is an unsigned char (0 to 255) - int main_stick_x = (joystate[_numPAD].axis[CTL_MAIN_X]>>8); - int main_stick_y = -(joystate[_numPAD].axis[CTL_MAIN_Y]>>8); - int sub_stick_x = (joystate[_numPAD].axis[CTL_SUB_X]>>8); - int sub_stick_y = -(joystate[_numPAD].axis[CTL_SUB_Y]>>8); - - // Quick fix - if(main_stick_x > 127) - main_stick_x = 127; - if(main_stick_y > 127) - main_stick_y = 127; - if(sub_stick_x > 127) - sub_stick_x = 127; - if(sub_stick_y > 127) - sub_stick_y = 127; - - if(main_stick_x < -128) - main_stick_x = -128; - if(main_stick_y < -128) - main_stick_y = -128; - if(sub_stick_x < -128) - sub_stick_x = -128; - if(sub_stick_y < -128) - sub_stick_y = -128; - - // Send values to Dolpin - if ((main_stick_x < deadzone2) || (main_stick_x > deadzone)) _pPADStatus->stickX += main_stick_x; - if ((main_stick_y < deadzone2) || (main_stick_y > deadzone)) _pPADStatus->stickY += main_stick_y; - if ((sub_stick_x < deadzone2) || (sub_stick_x > deadzone)) _pPADStatus->substickX += sub_stick_x; - if ((sub_stick_y < deadzone2) || (sub_stick_y > deadzone)) _pPADStatus->substickY += sub_stick_y; - - int triggervalue = 255; - if (joystate[_numPAD].halfpress) - triggervalue = 100; - - // Set buttons - if (joystate[_numPAD].buttons[CTL_L_SHOULDER]) - { - _pPADStatus->button|=PAD_TRIGGER_L; - _pPADStatus->triggerLeft = triggervalue; - } - if (joystate[_numPAD].buttons[CTL_R_SHOULDER]) - { - _pPADStatus->button|=PAD_TRIGGER_R; - _pPADStatus->triggerRight = triggervalue; - } - - if (joystate[_numPAD].buttons[CTL_A_BUTTON]) - { - _pPADStatus->button|=PAD_BUTTON_A; - _pPADStatus->analogA = 255; // Perhaps support pressure? - } - if (joystate[_numPAD].buttons[CTL_B_BUTTON]) - { - _pPADStatus->button|=PAD_BUTTON_B; - _pPADStatus->analogB = 255; // Perhaps support pressure? - } - if (joystate[_numPAD].buttons[CTL_X_BUTTON]) _pPADStatus->button|=PAD_BUTTON_X; - if (joystate[_numPAD].buttons[CTL_Y_BUTTON]) _pPADStatus->button|=PAD_BUTTON_Y; - if (joystate[_numPAD].buttons[CTL_Z_TRIGGER]) _pPADStatus->button|=PAD_TRIGGER_Z; - if (joystate[_numPAD].buttons[CTL_START]) _pPADStatus->button|=PAD_BUTTON_START; - - // Set D-pad - if(joysticks[_numPAD].controllertype == CTL_TYPE_JOYSTICK) - { - if(joystate[_numPAD].dpad == SDL_HAT_LEFTUP || joystate[_numPAD].dpad == SDL_HAT_UP || joystate[_numPAD].dpad == SDL_HAT_RIGHTUP ) _pPADStatus->button|=PAD_BUTTON_UP; - if(joystate[_numPAD].dpad == SDL_HAT_LEFTUP || joystate[_numPAD].dpad == SDL_HAT_LEFT || joystate[_numPAD].dpad == SDL_HAT_LEFTDOWN ) _pPADStatus->button|=PAD_BUTTON_LEFT; - if(joystate[_numPAD].dpad == SDL_HAT_LEFTDOWN || joystate[_numPAD].dpad == SDL_HAT_DOWN || joystate[_numPAD].dpad == SDL_HAT_RIGHTDOWN ) _pPADStatus->button|=PAD_BUTTON_DOWN; - if(joystate[_numPAD].dpad == SDL_HAT_RIGHTUP || joystate[_numPAD].dpad == SDL_HAT_RIGHT || joystate[_numPAD].dpad == SDL_HAT_RIGHTDOWN ) _pPADStatus->button|=PAD_BUTTON_RIGHT; - } - else - { - if(joystate[_numPAD].dpad2[CTL_D_PAD_UP]) - _pPADStatus->button|=PAD_BUTTON_UP; - if(joystate[_numPAD].dpad2[CTL_D_PAD_DOWN]) - _pPADStatus->button|=PAD_BUTTON_DOWN; - if(joystate[_numPAD].dpad2[CTL_D_PAD_LEFT]) - _pPADStatus->button|=PAD_BUTTON_LEFT; - if(joystate[_numPAD].dpad2[CTL_D_PAD_RIGHT]) - _pPADStatus->button|=PAD_BUTTON_RIGHT; - } - - _pPADStatus->err = PAD_ERR_NONE; - - - #ifdef _WIN32 - #ifdef USE_RUMBLE_DINPUT_HACK - if(joystate[_numPAD].halfpress) - if(!g_pDI) - if(FAILED(InitDirectInput(m_hWnd))) - { - MessageBox(NULL, SDL_GetError(), "Could not initialize DirectInput!", MB_ICONERROR); - g_rumbleEnable = FALSE; - //return; - } - else - g_rumbleEnable = TRUE; - - if (g_rumbleEnable) - { - g_pDevice->Acquire(); - - if(g_pEffect) - g_pEffect->Start(1, 0); - } - #endif - #elif defined(__linux__) - if(!fd) - { - sprintf(device_file_name, "/dev/input/event%d", joysticks[_numPAD].eventnum); //TODO: Make dynamic // - - /* Open device */ - fd = open(device_file_name, O_RDWR); - if (fd == -1) { - perror("Open device file"); - //Something wrong, probably permissions, just return now - return; - } - int n_effects = 0; - if (ioctl(fd, EVIOCGEFFECTS, &n_effects) == -1) { - perror("Ioctl number of effects"); - } - if(n_effects > 0) - CanRumble = true; - else - return; // Return since we can't do any effects - /* a strong rumbling effect */ - effect.type = FF_RUMBLE; - effect.id = -1; - effect.u.rumble.strong_magnitude = 0x8000; - effect.u.rumble.weak_magnitude = 0; - effect.replay.length = 5000; // Set to 5 seconds, if a Game needs more for a single rumble event, it is dumb and must be a demo - effect.replay.delay = 0; - if (ioctl(fd, EVIOCSFF, &effect) == -1) { - perror("Upload effect"); - CanRumble = false; //We have effects but it doesn't support the rumble we are using. This is basic rumble, should work for most - } - } - #endif -} - -// Set PAD rumble -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -// (Stop=0, Rumble=1) -void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength) -{ - //if(_numPAD > 0) - // return; - - // not supported by SDL - // So we need to use platform specific stuff - #ifdef _WIN32 - #ifdef USE_RUMBLE_DINPUT_HACK - static int a = 0; - - if ((_uType == 0) || (_uType == 2)) - { - a = 0; - } - else if (_uType == 1) - { - a = _uStrength > 2 ? 8000 : 0; - } - - a = int ((float)a * 0.96f); - - if (!g_rumbleEnable) - { - a = 0; - } - else - { - g_nYForce = a; - SetDeviceForcesXY(); - } - #endif - #elif defined(__linux__) - struct input_event event; - if(CanRumble) - { - if (_uType == 1) - { - event.type = EV_FF; - event.code = effect.id; - event.value = 1; - if (write(fd, (const void*) &event, sizeof(event)) == -1) { - perror("Play effect"); - exit(1); - } - } - if ((_uType == 0) || (_uType == 2)) - { - event.type = EV_FF; - event.code = effect.id; - event.value = 0; - if (write(fd, (const void*) &event, sizeof(event)) == -1) { - perror("Stop effect"); - exit(1); - } - } - } - #endif -} - -// Set PAD attached pads -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -unsigned int PAD_GetAttachedPads() -{ - unsigned int connected = 0; - - LoadConfig(); - - if(joysticks[0].enabled) - connected |= 1; - if(joysticks[1].enabled) - connected |= 2; - if(joysticks[2].enabled) - connected |= 4; - if(joysticks[3].enabled) - connected |= 8; - - return connected; -} - -// Savestates -// ŻŻŻŻŻŻŻŻŻŻ -unsigned int SaveLoadState(char *ptr, BOOL save) -{ - // not used - return 0; -} - -////////////////////////////////////////////////////////////////////////////////////////// -// Custom Functions -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ - -// Request joystick state -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void GetJoyState(int controller) -{ - SDL_JoystickUpdate(); - - joystate[controller].axis[CTL_MAIN_X] = SDL_JoystickGetAxis(joystate[controller].joy, joysticks[controller].axis[CTL_MAIN_X]); - joystate[controller].axis[CTL_MAIN_Y] = SDL_JoystickGetAxis(joystate[controller].joy, joysticks[controller].axis[CTL_MAIN_Y]); - joystate[controller].axis[CTL_SUB_X] = SDL_JoystickGetAxis(joystate[controller].joy, joysticks[controller].axis[CTL_SUB_X]); - joystate[controller].axis[CTL_SUB_Y] = SDL_JoystickGetAxis(joystate[controller].joy, joysticks[controller].axis[CTL_SUB_Y]); - - joystate[controller].buttons[CTL_L_SHOULDER] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].buttons[CTL_L_SHOULDER]); - joystate[controller].buttons[CTL_R_SHOULDER] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].buttons[CTL_R_SHOULDER]); - joystate[controller].buttons[CTL_A_BUTTON] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].buttons[CTL_A_BUTTON]); - joystate[controller].buttons[CTL_B_BUTTON] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].buttons[CTL_B_BUTTON]); - joystate[controller].buttons[CTL_X_BUTTON] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].buttons[CTL_X_BUTTON]); - joystate[controller].buttons[CTL_Y_BUTTON] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].buttons[CTL_Y_BUTTON]); - joystate[controller].buttons[CTL_Z_TRIGGER] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].buttons[CTL_Z_TRIGGER]); - joystate[controller].buttons[CTL_START] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].buttons[CTL_START]); - - joystate[controller].halfpress = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].halfpress); - - if(joysticks[controller].controllertype == CTL_TYPE_JOYSTICK) - joystate[controller].dpad = SDL_JoystickGetHat(joystate[controller].joy, joysticks[controller].dpad); - else - { - joystate[controller].dpad2[CTL_D_PAD_UP] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].dpad2[CTL_D_PAD_UP]); - joystate[controller].dpad2[CTL_D_PAD_DOWN] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].dpad2[CTL_D_PAD_DOWN]); - joystate[controller].dpad2[CTL_D_PAD_LEFT] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].dpad2[CTL_D_PAD_LEFT]); - joystate[controller].dpad2[CTL_D_PAD_RIGHT] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].dpad2[CTL_D_PAD_RIGHT]); - } -} - -// Search attached devices -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -int Search_Devices() -{ - // load config - #ifdef _DEBUG - DEBUG_INIT(); - #endif - - int numjoy = SDL_NumJoysticks(); - - if(numjoy == 0) - { - #ifdef _WIN32 - MessageBox(NULL, "No Joystick detected!", NULL, MB_ICONWARNING); - #else - printf("No Joystick detected!\n"); - #endif - return 0; - } - - if(joyinfo) - { - delete [] joyinfo; - joyinfo = new CONTROLLER_INFO [numjoy]; - } - else - { - joyinfo = new CONTROLLER_INFO [numjoy]; - } - - #ifdef _DEBUG - fprintf(pFile, "Scanning for devices\n"); - fprintf(pFile, "ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ\n"); - #endif - - for(int i = 0; i < numjoy; i++ ) - { - joyinfo[i].joy = SDL_JoystickOpen(i); - joyinfo[i].ID = i; - joyinfo[i].NumAxes = SDL_JoystickNumAxes(joyinfo[i].joy); - joyinfo[i].NumButtons = SDL_JoystickNumButtons(joyinfo[i].joy); - joyinfo[i].NumBalls = SDL_JoystickNumBalls(joyinfo[i].joy); - joyinfo[i].NumHats = SDL_JoystickNumHats(joyinfo[i].joy); - joyinfo[i].Name = SDL_JoystickName(i); - - #ifdef _DEBUG - fprintf(pFile, "ID: %d\n", i); - fprintf(pFile, "Name: %s\n", joyinfo[i].Name); - fprintf(pFile, "Buttons: %d\n", joyinfo[i].NumButtons); - fprintf(pFile, "Axes: %d\n", joyinfo[i].NumAxes); - fprintf(pFile, "Hats: %d\n", joyinfo[i].NumHats); - fprintf(pFile, "Balls: %d\n\n", joyinfo[i].NumBalls); - #endif - - // Close if opened - if(SDL_JoystickOpened(i)) - SDL_JoystickClose(joyinfo[i].joy); - } - - return numjoy; -} - -// Enable output log -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void DEBUG_INIT() -{ - if(pFile) - return; - - #ifdef _WIN32 - char dateStr [9]; - _strdate( dateStr); - char timeStr [9]; - _strtime( timeStr ); - #endif - - pFile = fopen ("nJoy-debug.txt","wt"); - fprintf(pFile, "nJoy v"INPUT_VERSION" Debug\n"); - #ifdef _WIN32 - fprintf(pFile, "Date: %s\nTime: %s\n", dateStr, timeStr); - #endif - fprintf(pFile, "ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ\n"); -} - -// Disable output log -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void DEBUG_QUIT() -{ - if(!pFile) - return; - - #ifdef _WIN32 - char timeStr [9]; - _strtime(timeStr); - - fprintf(pFile, "_______________\n"); - fprintf(pFile, "Time: %s", timeStr); - #endif - fclose(pFile); -} - -// Save settings to file -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void SaveConfig() -{ - IniFile file; - file.Load("nJoy.ini"); - - for (int i=0; i<4; i++) - { - char SectionName[32]; - sprintf(SectionName, "PAD%i", i+1); - - file.Set(SectionName, "l_shoulder", joysticks[i].buttons[CTL_L_SHOULDER]); - file.Set(SectionName, "r_shoulder", joysticks[i].buttons[CTL_R_SHOULDER]); - file.Set(SectionName, "a_button", joysticks[i].buttons[CTL_A_BUTTON]); - file.Set(SectionName, "b_button", joysticks[i].buttons[CTL_B_BUTTON]); - file.Set(SectionName, "x_button", joysticks[i].buttons[CTL_X_BUTTON]); - file.Set(SectionName, "y_button", joysticks[i].buttons[CTL_Y_BUTTON]); - file.Set(SectionName, "z_trigger", joysticks[i].buttons[CTL_Z_TRIGGER]); - file.Set(SectionName, "start_button", joysticks[i].buttons[CTL_START]); - file.Set(SectionName, "dpad", joysticks[i].dpad); - file.Set(SectionName, "dpad_up", joysticks[i].dpad2[CTL_D_PAD_UP]); - file.Set(SectionName, "dpad_down", joysticks[i].dpad2[CTL_D_PAD_DOWN]); - file.Set(SectionName, "dpad_left", joysticks[i].dpad2[CTL_D_PAD_LEFT]); - file.Set(SectionName, "dpad_right", joysticks[i].dpad2[CTL_D_PAD_RIGHT]); - file.Set(SectionName, "main_x", joysticks[i].axis[CTL_MAIN_X]); - file.Set(SectionName, "main_y", joysticks[i].axis[CTL_MAIN_Y]); - file.Set(SectionName, "sub_x", joysticks[i].axis[CTL_SUB_X]); - file.Set(SectionName, "sub_y", joysticks[i].axis[CTL_SUB_Y]); - file.Set(SectionName, "enabled", joysticks[i].enabled); - file.Set(SectionName, "deadzone", joysticks[i].deadzone); - file.Set(SectionName, "halfpress", joysticks[i].halfpress); - file.Set(SectionName, "joy_id", joysticks[i].ID); - file.Set(SectionName, "controllertype", joysticks[i].controllertype); - file.Set(SectionName, "eventnum", joysticks[i].eventnum); - } - - file.Save("nJoy.ini"); -} - -// Load settings from file -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void LoadConfig() -{ - IniFile file; - file.Load("nJoy.ini"); - - for (int i=0; i<4; i++) - { - char SectionName[32]; - sprintf(SectionName, "PAD%i", i+1); - - file.Get(SectionName, "l_shoulder", &joysticks[i].buttons[CTL_L_SHOULDER], 4); - file.Get(SectionName, "r_shoulder", &joysticks[i].buttons[CTL_R_SHOULDER], 5); - file.Get(SectionName, "a_button", &joysticks[i].buttons[CTL_A_BUTTON], 0); - file.Get(SectionName, "b_button", &joysticks[i].buttons[CTL_B_BUTTON], 1); - file.Get(SectionName, "x_button", &joysticks[i].buttons[CTL_X_BUTTON], 3); - file.Get(SectionName, "y_button", &joysticks[i].buttons[CTL_Y_BUTTON], 2); - file.Get(SectionName, "z_trigger", &joysticks[i].buttons[CTL_Z_TRIGGER], 7); - file.Get(SectionName, "start_button", &joysticks[i].buttons[CTL_START], 9); - file.Get(SectionName, "dpad", &joysticks[i].dpad, 0); - file.Get(SectionName, "dpad_up", &joysticks[i].dpad2[CTL_D_PAD_UP], 0); - file.Get(SectionName, "dpad_down", &joysticks[i].dpad2[CTL_D_PAD_DOWN], 0); - file.Get(SectionName, "dpad_left", &joysticks[i].dpad2[CTL_D_PAD_LEFT], 0); - file.Get(SectionName, "dpad_right", &joysticks[i].dpad2[CTL_D_PAD_RIGHT], 0); - file.Get(SectionName, "main_x", &joysticks[i].axis[CTL_MAIN_X], 0); - file.Get(SectionName, "main_y", &joysticks[i].axis[CTL_MAIN_Y], 1); - file.Get(SectionName, "sub_x", &joysticks[i].axis[CTL_SUB_X], 2); - file.Get(SectionName, "sub_y", &joysticks[i].axis[CTL_SUB_Y], 3); - file.Get(SectionName, "enabled", &joysticks[i].enabled, 1); - file.Get(SectionName, "deadzone", &joysticks[i].deadzone, 9); - file.Get(SectionName, "halfpress", &joysticks[i].halfpress, 6); - file.Get(SectionName, "joy_id", &joysticks[i].ID, 0); - file.Get(SectionName, "controllertype", &joysticks[i].controllertype, 0); - file.Get(SectionName, "eventnum", &joysticks[i].eventnum, 0); - } -} - - -#ifdef _WIN32 -////////////////////////////////////////////////////////////////////////////////////////// -// Rumble stuff :D! -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -// -#ifdef USE_RUMBLE_DINPUT_HACK -HRESULT InitDirectInput( HWND hDlg ) -{ - DIPROPDWORD dipdw; - HRESULT hr; - - // Register with the DirectInput subsystem and get a pointer to a IDirectInput interface we can use. - if(FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&g_pDI, NULL))) - { - return hr; - } - - // Look for a force feedback device we can use - if(FAILED(hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, EnumFFDevicesCallback, NULL, DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK))) - { - return hr; - } - - if(NULL == g_pDevice) - { - MessageBox(NULL, "Force feedback device not found. nJoy will now disable rumble." ,"FFConst" , MB_ICONERROR | MB_OK); - g_rumbleEnable = FALSE; - - return S_OK; - } - - // Set the data format to "simple joystick" - a predefined data format. A - // data format specifies which controls on a device we are interested in, - // and how they should be reported. - // - // This tells DirectInput that we will be passing a DIJOYSTATE structure to - // IDirectInputDevice8::GetDeviceState(). Even though we won't actually do - // it in this sample. But setting the data format is important so that the - // DIJOFS_* values work properly. - if(FAILED(hr = g_pDevice->SetDataFormat(&c_dfDIJoystick))) - return hr; - - // Set the cooperative level to let DInput know how this device should - // interact with the system and with other DInput applications. - // Exclusive access is required in order to perform force feedback. - //if(FAILED(hr = g_pDevice->SetCooperativeLevel(hDlg, DISCL_EXCLUSIVE | DISCL_FOREGROUND))) - - if(FAILED(hr = g_pDevice->SetCooperativeLevel(hDlg, DISCL_EXCLUSIVE | DISCL_FOREGROUND))) - { - return hr; - } - - // Since we will be playing force feedback effects, we should disable the - // auto-centering spring. - dipdw.diph.dwSize = sizeof(DIPROPDWORD); - dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); - dipdw.diph.dwObj = 0; - dipdw.diph.dwHow = DIPH_DEVICE; - dipdw.dwData = FALSE; - - if(FAILED(hr = g_pDevice->SetProperty(DIPROP_AUTOCENTER, &dipdw.diph))) - return hr; - - // Enumerate and count the axes of the joystick - if(FAILED(hr = g_pDevice->EnumObjects(EnumAxesCallback, (VOID*)&g_dwNumForceFeedbackAxis, DIDFT_AXIS))) - return hr; - - // This simple sample only supports one or two axis joysticks - if(g_dwNumForceFeedbackAxis > 2) - g_dwNumForceFeedbackAxis = 2; - - // This application needs only one effect: Applying raw forces. - DWORD rgdwAxes[2] = {DIJOFS_X, DIJOFS_Y}; - LONG rglDirection[2] = {0, 0}; - DICONSTANTFORCE cf = {0}; - - DIEFFECT eff; - ZeroMemory(&eff, sizeof(eff)); - eff.dwSize = sizeof(DIEFFECT); - eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; - eff.dwDuration = INFINITE; - eff.dwSamplePeriod = 0; - eff.dwGain = DI_FFNOMINALMAX; - eff.dwTriggerButton = DIEB_NOTRIGGER; - eff.dwTriggerRepeatInterval = 0; - eff.cAxes = g_dwNumForceFeedbackAxis; - eff.rgdwAxes = rgdwAxes; - eff.rglDirection = rglDirection; - eff.lpEnvelope = 0; - eff.cbTypeSpecificParams = sizeof( DICONSTANTFORCE ); - eff.lpvTypeSpecificParams = &cf; - eff.dwStartDelay = 0; - - // Create the prepared effect - if(FAILED(hr = g_pDevice->CreateEffect(GUID_ConstantForce, &eff, &g_pEffect, NULL))) - { - return hr; - } - - if(NULL == g_pEffect) - return E_FAIL; - - return S_OK; -} - -VOID FreeDirectInput() -{ - // Unacquire the device one last time just in case - // the app tried to exit while the device is still acquired. - if(g_pDevice) - g_pDevice->Unacquire(); - - // Release any DirectInput objects. - SAFE_RELEASE(g_pEffect); - SAFE_RELEASE(g_pDevice); - SAFE_RELEASE(g_pDI); -} - -BOOL CALLBACK EnumFFDevicesCallback( const DIDEVICEINSTANCE* pInst, VOID* pContext ) -{ - LPDIRECTINPUTDEVICE8 pDevice; - HRESULT hr; - - // Obtain an interface to the enumerated force feedback device. - hr = g_pDI->CreateDevice(pInst->guidInstance, &pDevice, NULL); - - // If it failed, then we can't use this device for some bizarre reason. - // (Maybe the user unplugged it while we were in the middle of enumerating it.) So continue enumerating - if( FAILED(hr)) - return DIENUM_CONTINUE; - - // We successfully created an IDirectInputDevice8. So stop looking for another one. - g_pDevice = pDevice; - - return DIENUM_STOP; -} - -BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext) -{ - DWORD* pdwNumForceFeedbackAxis = (DWORD*)pContext; - if((pdidoi->dwFlags & DIDOI_FFACTUATOR) != 0) - (*pdwNumForceFeedbackAxis)++; - - return DIENUM_CONTINUE; -} - -HRESULT SetDeviceForcesXY() -{ - // Modifying an effect is basically the same as creating a new one, except you need only specify the parameters you are modifying - LONG rglDirection[2] = { 0, 0 }; - - DICONSTANTFORCE cf; - - if( g_dwNumForceFeedbackAxis == 1 ) - { - // If only one force feedback axis, then apply only one direction and keep the direction at zero - cf.lMagnitude = g_nXForce; - rglDirection[0] = 0; - } - else - { - // If two force feedback axis, then apply magnitude from both directions - rglDirection[0] = g_nXForce; - rglDirection[1] = g_nYForce; - cf.lMagnitude = (DWORD)sqrt((double)g_nXForce * (double)g_nXForce + (double)g_nYForce * (double)g_nYForce ); - } - - DIEFFECT eff; - ZeroMemory(&eff, sizeof(eff)); - eff.dwSize = sizeof(DIEFFECT); - eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; - eff.cAxes = g_dwNumForceFeedbackAxis; - eff.rglDirection = rglDirection; - eff.lpEnvelope = 0; - eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE); - eff.lpvTypeSpecificParams = &cf; - eff.dwStartDelay = 0; - - // Now set the new parameters and start the effect immediately. - return g_pEffect->SetParameters(&eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START); -} -#endif -#endif + win.SetHWND(0); + + #else + if(SDL_Init(SDL_INIT_JOYSTICK ) < 0) + { + printf("Could not initialize SDL! (%s)\n", SDL_GetError()); + return; + } + + LoadConfig(); // load settings + + ConfigBox frame(NULL); + frame.ShowModal(); + #endif +} + +// Init PAD (start emulation) +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void PAD_Initialize(SPADInitialize _PADInitialize) +{ + emulator_running = TRUE; + #ifdef _DEBUG + DEBUG_INIT(); + #endif + + if(SDL_Init(SDL_INIT_JOYSTICK ) < 0) + { + #ifdef _WIN32 + MessageBox(NULL, SDL_GetError(), "Could not initialize SDL!", MB_ICONERROR); + #else + printf("Could not initialize SDL! (%s)\n", SDL_GetError()); + #endif + return; + } + + #ifdef _WIN32 + m_hWnd = (HWND)_PADInitialize.hWnd; + #endif + + LoadConfig(); // Load joystick mapping + + if(joysticks[0].enabled) + joystate[0].joy = SDL_JoystickOpen(joysticks[0].ID); + if(joysticks[1].enabled) + joystate[1].joy = SDL_JoystickOpen(joysticks[1].ID); + if(joysticks[2].enabled) + joystate[2].joy = SDL_JoystickOpen(joysticks[2].ID); + if(joysticks[3].enabled) + joystate[3].joy = SDL_JoystickOpen(joysticks[3].ID); +} + +// Shutdown PAD (stop emulation) +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void PAD_Shutdown() +{ + if(joysticks[0].enabled) + SDL_JoystickClose(joystate[0].joy); + if(joysticks[1].enabled) + SDL_JoystickClose(joystate[1].joy); + if(joysticks[2].enabled) + SDL_JoystickClose(joystate[2].joy); + if(joysticks[3].enabled) + SDL_JoystickClose(joystate[3].joy); + + SDL_Quit(); + + #ifdef _DEBUG + DEBUG_QUIT(); + #endif + + delete [] joyinfo; + + emulator_running = FALSE; + + #ifdef _WIN32 + #ifdef USE_RUMBLE_DINPUT_HACK + FreeDirectInput(); + #endif + #elif defined(__linux__) + close(fd); + #endif +} + +// Set PAD status +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) +{ + if(!joysticks[_numPAD].enabled) + return; + + // clear pad status + memset(_pPADStatus, 0, sizeof(SPADStatus)); + + // get pad status + GetJoyState(_numPAD); + + // Reset! + int base = 0x80; + _pPADStatus->stickY = base; + _pPADStatus->stickX = base; + _pPADStatus->substickX = base; + _pPADStatus->substickY = base; + _pPADStatus->button |= PAD_USE_ORIGIN; + + // Set analog controllers + // Set Deadzones perhaps out of function + int deadzone = (int)(((float)(128.00/100.00)) * (float)(joysticks[_numPAD].deadzone+1)); + int deadzone2 = (int)(((float)(-128.00/100.00)) * (float)(joysticks[_numPAD].deadzone+1)); + + // Adjust range + // The value returned by SDL_JoystickGetAxis is a signed integer (-32768 to 32768) + // The value used for the gamecube controller is an unsigned char (0 to 255) + int main_stick_x = (joystate[_numPAD].axis[CTL_MAIN_X]>>8); + int main_stick_y = -(joystate[_numPAD].axis[CTL_MAIN_Y]>>8); + int sub_stick_x = (joystate[_numPAD].axis[CTL_SUB_X]>>8); + int sub_stick_y = -(joystate[_numPAD].axis[CTL_SUB_Y]>>8); + + // Quick fix + if(main_stick_x > 127) + main_stick_x = 127; + if(main_stick_y > 127) + main_stick_y = 127; + if(sub_stick_x > 127) + sub_stick_x = 127; + if(sub_stick_y > 127) + sub_stick_y = 127; + + if(main_stick_x < -128) + main_stick_x = -128; + if(main_stick_y < -128) + main_stick_y = -128; + if(sub_stick_x < -128) + sub_stick_x = -128; + if(sub_stick_y < -128) + sub_stick_y = -128; + + // Send values to Dolpin + if ((main_stick_x < deadzone2) || (main_stick_x > deadzone)) _pPADStatus->stickX += main_stick_x; + if ((main_stick_y < deadzone2) || (main_stick_y > deadzone)) _pPADStatus->stickY += main_stick_y; + if ((sub_stick_x < deadzone2) || (sub_stick_x > deadzone)) _pPADStatus->substickX += sub_stick_x; + if ((sub_stick_y < deadzone2) || (sub_stick_y > deadzone)) _pPADStatus->substickY += sub_stick_y; + + int triggervalue = 255; + if (joystate[_numPAD].halfpress) + triggervalue = 100; + + // Set buttons + if (joystate[_numPAD].buttons[CTL_L_SHOULDER]) + { + _pPADStatus->button|=PAD_TRIGGER_L; + _pPADStatus->triggerLeft = triggervalue; + } + if (joystate[_numPAD].buttons[CTL_R_SHOULDER]) + { + _pPADStatus->button|=PAD_TRIGGER_R; + _pPADStatus->triggerRight = triggervalue; + } + + if (joystate[_numPAD].buttons[CTL_A_BUTTON]) + { + _pPADStatus->button|=PAD_BUTTON_A; + _pPADStatus->analogA = 255; // Perhaps support pressure? + } + if (joystate[_numPAD].buttons[CTL_B_BUTTON]) + { + _pPADStatus->button|=PAD_BUTTON_B; + _pPADStatus->analogB = 255; // Perhaps support pressure? + } + if (joystate[_numPAD].buttons[CTL_X_BUTTON]) _pPADStatus->button|=PAD_BUTTON_X; + if (joystate[_numPAD].buttons[CTL_Y_BUTTON]) _pPADStatus->button|=PAD_BUTTON_Y; + if (joystate[_numPAD].buttons[CTL_Z_TRIGGER]) _pPADStatus->button|=PAD_TRIGGER_Z; + if (joystate[_numPAD].buttons[CTL_START]) _pPADStatus->button|=PAD_BUTTON_START; + + // Set D-pad + if(joysticks[_numPAD].controllertype == CTL_TYPE_JOYSTICK) + { + if(joystate[_numPAD].dpad == SDL_HAT_LEFTUP || joystate[_numPAD].dpad == SDL_HAT_UP || joystate[_numPAD].dpad == SDL_HAT_RIGHTUP ) _pPADStatus->button|=PAD_BUTTON_UP; + if(joystate[_numPAD].dpad == SDL_HAT_LEFTUP || joystate[_numPAD].dpad == SDL_HAT_LEFT || joystate[_numPAD].dpad == SDL_HAT_LEFTDOWN ) _pPADStatus->button|=PAD_BUTTON_LEFT; + if(joystate[_numPAD].dpad == SDL_HAT_LEFTDOWN || joystate[_numPAD].dpad == SDL_HAT_DOWN || joystate[_numPAD].dpad == SDL_HAT_RIGHTDOWN ) _pPADStatus->button|=PAD_BUTTON_DOWN; + if(joystate[_numPAD].dpad == SDL_HAT_RIGHTUP || joystate[_numPAD].dpad == SDL_HAT_RIGHT || joystate[_numPAD].dpad == SDL_HAT_RIGHTDOWN ) _pPADStatus->button|=PAD_BUTTON_RIGHT; + } + else + { + if(joystate[_numPAD].dpad2[CTL_D_PAD_UP]) + _pPADStatus->button|=PAD_BUTTON_UP; + if(joystate[_numPAD].dpad2[CTL_D_PAD_DOWN]) + _pPADStatus->button|=PAD_BUTTON_DOWN; + if(joystate[_numPAD].dpad2[CTL_D_PAD_LEFT]) + _pPADStatus->button|=PAD_BUTTON_LEFT; + if(joystate[_numPAD].dpad2[CTL_D_PAD_RIGHT]) + _pPADStatus->button|=PAD_BUTTON_RIGHT; + } + + _pPADStatus->err = PAD_ERR_NONE; + + + #ifdef _WIN32 + #ifdef USE_RUMBLE_DINPUT_HACK + if(joystate[_numPAD].halfpress) + if(!g_pDI) + if(FAILED(InitDirectInput(m_hWnd))) + { + MessageBox(NULL, SDL_GetError(), "Could not initialize DirectInput!", MB_ICONERROR); + g_rumbleEnable = FALSE; + //return; + } + else + g_rumbleEnable = TRUE; + + if (g_rumbleEnable) + { + g_pDevice->Acquire(); + + if(g_pEffect) + g_pEffect->Start(1, 0); + } + #endif + #elif defined(__linux__) + if(!fd) + { + sprintf(device_file_name, "/dev/input/event%d", joysticks[_numPAD].eventnum); //TODO: Make dynamic // + + /* Open device */ + fd = open(device_file_name, O_RDWR); + if (fd == -1) { + perror("Open device file"); + //Something wrong, probably permissions, just return now + return; + } + int n_effects = 0; + if (ioctl(fd, EVIOCGEFFECTS, &n_effects) == -1) { + perror("Ioctl number of effects"); + } + if(n_effects > 0) + CanRumble = true; + else + return; // Return since we can't do any effects + /* a strong rumbling effect */ + effect.type = FF_RUMBLE; + effect.id = -1; + effect.u.rumble.strong_magnitude = 0x8000; + effect.u.rumble.weak_magnitude = 0; + effect.replay.length = 5000; // Set to 5 seconds, if a Game needs more for a single rumble event, it is dumb and must be a demo + effect.replay.delay = 0; + if (ioctl(fd, EVIOCSFF, &effect) == -1) { + perror("Upload effect"); + CanRumble = false; //We have effects but it doesn't support the rumble we are using. This is basic rumble, should work for most + } + } + #endif +} + +// Set PAD rumble +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +// (Stop=0, Rumble=1) +void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength) +{ + //if(_numPAD > 0) + // return; + + // not supported by SDL + // So we need to use platform specific stuff + #ifdef _WIN32 + #ifdef USE_RUMBLE_DINPUT_HACK + static int a = 0; + + if ((_uType == 0) || (_uType == 2)) + { + a = 0; + } + else if (_uType == 1) + { + a = _uStrength > 2 ? 8000 : 0; + } + + a = int ((float)a * 0.96f); + + if (!g_rumbleEnable) + { + a = 0; + } + else + { + g_nYForce = a; + SetDeviceForcesXY(); + } + #endif + #elif defined(__linux__) + struct input_event event; + if(CanRumble) + { + if (_uType == 1) + { + event.type = EV_FF; + event.code = effect.id; + event.value = 1; + if (write(fd, (const void*) &event, sizeof(event)) == -1) { + perror("Play effect"); + exit(1); + } + } + if ((_uType == 0) || (_uType == 2)) + { + event.type = EV_FF; + event.code = effect.id; + event.value = 0; + if (write(fd, (const void*) &event, sizeof(event)) == -1) { + perror("Stop effect"); + exit(1); + } + } + } + #endif +} + +// Set PAD attached pads +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +unsigned int PAD_GetAttachedPads() +{ + unsigned int connected = 0; + + LoadConfig(); + + if(joysticks[0].enabled) + connected |= 1; + if(joysticks[1].enabled) + connected |= 2; + if(joysticks[2].enabled) + connected |= 4; + if(joysticks[3].enabled) + connected |= 8; + + return connected; +} + +// Savestates +// ŻŻŻŻŻŻŻŻŻŻ +unsigned int SaveLoadState(char *ptr, BOOL save) +{ + // not used + return 0; +} + +////////////////////////////////////////////////////////////////////////////////////////// +// Custom Functions +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ + +// Request joystick state +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void GetJoyState(int controller) +{ + SDL_JoystickUpdate(); + + joystate[controller].axis[CTL_MAIN_X] = SDL_JoystickGetAxis(joystate[controller].joy, joysticks[controller].axis[CTL_MAIN_X]); + joystate[controller].axis[CTL_MAIN_Y] = SDL_JoystickGetAxis(joystate[controller].joy, joysticks[controller].axis[CTL_MAIN_Y]); + joystate[controller].axis[CTL_SUB_X] = SDL_JoystickGetAxis(joystate[controller].joy, joysticks[controller].axis[CTL_SUB_X]); + joystate[controller].axis[CTL_SUB_Y] = SDL_JoystickGetAxis(joystate[controller].joy, joysticks[controller].axis[CTL_SUB_Y]); + + joystate[controller].buttons[CTL_L_SHOULDER] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].buttons[CTL_L_SHOULDER]); + joystate[controller].buttons[CTL_R_SHOULDER] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].buttons[CTL_R_SHOULDER]); + joystate[controller].buttons[CTL_A_BUTTON] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].buttons[CTL_A_BUTTON]); + joystate[controller].buttons[CTL_B_BUTTON] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].buttons[CTL_B_BUTTON]); + joystate[controller].buttons[CTL_X_BUTTON] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].buttons[CTL_X_BUTTON]); + joystate[controller].buttons[CTL_Y_BUTTON] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].buttons[CTL_Y_BUTTON]); + joystate[controller].buttons[CTL_Z_TRIGGER] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].buttons[CTL_Z_TRIGGER]); + joystate[controller].buttons[CTL_START] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].buttons[CTL_START]); + + joystate[controller].halfpress = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].halfpress); + + if(joysticks[controller].controllertype == CTL_TYPE_JOYSTICK) + joystate[controller].dpad = SDL_JoystickGetHat(joystate[controller].joy, joysticks[controller].dpad); + else + { + joystate[controller].dpad2[CTL_D_PAD_UP] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].dpad2[CTL_D_PAD_UP]); + joystate[controller].dpad2[CTL_D_PAD_DOWN] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].dpad2[CTL_D_PAD_DOWN]); + joystate[controller].dpad2[CTL_D_PAD_LEFT] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].dpad2[CTL_D_PAD_LEFT]); + joystate[controller].dpad2[CTL_D_PAD_RIGHT] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].dpad2[CTL_D_PAD_RIGHT]); + } +} + +// Search attached devices +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +int Search_Devices() +{ + // load config + #ifdef _DEBUG + DEBUG_INIT(); + #endif + + int numjoy = SDL_NumJoysticks(); + + if(numjoy == 0) + { + #ifdef _WIN32 + MessageBox(NULL, "No Joystick detected!", NULL, MB_ICONWARNING); + #else + printf("No Joystick detected!\n"); + #endif + return 0; + } + + if(joyinfo) + { + delete [] joyinfo; + joyinfo = new CONTROLLER_INFO [numjoy]; + } + else + { + joyinfo = new CONTROLLER_INFO [numjoy]; + } + + #ifdef _DEBUG + fprintf(pFile, "Scanning for devices\n"); + fprintf(pFile, "ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ\n"); + #endif + + for(int i = 0; i < numjoy; i++ ) + { + joyinfo[i].joy = SDL_JoystickOpen(i); + joyinfo[i].ID = i; + joyinfo[i].NumAxes = SDL_JoystickNumAxes(joyinfo[i].joy); + joyinfo[i].NumButtons = SDL_JoystickNumButtons(joyinfo[i].joy); + joyinfo[i].NumBalls = SDL_JoystickNumBalls(joyinfo[i].joy); + joyinfo[i].NumHats = SDL_JoystickNumHats(joyinfo[i].joy); + joyinfo[i].Name = SDL_JoystickName(i); + + #ifdef _DEBUG + fprintf(pFile, "ID: %d\n", i); + fprintf(pFile, "Name: %s\n", joyinfo[i].Name); + fprintf(pFile, "Buttons: %d\n", joyinfo[i].NumButtons); + fprintf(pFile, "Axes: %d\n", joyinfo[i].NumAxes); + fprintf(pFile, "Hats: %d\n", joyinfo[i].NumHats); + fprintf(pFile, "Balls: %d\n\n", joyinfo[i].NumBalls); + #endif + + // Close if opened + if(SDL_JoystickOpened(i)) + SDL_JoystickClose(joyinfo[i].joy); + } + + return numjoy; +} + +// Enable output log +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void DEBUG_INIT() +{ + if(pFile) + return; + + #ifdef _WIN32 + char dateStr [9]; + _strdate( dateStr); + char timeStr [9]; + _strtime( timeStr ); + #endif + + pFile = fopen ("nJoy-debug.txt","wt"); + fprintf(pFile, "nJoy v"INPUT_VERSION" Debug\n"); + #ifdef _WIN32 + fprintf(pFile, "Date: %s\nTime: %s\n", dateStr, timeStr); + #endif + fprintf(pFile, "ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ\n"); +} + +// Disable output log +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void DEBUG_QUIT() +{ + if(!pFile) + return; + + #ifdef _WIN32 + char timeStr [9]; + _strtime(timeStr); + + fprintf(pFile, "_______________\n"); + fprintf(pFile, "Time: %s", timeStr); + #endif + fclose(pFile); +} + +// Save settings to file +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void SaveConfig() +{ + IniFile file; + file.Load("nJoy.ini"); + + for (int i=0; i<4; i++) + { + char SectionName[32]; + sprintf(SectionName, "PAD%i", i+1); + + file.Set(SectionName, "l_shoulder", joysticks[i].buttons[CTL_L_SHOULDER]); + file.Set(SectionName, "r_shoulder", joysticks[i].buttons[CTL_R_SHOULDER]); + file.Set(SectionName, "a_button", joysticks[i].buttons[CTL_A_BUTTON]); + file.Set(SectionName, "b_button", joysticks[i].buttons[CTL_B_BUTTON]); + file.Set(SectionName, "x_button", joysticks[i].buttons[CTL_X_BUTTON]); + file.Set(SectionName, "y_button", joysticks[i].buttons[CTL_Y_BUTTON]); + file.Set(SectionName, "z_trigger", joysticks[i].buttons[CTL_Z_TRIGGER]); + file.Set(SectionName, "start_button", joysticks[i].buttons[CTL_START]); + file.Set(SectionName, "dpad", joysticks[i].dpad); + file.Set(SectionName, "dpad_up", joysticks[i].dpad2[CTL_D_PAD_UP]); + file.Set(SectionName, "dpad_down", joysticks[i].dpad2[CTL_D_PAD_DOWN]); + file.Set(SectionName, "dpad_left", joysticks[i].dpad2[CTL_D_PAD_LEFT]); + file.Set(SectionName, "dpad_right", joysticks[i].dpad2[CTL_D_PAD_RIGHT]); + file.Set(SectionName, "main_x", joysticks[i].axis[CTL_MAIN_X]); + file.Set(SectionName, "main_y", joysticks[i].axis[CTL_MAIN_Y]); + file.Set(SectionName, "sub_x", joysticks[i].axis[CTL_SUB_X]); + file.Set(SectionName, "sub_y", joysticks[i].axis[CTL_SUB_Y]); + file.Set(SectionName, "enabled", joysticks[i].enabled); + file.Set(SectionName, "deadzone", joysticks[i].deadzone); + file.Set(SectionName, "halfpress", joysticks[i].halfpress); + file.Set(SectionName, "joy_id", joysticks[i].ID); + file.Set(SectionName, "controllertype", joysticks[i].controllertype); + file.Set(SectionName, "eventnum", joysticks[i].eventnum); + } + + file.Save("nJoy.ini"); +} + +// Load settings from file +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void LoadConfig() +{ + IniFile file; + file.Load("nJoy.ini"); + + for (int i=0; i<4; i++) + { + char SectionName[32]; + sprintf(SectionName, "PAD%i", i+1); + + file.Get(SectionName, "l_shoulder", &joysticks[i].buttons[CTL_L_SHOULDER], 4); + file.Get(SectionName, "r_shoulder", &joysticks[i].buttons[CTL_R_SHOULDER], 5); + file.Get(SectionName, "a_button", &joysticks[i].buttons[CTL_A_BUTTON], 0); + file.Get(SectionName, "b_button", &joysticks[i].buttons[CTL_B_BUTTON], 1); + file.Get(SectionName, "x_button", &joysticks[i].buttons[CTL_X_BUTTON], 3); + file.Get(SectionName, "y_button", &joysticks[i].buttons[CTL_Y_BUTTON], 2); + file.Get(SectionName, "z_trigger", &joysticks[i].buttons[CTL_Z_TRIGGER], 7); + file.Get(SectionName, "start_button", &joysticks[i].buttons[CTL_START], 9); + file.Get(SectionName, "dpad", &joysticks[i].dpad, 0); + file.Get(SectionName, "dpad_up", &joysticks[i].dpad2[CTL_D_PAD_UP], 0); + file.Get(SectionName, "dpad_down", &joysticks[i].dpad2[CTL_D_PAD_DOWN], 0); + file.Get(SectionName, "dpad_left", &joysticks[i].dpad2[CTL_D_PAD_LEFT], 0); + file.Get(SectionName, "dpad_right", &joysticks[i].dpad2[CTL_D_PAD_RIGHT], 0); + file.Get(SectionName, "main_x", &joysticks[i].axis[CTL_MAIN_X], 0); + file.Get(SectionName, "main_y", &joysticks[i].axis[CTL_MAIN_Y], 1); + file.Get(SectionName, "sub_x", &joysticks[i].axis[CTL_SUB_X], 2); + file.Get(SectionName, "sub_y", &joysticks[i].axis[CTL_SUB_Y], 3); + file.Get(SectionName, "enabled", &joysticks[i].enabled, 1); + file.Get(SectionName, "deadzone", &joysticks[i].deadzone, 9); + file.Get(SectionName, "halfpress", &joysticks[i].halfpress, 6); + file.Get(SectionName, "joy_id", &joysticks[i].ID, 0); + file.Get(SectionName, "controllertype", &joysticks[i].controllertype, 0); + file.Get(SectionName, "eventnum", &joysticks[i].eventnum, 0); + } +} + + +#ifdef _WIN32 +////////////////////////////////////////////////////////////////////////////////////////// +// Rumble stuff :D! +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +// +#ifdef USE_RUMBLE_DINPUT_HACK +HRESULT InitDirectInput( HWND hDlg ) +{ + DIPROPDWORD dipdw; + HRESULT hr; + + // Register with the DirectInput subsystem and get a pointer to a IDirectInput interface we can use. + if(FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&g_pDI, NULL))) + { + return hr; + } + + // Look for a force feedback device we can use + if(FAILED(hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, EnumFFDevicesCallback, NULL, DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK))) + { + return hr; + } + + if(NULL == g_pDevice) + { + MessageBox(NULL, "Force feedback device not found. nJoy will now disable rumble." ,"FFConst" , MB_ICONERROR | MB_OK); + g_rumbleEnable = FALSE; + + return S_OK; + } + + // Set the data format to "simple joystick" - a predefined data format. A + // data format specifies which controls on a device we are interested in, + // and how they should be reported. + // + // This tells DirectInput that we will be passing a DIJOYSTATE structure to + // IDirectInputDevice8::GetDeviceState(). Even though we won't actually do + // it in this sample. But setting the data format is important so that the + // DIJOFS_* values work properly. + if(FAILED(hr = g_pDevice->SetDataFormat(&c_dfDIJoystick))) + return hr; + + // Set the cooperative level to let DInput know how this device should + // interact with the system and with other DInput applications. + // Exclusive access is required in order to perform force feedback. + //if(FAILED(hr = g_pDevice->SetCooperativeLevel(hDlg, DISCL_EXCLUSIVE | DISCL_FOREGROUND))) + + if(FAILED(hr = g_pDevice->SetCooperativeLevel(hDlg, DISCL_EXCLUSIVE | DISCL_FOREGROUND))) + { + return hr; + } + + // Since we will be playing force feedback effects, we should disable the + // auto-centering spring. + dipdw.diph.dwSize = sizeof(DIPROPDWORD); + dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); + dipdw.diph.dwObj = 0; + dipdw.diph.dwHow = DIPH_DEVICE; + dipdw.dwData = FALSE; + + if(FAILED(hr = g_pDevice->SetProperty(DIPROP_AUTOCENTER, &dipdw.diph))) + return hr; + + // Enumerate and count the axes of the joystick + if(FAILED(hr = g_pDevice->EnumObjects(EnumAxesCallback, (VOID*)&g_dwNumForceFeedbackAxis, DIDFT_AXIS))) + return hr; + + // This simple sample only supports one or two axis joysticks + if(g_dwNumForceFeedbackAxis > 2) + g_dwNumForceFeedbackAxis = 2; + + // This application needs only one effect: Applying raw forces. + DWORD rgdwAxes[2] = {DIJOFS_X, DIJOFS_Y}; + LONG rglDirection[2] = {0, 0}; + DICONSTANTFORCE cf = {0}; + + DIEFFECT eff; + ZeroMemory(&eff, sizeof(eff)); + eff.dwSize = sizeof(DIEFFECT); + eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; + eff.dwDuration = INFINITE; + eff.dwSamplePeriod = 0; + eff.dwGain = DI_FFNOMINALMAX; + eff.dwTriggerButton = DIEB_NOTRIGGER; + eff.dwTriggerRepeatInterval = 0; + eff.cAxes = g_dwNumForceFeedbackAxis; + eff.rgdwAxes = rgdwAxes; + eff.rglDirection = rglDirection; + eff.lpEnvelope = 0; + eff.cbTypeSpecificParams = sizeof( DICONSTANTFORCE ); + eff.lpvTypeSpecificParams = &cf; + eff.dwStartDelay = 0; + + // Create the prepared effect + if(FAILED(hr = g_pDevice->CreateEffect(GUID_ConstantForce, &eff, &g_pEffect, NULL))) + { + return hr; + } + + if(NULL == g_pEffect) + return E_FAIL; + + return S_OK; +} + +VOID FreeDirectInput() +{ + // Unacquire the device one last time just in case + // the app tried to exit while the device is still acquired. + if(g_pDevice) + g_pDevice->Unacquire(); + + // Release any DirectInput objects. + SAFE_RELEASE(g_pEffect); + SAFE_RELEASE(g_pDevice); + SAFE_RELEASE(g_pDI); +} + +BOOL CALLBACK EnumFFDevicesCallback( const DIDEVICEINSTANCE* pInst, VOID* pContext ) +{ + LPDIRECTINPUTDEVICE8 pDevice; + HRESULT hr; + + // Obtain an interface to the enumerated force feedback device. + hr = g_pDI->CreateDevice(pInst->guidInstance, &pDevice, NULL); + + // If it failed, then we can't use this device for some bizarre reason. + // (Maybe the user unplugged it while we were in the middle of enumerating it.) So continue enumerating + if( FAILED(hr)) + return DIENUM_CONTINUE; + + // We successfully created an IDirectInputDevice8. So stop looking for another one. + g_pDevice = pDevice; + + return DIENUM_STOP; +} + +BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext) +{ + DWORD* pdwNumForceFeedbackAxis = (DWORD*)pContext; + if((pdidoi->dwFlags & DIDOI_FFACTUATOR) != 0) + (*pdwNumForceFeedbackAxis)++; + + return DIENUM_CONTINUE; +} + +HRESULT SetDeviceForcesXY() +{ + // Modifying an effect is basically the same as creating a new one, except you need only specify the parameters you are modifying + LONG rglDirection[2] = { 0, 0 }; + + DICONSTANTFORCE cf; + + if( g_dwNumForceFeedbackAxis == 1 ) + { + // If only one force feedback axis, then apply only one direction and keep the direction at zero + cf.lMagnitude = g_nXForce; + rglDirection[0] = 0; + } + else + { + // If two force feedback axis, then apply magnitude from both directions + rglDirection[0] = g_nXForce; + rglDirection[1] = g_nYForce; + cf.lMagnitude = (DWORD)sqrt((double)g_nXForce * (double)g_nXForce + (double)g_nYForce * (double)g_nYForce ); + } + + DIEFFECT eff; + ZeroMemory(&eff, sizeof(eff)); + eff.dwSize = sizeof(DIEFFECT); + eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; + eff.cAxes = g_dwNumForceFeedbackAxis; + eff.rglDirection = rglDirection; + eff.lpEnvelope = 0; + eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE); + eff.lpvTypeSpecificParams = &cf; + eff.dwStartDelay = 0; + + // Now set the new parameters and start the effect immediately. + return g_pEffect->SetParameters(&eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START); +} +#endif +#endif diff --git a/Source/Plugins/Plugin_nJoy_Testing/Src/GUI/AboutBox.cpp b/Source/Plugins/Plugin_nJoy_Testing/Src/GUI/AboutBox.cpp index 667b2675d2..e55e42ca2c 100644 --- a/Source/Plugins/Plugin_nJoy_Testing/Src/GUI/AboutBox.cpp +++ b/Source/Plugins/Plugin_nJoy_Testing/Src/GUI/AboutBox.cpp @@ -1,92 +1,92 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// Project description -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -// Name: nJoy -// Description: A Dolphin Compatible Input Plugin -// -// Author: Falcon4ever (nJoy@falcon4ever.com) -// Site: www.multigesture.net -// Copyright (C) 2003-2008 Dolphin Project. -// -////////////////////////////////////////////////////////////////////////////////////////// -// -// Licensetype: GNU General Public License (GPL) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. -// -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ -// -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ -// -////////////////////////////////////////////////////////////////////////////////////////// - -#include "AboutBox.h" -#include "../nJoy.h" -#include "Images/njoy.xpm" - - -BEGIN_EVENT_TABLE(AboutBox,wxDialog) - EVT_CLOSE(AboutBox::OnClose) - EVT_BUTTON(ID_OK, AboutBox::OKClick) -END_EVENT_TABLE() - -AboutBox::AboutBox(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) -: wxDialog(parent, id, title, position, size, style) -{ - CreateGUIControls(); -} - -AboutBox::~AboutBox() -{ - // empty -} - -void AboutBox::CreateGUIControls() -{ - SetTitle(wxT("About: nJoy Input Plugin")); - SetIcon(wxNullIcon); - //SetSize(8,8,200,399); - SetClientSize(200,376); - Center(); - -#ifndef _WIN32 - // Force a 8pt font so that it looks more or less "correct" regardless of the default font setting - wxFont f(8,wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL); - SetFont(f); -#endif - - m_thankyoutext = new wxStaticText(this, ID_THANKYOU, wxT(THANKYOU), wxPoint(18,196), wxDefaultSize, 0, wxT(THANKYOU)); - m_thankyoutext->Wrap(167); - m_specialthanks = new wxStaticText(this, ID_SPECIALTHANKS, wxT("F|RES and ector."), wxPoint(18,153), wxDefaultSize, 0, wxT("F|RES and ector.")); - m_pluginversion = new wxStaticText(this, ID_PLUGINVERSION, wxT("nJoy v"INPUT_VERSION" by Falcon4ever\n" "Release: "RELDAY"/"RELMONTH"/"RELYEAR"\n" "www.multigesture.net"), wxPoint(18,80), wxDefaultSize, 0, wxT("nJoy v"INPUT_VERSION" by Falcon4ever\n" "Release: "RELDAY"/"RELMONTH"/"RELYEAR"\n" "www.multigesture.net")); - m_OK = new wxButton(this, ID_OK, wxT("OK"), wxPoint(116,343), wxSize(75,25), 0, wxDefaultValidator, wxT("OK")); - m_version = new wxStaticText(this, ID_STATUSV, wxT("PUBLIC RELEASE"), wxPoint(14,349), wxDefaultSize, 0, wxT("PUBLIC RELEASE")); - m_thankyougroup = new wxStaticBox(this, IDG_THANKYOU, wxT("Greetings to:"), wxPoint(10,180), wxSize(180,160)); - m_specialthanksgroup = new wxStaticBox(this, IDG_SPECIALTHANKS, wxT("Special thanks to:"), wxPoint(10,135), wxSize(180,39)); - m_pluginversiongroup = new wxStaticBox(this, IDG_PLUGINVERSION, wxT("Plugin info:"), wxPoint(10,61), wxSize(180,68)); - - wxBitmap WxStaticBitmap1_BITMAP(AboutBox_WxStaticBitmap1_XPM); - m_njoylogo = new wxStaticBitmap(this, ID_AWESOMEPICTURE, WxStaticBitmap1_BITMAP, wxPoint(-1,-2), wxSize(200,60)); -} - -void AboutBox::OnClose(wxCloseEvent& /*event*/) -{ - EndModal(0); -} - -void AboutBox::OKClick(wxCommandEvent& event) -{ - if (event.GetId() == ID_OK) - { - Close(); - } -} +////////////////////////////////////////////////////////////////////////////////////////// +// Project description +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +// Name: nJoy +// Description: A Dolphin Compatible Input Plugin +// +// Author: Falcon4ever (nJoy@falcon4ever.com) +// Site: www.multigesture.net +// Copyright (C) 2003-2008 Dolphin Project. +// +////////////////////////////////////////////////////////////////////////////////////////// +// +// Licensetype: GNU General Public License (GPL) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. +// +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ +// +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +// +////////////////////////////////////////////////////////////////////////////////////////// + +#include "AboutBox.h" +#include "../nJoy.h" +#include "Images/njoy.xpm" + + +BEGIN_EVENT_TABLE(AboutBox,wxDialog) + EVT_CLOSE(AboutBox::OnClose) + EVT_BUTTON(ID_OK, AboutBox::OKClick) +END_EVENT_TABLE() + +AboutBox::AboutBox(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) +: wxDialog(parent, id, title, position, size, style) +{ + CreateGUIControls(); +} + +AboutBox::~AboutBox() +{ + // empty +} + +void AboutBox::CreateGUIControls() +{ + SetTitle(wxT("About: nJoy Input Plugin")); + SetIcon(wxNullIcon); + //SetSize(8,8,200,399); + SetClientSize(200,376); + Center(); + +#ifndef _WIN32 + // Force a 8pt font so that it looks more or less "correct" regardless of the default font setting + wxFont f(8,wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL); + SetFont(f); +#endif + + m_thankyoutext = new wxStaticText(this, ID_THANKYOU, wxT(THANKYOU), wxPoint(18,196), wxDefaultSize, 0, wxT(THANKYOU)); + m_thankyoutext->Wrap(167); + m_specialthanks = new wxStaticText(this, ID_SPECIALTHANKS, wxT("F|RES and ector."), wxPoint(18,153), wxDefaultSize, 0, wxT("F|RES and ector.")); + m_pluginversion = new wxStaticText(this, ID_PLUGINVERSION, wxT("nJoy v"INPUT_VERSION" by Falcon4ever\n" "Release: "RELDAY"/"RELMONTH"/"RELYEAR"\n" "www.multigesture.net"), wxPoint(18,80), wxDefaultSize, 0, wxT("nJoy v"INPUT_VERSION" by Falcon4ever\n" "Release: "RELDAY"/"RELMONTH"/"RELYEAR"\n" "www.multigesture.net")); + m_OK = new wxButton(this, ID_OK, wxT("OK"), wxPoint(116,343), wxSize(75,25), 0, wxDefaultValidator, wxT("OK")); + m_version = new wxStaticText(this, ID_STATUSV, wxT("PUBLIC RELEASE"), wxPoint(14,349), wxDefaultSize, 0, wxT("PUBLIC RELEASE")); + m_thankyougroup = new wxStaticBox(this, IDG_THANKYOU, wxT("Greetings to:"), wxPoint(10,180), wxSize(180,160)); + m_specialthanksgroup = new wxStaticBox(this, IDG_SPECIALTHANKS, wxT("Special thanks to:"), wxPoint(10,135), wxSize(180,39)); + m_pluginversiongroup = new wxStaticBox(this, IDG_PLUGINVERSION, wxT("Plugin info:"), wxPoint(10,61), wxSize(180,68)); + + wxBitmap WxStaticBitmap1_BITMAP(AboutBox_WxStaticBitmap1_XPM); + m_njoylogo = new wxStaticBitmap(this, ID_AWESOMEPICTURE, WxStaticBitmap1_BITMAP, wxPoint(-1,-2), wxSize(200,60)); +} + +void AboutBox::OnClose(wxCloseEvent& /*event*/) +{ + EndModal(0); +} + +void AboutBox::OKClick(wxCommandEvent& event) +{ + if (event.GetId() == ID_OK) + { + Close(); + } +} diff --git a/Source/Plugins/Plugin_nJoy_Testing/Src/GUI/ConfigBox.cpp b/Source/Plugins/Plugin_nJoy_Testing/Src/GUI/ConfigBox.cpp index e5aca13a7d..b96dda8866 100644 --- a/Source/Plugins/Plugin_nJoy_Testing/Src/GUI/ConfigBox.cpp +++ b/Source/Plugins/Plugin_nJoy_Testing/Src/GUI/ConfigBox.cpp @@ -1,759 +1,759 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// Project description -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -// Name: nJoy -// Description: A Dolphin Compatible Input Plugin -// -// Author: Falcon4ever (nJoy@falcon4ever.com) -// Site: www.multigesture.net -// Copyright (C) 2003-2008 Dolphin Project. -// -////////////////////////////////////////////////////////////////////////////////////////// -// -// Licensetype: GNU General Public License (GPL) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. -// -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ -// -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ -// -////////////////////////////////////////////////////////////////////////////////////////// - -#include "ConfigBox.h" -#include "../nJoy.h" -#include "Images/controller.xpm" - -extern CONTROLLER_INFO *joyinfo; -extern CONTROLLER_MAPPING joysticks[4]; -extern bool emulator_running; - -static const char* ControllerType[] = -{ - "Joystick (default)", - "Joystick (no hat)", -// "Joytstick (xbox360)", // Shoulder buttons -> axis -// "Keyboard" // Not supported yet, sorry F|RES ;( ... -}; - -BEGIN_EVENT_TABLE(ConfigBox,wxDialog) - EVT_CLOSE(ConfigBox::OnClose) - EVT_BUTTON(ID_ABOUT, ConfigBox::AboutClick) - EVT_BUTTON(ID_OK, ConfigBox::OKClick) - EVT_BUTTON(ID_CANCEL, ConfigBox::CancelClick) - EVT_COMBOBOX(IDC_JOYNAME, ConfigBox::ChangeJoystick) - EVT_COMBOBOX(IDC_CONTROLTYPE, ConfigBox::ChangeControllertype) - EVT_NOTEBOOK_PAGE_CHANGED(ID_NOTEBOOK, ConfigBox::NotebookPageChanged) - - EVT_BUTTON(IDB_SHOULDER_L, ConfigBox::GetInputs) - EVT_BUTTON(IDB_SHOULDER_R, ConfigBox::GetInputs) - EVT_BUTTON(IDB_BUTTON_A, ConfigBox::GetInputs) - EVT_BUTTON(IDB_BUTTON_B, ConfigBox::GetInputs) - EVT_BUTTON(IDB_BUTTON_X, ConfigBox::GetInputs) - EVT_BUTTON(IDB_BUTTON_Y, ConfigBox::GetInputs) - EVT_BUTTON(IDB_BUTTON_Z, ConfigBox::GetInputs) - EVT_BUTTON(IDB_BUTTONSTART, ConfigBox::GetInputs) - EVT_BUTTON(ID_BUTTONCALIBRATE, ConfigBox::Calibrate) - EVT_BUTTON(IDB_BUTTONHALFPRESS, ConfigBox::GetInputs) - EVT_BUTTON(IDB_DPAD_UP, ConfigBox::GetInputs) - EVT_BUTTON(IDB_DPAD_DOWN, ConfigBox::GetInputs) - EVT_BUTTON(IDB_DPAD_LEFT, ConfigBox::GetInputs) - EVT_BUTTON(IDB_DPAD_RIGHT, ConfigBox::GetInputs) - - EVT_BUTTON(IDB_ANALOG_MAIN_X, ConfigBox::GetInputs) - EVT_BUTTON(IDB_ANALOG_MAIN_Y, ConfigBox::GetInputs) - EVT_BUTTON(IDB_ANALOG_SUB_X, ConfigBox::GetInputs) - EVT_BUTTON(IDB_ANALOG_SUB_Y, ConfigBox::GetInputs) -END_EVENT_TABLE() - -ConfigBox::ConfigBox(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) -: wxDialog(parent, id, title, position, size, style) -{ - notebookpage = 0; - CreateGUIControls(); -} - -ConfigBox::~ConfigBox() -{ - // empty -} - -// Warning: horrible code below proceed at own risk! -void ConfigBox::CreateGUIControls() -{ - #ifndef _DEBUG - SetTitle(wxT("Configure: nJoy v"INPUT_VERSION" Input Plugin")); - #else - SetTitle(wxT("Configure: nJoy v"INPUT_VERSION" (Debug) Input Plugin")); - #endif - - SetIcon(wxNullIcon); - SetClientSize(637, 527); - Center(); - -#ifndef _WIN32 - // Force a 8pt font so that it looks more or less "correct" regardless of the default font setting - wxFont f(8,wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL); - SetFont(f); -#endif - - // Buttons - m_About = new wxButton(this, ID_ABOUT, wxT("About"), wxPoint(5, 497), wxSize(75, 25), 0, wxDefaultValidator, wxT("About")); - m_OK = new wxButton(this, ID_OK, wxT("OK"), wxPoint(475, 497), wxSize(75, 25), 0, wxDefaultValidator, wxT("OK")); - m_Cancel = new wxButton(this, ID_CANCEL, wxT("Cancel"), wxPoint(556, 497), wxSize(75, 25), 0, wxDefaultValidator, wxT("Cancel")); - - // Notebook - m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxPoint(6, 7),wxSize(625, 484)); - - // Controller pages - m_Controller[0] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE1, wxPoint(0, 0), wxSize(600, 400)); - m_Notebook->AddPage(m_Controller[0], wxT("Controller 1")); - m_Controller[1] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE2, wxPoint(0, 0), wxSize(600, 400)); - m_Notebook->AddPage(m_Controller[1], wxT("Controller 2")); - m_Controller[2] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE3, wxPoint(0, 0), wxSize(600, 400)); - m_Notebook->AddPage(m_Controller[2], wxT("Controller 3")); - m_Controller[3] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE4, wxPoint(0, 0), wxSize(600, 400)); - m_Notebook->AddPage(m_Controller[3], wxT("Controller 4")); - - // Add controls - wxArrayString arrayStringFor_Joyname; - wxArrayString arrayStringFor_Controltype; - wxArrayString arrayStringFor_Deadzone; - - // Search for devices and add the to the device list - if(Search_Devices()) - { - for(int x = 0; x < SDL_NumJoysticks(); x++) - { - arrayStringFor_Joyname.Add(wxString::FromAscii(joyinfo[x].Name)); - } - } - else - { - arrayStringFor_Joyname.Add(wxString::FromAscii("No Joystick detected!")); - } - - arrayStringFor_Controltype.Add(wxString::FromAscii(ControllerType[CTL_TYPE_JOYSTICK])); - arrayStringFor_Controltype.Add(wxString::FromAscii(ControllerType[CTL_TYPE_JOYSTICK_NO_HAT])); - // arrayStringFor_Controltype.Add(wxString::FromAscii(ControllerType[CTL_TYPE_JOYSTICK_XBOX360])); - // arrayStringFor_Controltype.Add(wxString::FromAscii(ControllerType[CTL_TYPE_KEYBOARD])); - - char buffer [8]; - for(int x = 1; x <= 100; x++) - { - sprintf (buffer, "%d %%", x); - arrayStringFor_Deadzone.Add(wxString::FromAscii(buffer)); - } - - wxBitmap WxStaticBitmap1_BITMAP(ConfigBox_WxStaticBitmap1_XPM); - - for(int i=0; i<4 ;i++) - { - - // Groups - m_gJoyname[i] = new wxStaticBox(m_Controller[i], IDG_JOYSTICK, wxT("Controller:"), wxPoint(5, 11), wxSize(608, 46)); - - #ifdef _WIN32 - m_Joyattach[i] = new wxCheckBox(m_Controller[i], IDC_JOYATTACH, wxT("Controller attached"), wxPoint(495, 26), wxSize(109, 25), 0, wxDefaultValidator, wxT("Controller attached")); - m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, wxEmptyString, wxPoint(12, 29), wxSize(476, 21), arrayStringFor_Joyname, 0, wxDefaultValidator, wxT("m_Joyname")); - m_gExtrasettings[i] = new wxStaticBox(m_Controller[i], IDG_EXTRASETTINGS, wxT("Extra settings:"), wxPoint(104, 385), wxSize(155, 69)); - m_Deadzone[i] = new wxComboBox(m_Controller[i], IDC_DEADZONE, wxEmptyString, wxPoint(167, 400), wxSize(59, 21), arrayStringFor_Deadzone, 0, wxDefaultValidator, wxT("m_Deadzone")); - m_gControllertype[i] = new wxStaticBox(m_Controller[i], IDG_CONTROLLERTYPE, wxT("Controller type:"), wxPoint(359, 383), wxSize(143, 44)); - m_Controltype[i] = new wxComboBox(m_Controller[i], IDC_CONTROLTYPE, wxEmptyString, wxPoint(366, 401), wxSize(131, 21), arrayStringFor_Controltype, 0, wxDefaultValidator, wxT("m_Controltype")); - #else - m_Joyattach[i] = new wxCheckBox(m_Controller[i], IDC_JOYATTACH, wxT("Controller attached"), wxPoint(470, 26), wxSize(140, 25), 0, wxDefaultValidator, wxT("Controller attached")); - m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, wxEmptyString, wxPoint(10, 25), wxSize(450, 25), arrayStringFor_Joyname, 0, wxDefaultValidator, wxT("m_Joyname")); - m_gExtrasettings[i] = new wxStaticBox(m_Controller[i], IDG_EXTRASETTINGS, wxT("Extra settings:"), wxPoint(100, 385), wxSize(155, 65)); - m_Deadzone[i] = new wxComboBox(m_Controller[i], IDC_DEADZONE, wxEmptyString, wxPoint(167, 398), wxSize(80, 25), arrayStringFor_Deadzone, 0, wxDefaultValidator, wxT("m_Deadzone")); - m_gControllertype[i] = new wxStaticBox(m_Controller[i], IDG_CONTROLLERTYPE, wxT("Controller type:"), wxPoint(359, 383), wxSize(160, 44)); - m_Controltype[i] = new wxComboBox(m_Controller[i], IDC_CONTROLTYPE, wxEmptyString, wxPoint(364, 396), wxSize(150, 25), arrayStringFor_Controltype, 0, wxDefaultValidator, wxT("m_Controltype")); - #endif - - // GUI left side buttons - m_JoyShoulderL[i] = new wxTextCtrl(m_Controller[i], ID_SHOULDER_L, wxT("0"), wxPoint(6, 80), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyShoulderL[i]->Enable(false); - m_JoyAnalogMainX[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_MAIN_X, wxT("0"), wxPoint(6, 218), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyAnalogMainX[i]->Enable(false); - m_JoyAnalogMainY[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_MAIN_Y, wxT("0"), wxPoint(6, 255), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyAnalogMainY[i]->Enable(false); - m_JoyDpadUp[i] = new wxTextCtrl(m_Controller[i], ID_DPAD_UP, wxT("0"), wxPoint(6, 296), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyDpadUp[i]->Enable(false); - m_JoyDpadDown[i] = new wxTextCtrl(m_Controller[i], ID_DPAD_DOWN, wxT("0"), wxPoint(6, 333), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyDpadDown[i]->Enable(false); - m_JoyDpadLeft[i] = new wxTextCtrl(m_Controller[i], ID_DPAD_LEFT, wxT("0"), wxPoint(6, 369), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyDpadLeft[i]->Enable(false); - m_JoyDpadRight[i] = new wxTextCtrl(m_Controller[i], ID_DPAD_RIGHT, wxT("0"), wxPoint(6, 406), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyDpadRight[i]->Enable(false); - m_bJoyShoulderL[i] = new wxButton(m_Controller[i], IDB_SHOULDER_L, wxEmptyString, wxPoint(70, 82), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyAnalogMainX[i] = new wxButton(m_Controller[i], IDB_ANALOG_MAIN_X, wxEmptyString, wxPoint(70, 220), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyAnalogMainY[i] = new wxButton(m_Controller[i], IDB_ANALOG_MAIN_Y, wxEmptyString, wxPoint(70, 257), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyDpadUp[i] = new wxButton(m_Controller[i], IDB_DPAD_UP, wxEmptyString, wxPoint(70, 298), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyDpadDown[i] = new wxButton(m_Controller[i], IDB_DPAD_DOWN, wxEmptyString, wxPoint(70, 335), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyDpadLeft[i] = new wxButton(m_Controller[i], IDB_DPAD_LEFT, wxEmptyString, wxPoint(70, 371), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyDpadRight[i] = new wxButton(m_Controller[i], IDB_DPAD_RIGHT, wxEmptyString, wxPoint(70, 408), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - - m_textMainX[i] = new wxStaticText(m_Controller[i], IDT_ANALOG_MAIN_X, wxT("X-axis"), wxPoint(6, 204), wxDefaultSize, 0, wxT("X-axis")); - m_textMainY[i] = new wxStaticText(m_Controller[i], IDT_ANALOG_MAIN_Y, wxT("Y-axis"), wxPoint(6, 241), wxDefaultSize, 0, wxT("Y-axis")); - m_textDpadUp[i] = new wxStaticText(m_Controller[i], IDT_DPAD_UP, wxT("Up"), wxPoint(6, 282), wxDefaultSize, 0, wxT("Up")); - m_textDpadDown[i] = new wxStaticText(m_Controller[i], IDT_DPAD_DOWN, wxT("Down"), wxPoint(6, 319), wxDefaultSize, 0, wxT("Down")); - m_textDpadLeft[i] = new wxStaticText(m_Controller[i], IDT_DPAD_LEFT, wxT("Left"), wxPoint(6, 354), wxDefaultSize, 0, wxT("Left")); - m_textDpadRight[i] = new wxStaticText(m_Controller[i], IDT_DPAD_RIGHT, wxT("Right"), wxPoint(6, 391), wxDefaultSize, 0, wxT("Right")); - - // GUI right side buttons - m_JoyShoulderR[i] = new wxTextCtrl(m_Controller[i], ID_SHOULDER_R, wxT("0"), wxPoint(552, 106), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyShoulderR[i]->Enable(false); - m_JoyButtonA[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_A, wxT("0"), wxPoint(552, 280), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyButtonA[i]->Enable(false); - m_JoyButtonB[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_B, wxT("0"), wxPoint(552, 80), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyButtonB[i]->Enable(false); - m_JoyButtonX[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_X, wxT("0"), wxPoint(552, 242), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyButtonX[i]->Enable(false); - m_JoyButtonY[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_Y, wxT("0"), wxPoint(552, 171), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyButtonY[i]->Enable(false); - m_JoyButtonZ[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_Z, wxT("0"), wxPoint(552, 145), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyButtonZ[i]->Enable(false); - m_JoyAnalogSubX[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_SUB_X, wxT("0"), wxPoint(552, 351), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyAnalogSubX[i]->Enable(false); - m_JoyAnalogSubY[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_SUB_Y, wxT("0"), wxPoint(552, 388), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyAnalogSubY[i]->Enable(false); - m_bJoyShoulderR[i] = new wxButton(m_Controller[i], IDB_SHOULDER_R, wxEmptyString, wxPoint(526, 108), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyButtonA[i] = new wxButton(m_Controller[i], IDB_BUTTON_A, wxEmptyString, wxPoint(526, 282), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyButtonB[i] = new wxButton(m_Controller[i], IDB_BUTTON_B, wxEmptyString, wxPoint(526, 82), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyButtonX[i] = new wxButton(m_Controller[i], IDB_BUTTON_X, wxEmptyString, wxPoint(526, 244), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyButtonY[i] = new wxButton(m_Controller[i], IDB_BUTTON_Y, wxEmptyString, wxPoint(526, 173), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyButtonZ[i] = new wxButton(m_Controller[i], IDB_BUTTON_Z, wxEmptyString, wxPoint(526, 147), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyAnalogSubX[i] = new wxButton(m_Controller[i], IDB_ANALOG_SUB_X, wxEmptyString, wxPoint(526, 353), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyAnalogSubY[i] = new wxButton(m_Controller[i], IDB_ANALOG_SUB_Y, wxEmptyString, wxPoint(526, 390), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - - m_textSubX[i] = new wxStaticText(m_Controller[i], IDT_ANALOG_SUB_X, wxT("X-axis"), wxPoint(552, 336), wxDefaultSize, 0, wxT("X-axis")); - m_textSubY[i] = new wxStaticText(m_Controller[i], IDT_ANALOG_SUB_Y, wxT("Y-axis"), wxPoint(552, 373), wxDefaultSize, 0, wxT("Y-axis")); - - // GUI center button - m_JoyButtonStart[i] = new wxTextCtrl(m_Controller[i], ID_BUTTONSTART, wxT("0"), wxPoint(278, 403), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyButtonStart[i]->Enable(false); - m_bJoyButtonCalibrate[i] = new wxButton(m_Controller[i], ID_BUTTONCALIBRATE, wxT("Calibrate"), wxPoint(297, 440), wxSize(21, 14), 0, wxDefaultValidator, wxT("Calibrate")); - m_JoyButtonHalfpress[i] = new wxTextCtrl(m_Controller[i], ID_BUTTONHALFPRESS, wxT("0"), wxPoint(167, 424), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); - m_JoyButtonHalfpress[i]->Enable(false); - m_bJoyButtonStart[i] = new wxButton(m_Controller[i], IDB_BUTTONSTART, wxEmptyString, wxPoint(297, 385), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - m_bJoyButtonHalfpress[i] = new wxButton(m_Controller[i], IDB_BUTTONHALFPRESS, wxEmptyString, wxPoint(231, 426), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); - - #ifdef _WIN32 - m_textDeadzone[i] = new wxStaticText(m_Controller[i], IDT_DEADZONE, wxT("Deadzone"), wxPoint(116, 404), wxDefaultSize, 0, wxT("Deadzone")); - m_textHalfpress[i] = new wxStaticText(m_Controller[i], IDT_BUTTONHALFPRESS, wxT("Half press"), wxPoint(116, 428), wxDefaultSize, 0, wxT("Half press")); - m_textWebsite[i] = new wxStaticText(m_Controller[i], IDT_WEBSITE, wxT("www.multigesture.net"), wxPoint(500, 438), wxDefaultSize, 0, wxT("www.multigesture.net")); - #else - m_textDeadzone[i] = new wxStaticText(m_Controller[i], IDT_DEADZONE, wxT("Deadzone"), wxPoint(105, 404), wxDefaultSize, 0, wxT("Deadzone")); - m_textHalfpress[i] = new wxStaticText(m_Controller[i], IDT_BUTTONHALFPRESS, wxT("Half press"), wxPoint(105, 428), wxDefaultSize, 0, wxT("Half press")); - m_textWebsite[i] = new wxStaticText(m_Controller[i], IDT_WEBSITE, wxT("www.multigesture.net"), wxPoint(480, 438), wxDefaultSize, 0, wxT("www.multigesture.net")); - #endif - - // TODO: Controller image - // Placeholder instead of bitmap - // m_PlaceholderBMP[i] = new wxTextCtrl(m_Controller[i], ID_CONTROLLERPICTURE, wxT("BITMAP HERE PLZ KTHX!"), wxPoint(98, 75), wxSize(423, 306), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("BITMAP HERE PLZ KTHX!")); - // m_PlaceholderBMP[i]->Enable(false); - - // You can enable the bitmap here: - // But it loads überslow on init... (only in windows, linux seems to load it fast!) - // AAaaand the XPM file (256 colours) looks crappier than the real bitmap... so maybe we can find a way to use a bitmap? - m_controllerimage[i] = new wxStaticBitmap(m_Controller[i], ID_CONTROLLERPICTURE, WxStaticBitmap1_BITMAP, wxPoint(98, 75), wxSize(421,304)); - - if(emulator_running) - { - m_Joyname[i]->Enable(false); - m_Joyattach[i]->Enable(false); - m_Controltype[i]->Enable(false); - } - - SetControllerAll(i); - } -} - -void ConfigBox::OnClose(wxCloseEvent& /*event*/) -{ - EndModal(0); -} - -void ConfigBox::AboutClick(wxCommandEvent& event) -{ -// Call about dialog -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -#ifdef _WIN32 - wxWindow win; - win.SetHWND((WXHWND)this->GetHWND()); - win.Enable(false); - - AboutBox frame(&win); - frame.ShowModal(); - - win.Enable(true); - win.SetHWND(0); -#else - AboutBox frame(NULL); - frame.ShowModal(); -#endif -} - -void ConfigBox::OKClick(wxCommandEvent& event) -{ - if (event.GetId() == ID_OK) - { - for(int i=0; i<4 ;i++) - GetControllerAll(i); - SaveConfig(); // save settings - LoadConfig(); // reload settings - Close(); - } -} - -void ConfigBox::CancelClick(wxCommandEvent& event) -{ - if (event.GetId() == ID_CANCEL) - { - LoadConfig(); // reload settings - Close(); - } -} - -void ConfigBox::Calibrate(wxCommandEvent& event) -{ - int controller = notebookpage; - - - SDL_Joystick *joy = SDL_JoystickOpen(joysticks[controller].ID); - int axes = SDL_JoystickNumAxes(joy); - Sint16 value; - unsigned long Started = SDL_GetTicks(); - while(1) - { - for(int b = 0; b < axes; b++) - { - SDL_JoystickUpdate(); - value = SDL_JoystickGetAxis(joy, b); - if(value < joysticks[controller].sData[b].Min) - joysticks[controller].sData[b].Min = value; - if(value > joysticks[controller].sData[b].Max) - joysticks[controller].sData[b].Max = value; - } - if(SDL_GetTicks() - Started >= 5000) - break; - } - for(int a = 0; a < axes;a++) - printf("Axis %d has a Min of %d, and a Max of %d\n", a, joysticks[controller].sData[a].Min, joysticks[controller].sData[a].Max); - if(SDL_JoystickOpened(joysticks[controller].ID)) - SDL_JoystickClose(joy); -} -// Set dialog items -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void ConfigBox::SetControllerAll(int controller) -{ - // http://wiki.wxwidgets.org/Converting_everything_to_and_from_wxString - wxString tmp; - m_Joyname[controller]->SetSelection(joysticks[controller].ID); - - m_JoyShoulderL[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_L_SHOULDER].c_str())); - m_JoyShoulderR[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_R_SHOULDER].c_str())); - - m_JoyButtonA[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_A_BUTTON].c_str())); - m_JoyButtonB[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_B_BUTTON].c_str())); - m_JoyButtonX[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_X_BUTTON].c_str())); - m_JoyButtonY[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_Y_BUTTON].c_str())); - m_JoyButtonZ[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_Z_TRIGGER].c_str())); - - m_JoyButtonStart[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_START].c_str())); - tmp << joysticks[controller].halfpress; m_JoyButtonHalfpress[controller]->SetValue(tmp); tmp.clear(); - - m_JoyAnalogMainX[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_MAIN_X].c_str())); - m_JoyAnalogMainY[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_MAIN_Y].c_str())); - m_JoyAnalogSubX[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_SUB_X].c_str())); - m_JoyAnalogSubY[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_SUB_Y].c_str())); - - if(joysticks[controller].enabled) - m_Joyattach[controller]->SetValue(TRUE); - else - m_Joyattach[controller]->SetValue(FALSE); - - m_Controltype[controller]->SetSelection(joysticks[controller].controllertype); - m_Deadzone[controller]->SetSelection(joysticks[controller].deadzone); - - UpdateVisibleItems(controller); - - if(joysticks[controller].controllertype == CTL_TYPE_JOYSTICK) - { - tmp << joysticks[controller].dpad; m_JoyDpadUp[controller]->SetValue(tmp); tmp.clear(); - } - else - { - tmp << joysticks[controller].dpad2[CTL_D_PAD_UP]; m_JoyDpadUp[controller]->SetValue(tmp); tmp.clear(); - tmp << joysticks[controller].dpad2[CTL_D_PAD_DOWN]; m_JoyDpadDown[controller]->SetValue(tmp); tmp.clear(); - tmp << joysticks[controller].dpad2[CTL_D_PAD_LEFT]; m_JoyDpadLeft[controller]->SetValue(tmp); tmp.clear(); - tmp << joysticks[controller].dpad2[CTL_D_PAD_RIGHT]; m_JoyDpadRight[controller]->SetValue(tmp); tmp.clear(); - } -} - -// Get dialog items -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void ConfigBox::GetControllerAll(int controller) -{ - wxString tmp; - long lvalue; - - joysticks[controller].ID = m_Joyname[controller]->GetSelection(); - - joysticks[controller].buttons[CTL_L_SHOULDER] = std::string(m_JoyShoulderL[controller]->GetValue().mb_str()); tmp.clear(); - joysticks[controller].buttons[CTL_R_SHOULDER] = std::string(m_JoyShoulderR[controller]->GetValue().mb_str()); tmp.clear(); - - joysticks[controller].buttons[CTL_A_BUTTON] = std::string(m_JoyButtonA[controller]->GetValue().mb_str()); tmp.clear(); - joysticks[controller].buttons[CTL_B_BUTTON] = std::string(m_JoyButtonB[controller]->GetValue().mb_str()); tmp.clear(); - joysticks[controller].buttons[CTL_X_BUTTON] = std::string(m_JoyButtonX[controller]->GetValue().mb_str()); tmp.clear(); - joysticks[controller].buttons[CTL_Y_BUTTON] = std::string(m_JoyButtonY[controller]->GetValue().mb_str()); tmp.clear(); - joysticks[controller].buttons[CTL_Z_TRIGGER] = std::string(m_JoyButtonZ[controller]->GetValue().mb_str()); tmp.clear(); - joysticks[controller].buttons[CTL_START] = std::string(m_JoyButtonStart[controller]->GetValue().mb_str()); tmp.clear(); - - m_JoyButtonHalfpress[controller]->GetValue().ToLong(&lvalue); joysticks[controller].halfpress = lvalue; tmp.clear(); - - if(joysticks[controller].controllertype == CTL_TYPE_JOYSTICK) - { - m_JoyDpadUp[controller]->GetValue().ToLong(&lvalue); joysticks[controller].dpad = lvalue; tmp.clear(); - } - else - { - m_JoyDpadUp[controller]->GetValue().ToLong(&lvalue); joysticks[controller].dpad2[CTL_D_PAD_UP] = lvalue; tmp.clear(); - m_JoyDpadDown[controller]->GetValue().ToLong(&lvalue); joysticks[controller].dpad2[CTL_D_PAD_DOWN] = lvalue; tmp.clear(); - m_JoyDpadLeft[controller]->GetValue().ToLong(&lvalue); joysticks[controller].dpad2[CTL_D_PAD_LEFT] = lvalue; tmp.clear(); - m_JoyDpadRight[controller]->GetValue().ToLong(&lvalue); joysticks[controller].dpad2[CTL_D_PAD_RIGHT] = lvalue; tmp.clear(); - } - - joysticks[controller].buttons[CTL_MAIN_X] = std::string(m_JoyAnalogMainX[controller]->GetValue().mb_str()); tmp.clear(); - joysticks[controller].buttons[CTL_MAIN_Y] = std::string(m_JoyAnalogMainY[controller]->GetValue().mb_str()); tmp.clear(); - joysticks[controller].buttons[CTL_SUB_X] = std::string(m_JoyAnalogSubX[controller]->GetValue().mb_str()); tmp.clear(); - joysticks[controller].buttons[CTL_SUB_Y] = std::string(m_JoyAnalogSubY[controller]->GetValue().mb_str()); tmp.clear(); - - joysticks[controller].enabled = m_Joyattach[controller]->GetValue(); - - joysticks[controller].controllertype = m_Controltype[controller]->GetSelection(); - joysticks[controller].deadzone = m_Deadzone[controller]->GetSelection(); -} - -void ConfigBox::UpdateVisibleItems(int controller) -{ - if(joysticks[controller].controllertype) - { - m_JoyDpadDown[controller]->Show(TRUE); - m_JoyDpadLeft[controller]->Show(TRUE); - m_JoyDpadRight[controller]->Show(TRUE); - - m_bJoyDpadDown[controller]->Show(TRUE); - m_bJoyDpadLeft[controller]->Show(TRUE); - m_bJoyDpadRight[controller]->Show(TRUE); - - m_textDpadUp[controller]->Show(TRUE); - m_textDpadDown[controller]->Show(TRUE); - m_textDpadLeft[controller]->Show(TRUE); - m_textDpadRight[controller]->Show(TRUE); - } - else - { - m_JoyDpadDown[controller]->Show(FALSE); - m_JoyDpadLeft[controller]->Show(FALSE); - m_JoyDpadRight[controller]->Show(FALSE); - - m_bJoyDpadDown[controller]->Show(FALSE); - m_bJoyDpadLeft[controller]->Show(FALSE); - m_bJoyDpadRight[controller]->Show(FALSE); - - m_textDpadUp[controller]->Show(FALSE); - m_textDpadDown[controller]->Show(FALSE); - m_textDpadLeft[controller]->Show(FALSE); - m_textDpadRight[controller]->Show(FALSE); - } -} - -void ConfigBox::ChangeJoystick(wxCommandEvent& event) -{ - joysticks[0].ID = m_Joyname[0]->GetSelection(); - joysticks[1].ID = m_Joyname[1]->GetSelection(); - joysticks[2].ID = m_Joyname[2]->GetSelection(); - joysticks[3].ID = m_Joyname[3]->GetSelection(); -} - -void ConfigBox::ChangeControllertype(wxCommandEvent& event) -{ - joysticks[0].controllertype = m_Controltype[0]->GetSelection(); - joysticks[1].controllertype = m_Controltype[1]->GetSelection(); - joysticks[2].controllertype = m_Controltype[2]->GetSelection(); - joysticks[3].controllertype = m_Controltype[3]->GetSelection(); - - for(int i=0; i<4 ;i++) - UpdateVisibleItems(i); -} - -void ConfigBox::NotebookPageChanged(wxNotebookEvent& event) -{ - notebookpage = event.GetSelection(); -} - -void ConfigBox::SetButtonText(int id, char text[128]) -{ - int controller = notebookpage; - - switch(id) - { - case IDB_SHOULDER_L: - { - m_JoyShoulderL[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_SHOULDER_R: - { - m_JoyShoulderR[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_BUTTON_A: - { - m_JoyButtonA[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_BUTTON_B: - { - m_JoyButtonB[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_BUTTON_X: - { - m_JoyButtonX[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_BUTTON_Y: - { - m_JoyButtonY[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_BUTTON_Z: - { - m_JoyButtonZ[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_BUTTONSTART: - { - m_JoyButtonStart[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_BUTTONHALFPRESS: - { - m_JoyButtonHalfpress[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_DPAD_UP: - { - m_JoyDpadUp[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_DPAD_DOWN: - { - m_JoyDpadDown[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_DPAD_LEFT: - { - m_JoyDpadLeft[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_DPAD_RIGHT: - { - m_JoyDpadRight[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_ANALOG_MAIN_X: - { - m_JoyAnalogMainX[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_ANALOG_MAIN_Y: - { - m_JoyAnalogMainY[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_ANALOG_SUB_X: - { - m_JoyAnalogSubX[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - case IDB_ANALOG_SUB_Y: - { - m_JoyAnalogSubY[controller]->SetValue(wxString::FromAscii(text)); - } - break; - - default: - break; - } -} -void ConfigBox::GetInputs(wxCommandEvent& event) -{ - int ID = event.GetId(); - int controller = notebookpage; - - // DPAD type check! - if(ID == IDB_DPAD_UP) - if(joysticks[controller].controllertype == 0) - { - GetHats(ID); - return; - } - - SDL_Joystick *joy = SDL_JoystickOpen(joysticks[controller].ID); - - char format[128]; - int buttons = SDL_JoystickNumButtons(joy); - int axes = SDL_JoystickNumAxes(joy); - char type = 'N'; // B, A, H, N = Nan - bool waiting = true; - bool succeed = false; - int pressed = 0; - Sint16 value; - - int counter1 = 0; - int counter2 = 10; - - sprintf(format, "[%d]", counter2); - SetButtonText(ID, format); - wxWindow::Update(); // win only? doesnt seem to work in linux... - - SDL_JoystickUpdate(); - while(waiting) - { - SDL_JoystickUpdate(); - for(int b = 0; b < buttons; b++) - { - if(SDL_JoystickGetButton(joy, b)) - { - pressed = b; - waiting = false; - succeed = true; - type = 'B'; - goto InputEnd; - } - } - for(int b = 0; b < axes; b++) - { - value = SDL_JoystickGetAxis(joy, b); - if(value <= (joysticks[controller].sData[b].Min - (joysticks[controller].sData[b].Min * joysticks[controller].deadzone / 100)) || value >= (joysticks[controller].sData[b].Max - (joysticks[controller].sData[b].Max * joysticks[controller].deadzone / 100))) // Add and subtract a small value - { // It allows for some small jitter - printf("value %d, Min %d Max %d Removal %d\n", value, joysticks[controller].sData[b].Min,joysticks[controller].sData[b].Max, (joysticks[controller].sData[b].Min * joysticks[controller].deadzone / 100)); - value = value <= (joysticks[controller].sData[b].Min - joysticks[controller].sData[b].Min * joysticks[controller].deadzone) ? -1 : 1; // Makes it know if the value is negative or positive - pressed = b; - waiting = false; - succeed = true; - type = 'A'; - goto InputEnd; - } - } -InputEnd: - counter1++; - if(counter1==100) - { - counter1=0; - counter2--; - - sprintf(format, "[%d]", counter2); - SetButtonText(ID, format); - wxWindow::Update(); // win only? doesnt seem to work in linux... - - if(counter2<0) - waiting = false; - } - SLEEP(10); - } - if(type == 'A') - sprintf(format, "%c%c%d" , type, value < 0 ? '-' : '+', succeed ? pressed : -1); - else - sprintf(format, "%c%d" , type, succeed ? pressed : -1); - SetButtonText(ID, format); - - if(SDL_JoystickOpened(joysticks[controller].ID)) - SDL_JoystickClose(joy); -} - -// Wait for D-Pad -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void ConfigBox::GetHats(int ID) -{ - int controller = notebookpage; - - SDL_Joystick *joy; - joy=SDL_JoystickOpen(joysticks[controller].ID); - - char format[128]; - int hats = SDL_JoystickNumHats(joy); - bool waiting = true; - bool succeed = false; - int pressed = 0; - - int counter1 = 0; - int counter2 = 10; - - sprintf(format, "[%d]", counter2); - SetButtonText(ID, format); - wxWindow::Update(); // win only? doesnt seem to work in linux... - - while(waiting) - { - SDL_JoystickUpdate(); - for(int b = 0; b < hats; b++) - { - if(SDL_JoystickGetHat(joy, b)) - { - pressed = b; - waiting = false; - succeed = true; - break; - } - } - - counter1++; - if(counter1==100) - { - counter1=0; - counter2--; - - sprintf(format, "[%d]", counter2); - SetButtonText(ID, format); - wxWindow::Update(); // win only? doesnt seem to work in linux... - - if(counter2<0) - waiting = false; - } - SLEEP(10); - } - - sprintf(format, "H%d", succeed ? pressed : -1); - SetButtonText(ID, format); - - if(SDL_JoystickOpened(joysticks[controller].ID)) - SDL_JoystickClose(joy); -} +////////////////////////////////////////////////////////////////////////////////////////// +// Project description +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +// Name: nJoy +// Description: A Dolphin Compatible Input Plugin +// +// Author: Falcon4ever (nJoy@falcon4ever.com) +// Site: www.multigesture.net +// Copyright (C) 2003-2008 Dolphin Project. +// +////////////////////////////////////////////////////////////////////////////////////////// +// +// Licensetype: GNU General Public License (GPL) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. +// +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ +// +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +// +////////////////////////////////////////////////////////////////////////////////////////// + +#include "ConfigBox.h" +#include "../nJoy.h" +#include "Images/controller.xpm" + +extern CONTROLLER_INFO *joyinfo; +extern CONTROLLER_MAPPING joysticks[4]; +extern bool emulator_running; + +static const char* ControllerType[] = +{ + "Joystick (default)", + "Joystick (no hat)", +// "Joytstick (xbox360)", // Shoulder buttons -> axis +// "Keyboard" // Not supported yet, sorry F|RES ;( ... +}; + +BEGIN_EVENT_TABLE(ConfigBox,wxDialog) + EVT_CLOSE(ConfigBox::OnClose) + EVT_BUTTON(ID_ABOUT, ConfigBox::AboutClick) + EVT_BUTTON(ID_OK, ConfigBox::OKClick) + EVT_BUTTON(ID_CANCEL, ConfigBox::CancelClick) + EVT_COMBOBOX(IDC_JOYNAME, ConfigBox::ChangeJoystick) + EVT_COMBOBOX(IDC_CONTROLTYPE, ConfigBox::ChangeControllertype) + EVT_NOTEBOOK_PAGE_CHANGED(ID_NOTEBOOK, ConfigBox::NotebookPageChanged) + + EVT_BUTTON(IDB_SHOULDER_L, ConfigBox::GetInputs) + EVT_BUTTON(IDB_SHOULDER_R, ConfigBox::GetInputs) + EVT_BUTTON(IDB_BUTTON_A, ConfigBox::GetInputs) + EVT_BUTTON(IDB_BUTTON_B, ConfigBox::GetInputs) + EVT_BUTTON(IDB_BUTTON_X, ConfigBox::GetInputs) + EVT_BUTTON(IDB_BUTTON_Y, ConfigBox::GetInputs) + EVT_BUTTON(IDB_BUTTON_Z, ConfigBox::GetInputs) + EVT_BUTTON(IDB_BUTTONSTART, ConfigBox::GetInputs) + EVT_BUTTON(ID_BUTTONCALIBRATE, ConfigBox::Calibrate) + EVT_BUTTON(IDB_BUTTONHALFPRESS, ConfigBox::GetInputs) + EVT_BUTTON(IDB_DPAD_UP, ConfigBox::GetInputs) + EVT_BUTTON(IDB_DPAD_DOWN, ConfigBox::GetInputs) + EVT_BUTTON(IDB_DPAD_LEFT, ConfigBox::GetInputs) + EVT_BUTTON(IDB_DPAD_RIGHT, ConfigBox::GetInputs) + + EVT_BUTTON(IDB_ANALOG_MAIN_X, ConfigBox::GetInputs) + EVT_BUTTON(IDB_ANALOG_MAIN_Y, ConfigBox::GetInputs) + EVT_BUTTON(IDB_ANALOG_SUB_X, ConfigBox::GetInputs) + EVT_BUTTON(IDB_ANALOG_SUB_Y, ConfigBox::GetInputs) +END_EVENT_TABLE() + +ConfigBox::ConfigBox(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) +: wxDialog(parent, id, title, position, size, style) +{ + notebookpage = 0; + CreateGUIControls(); +} + +ConfigBox::~ConfigBox() +{ + // empty +} + +// Warning: horrible code below proceed at own risk! +void ConfigBox::CreateGUIControls() +{ + #ifndef _DEBUG + SetTitle(wxT("Configure: nJoy v"INPUT_VERSION" Input Plugin")); + #else + SetTitle(wxT("Configure: nJoy v"INPUT_VERSION" (Debug) Input Plugin")); + #endif + + SetIcon(wxNullIcon); + SetClientSize(637, 527); + Center(); + +#ifndef _WIN32 + // Force a 8pt font so that it looks more or less "correct" regardless of the default font setting + wxFont f(8,wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL); + SetFont(f); +#endif + + // Buttons + m_About = new wxButton(this, ID_ABOUT, wxT("About"), wxPoint(5, 497), wxSize(75, 25), 0, wxDefaultValidator, wxT("About")); + m_OK = new wxButton(this, ID_OK, wxT("OK"), wxPoint(475, 497), wxSize(75, 25), 0, wxDefaultValidator, wxT("OK")); + m_Cancel = new wxButton(this, ID_CANCEL, wxT("Cancel"), wxPoint(556, 497), wxSize(75, 25), 0, wxDefaultValidator, wxT("Cancel")); + + // Notebook + m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxPoint(6, 7),wxSize(625, 484)); + + // Controller pages + m_Controller[0] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE1, wxPoint(0, 0), wxSize(600, 400)); + m_Notebook->AddPage(m_Controller[0], wxT("Controller 1")); + m_Controller[1] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE2, wxPoint(0, 0), wxSize(600, 400)); + m_Notebook->AddPage(m_Controller[1], wxT("Controller 2")); + m_Controller[2] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE3, wxPoint(0, 0), wxSize(600, 400)); + m_Notebook->AddPage(m_Controller[2], wxT("Controller 3")); + m_Controller[3] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE4, wxPoint(0, 0), wxSize(600, 400)); + m_Notebook->AddPage(m_Controller[3], wxT("Controller 4")); + + // Add controls + wxArrayString arrayStringFor_Joyname; + wxArrayString arrayStringFor_Controltype; + wxArrayString arrayStringFor_Deadzone; + + // Search for devices and add the to the device list + if(Search_Devices()) + { + for(int x = 0; x < SDL_NumJoysticks(); x++) + { + arrayStringFor_Joyname.Add(wxString::FromAscii(joyinfo[x].Name)); + } + } + else + { + arrayStringFor_Joyname.Add(wxString::FromAscii("No Joystick detected!")); + } + + arrayStringFor_Controltype.Add(wxString::FromAscii(ControllerType[CTL_TYPE_JOYSTICK])); + arrayStringFor_Controltype.Add(wxString::FromAscii(ControllerType[CTL_TYPE_JOYSTICK_NO_HAT])); + // arrayStringFor_Controltype.Add(wxString::FromAscii(ControllerType[CTL_TYPE_JOYSTICK_XBOX360])); + // arrayStringFor_Controltype.Add(wxString::FromAscii(ControllerType[CTL_TYPE_KEYBOARD])); + + char buffer [8]; + for(int x = 1; x <= 100; x++) + { + sprintf (buffer, "%d %%", x); + arrayStringFor_Deadzone.Add(wxString::FromAscii(buffer)); + } + + wxBitmap WxStaticBitmap1_BITMAP(ConfigBox_WxStaticBitmap1_XPM); + + for(int i=0; i<4 ;i++) + { + + // Groups + m_gJoyname[i] = new wxStaticBox(m_Controller[i], IDG_JOYSTICK, wxT("Controller:"), wxPoint(5, 11), wxSize(608, 46)); + + #ifdef _WIN32 + m_Joyattach[i] = new wxCheckBox(m_Controller[i], IDC_JOYATTACH, wxT("Controller attached"), wxPoint(495, 26), wxSize(109, 25), 0, wxDefaultValidator, wxT("Controller attached")); + m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, wxEmptyString, wxPoint(12, 29), wxSize(476, 21), arrayStringFor_Joyname, 0, wxDefaultValidator, wxT("m_Joyname")); + m_gExtrasettings[i] = new wxStaticBox(m_Controller[i], IDG_EXTRASETTINGS, wxT("Extra settings:"), wxPoint(104, 385), wxSize(155, 69)); + m_Deadzone[i] = new wxComboBox(m_Controller[i], IDC_DEADZONE, wxEmptyString, wxPoint(167, 400), wxSize(59, 21), arrayStringFor_Deadzone, 0, wxDefaultValidator, wxT("m_Deadzone")); + m_gControllertype[i] = new wxStaticBox(m_Controller[i], IDG_CONTROLLERTYPE, wxT("Controller type:"), wxPoint(359, 383), wxSize(143, 44)); + m_Controltype[i] = new wxComboBox(m_Controller[i], IDC_CONTROLTYPE, wxEmptyString, wxPoint(366, 401), wxSize(131, 21), arrayStringFor_Controltype, 0, wxDefaultValidator, wxT("m_Controltype")); + #else + m_Joyattach[i] = new wxCheckBox(m_Controller[i], IDC_JOYATTACH, wxT("Controller attached"), wxPoint(470, 26), wxSize(140, 25), 0, wxDefaultValidator, wxT("Controller attached")); + m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, wxEmptyString, wxPoint(10, 25), wxSize(450, 25), arrayStringFor_Joyname, 0, wxDefaultValidator, wxT("m_Joyname")); + m_gExtrasettings[i] = new wxStaticBox(m_Controller[i], IDG_EXTRASETTINGS, wxT("Extra settings:"), wxPoint(100, 385), wxSize(155, 65)); + m_Deadzone[i] = new wxComboBox(m_Controller[i], IDC_DEADZONE, wxEmptyString, wxPoint(167, 398), wxSize(80, 25), arrayStringFor_Deadzone, 0, wxDefaultValidator, wxT("m_Deadzone")); + m_gControllertype[i] = new wxStaticBox(m_Controller[i], IDG_CONTROLLERTYPE, wxT("Controller type:"), wxPoint(359, 383), wxSize(160, 44)); + m_Controltype[i] = new wxComboBox(m_Controller[i], IDC_CONTROLTYPE, wxEmptyString, wxPoint(364, 396), wxSize(150, 25), arrayStringFor_Controltype, 0, wxDefaultValidator, wxT("m_Controltype")); + #endif + + // GUI left side buttons + m_JoyShoulderL[i] = new wxTextCtrl(m_Controller[i], ID_SHOULDER_L, wxT("0"), wxPoint(6, 80), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyShoulderL[i]->Enable(false); + m_JoyAnalogMainX[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_MAIN_X, wxT("0"), wxPoint(6, 218), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyAnalogMainX[i]->Enable(false); + m_JoyAnalogMainY[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_MAIN_Y, wxT("0"), wxPoint(6, 255), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyAnalogMainY[i]->Enable(false); + m_JoyDpadUp[i] = new wxTextCtrl(m_Controller[i], ID_DPAD_UP, wxT("0"), wxPoint(6, 296), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyDpadUp[i]->Enable(false); + m_JoyDpadDown[i] = new wxTextCtrl(m_Controller[i], ID_DPAD_DOWN, wxT("0"), wxPoint(6, 333), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyDpadDown[i]->Enable(false); + m_JoyDpadLeft[i] = new wxTextCtrl(m_Controller[i], ID_DPAD_LEFT, wxT("0"), wxPoint(6, 369), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyDpadLeft[i]->Enable(false); + m_JoyDpadRight[i] = new wxTextCtrl(m_Controller[i], ID_DPAD_RIGHT, wxT("0"), wxPoint(6, 406), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyDpadRight[i]->Enable(false); + m_bJoyShoulderL[i] = new wxButton(m_Controller[i], IDB_SHOULDER_L, wxEmptyString, wxPoint(70, 82), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyAnalogMainX[i] = new wxButton(m_Controller[i], IDB_ANALOG_MAIN_X, wxEmptyString, wxPoint(70, 220), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyAnalogMainY[i] = new wxButton(m_Controller[i], IDB_ANALOG_MAIN_Y, wxEmptyString, wxPoint(70, 257), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyDpadUp[i] = new wxButton(m_Controller[i], IDB_DPAD_UP, wxEmptyString, wxPoint(70, 298), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyDpadDown[i] = new wxButton(m_Controller[i], IDB_DPAD_DOWN, wxEmptyString, wxPoint(70, 335), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyDpadLeft[i] = new wxButton(m_Controller[i], IDB_DPAD_LEFT, wxEmptyString, wxPoint(70, 371), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyDpadRight[i] = new wxButton(m_Controller[i], IDB_DPAD_RIGHT, wxEmptyString, wxPoint(70, 408), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + + m_textMainX[i] = new wxStaticText(m_Controller[i], IDT_ANALOG_MAIN_X, wxT("X-axis"), wxPoint(6, 204), wxDefaultSize, 0, wxT("X-axis")); + m_textMainY[i] = new wxStaticText(m_Controller[i], IDT_ANALOG_MAIN_Y, wxT("Y-axis"), wxPoint(6, 241), wxDefaultSize, 0, wxT("Y-axis")); + m_textDpadUp[i] = new wxStaticText(m_Controller[i], IDT_DPAD_UP, wxT("Up"), wxPoint(6, 282), wxDefaultSize, 0, wxT("Up")); + m_textDpadDown[i] = new wxStaticText(m_Controller[i], IDT_DPAD_DOWN, wxT("Down"), wxPoint(6, 319), wxDefaultSize, 0, wxT("Down")); + m_textDpadLeft[i] = new wxStaticText(m_Controller[i], IDT_DPAD_LEFT, wxT("Left"), wxPoint(6, 354), wxDefaultSize, 0, wxT("Left")); + m_textDpadRight[i] = new wxStaticText(m_Controller[i], IDT_DPAD_RIGHT, wxT("Right"), wxPoint(6, 391), wxDefaultSize, 0, wxT("Right")); + + // GUI right side buttons + m_JoyShoulderR[i] = new wxTextCtrl(m_Controller[i], ID_SHOULDER_R, wxT("0"), wxPoint(552, 106), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyShoulderR[i]->Enable(false); + m_JoyButtonA[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_A, wxT("0"), wxPoint(552, 280), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyButtonA[i]->Enable(false); + m_JoyButtonB[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_B, wxT("0"), wxPoint(552, 80), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyButtonB[i]->Enable(false); + m_JoyButtonX[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_X, wxT("0"), wxPoint(552, 242), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyButtonX[i]->Enable(false); + m_JoyButtonY[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_Y, wxT("0"), wxPoint(552, 171), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyButtonY[i]->Enable(false); + m_JoyButtonZ[i] = new wxTextCtrl(m_Controller[i], ID_BUTTON_Z, wxT("0"), wxPoint(552, 145), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyButtonZ[i]->Enable(false); + m_JoyAnalogSubX[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_SUB_X, wxT("0"), wxPoint(552, 351), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyAnalogSubX[i]->Enable(false); + m_JoyAnalogSubY[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_SUB_Y, wxT("0"), wxPoint(552, 388), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyAnalogSubY[i]->Enable(false); + m_bJoyShoulderR[i] = new wxButton(m_Controller[i], IDB_SHOULDER_R, wxEmptyString, wxPoint(526, 108), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyButtonA[i] = new wxButton(m_Controller[i], IDB_BUTTON_A, wxEmptyString, wxPoint(526, 282), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyButtonB[i] = new wxButton(m_Controller[i], IDB_BUTTON_B, wxEmptyString, wxPoint(526, 82), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyButtonX[i] = new wxButton(m_Controller[i], IDB_BUTTON_X, wxEmptyString, wxPoint(526, 244), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyButtonY[i] = new wxButton(m_Controller[i], IDB_BUTTON_Y, wxEmptyString, wxPoint(526, 173), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyButtonZ[i] = new wxButton(m_Controller[i], IDB_BUTTON_Z, wxEmptyString, wxPoint(526, 147), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyAnalogSubX[i] = new wxButton(m_Controller[i], IDB_ANALOG_SUB_X, wxEmptyString, wxPoint(526, 353), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyAnalogSubY[i] = new wxButton(m_Controller[i], IDB_ANALOG_SUB_Y, wxEmptyString, wxPoint(526, 390), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + + m_textSubX[i] = new wxStaticText(m_Controller[i], IDT_ANALOG_SUB_X, wxT("X-axis"), wxPoint(552, 336), wxDefaultSize, 0, wxT("X-axis")); + m_textSubY[i] = new wxStaticText(m_Controller[i], IDT_ANALOG_SUB_Y, wxT("Y-axis"), wxPoint(552, 373), wxDefaultSize, 0, wxT("Y-axis")); + + // GUI center button + m_JoyButtonStart[i] = new wxTextCtrl(m_Controller[i], ID_BUTTONSTART, wxT("0"), wxPoint(278, 403), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyButtonStart[i]->Enable(false); + m_bJoyButtonCalibrate[i] = new wxButton(m_Controller[i], ID_BUTTONCALIBRATE, wxT("Calibrate"), wxPoint(297, 440), wxSize(21, 14), 0, wxDefaultValidator, wxT("Calibrate")); + m_JoyButtonHalfpress[i] = new wxTextCtrl(m_Controller[i], ID_BUTTONHALFPRESS, wxT("0"), wxPoint(167, 424), wxSize(59, 19), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("0")); + m_JoyButtonHalfpress[i]->Enable(false); + m_bJoyButtonStart[i] = new wxButton(m_Controller[i], IDB_BUTTONSTART, wxEmptyString, wxPoint(297, 385), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + m_bJoyButtonHalfpress[i] = new wxButton(m_Controller[i], IDB_BUTTONHALFPRESS, wxEmptyString, wxPoint(231, 426), wxSize(21, 14), 0, wxDefaultValidator, wxEmptyString); + + #ifdef _WIN32 + m_textDeadzone[i] = new wxStaticText(m_Controller[i], IDT_DEADZONE, wxT("Deadzone"), wxPoint(116, 404), wxDefaultSize, 0, wxT("Deadzone")); + m_textHalfpress[i] = new wxStaticText(m_Controller[i], IDT_BUTTONHALFPRESS, wxT("Half press"), wxPoint(116, 428), wxDefaultSize, 0, wxT("Half press")); + m_textWebsite[i] = new wxStaticText(m_Controller[i], IDT_WEBSITE, wxT("www.multigesture.net"), wxPoint(500, 438), wxDefaultSize, 0, wxT("www.multigesture.net")); + #else + m_textDeadzone[i] = new wxStaticText(m_Controller[i], IDT_DEADZONE, wxT("Deadzone"), wxPoint(105, 404), wxDefaultSize, 0, wxT("Deadzone")); + m_textHalfpress[i] = new wxStaticText(m_Controller[i], IDT_BUTTONHALFPRESS, wxT("Half press"), wxPoint(105, 428), wxDefaultSize, 0, wxT("Half press")); + m_textWebsite[i] = new wxStaticText(m_Controller[i], IDT_WEBSITE, wxT("www.multigesture.net"), wxPoint(480, 438), wxDefaultSize, 0, wxT("www.multigesture.net")); + #endif + + // TODO: Controller image + // Placeholder instead of bitmap + // m_PlaceholderBMP[i] = new wxTextCtrl(m_Controller[i], ID_CONTROLLERPICTURE, wxT("BITMAP HERE PLZ KTHX!"), wxPoint(98, 75), wxSize(423, 306), wxTE_READONLY | wxTE_CENTRE, wxDefaultValidator, wxT("BITMAP HERE PLZ KTHX!")); + // m_PlaceholderBMP[i]->Enable(false); + + // You can enable the bitmap here: + // But it loads überslow on init... (only in windows, linux seems to load it fast!) + // AAaaand the XPM file (256 colours) looks crappier than the real bitmap... so maybe we can find a way to use a bitmap? + m_controllerimage[i] = new wxStaticBitmap(m_Controller[i], ID_CONTROLLERPICTURE, WxStaticBitmap1_BITMAP, wxPoint(98, 75), wxSize(421,304)); + + if(emulator_running) + { + m_Joyname[i]->Enable(false); + m_Joyattach[i]->Enable(false); + m_Controltype[i]->Enable(false); + } + + SetControllerAll(i); + } +} + +void ConfigBox::OnClose(wxCloseEvent& /*event*/) +{ + EndModal(0); +} + +void ConfigBox::AboutClick(wxCommandEvent& event) +{ +// Call about dialog +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +#ifdef _WIN32 + wxWindow win; + win.SetHWND((WXHWND)this->GetHWND()); + win.Enable(false); + + AboutBox frame(&win); + frame.ShowModal(); + + win.Enable(true); + win.SetHWND(0); +#else + AboutBox frame(NULL); + frame.ShowModal(); +#endif +} + +void ConfigBox::OKClick(wxCommandEvent& event) +{ + if (event.GetId() == ID_OK) + { + for(int i=0; i<4 ;i++) + GetControllerAll(i); + SaveConfig(); // save settings + LoadConfig(); // reload settings + Close(); + } +} + +void ConfigBox::CancelClick(wxCommandEvent& event) +{ + if (event.GetId() == ID_CANCEL) + { + LoadConfig(); // reload settings + Close(); + } +} + +void ConfigBox::Calibrate(wxCommandEvent& event) +{ + int controller = notebookpage; + + + SDL_Joystick *joy = SDL_JoystickOpen(joysticks[controller].ID); + int axes = SDL_JoystickNumAxes(joy); + Sint16 value; + unsigned long Started = SDL_GetTicks(); + while(1) + { + for(int b = 0; b < axes; b++) + { + SDL_JoystickUpdate(); + value = SDL_JoystickGetAxis(joy, b); + if(value < joysticks[controller].sData[b].Min) + joysticks[controller].sData[b].Min = value; + if(value > joysticks[controller].sData[b].Max) + joysticks[controller].sData[b].Max = value; + } + if(SDL_GetTicks() - Started >= 5000) + break; + } + for(int a = 0; a < axes;a++) + printf("Axis %d has a Min of %d, and a Max of %d\n", a, joysticks[controller].sData[a].Min, joysticks[controller].sData[a].Max); + if(SDL_JoystickOpened(joysticks[controller].ID)) + SDL_JoystickClose(joy); +} +// Set dialog items +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void ConfigBox::SetControllerAll(int controller) +{ + // http://wiki.wxwidgets.org/Converting_everything_to_and_from_wxString + wxString tmp; + m_Joyname[controller]->SetSelection(joysticks[controller].ID); + + m_JoyShoulderL[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_L_SHOULDER].c_str())); + m_JoyShoulderR[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_R_SHOULDER].c_str())); + + m_JoyButtonA[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_A_BUTTON].c_str())); + m_JoyButtonB[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_B_BUTTON].c_str())); + m_JoyButtonX[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_X_BUTTON].c_str())); + m_JoyButtonY[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_Y_BUTTON].c_str())); + m_JoyButtonZ[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_Z_TRIGGER].c_str())); + + m_JoyButtonStart[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_START].c_str())); + tmp << joysticks[controller].halfpress; m_JoyButtonHalfpress[controller]->SetValue(tmp); tmp.clear(); + + m_JoyAnalogMainX[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_MAIN_X].c_str())); + m_JoyAnalogMainY[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_MAIN_Y].c_str())); + m_JoyAnalogSubX[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_SUB_X].c_str())); + m_JoyAnalogSubY[controller]->SetValue(wxString::FromAscii(joysticks[controller].buttons[CTL_SUB_Y].c_str())); + + if(joysticks[controller].enabled) + m_Joyattach[controller]->SetValue(TRUE); + else + m_Joyattach[controller]->SetValue(FALSE); + + m_Controltype[controller]->SetSelection(joysticks[controller].controllertype); + m_Deadzone[controller]->SetSelection(joysticks[controller].deadzone); + + UpdateVisibleItems(controller); + + if(joysticks[controller].controllertype == CTL_TYPE_JOYSTICK) + { + tmp << joysticks[controller].dpad; m_JoyDpadUp[controller]->SetValue(tmp); tmp.clear(); + } + else + { + tmp << joysticks[controller].dpad2[CTL_D_PAD_UP]; m_JoyDpadUp[controller]->SetValue(tmp); tmp.clear(); + tmp << joysticks[controller].dpad2[CTL_D_PAD_DOWN]; m_JoyDpadDown[controller]->SetValue(tmp); tmp.clear(); + tmp << joysticks[controller].dpad2[CTL_D_PAD_LEFT]; m_JoyDpadLeft[controller]->SetValue(tmp); tmp.clear(); + tmp << joysticks[controller].dpad2[CTL_D_PAD_RIGHT]; m_JoyDpadRight[controller]->SetValue(tmp); tmp.clear(); + } +} + +// Get dialog items +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void ConfigBox::GetControllerAll(int controller) +{ + wxString tmp; + long lvalue; + + joysticks[controller].ID = m_Joyname[controller]->GetSelection(); + + joysticks[controller].buttons[CTL_L_SHOULDER] = std::string(m_JoyShoulderL[controller]->GetValue().mb_str()); tmp.clear(); + joysticks[controller].buttons[CTL_R_SHOULDER] = std::string(m_JoyShoulderR[controller]->GetValue().mb_str()); tmp.clear(); + + joysticks[controller].buttons[CTL_A_BUTTON] = std::string(m_JoyButtonA[controller]->GetValue().mb_str()); tmp.clear(); + joysticks[controller].buttons[CTL_B_BUTTON] = std::string(m_JoyButtonB[controller]->GetValue().mb_str()); tmp.clear(); + joysticks[controller].buttons[CTL_X_BUTTON] = std::string(m_JoyButtonX[controller]->GetValue().mb_str()); tmp.clear(); + joysticks[controller].buttons[CTL_Y_BUTTON] = std::string(m_JoyButtonY[controller]->GetValue().mb_str()); tmp.clear(); + joysticks[controller].buttons[CTL_Z_TRIGGER] = std::string(m_JoyButtonZ[controller]->GetValue().mb_str()); tmp.clear(); + joysticks[controller].buttons[CTL_START] = std::string(m_JoyButtonStart[controller]->GetValue().mb_str()); tmp.clear(); + + m_JoyButtonHalfpress[controller]->GetValue().ToLong(&lvalue); joysticks[controller].halfpress = lvalue; tmp.clear(); + + if(joysticks[controller].controllertype == CTL_TYPE_JOYSTICK) + { + m_JoyDpadUp[controller]->GetValue().ToLong(&lvalue); joysticks[controller].dpad = lvalue; tmp.clear(); + } + else + { + m_JoyDpadUp[controller]->GetValue().ToLong(&lvalue); joysticks[controller].dpad2[CTL_D_PAD_UP] = lvalue; tmp.clear(); + m_JoyDpadDown[controller]->GetValue().ToLong(&lvalue); joysticks[controller].dpad2[CTL_D_PAD_DOWN] = lvalue; tmp.clear(); + m_JoyDpadLeft[controller]->GetValue().ToLong(&lvalue); joysticks[controller].dpad2[CTL_D_PAD_LEFT] = lvalue; tmp.clear(); + m_JoyDpadRight[controller]->GetValue().ToLong(&lvalue); joysticks[controller].dpad2[CTL_D_PAD_RIGHT] = lvalue; tmp.clear(); + } + + joysticks[controller].buttons[CTL_MAIN_X] = std::string(m_JoyAnalogMainX[controller]->GetValue().mb_str()); tmp.clear(); + joysticks[controller].buttons[CTL_MAIN_Y] = std::string(m_JoyAnalogMainY[controller]->GetValue().mb_str()); tmp.clear(); + joysticks[controller].buttons[CTL_SUB_X] = std::string(m_JoyAnalogSubX[controller]->GetValue().mb_str()); tmp.clear(); + joysticks[controller].buttons[CTL_SUB_Y] = std::string(m_JoyAnalogSubY[controller]->GetValue().mb_str()); tmp.clear(); + + joysticks[controller].enabled = m_Joyattach[controller]->GetValue(); + + joysticks[controller].controllertype = m_Controltype[controller]->GetSelection(); + joysticks[controller].deadzone = m_Deadzone[controller]->GetSelection(); +} + +void ConfigBox::UpdateVisibleItems(int controller) +{ + if(joysticks[controller].controllertype) + { + m_JoyDpadDown[controller]->Show(TRUE); + m_JoyDpadLeft[controller]->Show(TRUE); + m_JoyDpadRight[controller]->Show(TRUE); + + m_bJoyDpadDown[controller]->Show(TRUE); + m_bJoyDpadLeft[controller]->Show(TRUE); + m_bJoyDpadRight[controller]->Show(TRUE); + + m_textDpadUp[controller]->Show(TRUE); + m_textDpadDown[controller]->Show(TRUE); + m_textDpadLeft[controller]->Show(TRUE); + m_textDpadRight[controller]->Show(TRUE); + } + else + { + m_JoyDpadDown[controller]->Show(FALSE); + m_JoyDpadLeft[controller]->Show(FALSE); + m_JoyDpadRight[controller]->Show(FALSE); + + m_bJoyDpadDown[controller]->Show(FALSE); + m_bJoyDpadLeft[controller]->Show(FALSE); + m_bJoyDpadRight[controller]->Show(FALSE); + + m_textDpadUp[controller]->Show(FALSE); + m_textDpadDown[controller]->Show(FALSE); + m_textDpadLeft[controller]->Show(FALSE); + m_textDpadRight[controller]->Show(FALSE); + } +} + +void ConfigBox::ChangeJoystick(wxCommandEvent& event) +{ + joysticks[0].ID = m_Joyname[0]->GetSelection(); + joysticks[1].ID = m_Joyname[1]->GetSelection(); + joysticks[2].ID = m_Joyname[2]->GetSelection(); + joysticks[3].ID = m_Joyname[3]->GetSelection(); +} + +void ConfigBox::ChangeControllertype(wxCommandEvent& event) +{ + joysticks[0].controllertype = m_Controltype[0]->GetSelection(); + joysticks[1].controllertype = m_Controltype[1]->GetSelection(); + joysticks[2].controllertype = m_Controltype[2]->GetSelection(); + joysticks[3].controllertype = m_Controltype[3]->GetSelection(); + + for(int i=0; i<4 ;i++) + UpdateVisibleItems(i); +} + +void ConfigBox::NotebookPageChanged(wxNotebookEvent& event) +{ + notebookpage = event.GetSelection(); +} + +void ConfigBox::SetButtonText(int id, char text[128]) +{ + int controller = notebookpage; + + switch(id) + { + case IDB_SHOULDER_L: + { + m_JoyShoulderL[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_SHOULDER_R: + { + m_JoyShoulderR[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_BUTTON_A: + { + m_JoyButtonA[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_BUTTON_B: + { + m_JoyButtonB[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_BUTTON_X: + { + m_JoyButtonX[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_BUTTON_Y: + { + m_JoyButtonY[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_BUTTON_Z: + { + m_JoyButtonZ[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_BUTTONSTART: + { + m_JoyButtonStart[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_BUTTONHALFPRESS: + { + m_JoyButtonHalfpress[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_DPAD_UP: + { + m_JoyDpadUp[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_DPAD_DOWN: + { + m_JoyDpadDown[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_DPAD_LEFT: + { + m_JoyDpadLeft[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_DPAD_RIGHT: + { + m_JoyDpadRight[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_ANALOG_MAIN_X: + { + m_JoyAnalogMainX[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_ANALOG_MAIN_Y: + { + m_JoyAnalogMainY[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_ANALOG_SUB_X: + { + m_JoyAnalogSubX[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + case IDB_ANALOG_SUB_Y: + { + m_JoyAnalogSubY[controller]->SetValue(wxString::FromAscii(text)); + } + break; + + default: + break; + } +} +void ConfigBox::GetInputs(wxCommandEvent& event) +{ + int ID = event.GetId(); + int controller = notebookpage; + + // DPAD type check! + if(ID == IDB_DPAD_UP) + if(joysticks[controller].controllertype == 0) + { + GetHats(ID); + return; + } + + SDL_Joystick *joy = SDL_JoystickOpen(joysticks[controller].ID); + + char format[128]; + int buttons = SDL_JoystickNumButtons(joy); + int axes = SDL_JoystickNumAxes(joy); + char type = 'N'; // B, A, H, N = Nan + bool waiting = true; + bool succeed = false; + int pressed = 0; + Sint16 value; + + int counter1 = 0; + int counter2 = 10; + + sprintf(format, "[%d]", counter2); + SetButtonText(ID, format); + wxWindow::Update(); // win only? doesnt seem to work in linux... + + SDL_JoystickUpdate(); + while(waiting) + { + SDL_JoystickUpdate(); + for(int b = 0; b < buttons; b++) + { + if(SDL_JoystickGetButton(joy, b)) + { + pressed = b; + waiting = false; + succeed = true; + type = 'B'; + goto InputEnd; + } + } + for(int b = 0; b < axes; b++) + { + value = SDL_JoystickGetAxis(joy, b); + if(value <= (joysticks[controller].sData[b].Min - (joysticks[controller].sData[b].Min * joysticks[controller].deadzone / 100)) || value >= (joysticks[controller].sData[b].Max - (joysticks[controller].sData[b].Max * joysticks[controller].deadzone / 100))) // Add and subtract a small value + { // It allows for some small jitter + printf("value %d, Min %d Max %d Removal %d\n", value, joysticks[controller].sData[b].Min,joysticks[controller].sData[b].Max, (joysticks[controller].sData[b].Min * joysticks[controller].deadzone / 100)); + value = value <= (joysticks[controller].sData[b].Min - joysticks[controller].sData[b].Min * joysticks[controller].deadzone) ? -1 : 1; // Makes it know if the value is negative or positive + pressed = b; + waiting = false; + succeed = true; + type = 'A'; + goto InputEnd; + } + } +InputEnd: + counter1++; + if(counter1==100) + { + counter1=0; + counter2--; + + sprintf(format, "[%d]", counter2); + SetButtonText(ID, format); + wxWindow::Update(); // win only? doesnt seem to work in linux... + + if(counter2<0) + waiting = false; + } + SLEEP(10); + } + if(type == 'A') + sprintf(format, "%c%c%d" , type, value < 0 ? '-' : '+', succeed ? pressed : -1); + else + sprintf(format, "%c%d" , type, succeed ? pressed : -1); + SetButtonText(ID, format); + + if(SDL_JoystickOpened(joysticks[controller].ID)) + SDL_JoystickClose(joy); +} + +// Wait for D-Pad +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void ConfigBox::GetHats(int ID) +{ + int controller = notebookpage; + + SDL_Joystick *joy; + joy=SDL_JoystickOpen(joysticks[controller].ID); + + char format[128]; + int hats = SDL_JoystickNumHats(joy); + bool waiting = true; + bool succeed = false; + int pressed = 0; + + int counter1 = 0; + int counter2 = 10; + + sprintf(format, "[%d]", counter2); + SetButtonText(ID, format); + wxWindow::Update(); // win only? doesnt seem to work in linux... + + while(waiting) + { + SDL_JoystickUpdate(); + for(int b = 0; b < hats; b++) + { + if(SDL_JoystickGetHat(joy, b)) + { + pressed = b; + waiting = false; + succeed = true; + break; + } + } + + counter1++; + if(counter1==100) + { + counter1=0; + counter2--; + + sprintf(format, "[%d]", counter2); + SetButtonText(ID, format); + wxWindow::Update(); // win only? doesnt seem to work in linux... + + if(counter2<0) + waiting = false; + } + SLEEP(10); + } + + sprintf(format, "H%d", succeed ? pressed : -1); + SetButtonText(ID, format); + + if(SDL_JoystickOpened(joysticks[controller].ID)) + SDL_JoystickClose(joy); +} diff --git a/Source/Plugins/Plugin_nJoy_Testing/Src/nJoy.cpp b/Source/Plugins/Plugin_nJoy_Testing/Src/nJoy.cpp index 06f701f00f..488f2c8cd9 100644 --- a/Source/Plugins/Plugin_nJoy_Testing/Src/nJoy.cpp +++ b/Source/Plugins/Plugin_nJoy_Testing/Src/nJoy.cpp @@ -1,937 +1,937 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// Project description -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -// Name: nJoy -// Description: A Dolphin Compatible Input Plugin -// -// Author: Falcon4ever (nJoy@falcon4ever.com) -// Site: www.multigesture.net -// Copyright (C) 2003-2008 Dolphin Project. -// -////////////////////////////////////////////////////////////////////////////////////////// -// -// Licensetype: GNU General Public License (GPL) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. -// -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ -// -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ -// -////////////////////////////////////////////////////////////////////////////////////////// - -#include "nJoy.h" - -////////////////////////////////////////////////////////////////////////////////////////// -// Variables -// ŻŻŻŻŻŻŻŻŻ - -FILE *pFile; -HINSTANCE nJoy_hInst = NULL; -CONTROLLER_INFO *joyinfo = 0; -CONTROLLER_STATE joystate[4]; -CONTROLLER_MAPPING joysticks[4]; -bool emulator_running = FALSE; - -// Handle to window -HWND m_hWnd; - -#ifdef USE_RUMBLE_DINPUT_HACK -bool g_rumbleEnable = FALSE; -#endif - -// Rumble in windows -#ifdef _WIN32 - -#ifdef USE_RUMBLE_DINPUT_HACK -LPDIRECTINPUT8 g_pDI = NULL; -LPDIRECTINPUTDEVICE8 g_pDevice = NULL; -LPDIRECTINPUTEFFECT g_pEffect = NULL; - -DWORD g_dwNumForceFeedbackAxis = 0; -INT g_nXForce = 0; -INT g_nYForce = 0; - -#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } - -HRESULT InitDirectInput(HWND hDlg); -VOID FreeDirectInput(); -BOOL CALLBACK EnumFFDevicesCallback(const DIDEVICEINSTANCE* pInst, VOID* pContext); -BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext); -HRESULT SetDeviceForcesXY(); -#endif - -#elif defined(__linux__) - int fd; - char device_file_name[64]; - struct ff_effect effect; - bool CanRumble = false; -#endif - -////////////////////////////////////////////////////////////////////////////////////////// -// wxWidgets -// ŻŻŻŻŻŻŻŻŻ -class wxDLLApp : public wxApp -{ - bool OnInit() - { - return true; - } -}; - -IMPLEMENT_APP_NO_MAIN(wxDLLApp) -WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst); - -////////////////////////////////////////////////////////////////////////////////////////// -// DllMain -// ŻŻŻŻŻŻŻ -#ifdef _WIN32 -BOOL APIENTRY DllMain( HINSTANCE hinstDLL, // DLL module handle - DWORD dwReason, // reason called - LPVOID lpvReserved) // reserved -{ - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - { - //use wxInitialize() if you don't want GUI instead of the following 12 lines - wxSetInstance((HINSTANCE)hinstDLL); - int argc = 0; - char **argv = NULL; - wxEntryStart(argc, argv); - - if ( !wxTheApp || !wxTheApp->CallOnInit() ) - return FALSE; - } - break; - - case DLL_PROCESS_DETACH: - wxEntryCleanup(); //use wxUninitialize() if you don't want GUI - break; - - default: - break; - } - - nJoy_hInst = hinstDLL; - return TRUE; -} -#endif - -////////////////////////////////////////////////////////////////////////////////////////// -// Input Plugin Functions (from spec's) -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ - -// Get properties of plugin -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void GetDllInfo(PLUGIN_INFO* _PluginInfo) -{ - _PluginInfo->Version = 0x0100; - _PluginInfo->Type = PLUGIN_TYPE_PAD; - -#ifdef DEBUGFAST - sprintf(_PluginInfo->Name, "nJoy v"INPUT_VERSION" (DebugFast) by Falcon4ever"); -#else -#ifndef _DEBUG - sprintf(_PluginInfo->Name, "nJoy v"INPUT_VERSION " by Falcon4ever"); -#else - sprintf(_PluginInfo->Name, "nJoy v"INPUT_VERSION" (Debug) by Falcon4ever"); -#endif -#endif -} - -// Call config dialog -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void DllConfig(HWND _hParent) -{ - #ifdef _WIN32 - if(SDL_Init(SDL_INIT_JOYSTICK ) < 0) - { - MessageBox(NULL, SDL_GetError(), "Could not initialize SDL!", MB_ICONERROR); - return; - } - - LoadConfig(); // load settings +////////////////////////////////////////////////////////////////////////////////////////// +// Project description +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +// Name: nJoy +// Description: A Dolphin Compatible Input Plugin +// +// Author: Falcon4ever (nJoy@falcon4ever.com) +// Site: www.multigesture.net +// Copyright (C) 2003-2008 Dolphin Project. +// +////////////////////////////////////////////////////////////////////////////////////////// +// +// Licensetype: GNU General Public License (GPL) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. +// +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ +// +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +// +////////////////////////////////////////////////////////////////////////////////////////// + +#include "nJoy.h" + +////////////////////////////////////////////////////////////////////////////////////////// +// Variables +// ŻŻŻŻŻŻŻŻŻ + +FILE *pFile; +HINSTANCE nJoy_hInst = NULL; +CONTROLLER_INFO *joyinfo = 0; +CONTROLLER_STATE joystate[4]; +CONTROLLER_MAPPING joysticks[4]; +bool emulator_running = FALSE; + +// Handle to window +HWND m_hWnd; + +#ifdef USE_RUMBLE_DINPUT_HACK +bool g_rumbleEnable = FALSE; +#endif + +// Rumble in windows +#ifdef _WIN32 + +#ifdef USE_RUMBLE_DINPUT_HACK +LPDIRECTINPUT8 g_pDI = NULL; +LPDIRECTINPUTDEVICE8 g_pDevice = NULL; +LPDIRECTINPUTEFFECT g_pEffect = NULL; + +DWORD g_dwNumForceFeedbackAxis = 0; +INT g_nXForce = 0; +INT g_nYForce = 0; + +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + +HRESULT InitDirectInput(HWND hDlg); +VOID FreeDirectInput(); +BOOL CALLBACK EnumFFDevicesCallback(const DIDEVICEINSTANCE* pInst, VOID* pContext); +BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext); +HRESULT SetDeviceForcesXY(); +#endif + +#elif defined(__linux__) + int fd; + char device_file_name[64]; + struct ff_effect effect; + bool CanRumble = false; +#endif + +////////////////////////////////////////////////////////////////////////////////////////// +// wxWidgets +// ŻŻŻŻŻŻŻŻŻ +class wxDLLApp : public wxApp +{ + bool OnInit() + { + return true; + } +}; + +IMPLEMENT_APP_NO_MAIN(wxDLLApp) +WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst); + +////////////////////////////////////////////////////////////////////////////////////////// +// DllMain +// ŻŻŻŻŻŻŻ +#ifdef _WIN32 +BOOL APIENTRY DllMain( HINSTANCE hinstDLL, // DLL module handle + DWORD dwReason, // reason called + LPVOID lpvReserved) // reserved +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + { + //use wxInitialize() if you don't want GUI instead of the following 12 lines + wxSetInstance((HINSTANCE)hinstDLL); + int argc = 0; + char **argv = NULL; + wxEntryStart(argc, argv); + + if ( !wxTheApp || !wxTheApp->CallOnInit() ) + return FALSE; + } + break; + + case DLL_PROCESS_DETACH: + wxEntryCleanup(); //use wxUninitialize() if you don't want GUI + break; + + default: + break; + } + + nJoy_hInst = hinstDLL; + return TRUE; +} +#endif + +////////////////////////////////////////////////////////////////////////////////////////// +// Input Plugin Functions (from spec's) +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ + +// Get properties of plugin +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void GetDllInfo(PLUGIN_INFO* _PluginInfo) +{ + _PluginInfo->Version = 0x0100; + _PluginInfo->Type = PLUGIN_TYPE_PAD; + +#ifdef DEBUGFAST + sprintf(_PluginInfo->Name, "nJoy v"INPUT_VERSION" (DebugFast) by Falcon4ever"); +#else +#ifndef _DEBUG + sprintf(_PluginInfo->Name, "nJoy v"INPUT_VERSION " by Falcon4ever"); +#else + sprintf(_PluginInfo->Name, "nJoy v"INPUT_VERSION" (Debug) by Falcon4ever"); +#endif +#endif +} + +// Call config dialog +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void DllConfig(HWND _hParent) +{ + #ifdef _WIN32 + if(SDL_Init(SDL_INIT_JOYSTICK ) < 0) + { + MessageBox(NULL, SDL_GetError(), "Could not initialize SDL!", MB_ICONERROR); + return; + } + + LoadConfig(); // load settings wxWindow win; win.SetHWND(_hParent); ConfigBox frame(&win); frame.ShowModal(); - win.SetHWND(0); - - #else - if(SDL_Init(SDL_INIT_JOYSTICK ) < 0) - { - printf("Could not initialize SDL! (%s)\n", SDL_GetError()); - return; - } - - LoadConfig(); // load settings - - ConfigBox frame(NULL); - frame.ShowModal(); - #endif -} - -// Init PAD (start emulation) -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void PAD_Initialize(SPADInitialize _PADInitialize) -{ - emulator_running = TRUE; - #ifdef _DEBUG - DEBUG_INIT(); - #endif - - if(SDL_Init(SDL_INIT_JOYSTICK ) < 0) - { - #ifdef _WIN32 - MessageBox(NULL, SDL_GetError(), "Could not initialize SDL!", MB_ICONERROR); - #else - printf("Could not initialize SDL! (%s)\n", SDL_GetError()); - #endif - return; - } - - #ifdef _WIN32 - m_hWnd = (HWND)_PADInitialize.hWnd; - #endif - - LoadConfig(); // Load joystick mapping - - if(joysticks[0].enabled) - joystate[0].joy = SDL_JoystickOpen(joysticks[0].ID); - if(joysticks[1].enabled) - joystate[1].joy = SDL_JoystickOpen(joysticks[1].ID); - if(joysticks[2].enabled) - joystate[2].joy = SDL_JoystickOpen(joysticks[2].ID); - if(joysticks[3].enabled) - joystate[3].joy = SDL_JoystickOpen(joysticks[3].ID); -} - -// Shutdown PAD (stop emulation) -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void PAD_Shutdown() -{ - if(joysticks[0].enabled) - SDL_JoystickClose(joystate[0].joy); - if(joysticks[1].enabled) - SDL_JoystickClose(joystate[1].joy); - if(joysticks[2].enabled) - SDL_JoystickClose(joystate[2].joy); - if(joysticks[3].enabled) - SDL_JoystickClose(joystate[3].joy); - - SDL_Quit(); - - #ifdef _DEBUG - DEBUG_QUIT(); - #endif - - delete [] joyinfo; - - emulator_running = FALSE; - - #ifdef _WIN32 - #ifdef USE_RUMBLE_DINPUT_HACK - FreeDirectInput(); - #endif - #elif defined(__linux__) - close(fd); - #endif -} - -// Set PAD status -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) -{ - if(!joysticks[_numPAD].enabled) - return; - - // clear pad status - memset(_pPADStatus, 0, sizeof(SPADStatus)); - - // get pad status - GetJoyState(_numPAD); - - // Reset! - int base = 0x80; - _pPADStatus->stickY = base; - _pPADStatus->stickX = base; - _pPADStatus->substickX = base; - _pPADStatus->substickY = base; - _pPADStatus->button |= PAD_USE_ORIGIN; - - // Set analog controllers - // Set Deadzones perhaps out of function - int deadzone = (int)(((float)(128.00/100.00)) * (float)(joysticks[_numPAD].deadzone+1)); - int deadzone2 = (int)(((float)(-128.00/100.00)) * (float)(joysticks[_numPAD].deadzone+1)); - - // Adjust range - // The value returned by SDL_JoystickGetAxis is a signed integer (-32768 to 32768) - // The value used for the gamecube controller is an unsigned char (0 to 255) - int main_stick_x = (joystate[_numPAD].buttons[CTL_MAIN_X]>>8); - int main_stick_y = -(joystate[_numPAD].buttons[CTL_MAIN_Y]>>8); - int sub_stick_x = (joystate[_numPAD].buttons[CTL_SUB_X]>>8); - int sub_stick_y = -(joystate[_numPAD].buttons[CTL_SUB_Y]>>8); - - // Quick fix - if(main_stick_x > 127) - main_stick_x = 127; - if(main_stick_y > 127) - main_stick_y = 127; - if(sub_stick_x > 127) - sub_stick_x = 127; - if(sub_stick_y > 127) - sub_stick_y = 127; - - if(main_stick_x < -128) - main_stick_x = -128; - if(main_stick_y < -128) - main_stick_y = -128; - if(sub_stick_x < -128) - sub_stick_x = -128; - if(sub_stick_y < -128) - sub_stick_y = -128; - - // Send values to Dolpin - if ((main_stick_x < deadzone2) || (main_stick_x > deadzone)) _pPADStatus->stickX += main_stick_x; - if ((main_stick_y < deadzone2) || (main_stick_y > deadzone)) _pPADStatus->stickY += main_stick_y; - if ((sub_stick_x < deadzone2) || (sub_stick_x > deadzone)) _pPADStatus->substickX += sub_stick_x; - if ((sub_stick_y < deadzone2) || (sub_stick_y > deadzone)) _pPADStatus->substickY += sub_stick_y; - - int triggervalue = 255; - if (joystate[_numPAD].halfpress) - triggervalue = 100; - - // Set buttons - if (joystate[_numPAD].buttons[CTL_L_SHOULDER]) - { - _pPADStatus->button|=PAD_TRIGGER_L; - _pPADStatus->triggerLeft = triggervalue; - } - if (joystate[_numPAD].buttons[CTL_R_SHOULDER]) - { - _pPADStatus->button|=PAD_TRIGGER_R; - _pPADStatus->triggerRight = triggervalue; - } - - if (joystate[_numPAD].buttons[CTL_A_BUTTON]) - { - _pPADStatus->button|=PAD_BUTTON_A; - _pPADStatus->analogA = 255; // Perhaps support pressure? - } - if (joystate[_numPAD].buttons[CTL_B_BUTTON]) - { - _pPADStatus->button|=PAD_BUTTON_B; - _pPADStatus->analogB = 255; // Perhaps support pressure? - } - if (joystate[_numPAD].buttons[CTL_X_BUTTON]) _pPADStatus->button|=PAD_BUTTON_X; - if (joystate[_numPAD].buttons[CTL_Y_BUTTON]) _pPADStatus->button|=PAD_BUTTON_Y; - if (joystate[_numPAD].buttons[CTL_Z_TRIGGER]) _pPADStatus->button|=PAD_TRIGGER_Z; - if (joystate[_numPAD].buttons[CTL_START]) _pPADStatus->button|=PAD_BUTTON_START; - - // Set D-pad - if(joysticks[_numPAD].controllertype == CTL_TYPE_JOYSTICK) - { - if(joystate[_numPAD].dpad == SDL_HAT_LEFTUP || joystate[_numPAD].dpad == SDL_HAT_UP || joystate[_numPAD].dpad == SDL_HAT_RIGHTUP ) _pPADStatus->button|=PAD_BUTTON_UP; - if(joystate[_numPAD].dpad == SDL_HAT_LEFTUP || joystate[_numPAD].dpad == SDL_HAT_LEFT || joystate[_numPAD].dpad == SDL_HAT_LEFTDOWN ) _pPADStatus->button|=PAD_BUTTON_LEFT; - if(joystate[_numPAD].dpad == SDL_HAT_LEFTDOWN || joystate[_numPAD].dpad == SDL_HAT_DOWN || joystate[_numPAD].dpad == SDL_HAT_RIGHTDOWN ) _pPADStatus->button|=PAD_BUTTON_DOWN; - if(joystate[_numPAD].dpad == SDL_HAT_RIGHTUP || joystate[_numPAD].dpad == SDL_HAT_RIGHT || joystate[_numPAD].dpad == SDL_HAT_RIGHTDOWN ) _pPADStatus->button|=PAD_BUTTON_RIGHT; - } - else - { - if(joystate[_numPAD].dpad2[CTL_D_PAD_UP]) - _pPADStatus->button|=PAD_BUTTON_UP; - if(joystate[_numPAD].dpad2[CTL_D_PAD_DOWN]) - _pPADStatus->button|=PAD_BUTTON_DOWN; - if(joystate[_numPAD].dpad2[CTL_D_PAD_LEFT]) - _pPADStatus->button|=PAD_BUTTON_LEFT; - if(joystate[_numPAD].dpad2[CTL_D_PAD_RIGHT]) - _pPADStatus->button|=PAD_BUTTON_RIGHT; - } - - _pPADStatus->err = PAD_ERR_NONE; - - - #ifdef _WIN32 - #ifdef USE_RUMBLE_DINPUT_HACK - if(joystate[_numPAD].halfpress) - if(!g_pDI) - if(FAILED(InitDirectInput(m_hWnd))) - { - MessageBox(NULL, SDL_GetError(), "Could not initialize DirectInput!", MB_ICONERROR); - g_rumbleEnable = FALSE; - //return; - } - else - g_rumbleEnable = TRUE; - - if (g_rumbleEnable) - { - g_pDevice->Acquire(); - - if(g_pEffect) - g_pEffect->Start(1, 0); - } - #endif - #elif defined(__linux__) - if(!fd) - { - sprintf(device_file_name, "/dev/input/event%d", joysticks[_numPAD].eventnum); //TODO: Make dynamic // - - /* Open device */ - fd = open(device_file_name, O_RDWR); - if (fd == -1) { - perror("Open device file"); - //Something wrong, probably permissions, just return now - return; - } - int n_effects = 0; - if (ioctl(fd, EVIOCGEFFECTS, &n_effects) == -1) { - perror("Ioctl number of effects"); - } - if(n_effects > 0) - CanRumble = true; - else - return; // Return since we can't do any effects - /* a strong rumbling effect */ - effect.type = FF_RUMBLE; - effect.id = -1; - effect.u.rumble.strong_magnitude = 0x8000; - effect.u.rumble.weak_magnitude = 0; - effect.replay.length = 5000; // Set to 5 seconds, if a Game needs more for a single rumble event, it is dumb and must be a demo - effect.replay.delay = 0; - if (ioctl(fd, EVIOCSFF, &effect) == -1) { - perror("Upload effect"); - CanRumble = false; //We have effects but it doesn't support the rumble we are using. This is basic rumble, should work for most - } - } - #endif -} - -// Set PAD rumble -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -// (Stop=0, Rumble=1) -void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength) -{ - //if(_numPAD > 0) - // return; - - // not supported by SDL - // So we need to use platform specific stuff - #ifdef _WIN32 - #ifdef USE_RUMBLE_DINPUT_HACK - static int a = 0; - - if ((_uType == 0) || (_uType == 2)) - { - a = 0; - } - else if (_uType == 1) - { - a = _uStrength > 2 ? 8000 : 0; - } - - a = int ((float)a * 0.96f); - - if (!g_rumbleEnable) - { - a = 0; - } - else - { - g_nYForce = a; - SetDeviceForcesXY(); - } - #endif - #elif defined(__linux__) - struct input_event event; - if(CanRumble) - { - if (_uType == 1) - { - event.type = EV_FF; - event.code = effect.id; - event.value = 1; - if (write(fd, (const void*) &event, sizeof(event)) == -1) { - perror("Play effect"); - exit(1); - } - } - if ((_uType == 0) || (_uType == 2)) - { - event.type = EV_FF; - event.code = effect.id; - event.value = 0; - if (write(fd, (const void*) &event, sizeof(event)) == -1) { - perror("Stop effect"); - exit(1); - } - } - } - #endif -} - -// Set PAD attached pads -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -unsigned int PAD_GetAttachedPads() -{ - unsigned int connected = 0; - - LoadConfig(); - - if(joysticks[0].enabled) - connected |= 1; - if(joysticks[1].enabled) - connected |= 2; - if(joysticks[2].enabled) - connected |= 4; - if(joysticks[3].enabled) - connected |= 8; - - return connected; -} - -// Savestates -// ŻŻŻŻŻŻŻŻŻŻ -unsigned int SaveLoadState(char *ptr, BOOL save) -{ - // not used - return 0; -} - -////////////////////////////////////////////////////////////////////////////////////////// -// Custom Functions -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ - -// Request joystick state -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void GetJoyState(int controller) -{ - SDL_JoystickUpdate(); - - for(int a = 0; a < CTRL_END; a++) - { - char Type = (joysticks[controller].buttons[a].c_str())[0]; - //printf("Type %c, entire %s\n", Type, joysticks[controller].buttons[a].c_str()); - switch(Type) - { - case 'A': - joystate[controller].buttons[a] = SDL_JoystickGetAxis(joystate[controller].joy, atoi(joysticks[controller].buttons[a].c_str() + 2)); // Skip the A AND the +/- sign - break; - case 'B': - joystate[controller].buttons[a] = SDL_JoystickGetButton(joystate[controller].joy, atoi(joysticks[controller].buttons[a].c_str() + 1)); - break; - case 'H': - printf("We aren't Expecting Hat here!\n"); - break; - default: - printf("Unknown button type %c, number %d, Full %s\n", Type, a, joysticks[controller].buttons[a].c_str()); - break; - } - } - - joystate[controller].halfpress = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].halfpress); - - if(joysticks[controller].controllertype == CTL_TYPE_JOYSTICK) - joystate[controller].dpad = SDL_JoystickGetHat(joystate[controller].joy, joysticks[controller].dpad); - else - { - joystate[controller].dpad2[CTL_D_PAD_UP] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].dpad2[CTL_D_PAD_UP]); - joystate[controller].dpad2[CTL_D_PAD_DOWN] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].dpad2[CTL_D_PAD_DOWN]); - joystate[controller].dpad2[CTL_D_PAD_LEFT] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].dpad2[CTL_D_PAD_LEFT]); - joystate[controller].dpad2[CTL_D_PAD_RIGHT] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].dpad2[CTL_D_PAD_RIGHT]); - } -} - -// Search attached devices -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -int Search_Devices() -{ - // load config - #ifdef _DEBUG - DEBUG_INIT(); - #endif - - int numjoy = SDL_NumJoysticks(); - - if(numjoy == 0) - { - #ifdef _WIN32 - MessageBox(NULL, "No Joystick detected!", NULL, MB_ICONWARNING); - #else - printf("No Joystick detected!\n"); - #endif - return 0; - } - - if(joyinfo) - { - delete [] joyinfo; - joyinfo = new CONTROLLER_INFO [numjoy]; - } - else - { - joyinfo = new CONTROLLER_INFO [numjoy]; - } - - #ifdef _DEBUG - fprintf(pFile, "Scanning for devices\n"); - fprintf(pFile, "ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ\n"); - #endif - - for(int i = 0; i < numjoy; i++ ) - { - joyinfo[i].joy = SDL_JoystickOpen(i); - joyinfo[i].ID = i; - joyinfo[i].NumAxes = SDL_JoystickNumAxes(joyinfo[i].joy); - joyinfo[i].NumButtons = SDL_JoystickNumButtons(joyinfo[i].joy); - joyinfo[i].NumBalls = SDL_JoystickNumBalls(joyinfo[i].joy); - joyinfo[i].NumHats = SDL_JoystickNumHats(joyinfo[i].joy); - joyinfo[i].Name = SDL_JoystickName(i); - - printf("ID: %d\n", i); - printf("Name: %s\n", joyinfo[i].Name); - printf("Buttons: %d\n", joyinfo[i].NumButtons); - printf("Axises: %d\n", joyinfo[i].NumAxes); - printf("Hats: %d\n", joyinfo[i].NumHats); - printf("Balls: %d\n\n", joyinfo[i].NumBalls); - - // Close if opened - if(SDL_JoystickOpened(i)) - SDL_JoystickClose(joyinfo[i].joy); - } - - return numjoy; -} - -// Enable output log -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void DEBUG_INIT() -{ - if(pFile) - return; - - #ifdef _WIN32 - char dateStr [9]; - _strdate( dateStr); - char timeStr [9]; - _strtime( timeStr ); - #endif - - pFile = fopen ("nJoy-debug.txt","wt"); - fprintf(pFile, "nJoy v"INPUT_VERSION" Debug\n"); - #ifdef _WIN32 - fprintf(pFile, "Date: %s\nTime: %s\n", dateStr, timeStr); - #endif - fprintf(pFile, "ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ\n"); -} - -// Disable output log -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void DEBUG_QUIT() -{ - if(!pFile) - return; - - #ifdef _WIN32 - char timeStr [9]; - _strtime(timeStr); - - fprintf(pFile, "_______________\n"); - fprintf(pFile, "Time: %s", timeStr); - #endif - fclose(pFile); -} - -// Save settings to file -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void SaveConfig() -{ - IniFile file; - file.Load("nJoy.ini"); - - for (int i=0; i<4; i++) - { - char SectionName[32]; - sprintf(SectionName, "PAD%i", i+1); - - file.Set(SectionName, "l_shoulder", joysticks[i].buttons[CTL_L_SHOULDER]); - file.Set(SectionName, "r_shoulder", joysticks[i].buttons[CTL_R_SHOULDER]); - file.Set(SectionName, "a_button", joysticks[i].buttons[CTL_A_BUTTON]); - file.Set(SectionName, "b_button", joysticks[i].buttons[CTL_B_BUTTON]); - file.Set(SectionName, "x_button", joysticks[i].buttons[CTL_X_BUTTON]); - file.Set(SectionName, "y_button", joysticks[i].buttons[CTL_Y_BUTTON]); - file.Set(SectionName, "z_trigger", joysticks[i].buttons[CTL_Z_TRIGGER]); - file.Set(SectionName, "start_button", joysticks[i].buttons[CTL_START]); - file.Set(SectionName, "dpad", joysticks[i].dpad); - file.Set(SectionName, "dpad_up", joysticks[i].dpad2[CTL_D_PAD_UP]); - file.Set(SectionName, "dpad_down", joysticks[i].dpad2[CTL_D_PAD_DOWN]); - file.Set(SectionName, "dpad_left", joysticks[i].dpad2[CTL_D_PAD_LEFT]); - file.Set(SectionName, "dpad_right", joysticks[i].dpad2[CTL_D_PAD_RIGHT]); - file.Set(SectionName, "main_x", joysticks[i].buttons[CTL_MAIN_X]); - file.Set(SectionName, "main_y", joysticks[i].buttons[CTL_MAIN_Y]); - file.Set(SectionName, "sub_x", joysticks[i].buttons[CTL_SUB_X]); - file.Set(SectionName, "sub_y", joysticks[i].buttons[CTL_SUB_Y]); - file.Set(SectionName, "enabled", joysticks[i].enabled); - file.Set(SectionName, "deadzone", joysticks[i].deadzone); - file.Set(SectionName, "halfpress", joysticks[i].halfpress); - file.Set(SectionName, "joy_id", joysticks[i].ID); - file.Set(SectionName, "controllertype", joysticks[i].controllertype); - file.Set(SectionName, "eventnum", joysticks[i].eventnum); - for(int a = 0; a < MAX_AXISES; a++) - { - char Section[32]; - sprintf(Section, "SAxis%dMin", a); - file.Set(SectionName, Section, (int)joysticks[i].sData[a].Min); - sprintf(Section, "SAxis%dMax", a); - file.Set(SectionName, Section, (int)joysticks[i].sData[a].Max); - } - } - - file.Save("nJoy.ini"); -} - -// Load settings from file -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void LoadConfig() -{ - IniFile file; - file.Load("nJoy.ini"); - - for (int i=0; i<4; i++) - { - char SectionName[32]; - sprintf(SectionName, "PAD%i", i+1); - - file.Get(SectionName, "l_shoulder", &joysticks[i].buttons[CTL_L_SHOULDER], "B4"); - file.Get(SectionName, "r_shoulder", &joysticks[i].buttons[CTL_R_SHOULDER], "B5"); - file.Get(SectionName, "a_button", &joysticks[i].buttons[CTL_A_BUTTON], "B0"); - file.Get(SectionName, "b_button", &joysticks[i].buttons[CTL_B_BUTTON], "B1"); - file.Get(SectionName, "x_button", &joysticks[i].buttons[CTL_X_BUTTON], "B3"); - file.Get(SectionName, "y_button", &joysticks[i].buttons[CTL_Y_BUTTON], "B2"); - file.Get(SectionName, "z_trigger", &joysticks[i].buttons[CTL_Z_TRIGGER], "B7"); - file.Get(SectionName, "start_button", &joysticks[i].buttons[CTL_START], "B9"); - file.Get(SectionName, "dpad", &joysticks[i].dpad, 0); - file.Get(SectionName, "dpad_up", &joysticks[i].dpad2[CTL_D_PAD_UP], 0); - file.Get(SectionName, "dpad_down", &joysticks[i].dpad2[CTL_D_PAD_DOWN], 0); - file.Get(SectionName, "dpad_left", &joysticks[i].dpad2[CTL_D_PAD_LEFT], 0); - file.Get(SectionName, "dpad_right", &joysticks[i].dpad2[CTL_D_PAD_RIGHT], 0); - file.Get(SectionName, "main_x", &joysticks[i].buttons[CTL_MAIN_X], "A0"); - file.Get(SectionName, "main_y", &joysticks[i].buttons[CTL_MAIN_Y], "A1"); - file.Get(SectionName, "sub_x", &joysticks[i].buttons[CTL_SUB_X], "A2"); - file.Get(SectionName, "sub_y", &joysticks[i].buttons[CTL_SUB_Y], "A3"); - file.Get(SectionName, "enabled", &joysticks[i].enabled, 1); - file.Get(SectionName, "deadzone", &joysticks[i].deadzone, 9); - file.Get(SectionName, "halfpress", &joysticks[i].halfpress, 6); - file.Get(SectionName, "joy_id", &joysticks[i].ID, 0); - file.Get(SectionName, "controllertype", &joysticks[i].controllertype, 0); - file.Get(SectionName, "eventnum", &joysticks[i].eventnum, 0); - for(int a = 0; a < MAX_AXISES; a++) - { - char Section[32]; - int Min; - int Max; - sprintf(Section, "SAxis%dMin", a); - file.Get(SectionName, Section, &Min, 0); - sprintf(Section, "SAxis%dMax", a); - file.Get(SectionName, Section, &Max, 0); - joysticks[i].sData[a].Min = Min; - joysticks[i].sData[a].Max = Max; - } - } -} - - -#ifdef _WIN32 -////////////////////////////////////////////////////////////////////////////////////////// -// Rumble stuff :D! -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -// -#ifdef USE_RUMBLE_DINPUT_HACK -HRESULT InitDirectInput( HWND hDlg ) -{ - DIPROPDWORD dipdw; - HRESULT hr; - - // Register with the DirectInput subsystem and get a pointer to a IDirectInput interface we can use. - if(FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&g_pDI, NULL))) - { - return hr; - } - - // Look for a force feedback device we can use - if(FAILED(hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, EnumFFDevicesCallback, NULL, DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK))) - { - return hr; - } - - if(NULL == g_pDevice) - { - MessageBox(NULL, "Force feedback device not found. nJoy will now disable rumble." ,"FFConst" , MB_ICONERROR | MB_OK); - g_rumbleEnable = FALSE; - - return S_OK; - } - - // Set the data format to "simple joystick" - a predefined data format. A - // data format specifies which controls on a device we are interested in, - // and how they should be reported. - // - // This tells DirectInput that we will be passing a DIJOYSTATE structure to - // IDirectInputDevice8::GetDeviceState(). Even though we won't actually do - // it in this sample. But setting the data format is important so that the - // DIJOFS_* values work properly. - if(FAILED(hr = g_pDevice->SetDataFormat(&c_dfDIJoystick))) - return hr; - - // Set the cooperative level to let DInput know how this device should - // interact with the system and with other DInput applications. - // Exclusive access is required in order to perform force feedback. - //if(FAILED(hr = g_pDevice->SetCooperativeLevel(hDlg, DISCL_EXCLUSIVE | DISCL_FOREGROUND))) - - if(FAILED(hr = g_pDevice->SetCooperativeLevel(hDlg, DISCL_EXCLUSIVE | DISCL_FOREGROUND))) - { - return hr; - } - - // Since we will be playing force feedback effects, we should disable the - // auto-centering spring. - dipdw.diph.dwSize = sizeof(DIPROPDWORD); - dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); - dipdw.diph.dwObj = 0; - dipdw.diph.dwHow = DIPH_DEVICE; - dipdw.dwData = FALSE; - - if(FAILED(hr = g_pDevice->SetProperty(DIPROP_AUTOCENTER, &dipdw.diph))) - return hr; - - // Enumerate and count the axes of the joystick - if(FAILED(hr = g_pDevice->EnumObjects(EnumAxesCallback, (VOID*)&g_dwNumForceFeedbackAxis, DIDFT_AXIS))) - return hr; - - // This simple sample only supports one or two axis joysticks - if(g_dwNumForceFeedbackAxis > 2) - g_dwNumForceFeedbackAxis = 2; - - // This application needs only one effect: Applying raw forces. - DWORD rgdwAxes[2] = {DIJOFS_X, DIJOFS_Y}; - LONG rglDirection[2] = {0, 0}; - DICONSTANTFORCE cf = {0}; - - DIEFFECT eff; - ZeroMemory(&eff, sizeof(eff)); - eff.dwSize = sizeof(DIEFFECT); - eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; - eff.dwDuration = INFINITE; - eff.dwSamplePeriod = 0; - eff.dwGain = DI_FFNOMINALMAX; - eff.dwTriggerButton = DIEB_NOTRIGGER; - eff.dwTriggerRepeatInterval = 0; - eff.cAxes = g_dwNumForceFeedbackAxis; - eff.rgdwAxes = rgdwAxes; - eff.rglDirection = rglDirection; - eff.lpEnvelope = 0; - eff.cbTypeSpecificParams = sizeof( DICONSTANTFORCE ); - eff.lpvTypeSpecificParams = &cf; - eff.dwStartDelay = 0; - - // Create the prepared effect - if(FAILED(hr = g_pDevice->CreateEffect(GUID_ConstantForce, &eff, &g_pEffect, NULL))) - { - return hr; - } - - if(NULL == g_pEffect) - return E_FAIL; - - return S_OK; -} - -VOID FreeDirectInput() -{ - // Unacquire the device one last time just in case - // the app tried to exit while the device is still acquired. - if(g_pDevice) - g_pDevice->Unacquire(); - - // Release any DirectInput objects. - SAFE_RELEASE(g_pEffect); - SAFE_RELEASE(g_pDevice); - SAFE_RELEASE(g_pDI); -} - -BOOL CALLBACK EnumFFDevicesCallback( const DIDEVICEINSTANCE* pInst, VOID* pContext ) -{ - LPDIRECTINPUTDEVICE8 pDevice; - HRESULT hr; - - // Obtain an interface to the enumerated force feedback device. - hr = g_pDI->CreateDevice(pInst->guidInstance, &pDevice, NULL); - - // If it failed, then we can't use this device for some bizarre reason. - // (Maybe the user unplugged it while we were in the middle of enumerating it.) So continue enumerating - if( FAILED(hr)) - return DIENUM_CONTINUE; - - // We successfully created an IDirectInputDevice8. So stop looking for another one. - g_pDevice = pDevice; - - return DIENUM_STOP; -} - -BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext) -{ - DWORD* pdwNumForceFeedbackAxis = (DWORD*)pContext; - if((pdidoi->dwFlags & DIDOI_FFACTUATOR) != 0) - (*pdwNumForceFeedbackAxis)++; - - return DIENUM_CONTINUE; -} - -HRESULT SetDeviceForcesXY() -{ - // Modifying an effect is basically the same as creating a new one, except you need only specify the parameters you are modifying - LONG rglDirection[2] = { 0, 0 }; - - DICONSTANTFORCE cf; - - if( g_dwNumForceFeedbackAxis == 1 ) - { - // If only one force feedback axis, then apply only one direction and keep the direction at zero - cf.lMagnitude = g_nXForce; - rglDirection[0] = 0; - } - else - { - // If two force feedback axis, then apply magnitude from both directions - rglDirection[0] = g_nXForce; - rglDirection[1] = g_nYForce; - cf.lMagnitude = (DWORD)sqrt((double)g_nXForce * (double)g_nXForce + (double)g_nYForce * (double)g_nYForce ); - } - - DIEFFECT eff; - ZeroMemory(&eff, sizeof(eff)); - eff.dwSize = sizeof(DIEFFECT); - eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; - eff.cAxes = g_dwNumForceFeedbackAxis; - eff.rglDirection = rglDirection; - eff.lpEnvelope = 0; - eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE); - eff.lpvTypeSpecificParams = &cf; - eff.dwStartDelay = 0; - - // Now set the new parameters and start the effect immediately. - return g_pEffect->SetParameters(&eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START); -} -#endif -#endif + win.SetHWND(0); + + #else + if(SDL_Init(SDL_INIT_JOYSTICK ) < 0) + { + printf("Could not initialize SDL! (%s)\n", SDL_GetError()); + return; + } + + LoadConfig(); // load settings + + ConfigBox frame(NULL); + frame.ShowModal(); + #endif +} + +// Init PAD (start emulation) +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void PAD_Initialize(SPADInitialize _PADInitialize) +{ + emulator_running = TRUE; + #ifdef _DEBUG + DEBUG_INIT(); + #endif + + if(SDL_Init(SDL_INIT_JOYSTICK ) < 0) + { + #ifdef _WIN32 + MessageBox(NULL, SDL_GetError(), "Could not initialize SDL!", MB_ICONERROR); + #else + printf("Could not initialize SDL! (%s)\n", SDL_GetError()); + #endif + return; + } + + #ifdef _WIN32 + m_hWnd = (HWND)_PADInitialize.hWnd; + #endif + + LoadConfig(); // Load joystick mapping + + if(joysticks[0].enabled) + joystate[0].joy = SDL_JoystickOpen(joysticks[0].ID); + if(joysticks[1].enabled) + joystate[1].joy = SDL_JoystickOpen(joysticks[1].ID); + if(joysticks[2].enabled) + joystate[2].joy = SDL_JoystickOpen(joysticks[2].ID); + if(joysticks[3].enabled) + joystate[3].joy = SDL_JoystickOpen(joysticks[3].ID); +} + +// Shutdown PAD (stop emulation) +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void PAD_Shutdown() +{ + if(joysticks[0].enabled) + SDL_JoystickClose(joystate[0].joy); + if(joysticks[1].enabled) + SDL_JoystickClose(joystate[1].joy); + if(joysticks[2].enabled) + SDL_JoystickClose(joystate[2].joy); + if(joysticks[3].enabled) + SDL_JoystickClose(joystate[3].joy); + + SDL_Quit(); + + #ifdef _DEBUG + DEBUG_QUIT(); + #endif + + delete [] joyinfo; + + emulator_running = FALSE; + + #ifdef _WIN32 + #ifdef USE_RUMBLE_DINPUT_HACK + FreeDirectInput(); + #endif + #elif defined(__linux__) + close(fd); + #endif +} + +// Set PAD status +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) +{ + if(!joysticks[_numPAD].enabled) + return; + + // clear pad status + memset(_pPADStatus, 0, sizeof(SPADStatus)); + + // get pad status + GetJoyState(_numPAD); + + // Reset! + int base = 0x80; + _pPADStatus->stickY = base; + _pPADStatus->stickX = base; + _pPADStatus->substickX = base; + _pPADStatus->substickY = base; + _pPADStatus->button |= PAD_USE_ORIGIN; + + // Set analog controllers + // Set Deadzones perhaps out of function + int deadzone = (int)(((float)(128.00/100.00)) * (float)(joysticks[_numPAD].deadzone+1)); + int deadzone2 = (int)(((float)(-128.00/100.00)) * (float)(joysticks[_numPAD].deadzone+1)); + + // Adjust range + // The value returned by SDL_JoystickGetAxis is a signed integer (-32768 to 32768) + // The value used for the gamecube controller is an unsigned char (0 to 255) + int main_stick_x = (joystate[_numPAD].buttons[CTL_MAIN_X]>>8); + int main_stick_y = -(joystate[_numPAD].buttons[CTL_MAIN_Y]>>8); + int sub_stick_x = (joystate[_numPAD].buttons[CTL_SUB_X]>>8); + int sub_stick_y = -(joystate[_numPAD].buttons[CTL_SUB_Y]>>8); + + // Quick fix + if(main_stick_x > 127) + main_stick_x = 127; + if(main_stick_y > 127) + main_stick_y = 127; + if(sub_stick_x > 127) + sub_stick_x = 127; + if(sub_stick_y > 127) + sub_stick_y = 127; + + if(main_stick_x < -128) + main_stick_x = -128; + if(main_stick_y < -128) + main_stick_y = -128; + if(sub_stick_x < -128) + sub_stick_x = -128; + if(sub_stick_y < -128) + sub_stick_y = -128; + + // Send values to Dolpin + if ((main_stick_x < deadzone2) || (main_stick_x > deadzone)) _pPADStatus->stickX += main_stick_x; + if ((main_stick_y < deadzone2) || (main_stick_y > deadzone)) _pPADStatus->stickY += main_stick_y; + if ((sub_stick_x < deadzone2) || (sub_stick_x > deadzone)) _pPADStatus->substickX += sub_stick_x; + if ((sub_stick_y < deadzone2) || (sub_stick_y > deadzone)) _pPADStatus->substickY += sub_stick_y; + + int triggervalue = 255; + if (joystate[_numPAD].halfpress) + triggervalue = 100; + + // Set buttons + if (joystate[_numPAD].buttons[CTL_L_SHOULDER]) + { + _pPADStatus->button|=PAD_TRIGGER_L; + _pPADStatus->triggerLeft = triggervalue; + } + if (joystate[_numPAD].buttons[CTL_R_SHOULDER]) + { + _pPADStatus->button|=PAD_TRIGGER_R; + _pPADStatus->triggerRight = triggervalue; + } + + if (joystate[_numPAD].buttons[CTL_A_BUTTON]) + { + _pPADStatus->button|=PAD_BUTTON_A; + _pPADStatus->analogA = 255; // Perhaps support pressure? + } + if (joystate[_numPAD].buttons[CTL_B_BUTTON]) + { + _pPADStatus->button|=PAD_BUTTON_B; + _pPADStatus->analogB = 255; // Perhaps support pressure? + } + if (joystate[_numPAD].buttons[CTL_X_BUTTON]) _pPADStatus->button|=PAD_BUTTON_X; + if (joystate[_numPAD].buttons[CTL_Y_BUTTON]) _pPADStatus->button|=PAD_BUTTON_Y; + if (joystate[_numPAD].buttons[CTL_Z_TRIGGER]) _pPADStatus->button|=PAD_TRIGGER_Z; + if (joystate[_numPAD].buttons[CTL_START]) _pPADStatus->button|=PAD_BUTTON_START; + + // Set D-pad + if(joysticks[_numPAD].controllertype == CTL_TYPE_JOYSTICK) + { + if(joystate[_numPAD].dpad == SDL_HAT_LEFTUP || joystate[_numPAD].dpad == SDL_HAT_UP || joystate[_numPAD].dpad == SDL_HAT_RIGHTUP ) _pPADStatus->button|=PAD_BUTTON_UP; + if(joystate[_numPAD].dpad == SDL_HAT_LEFTUP || joystate[_numPAD].dpad == SDL_HAT_LEFT || joystate[_numPAD].dpad == SDL_HAT_LEFTDOWN ) _pPADStatus->button|=PAD_BUTTON_LEFT; + if(joystate[_numPAD].dpad == SDL_HAT_LEFTDOWN || joystate[_numPAD].dpad == SDL_HAT_DOWN || joystate[_numPAD].dpad == SDL_HAT_RIGHTDOWN ) _pPADStatus->button|=PAD_BUTTON_DOWN; + if(joystate[_numPAD].dpad == SDL_HAT_RIGHTUP || joystate[_numPAD].dpad == SDL_HAT_RIGHT || joystate[_numPAD].dpad == SDL_HAT_RIGHTDOWN ) _pPADStatus->button|=PAD_BUTTON_RIGHT; + } + else + { + if(joystate[_numPAD].dpad2[CTL_D_PAD_UP]) + _pPADStatus->button|=PAD_BUTTON_UP; + if(joystate[_numPAD].dpad2[CTL_D_PAD_DOWN]) + _pPADStatus->button|=PAD_BUTTON_DOWN; + if(joystate[_numPAD].dpad2[CTL_D_PAD_LEFT]) + _pPADStatus->button|=PAD_BUTTON_LEFT; + if(joystate[_numPAD].dpad2[CTL_D_PAD_RIGHT]) + _pPADStatus->button|=PAD_BUTTON_RIGHT; + } + + _pPADStatus->err = PAD_ERR_NONE; + + + #ifdef _WIN32 + #ifdef USE_RUMBLE_DINPUT_HACK + if(joystate[_numPAD].halfpress) + if(!g_pDI) + if(FAILED(InitDirectInput(m_hWnd))) + { + MessageBox(NULL, SDL_GetError(), "Could not initialize DirectInput!", MB_ICONERROR); + g_rumbleEnable = FALSE; + //return; + } + else + g_rumbleEnable = TRUE; + + if (g_rumbleEnable) + { + g_pDevice->Acquire(); + + if(g_pEffect) + g_pEffect->Start(1, 0); + } + #endif + #elif defined(__linux__) + if(!fd) + { + sprintf(device_file_name, "/dev/input/event%d", joysticks[_numPAD].eventnum); //TODO: Make dynamic // + + /* Open device */ + fd = open(device_file_name, O_RDWR); + if (fd == -1) { + perror("Open device file"); + //Something wrong, probably permissions, just return now + return; + } + int n_effects = 0; + if (ioctl(fd, EVIOCGEFFECTS, &n_effects) == -1) { + perror("Ioctl number of effects"); + } + if(n_effects > 0) + CanRumble = true; + else + return; // Return since we can't do any effects + /* a strong rumbling effect */ + effect.type = FF_RUMBLE; + effect.id = -1; + effect.u.rumble.strong_magnitude = 0x8000; + effect.u.rumble.weak_magnitude = 0; + effect.replay.length = 5000; // Set to 5 seconds, if a Game needs more for a single rumble event, it is dumb and must be a demo + effect.replay.delay = 0; + if (ioctl(fd, EVIOCSFF, &effect) == -1) { + perror("Upload effect"); + CanRumble = false; //We have effects but it doesn't support the rumble we are using. This is basic rumble, should work for most + } + } + #endif +} + +// Set PAD rumble +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +// (Stop=0, Rumble=1) +void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength) +{ + //if(_numPAD > 0) + // return; + + // not supported by SDL + // So we need to use platform specific stuff + #ifdef _WIN32 + #ifdef USE_RUMBLE_DINPUT_HACK + static int a = 0; + + if ((_uType == 0) || (_uType == 2)) + { + a = 0; + } + else if (_uType == 1) + { + a = _uStrength > 2 ? 8000 : 0; + } + + a = int ((float)a * 0.96f); + + if (!g_rumbleEnable) + { + a = 0; + } + else + { + g_nYForce = a; + SetDeviceForcesXY(); + } + #endif + #elif defined(__linux__) + struct input_event event; + if(CanRumble) + { + if (_uType == 1) + { + event.type = EV_FF; + event.code = effect.id; + event.value = 1; + if (write(fd, (const void*) &event, sizeof(event)) == -1) { + perror("Play effect"); + exit(1); + } + } + if ((_uType == 0) || (_uType == 2)) + { + event.type = EV_FF; + event.code = effect.id; + event.value = 0; + if (write(fd, (const void*) &event, sizeof(event)) == -1) { + perror("Stop effect"); + exit(1); + } + } + } + #endif +} + +// Set PAD attached pads +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +unsigned int PAD_GetAttachedPads() +{ + unsigned int connected = 0; + + LoadConfig(); + + if(joysticks[0].enabled) + connected |= 1; + if(joysticks[1].enabled) + connected |= 2; + if(joysticks[2].enabled) + connected |= 4; + if(joysticks[3].enabled) + connected |= 8; + + return connected; +} + +// Savestates +// ŻŻŻŻŻŻŻŻŻŻ +unsigned int SaveLoadState(char *ptr, BOOL save) +{ + // not used + return 0; +} + +////////////////////////////////////////////////////////////////////////////////////////// +// Custom Functions +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ + +// Request joystick state +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void GetJoyState(int controller) +{ + SDL_JoystickUpdate(); + + for(int a = 0; a < CTRL_END; a++) + { + char Type = (joysticks[controller].buttons[a].c_str())[0]; + //printf("Type %c, entire %s\n", Type, joysticks[controller].buttons[a].c_str()); + switch(Type) + { + case 'A': + joystate[controller].buttons[a] = SDL_JoystickGetAxis(joystate[controller].joy, atoi(joysticks[controller].buttons[a].c_str() + 2)); // Skip the A AND the +/- sign + break; + case 'B': + joystate[controller].buttons[a] = SDL_JoystickGetButton(joystate[controller].joy, atoi(joysticks[controller].buttons[a].c_str() + 1)); + break; + case 'H': + printf("We aren't Expecting Hat here!\n"); + break; + default: + printf("Unknown button type %c, number %d, Full %s\n", Type, a, joysticks[controller].buttons[a].c_str()); + break; + } + } + + joystate[controller].halfpress = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].halfpress); + + if(joysticks[controller].controllertype == CTL_TYPE_JOYSTICK) + joystate[controller].dpad = SDL_JoystickGetHat(joystate[controller].joy, joysticks[controller].dpad); + else + { + joystate[controller].dpad2[CTL_D_PAD_UP] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].dpad2[CTL_D_PAD_UP]); + joystate[controller].dpad2[CTL_D_PAD_DOWN] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].dpad2[CTL_D_PAD_DOWN]); + joystate[controller].dpad2[CTL_D_PAD_LEFT] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].dpad2[CTL_D_PAD_LEFT]); + joystate[controller].dpad2[CTL_D_PAD_RIGHT] = SDL_JoystickGetButton(joystate[controller].joy, joysticks[controller].dpad2[CTL_D_PAD_RIGHT]); + } +} + +// Search attached devices +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +int Search_Devices() +{ + // load config + #ifdef _DEBUG + DEBUG_INIT(); + #endif + + int numjoy = SDL_NumJoysticks(); + + if(numjoy == 0) + { + #ifdef _WIN32 + MessageBox(NULL, "No Joystick detected!", NULL, MB_ICONWARNING); + #else + printf("No Joystick detected!\n"); + #endif + return 0; + } + + if(joyinfo) + { + delete [] joyinfo; + joyinfo = new CONTROLLER_INFO [numjoy]; + } + else + { + joyinfo = new CONTROLLER_INFO [numjoy]; + } + + #ifdef _DEBUG + fprintf(pFile, "Scanning for devices\n"); + fprintf(pFile, "ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ\n"); + #endif + + for(int i = 0; i < numjoy; i++ ) + { + joyinfo[i].joy = SDL_JoystickOpen(i); + joyinfo[i].ID = i; + joyinfo[i].NumAxes = SDL_JoystickNumAxes(joyinfo[i].joy); + joyinfo[i].NumButtons = SDL_JoystickNumButtons(joyinfo[i].joy); + joyinfo[i].NumBalls = SDL_JoystickNumBalls(joyinfo[i].joy); + joyinfo[i].NumHats = SDL_JoystickNumHats(joyinfo[i].joy); + joyinfo[i].Name = SDL_JoystickName(i); + + printf("ID: %d\n", i); + printf("Name: %s\n", joyinfo[i].Name); + printf("Buttons: %d\n", joyinfo[i].NumButtons); + printf("Axises: %d\n", joyinfo[i].NumAxes); + printf("Hats: %d\n", joyinfo[i].NumHats); + printf("Balls: %d\n\n", joyinfo[i].NumBalls); + + // Close if opened + if(SDL_JoystickOpened(i)) + SDL_JoystickClose(joyinfo[i].joy); + } + + return numjoy; +} + +// Enable output log +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void DEBUG_INIT() +{ + if(pFile) + return; + + #ifdef _WIN32 + char dateStr [9]; + _strdate( dateStr); + char timeStr [9]; + _strtime( timeStr ); + #endif + + pFile = fopen ("nJoy-debug.txt","wt"); + fprintf(pFile, "nJoy v"INPUT_VERSION" Debug\n"); + #ifdef _WIN32 + fprintf(pFile, "Date: %s\nTime: %s\n", dateStr, timeStr); + #endif + fprintf(pFile, "ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ\n"); +} + +// Disable output log +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void DEBUG_QUIT() +{ + if(!pFile) + return; + + #ifdef _WIN32 + char timeStr [9]; + _strtime(timeStr); + + fprintf(pFile, "_______________\n"); + fprintf(pFile, "Time: %s", timeStr); + #endif + fclose(pFile); +} + +// Save settings to file +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void SaveConfig() +{ + IniFile file; + file.Load("nJoy.ini"); + + for (int i=0; i<4; i++) + { + char SectionName[32]; + sprintf(SectionName, "PAD%i", i+1); + + file.Set(SectionName, "l_shoulder", joysticks[i].buttons[CTL_L_SHOULDER]); + file.Set(SectionName, "r_shoulder", joysticks[i].buttons[CTL_R_SHOULDER]); + file.Set(SectionName, "a_button", joysticks[i].buttons[CTL_A_BUTTON]); + file.Set(SectionName, "b_button", joysticks[i].buttons[CTL_B_BUTTON]); + file.Set(SectionName, "x_button", joysticks[i].buttons[CTL_X_BUTTON]); + file.Set(SectionName, "y_button", joysticks[i].buttons[CTL_Y_BUTTON]); + file.Set(SectionName, "z_trigger", joysticks[i].buttons[CTL_Z_TRIGGER]); + file.Set(SectionName, "start_button", joysticks[i].buttons[CTL_START]); + file.Set(SectionName, "dpad", joysticks[i].dpad); + file.Set(SectionName, "dpad_up", joysticks[i].dpad2[CTL_D_PAD_UP]); + file.Set(SectionName, "dpad_down", joysticks[i].dpad2[CTL_D_PAD_DOWN]); + file.Set(SectionName, "dpad_left", joysticks[i].dpad2[CTL_D_PAD_LEFT]); + file.Set(SectionName, "dpad_right", joysticks[i].dpad2[CTL_D_PAD_RIGHT]); + file.Set(SectionName, "main_x", joysticks[i].buttons[CTL_MAIN_X]); + file.Set(SectionName, "main_y", joysticks[i].buttons[CTL_MAIN_Y]); + file.Set(SectionName, "sub_x", joysticks[i].buttons[CTL_SUB_X]); + file.Set(SectionName, "sub_y", joysticks[i].buttons[CTL_SUB_Y]); + file.Set(SectionName, "enabled", joysticks[i].enabled); + file.Set(SectionName, "deadzone", joysticks[i].deadzone); + file.Set(SectionName, "halfpress", joysticks[i].halfpress); + file.Set(SectionName, "joy_id", joysticks[i].ID); + file.Set(SectionName, "controllertype", joysticks[i].controllertype); + file.Set(SectionName, "eventnum", joysticks[i].eventnum); + for(int a = 0; a < MAX_AXISES; a++) + { + char Section[32]; + sprintf(Section, "SAxis%dMin", a); + file.Set(SectionName, Section, (int)joysticks[i].sData[a].Min); + sprintf(Section, "SAxis%dMax", a); + file.Set(SectionName, Section, (int)joysticks[i].sData[a].Max); + } + } + + file.Save("nJoy.ini"); +} + +// Load settings from file +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void LoadConfig() +{ + IniFile file; + file.Load("nJoy.ini"); + + for (int i=0; i<4; i++) + { + char SectionName[32]; + sprintf(SectionName, "PAD%i", i+1); + + file.Get(SectionName, "l_shoulder", &joysticks[i].buttons[CTL_L_SHOULDER], "B4"); + file.Get(SectionName, "r_shoulder", &joysticks[i].buttons[CTL_R_SHOULDER], "B5"); + file.Get(SectionName, "a_button", &joysticks[i].buttons[CTL_A_BUTTON], "B0"); + file.Get(SectionName, "b_button", &joysticks[i].buttons[CTL_B_BUTTON], "B1"); + file.Get(SectionName, "x_button", &joysticks[i].buttons[CTL_X_BUTTON], "B3"); + file.Get(SectionName, "y_button", &joysticks[i].buttons[CTL_Y_BUTTON], "B2"); + file.Get(SectionName, "z_trigger", &joysticks[i].buttons[CTL_Z_TRIGGER], "B7"); + file.Get(SectionName, "start_button", &joysticks[i].buttons[CTL_START], "B9"); + file.Get(SectionName, "dpad", &joysticks[i].dpad, 0); + file.Get(SectionName, "dpad_up", &joysticks[i].dpad2[CTL_D_PAD_UP], 0); + file.Get(SectionName, "dpad_down", &joysticks[i].dpad2[CTL_D_PAD_DOWN], 0); + file.Get(SectionName, "dpad_left", &joysticks[i].dpad2[CTL_D_PAD_LEFT], 0); + file.Get(SectionName, "dpad_right", &joysticks[i].dpad2[CTL_D_PAD_RIGHT], 0); + file.Get(SectionName, "main_x", &joysticks[i].buttons[CTL_MAIN_X], "A0"); + file.Get(SectionName, "main_y", &joysticks[i].buttons[CTL_MAIN_Y], "A1"); + file.Get(SectionName, "sub_x", &joysticks[i].buttons[CTL_SUB_X], "A2"); + file.Get(SectionName, "sub_y", &joysticks[i].buttons[CTL_SUB_Y], "A3"); + file.Get(SectionName, "enabled", &joysticks[i].enabled, 1); + file.Get(SectionName, "deadzone", &joysticks[i].deadzone, 9); + file.Get(SectionName, "halfpress", &joysticks[i].halfpress, 6); + file.Get(SectionName, "joy_id", &joysticks[i].ID, 0); + file.Get(SectionName, "controllertype", &joysticks[i].controllertype, 0); + file.Get(SectionName, "eventnum", &joysticks[i].eventnum, 0); + for(int a = 0; a < MAX_AXISES; a++) + { + char Section[32]; + int Min; + int Max; + sprintf(Section, "SAxis%dMin", a); + file.Get(SectionName, Section, &Min, 0); + sprintf(Section, "SAxis%dMax", a); + file.Get(SectionName, Section, &Max, 0); + joysticks[i].sData[a].Min = Min; + joysticks[i].sData[a].Max = Max; + } + } +} + + +#ifdef _WIN32 +////////////////////////////////////////////////////////////////////////////////////////// +// Rumble stuff :D! +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +// +#ifdef USE_RUMBLE_DINPUT_HACK +HRESULT InitDirectInput( HWND hDlg ) +{ + DIPROPDWORD dipdw; + HRESULT hr; + + // Register with the DirectInput subsystem and get a pointer to a IDirectInput interface we can use. + if(FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&g_pDI, NULL))) + { + return hr; + } + + // Look for a force feedback device we can use + if(FAILED(hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, EnumFFDevicesCallback, NULL, DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK))) + { + return hr; + } + + if(NULL == g_pDevice) + { + MessageBox(NULL, "Force feedback device not found. nJoy will now disable rumble." ,"FFConst" , MB_ICONERROR | MB_OK); + g_rumbleEnable = FALSE; + + return S_OK; + } + + // Set the data format to "simple joystick" - a predefined data format. A + // data format specifies which controls on a device we are interested in, + // and how they should be reported. + // + // This tells DirectInput that we will be passing a DIJOYSTATE structure to + // IDirectInputDevice8::GetDeviceState(). Even though we won't actually do + // it in this sample. But setting the data format is important so that the + // DIJOFS_* values work properly. + if(FAILED(hr = g_pDevice->SetDataFormat(&c_dfDIJoystick))) + return hr; + + // Set the cooperative level to let DInput know how this device should + // interact with the system and with other DInput applications. + // Exclusive access is required in order to perform force feedback. + //if(FAILED(hr = g_pDevice->SetCooperativeLevel(hDlg, DISCL_EXCLUSIVE | DISCL_FOREGROUND))) + + if(FAILED(hr = g_pDevice->SetCooperativeLevel(hDlg, DISCL_EXCLUSIVE | DISCL_FOREGROUND))) + { + return hr; + } + + // Since we will be playing force feedback effects, we should disable the + // auto-centering spring. + dipdw.diph.dwSize = sizeof(DIPROPDWORD); + dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); + dipdw.diph.dwObj = 0; + dipdw.diph.dwHow = DIPH_DEVICE; + dipdw.dwData = FALSE; + + if(FAILED(hr = g_pDevice->SetProperty(DIPROP_AUTOCENTER, &dipdw.diph))) + return hr; + + // Enumerate and count the axes of the joystick + if(FAILED(hr = g_pDevice->EnumObjects(EnumAxesCallback, (VOID*)&g_dwNumForceFeedbackAxis, DIDFT_AXIS))) + return hr; + + // This simple sample only supports one or two axis joysticks + if(g_dwNumForceFeedbackAxis > 2) + g_dwNumForceFeedbackAxis = 2; + + // This application needs only one effect: Applying raw forces. + DWORD rgdwAxes[2] = {DIJOFS_X, DIJOFS_Y}; + LONG rglDirection[2] = {0, 0}; + DICONSTANTFORCE cf = {0}; + + DIEFFECT eff; + ZeroMemory(&eff, sizeof(eff)); + eff.dwSize = sizeof(DIEFFECT); + eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; + eff.dwDuration = INFINITE; + eff.dwSamplePeriod = 0; + eff.dwGain = DI_FFNOMINALMAX; + eff.dwTriggerButton = DIEB_NOTRIGGER; + eff.dwTriggerRepeatInterval = 0; + eff.cAxes = g_dwNumForceFeedbackAxis; + eff.rgdwAxes = rgdwAxes; + eff.rglDirection = rglDirection; + eff.lpEnvelope = 0; + eff.cbTypeSpecificParams = sizeof( DICONSTANTFORCE ); + eff.lpvTypeSpecificParams = &cf; + eff.dwStartDelay = 0; + + // Create the prepared effect + if(FAILED(hr = g_pDevice->CreateEffect(GUID_ConstantForce, &eff, &g_pEffect, NULL))) + { + return hr; + } + + if(NULL == g_pEffect) + return E_FAIL; + + return S_OK; +} + +VOID FreeDirectInput() +{ + // Unacquire the device one last time just in case + // the app tried to exit while the device is still acquired. + if(g_pDevice) + g_pDevice->Unacquire(); + + // Release any DirectInput objects. + SAFE_RELEASE(g_pEffect); + SAFE_RELEASE(g_pDevice); + SAFE_RELEASE(g_pDI); +} + +BOOL CALLBACK EnumFFDevicesCallback( const DIDEVICEINSTANCE* pInst, VOID* pContext ) +{ + LPDIRECTINPUTDEVICE8 pDevice; + HRESULT hr; + + // Obtain an interface to the enumerated force feedback device. + hr = g_pDI->CreateDevice(pInst->guidInstance, &pDevice, NULL); + + // If it failed, then we can't use this device for some bizarre reason. + // (Maybe the user unplugged it while we were in the middle of enumerating it.) So continue enumerating + if( FAILED(hr)) + return DIENUM_CONTINUE; + + // We successfully created an IDirectInputDevice8. So stop looking for another one. + g_pDevice = pDevice; + + return DIENUM_STOP; +} + +BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext) +{ + DWORD* pdwNumForceFeedbackAxis = (DWORD*)pContext; + if((pdidoi->dwFlags & DIDOI_FFACTUATOR) != 0) + (*pdwNumForceFeedbackAxis)++; + + return DIENUM_CONTINUE; +} + +HRESULT SetDeviceForcesXY() +{ + // Modifying an effect is basically the same as creating a new one, except you need only specify the parameters you are modifying + LONG rglDirection[2] = { 0, 0 }; + + DICONSTANTFORCE cf; + + if( g_dwNumForceFeedbackAxis == 1 ) + { + // If only one force feedback axis, then apply only one direction and keep the direction at zero + cf.lMagnitude = g_nXForce; + rglDirection[0] = 0; + } + else + { + // If two force feedback axis, then apply magnitude from both directions + rglDirection[0] = g_nXForce; + rglDirection[1] = g_nYForce; + cf.lMagnitude = (DWORD)sqrt((double)g_nXForce * (double)g_nXForce + (double)g_nYForce * (double)g_nYForce ); + } + + DIEFFECT eff; + ZeroMemory(&eff, sizeof(eff)); + eff.dwSize = sizeof(DIEFFECT); + eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; + eff.cAxes = g_dwNumForceFeedbackAxis; + eff.rglDirection = rglDirection; + eff.lpEnvelope = 0; + eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE); + eff.lpvTypeSpecificParams = &cf; + eff.dwStartDelay = 0; + + // Now set the new parameters and start the effect immediately. + return g_pEffect->SetParameters(&eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START); +} +#endif +#endif