mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
set svn:eol-style=native for Plugins/**.cpp
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1441 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -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");
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
// ==============
|
||||
|
@ -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 <iostream>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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 <iostream>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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<<mode;
|
||||
m_AliasModeCB->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<<mode;
|
||||
m_AliasModeCB->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());
|
||||
}
|
||||
|
@ -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 <wx/wx.h>
|
||||
#include <wx/filepicker.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/aboutdlg.h>
|
||||
#endif
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
#include "pluginspecs_video.h"
|
||||
#include "main.h"
|
||||
|
||||
#include "IniFile.h"
|
||||
#include <assert.h>
|
||||
|
||||
#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 <wx/wx.h>
|
||||
#include <wx/filepicker.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/aboutdlg.h>
|
||||
#endif
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
#include "pluginspecs_video.h"
|
||||
#include "main.h"
|
||||
|
||||
#include "IniFile.h"
|
||||
#include <assert.h>
|
||||
|
||||
#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
|
||||
}
|
||||
|
@ -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 <stdio.h>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#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<u32> 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 <stdio.h>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#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<u32> 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;
|
||||
}
|
||||
|
@ -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 <string>
|
||||
#include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#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 <string>
|
||||
#include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#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
|
||||
|
@ -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 <iostream>
|
||||
#include <vector>
|
||||
#include <string> // so that we can test std::string == abc
|
||||
#include <math.h> // for the pow() function
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#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<u16> 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 <iostream>
|
||||
#include <vector>
|
||||
#include <string> // so that we can test std::string == abc
|
||||
#include <math.h> // for the pow() function
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#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<u16> 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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 <windows.h>
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/filepicker.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/aboutdlg.h>
|
||||
|
||||
#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 <windows.h>
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/filepicker.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/aboutdlg.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
@ -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);"
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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 <map>
|
||||
|
||||
#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<VertexLoaderUID, VertexLoader *> 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 <map>
|
||||
|
||||
#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<VertexLoaderUID, VertexLoader *> 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;
|
||||
}
|
||||
}
|
||||
|
@ -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]<<ASHIFT;
|
||||
col |= lut4to8[(val>>12)&0xF] <<RSHIFT;
|
||||
col |= lut4to8[(val>>8)&0xF] <<GSHIFT;
|
||||
col |= lut4to8[(val>>4)&0xF] <<BSHIFT;
|
||||
_SetCol(col);
|
||||
}
|
||||
|
||||
void _SetCol6666(u32 val)
|
||||
{
|
||||
u32 col = lut6to8[(val>>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<<ASHIFT));
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline u32 _Read24(u32 iAddress)
|
||||
{
|
||||
u32 col = Memory_Read_U8(iAddress) << RSHIFT; //should just get a pointer to main memory instead of going thru slow memhandler
|
||||
col |= Memory_Read_U8(iAddress+1) << GSHIFT; //we can guarantee that it is reading from main memory
|
||||
col |= Memory_Read_U8(iAddress+2) << BSHIFT;
|
||||
return col | (0xFF<<ASHIFT);
|
||||
}
|
||||
|
||||
inline u32 _Read32(u32 iAddress)
|
||||
{
|
||||
u32 col = Memory_Read_U8(iAddress) << RSHIFT; //should just get a pointer to main memory instead of going thru slow memhandler
|
||||
col |= Memory_Read_U8(iAddress+1) << GSHIFT; //we can guarantee that it is reading from main memory
|
||||
col |= Memory_Read_U8(iAddress+2) << BSHIFT;
|
||||
col |= Memory_Read_U8(iAddress+3) << ASHIFT;
|
||||
return col;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void LOADERDECL Color_ReadDirect_24b_888()
|
||||
{
|
||||
u32 col = DataReadU8()<<RSHIFT;
|
||||
col |= DataReadU8()<<GSHIFT;
|
||||
col |= DataReadU8()<<BSHIFT;
|
||||
_SetCol(col | (0xFF<<ASHIFT));
|
||||
}
|
||||
|
||||
void LOADERDECL Color_ReadDirect_32b_888x(){
|
||||
u32 col = DataReadU8()<<RSHIFT;
|
||||
col |= DataReadU8()<<GSHIFT;
|
||||
col |= DataReadU8()<<BSHIFT;
|
||||
_SetCol(col | (0xFF<<ASHIFT));
|
||||
DataReadU8();
|
||||
}
|
||||
void LOADERDECL Color_ReadDirect_16b_565()
|
||||
{
|
||||
_SetCol565(DataReadU16());
|
||||
}
|
||||
void LOADERDECL Color_ReadDirect_16b_4444()
|
||||
{
|
||||
_SetCol4444(DataReadU16());
|
||||
}
|
||||
void LOADERDECL Color_ReadDirect_24b_6666()
|
||||
{
|
||||
u32 val = DataReadU8()<<16;
|
||||
val|=DataReadU8()<<8;
|
||||
val|=DataReadU8();
|
||||
_SetCol6666(val);
|
||||
}
|
||||
|
||||
// F|RES: i am not 100 percent show, but the colElements seems to be important for rendering only
|
||||
// at least it fixes mario party 4
|
||||
//
|
||||
// if (colElements[colIndex])
|
||||
// else
|
||||
// col |= 0xFF<<ASHIFT;
|
||||
//
|
||||
void LOADERDECL Color_ReadDirect_32b_8888()
|
||||
{
|
||||
// TODO (mb2): check this
|
||||
u32 col = DataReadU8()<<RSHIFT;
|
||||
col |= DataReadU8()<<GSHIFT;
|
||||
col |= DataReadU8()<<BSHIFT;
|
||||
col |= DataReadU8()<<ASHIFT;
|
||||
|
||||
// "kill" the alpha
|
||||
if (!colElements[colIndex])
|
||||
col |= 0xFF<<ASHIFT;
|
||||
|
||||
_SetCol(col);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void LOADERDECL Color_ReadIndex8_16b_565()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u16 val = Memory_Read_U16(iAddress);
|
||||
_SetCol565(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_24b_888()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read24(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_32b_888x()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR]+colIndex);
|
||||
_SetCol(_Read24(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_16b_4444()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u16 val = Memory_Read_U16(iAddress);
|
||||
_SetCol4444(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_24b_6666()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u32 val = Memory_Read_U8(iAddress+2) |
|
||||
(Memory_Read_U8(iAddress+1)<<8) |
|
||||
(Memory_Read_U8(iAddress)<<16);
|
||||
|
||||
_SetCol6666(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_32b_8888()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read32(iAddress));
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void LOADERDECL Color_ReadIndex16_16b_565()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u16 val = Memory_Read_U16(iAddress);
|
||||
_SetCol565(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_24b_888()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read24(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_32b_888x()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read24(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_16b_4444()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u16 val = Memory_Read_U16(iAddress);
|
||||
_SetCol4444(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_24b_6666()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u32 val = Memory_Read_U8(iAddress+2) |
|
||||
(Memory_Read_U8(iAddress+1)<<8) |
|
||||
(Memory_Read_U8(iAddress)<<16);
|
||||
_SetCol6666(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_32b_8888()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read32(iAddress));
|
||||
}
|
||||
|
||||
#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 _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]<<ASHIFT;
|
||||
col |= lut4to8[(val>>12)&0xF] <<RSHIFT;
|
||||
col |= lut4to8[(val>>8)&0xF] <<GSHIFT;
|
||||
col |= lut4to8[(val>>4)&0xF] <<BSHIFT;
|
||||
_SetCol(col);
|
||||
}
|
||||
|
||||
void _SetCol6666(u32 val)
|
||||
{
|
||||
u32 col = lut6to8[(val>>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<<ASHIFT));
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
inline u32 _Read24(u32 iAddress)
|
||||
{
|
||||
u32 col = Memory_Read_U8(iAddress) << RSHIFT; //should just get a pointer to main memory instead of going thru slow memhandler
|
||||
col |= Memory_Read_U8(iAddress+1) << GSHIFT; //we can guarantee that it is reading from main memory
|
||||
col |= Memory_Read_U8(iAddress+2) << BSHIFT;
|
||||
return col | (0xFF<<ASHIFT);
|
||||
}
|
||||
|
||||
inline u32 _Read32(u32 iAddress)
|
||||
{
|
||||
u32 col = Memory_Read_U8(iAddress) << RSHIFT; //should just get a pointer to main memory instead of going thru slow memhandler
|
||||
col |= Memory_Read_U8(iAddress+1) << GSHIFT; //we can guarantee that it is reading from main memory
|
||||
col |= Memory_Read_U8(iAddress+2) << BSHIFT;
|
||||
col |= Memory_Read_U8(iAddress+3) << ASHIFT;
|
||||
return col;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void LOADERDECL Color_ReadDirect_24b_888()
|
||||
{
|
||||
u32 col = DataReadU8()<<RSHIFT;
|
||||
col |= DataReadU8()<<GSHIFT;
|
||||
col |= DataReadU8()<<BSHIFT;
|
||||
_SetCol(col | (0xFF<<ASHIFT));
|
||||
}
|
||||
|
||||
void LOADERDECL Color_ReadDirect_32b_888x(){
|
||||
u32 col = DataReadU8()<<RSHIFT;
|
||||
col |= DataReadU8()<<GSHIFT;
|
||||
col |= DataReadU8()<<BSHIFT;
|
||||
_SetCol(col | (0xFF<<ASHIFT));
|
||||
DataReadU8();
|
||||
}
|
||||
void LOADERDECL Color_ReadDirect_16b_565()
|
||||
{
|
||||
_SetCol565(DataReadU16());
|
||||
}
|
||||
void LOADERDECL Color_ReadDirect_16b_4444()
|
||||
{
|
||||
_SetCol4444(DataReadU16());
|
||||
}
|
||||
void LOADERDECL Color_ReadDirect_24b_6666()
|
||||
{
|
||||
u32 val = DataReadU8()<<16;
|
||||
val|=DataReadU8()<<8;
|
||||
val|=DataReadU8();
|
||||
_SetCol6666(val);
|
||||
}
|
||||
|
||||
// F|RES: i am not 100 percent show, but the colElements seems to be important for rendering only
|
||||
// at least it fixes mario party 4
|
||||
//
|
||||
// if (colElements[colIndex])
|
||||
// else
|
||||
// col |= 0xFF<<ASHIFT;
|
||||
//
|
||||
void LOADERDECL Color_ReadDirect_32b_8888()
|
||||
{
|
||||
// TODO (mb2): check this
|
||||
u32 col = DataReadU8()<<RSHIFT;
|
||||
col |= DataReadU8()<<GSHIFT;
|
||||
col |= DataReadU8()<<BSHIFT;
|
||||
col |= DataReadU8()<<ASHIFT;
|
||||
|
||||
// "kill" the alpha
|
||||
if (!colElements[colIndex])
|
||||
col |= 0xFF<<ASHIFT;
|
||||
|
||||
_SetCol(col);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void LOADERDECL Color_ReadIndex8_16b_565()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u16 val = Memory_Read_U16(iAddress);
|
||||
_SetCol565(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_24b_888()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read24(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_32b_888x()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR]+colIndex);
|
||||
_SetCol(_Read24(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_16b_4444()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u16 val = Memory_Read_U16(iAddress);
|
||||
_SetCol4444(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_24b_6666()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u32 val = Memory_Read_U8(iAddress+2) |
|
||||
(Memory_Read_U8(iAddress+1)<<8) |
|
||||
(Memory_Read_U8(iAddress)<<16);
|
||||
|
||||
_SetCol6666(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_32b_8888()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read32(iAddress));
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void LOADERDECL Color_ReadIndex16_16b_565()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u16 val = Memory_Read_U16(iAddress);
|
||||
_SetCol565(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_24b_888()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read24(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_32b_888x()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read24(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_16b_4444()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u16 val = Memory_Read_U16(iAddress);
|
||||
_SetCol4444(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_24b_6666()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
u32 val = Memory_Read_U8(iAddress+2) |
|
||||
(Memory_Read_U8(iAddress+1)<<8) |
|
||||
(Memory_Read_U8(iAddress)<<16);
|
||||
_SetCol6666(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_32b_8888()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read32(iAddress));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,424 +1,424 @@
|
||||
// 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 "VertexLoader.h"
|
||||
#include "VertexManager.h"
|
||||
#include "VertexLoader_Normal.h"
|
||||
|
||||
#define LOG_NORM8() PRIM_LOG("norm: %f %f %f, ", ((s8*)VertexManager::s_pCurBufferPointer)[-3]/127.0f, ((s8*)VertexManager::s_pCurBufferPointer)[-2]/127.0f, ((s8*)VertexManager::s_pCurBufferPointer)[-1]/127.0f);
|
||||
#define LOG_NORM16() PRIM_LOG("norm: %f %f %f, ", ((s16*)VertexManager::s_pCurBufferPointer)[-3]/32767.0f, ((s16*)VertexManager::s_pCurBufferPointer)[-2]/32767.0f, ((s16*)VertexManager::s_pCurBufferPointer)[-1]/32767.0f);
|
||||
#define LOG_NORMF() PRIM_LOG("norm: %f %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[-3], ((float*)VertexManager::s_pCurBufferPointer)[-2], ((float*)VertexManager::s_pCurBufferPointer)[-1]);
|
||||
|
||||
VertexLoader_Normal::Set VertexLoader_Normal::m_Table[NUM_NRM_TYPE][NUM_NRM_INDICES][NUM_NRM_ELEMENTS][NUM_NRM_FORMAT];
|
||||
|
||||
void VertexLoader_Normal::Init(void)
|
||||
{
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Set(3, Normal_DirectByte); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Set(3, Normal_DirectByte);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Set(6, Normal_DirectShort); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Set(6, Normal_DirectShort);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Set(12, Normal_DirectFloat);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Set(9, Normal_DirectByte3); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Set(9, Normal_DirectByte3);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Set(18, Normal_DirectShort3); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Set(18, Normal_DirectShort3);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Set(36, Normal_DirectFloat3);
|
||||
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Set(3, Normal_DirectByte); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Set(3, Normal_DirectByte);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Set(6, Normal_DirectShort); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Set(6, Normal_DirectShort);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Set(12, Normal_DirectFloat);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Set(9, Normal_DirectByte3); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Set(9, Normal_DirectByte3);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Set(18, Normal_DirectShort3); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Set(18, Normal_DirectShort3);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Set(36, Normal_DirectFloat3);
|
||||
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Set(1, Normal_Index8_Byte); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Set(1, Normal_Index8_Byte);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Set(1, Normal_Index8_Short); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Set(1, Normal_Index8_Short);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Set(1, Normal_Index8_Float);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Set(1, Normal_Index8_Byte3_Indices1); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Set(1, Normal_Index8_Byte3_Indices1);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Set(1, Normal_Index8_Short3_Indices1); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Set(1, Normal_Index8_Short3_Indices1);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Set(1, Normal_Index8_Float3_Indices1);
|
||||
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Set(1, Normal_Index8_Byte); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Set(1, Normal_Index8_Byte);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Set(1, Normal_Index8_Short); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Set(1, Normal_Index8_Short);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Set(1, Normal_Index8_Float);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Set(3, Normal_Index8_Byte3_Indices3); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Set(3, Normal_Index8_Byte3_Indices3);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Set(3, Normal_Index8_Short3_Indices3); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Set(3, Normal_Index8_Short3_Indices3);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Set(3, Normal_Index8_Float3_Indices3);
|
||||
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Set(2, Normal_Index16_Byte); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Set(2, Normal_Index16_Byte);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Set(2, Normal_Index16_Short); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Set(2, Normal_Index16_Short);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Set(2, Normal_Index16_Float);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Set(2, Normal_Index16_Byte3_Indices1); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Set(2, Normal_Index16_Byte3_Indices1);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Set(2, Normal_Index16_Short3_Indices1); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Set(2, Normal_Index16_Short3_Indices1);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Set(2, Normal_Index16_Float3_Indices1);
|
||||
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Set(2, Normal_Index16_Byte); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Set(2, Normal_Index16_Byte);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Set(2, Normal_Index16_Short); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Set(2, Normal_Index16_Short);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Set(2, Normal_Index16_Float);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Set(6, Normal_Index16_Byte3_Indices3); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Set(6, Normal_Index16_Byte3_Indices3);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Set(6, Normal_Index16_Short3_Indices3); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Set(6, Normal_Index16_Short3_Indices3);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Set(6, Normal_Index16_Float3_Indices3);
|
||||
}
|
||||
|
||||
unsigned int VertexLoader_Normal::GetSize(unsigned int _type, unsigned int _format, unsigned int _elements, unsigned int _index3)
|
||||
{
|
||||
return m_Table[_type][_index3][_elements][_format].gc_size;
|
||||
}
|
||||
|
||||
TPipelineFunction VertexLoader_Normal::GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements, unsigned int _index3)
|
||||
{
|
||||
TPipelineFunction pFunc = m_Table[_type][_index3][_elements][_format].function;
|
||||
return pFunc;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// --- Direct ---
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectByte()
|
||||
{
|
||||
*VertexManager::s_pCurBufferPointer++ = DataReadU8();
|
||||
*VertexManager::s_pCurBufferPointer++ = DataReadU8();
|
||||
*VertexManager::s_pCurBufferPointer++ = DataReadU8();
|
||||
VertexManager::s_pCurBufferPointer++;
|
||||
LOG_NORM8();
|
||||
// ((float*)VertexManager::s_pCurBufferPointer)[0] = ((float)(signed char)DataReadU8()+0.5f) / 127.5f;
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectShort()
|
||||
{
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[0] = DataReadU16();
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[1] = DataReadU16();
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[2] = DataReadU16();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
LOG_NORM16()
|
||||
// ((float*)VertexManager::s_pCurBufferPointer)[0] = ((float)(signed short)DataReadU16()+0.5f) / 32767.5f;
|
||||
// ((float*)VertexManager::s_pCurBufferPointer)[1] = ((float)(signed short)DataReadU16()+0.5f) / 32767.5f;
|
||||
// ((float*)VertexManager::s_pCurBufferPointer)[2] = ((float)(signed short)DataReadU16()+0.5f) / 32767.5f;
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectFloat()
|
||||
{
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = DataReadU32();
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = DataReadU32();
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = DataReadU32();
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORMF()
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectByte3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
*VertexManager::s_pCurBufferPointer++ = DataReadU8();
|
||||
*VertexManager::s_pCurBufferPointer++ = DataReadU8();
|
||||
*VertexManager::s_pCurBufferPointer++ = DataReadU8();
|
||||
VertexManager::s_pCurBufferPointer++;
|
||||
LOG_NORM8();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectShort3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[0] = DataReadU16();
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[1] = DataReadU16();
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[2] = DataReadU16();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
LOG_NORM16();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectFloat3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = DataReadU32();
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = DataReadU32();
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = DataReadU32();
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORMF();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// --- Index8 ---
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Byte()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+1);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+2);
|
||||
VertexManager::s_pCurBufferPointer++;
|
||||
// ((float*)VertexManager::s_pCurBufferPointer)[0] = ((float)(signed char)Memory_Read_U8(iAddress)+0.5f) / 127.5f;
|
||||
// ((float*)VertexManager::s_pCurBufferPointer)[1] = ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f;
|
||||
// ((float*)VertexManager::s_pCurBufferPointer)[2] = ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f;
|
||||
// VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORM8();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Short()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U16(iAddress);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U16(iAddress+2);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U16(iAddress+4);
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
LOG_NORM16();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Float()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress+4);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U32(iAddress+8);
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORMF();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Byte3_Indices1()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+1);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+2);
|
||||
VertexManager::s_pCurBufferPointer++;
|
||||
LOG_NORM8();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Short3_Indices1()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U16(iAddress);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U16(iAddress+2);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U16(iAddress+4);
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
LOG_NORM16();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Float3_Indices1()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress+4);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U32(iAddress+8);
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORMF();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Byte3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+1);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+2);
|
||||
*VertexManager::s_pCurBufferPointer++;
|
||||
LOG_NORM8();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Short3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U16(iAddress);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U16(iAddress+2);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U16(iAddress+4);
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
LOG_NORM16();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Float3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress+4);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U32(iAddress+8);
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORMF();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// --- Index16 ---
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Byte()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+1);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+2);
|
||||
VertexManager::s_pCurBufferPointer++;
|
||||
LOG_NORM8();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Short()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U16(iAddress);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U16(iAddress+2);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U16(iAddress+4);
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
LOG_NORM16();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Float()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress+4);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U32(iAddress+8);
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORMF();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Byte3_Indices1()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+1);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+2);
|
||||
VertexManager::s_pCurBufferPointer++;
|
||||
LOG_NORM8();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Short3_Indices1()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U16(iAddress);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U16(iAddress+2);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U16(iAddress+4);
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
LOG_NORM16();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Float3_Indices1()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress+4);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U32(iAddress+8);
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORMF();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Byte3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+1);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+2);
|
||||
VertexManager::s_pCurBufferPointer++;
|
||||
LOG_NORM8();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Short3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U16(iAddress);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U16(iAddress+2);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U16(iAddress+4);
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
LOG_NORM16();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Float3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress+4);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U32(iAddress+8);
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORMF();
|
||||
}
|
||||
}
|
||||
// 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 "VertexLoader.h"
|
||||
#include "VertexManager.h"
|
||||
#include "VertexLoader_Normal.h"
|
||||
|
||||
#define LOG_NORM8() PRIM_LOG("norm: %f %f %f, ", ((s8*)VertexManager::s_pCurBufferPointer)[-3]/127.0f, ((s8*)VertexManager::s_pCurBufferPointer)[-2]/127.0f, ((s8*)VertexManager::s_pCurBufferPointer)[-1]/127.0f);
|
||||
#define LOG_NORM16() PRIM_LOG("norm: %f %f %f, ", ((s16*)VertexManager::s_pCurBufferPointer)[-3]/32767.0f, ((s16*)VertexManager::s_pCurBufferPointer)[-2]/32767.0f, ((s16*)VertexManager::s_pCurBufferPointer)[-1]/32767.0f);
|
||||
#define LOG_NORMF() PRIM_LOG("norm: %f %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[-3], ((float*)VertexManager::s_pCurBufferPointer)[-2], ((float*)VertexManager::s_pCurBufferPointer)[-1]);
|
||||
|
||||
VertexLoader_Normal::Set VertexLoader_Normal::m_Table[NUM_NRM_TYPE][NUM_NRM_INDICES][NUM_NRM_ELEMENTS][NUM_NRM_FORMAT];
|
||||
|
||||
void VertexLoader_Normal::Init(void)
|
||||
{
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Set(3, Normal_DirectByte); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Set(3, Normal_DirectByte);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Set(6, Normal_DirectShort); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Set(6, Normal_DirectShort);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Set(12, Normal_DirectFloat);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Set(9, Normal_DirectByte3); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Set(9, Normal_DirectByte3);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Set(18, Normal_DirectShort3); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Set(18, Normal_DirectShort3);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Set(36, Normal_DirectFloat3);
|
||||
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Set(3, Normal_DirectByte); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Set(3, Normal_DirectByte);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Set(6, Normal_DirectShort); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Set(6, Normal_DirectShort);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Set(12, Normal_DirectFloat);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Set(9, Normal_DirectByte3); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Set(9, Normal_DirectByte3);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Set(18, Normal_DirectShort3); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Set(18, Normal_DirectShort3);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Set(36, Normal_DirectFloat3);
|
||||
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Set(1, Normal_Index8_Byte); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Set(1, Normal_Index8_Byte);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Set(1, Normal_Index8_Short); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Set(1, Normal_Index8_Short);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Set(1, Normal_Index8_Float);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Set(1, Normal_Index8_Byte3_Indices1); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Set(1, Normal_Index8_Byte3_Indices1);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Set(1, Normal_Index8_Short3_Indices1); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Set(1, Normal_Index8_Short3_Indices1);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Set(1, Normal_Index8_Float3_Indices1);
|
||||
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Set(1, Normal_Index8_Byte); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Set(1, Normal_Index8_Byte);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Set(1, Normal_Index8_Short); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Set(1, Normal_Index8_Short);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Set(1, Normal_Index8_Float);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Set(3, Normal_Index8_Byte3_Indices3); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Set(3, Normal_Index8_Byte3_Indices3);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Set(3, Normal_Index8_Short3_Indices3); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Set(3, Normal_Index8_Short3_Indices3);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Set(3, Normal_Index8_Float3_Indices3);
|
||||
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Set(2, Normal_Index16_Byte); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Set(2, Normal_Index16_Byte);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Set(2, Normal_Index16_Short); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Set(2, Normal_Index16_Short);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Set(2, Normal_Index16_Float);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Set(2, Normal_Index16_Byte3_Indices1); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Set(2, Normal_Index16_Byte3_Indices1);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Set(2, Normal_Index16_Short3_Indices1); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Set(2, Normal_Index16_Short3_Indices1);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Set(2, Normal_Index16_Float3_Indices1);
|
||||
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Set(2, Normal_Index16_Byte); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Set(2, Normal_Index16_Byte);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Set(2, Normal_Index16_Short); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Set(2, Normal_Index16_Short);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Set(2, Normal_Index16_Float);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Set(6, Normal_Index16_Byte3_Indices3); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Set(6, Normal_Index16_Byte3_Indices3);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Set(6, Normal_Index16_Short3_Indices3); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Set(6, Normal_Index16_Short3_Indices3);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Set(6, Normal_Index16_Float3_Indices3);
|
||||
}
|
||||
|
||||
unsigned int VertexLoader_Normal::GetSize(unsigned int _type, unsigned int _format, unsigned int _elements, unsigned int _index3)
|
||||
{
|
||||
return m_Table[_type][_index3][_elements][_format].gc_size;
|
||||
}
|
||||
|
||||
TPipelineFunction VertexLoader_Normal::GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements, unsigned int _index3)
|
||||
{
|
||||
TPipelineFunction pFunc = m_Table[_type][_index3][_elements][_format].function;
|
||||
return pFunc;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// --- Direct ---
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectByte()
|
||||
{
|
||||
*VertexManager::s_pCurBufferPointer++ = DataReadU8();
|
||||
*VertexManager::s_pCurBufferPointer++ = DataReadU8();
|
||||
*VertexManager::s_pCurBufferPointer++ = DataReadU8();
|
||||
VertexManager::s_pCurBufferPointer++;
|
||||
LOG_NORM8();
|
||||
// ((float*)VertexManager::s_pCurBufferPointer)[0] = ((float)(signed char)DataReadU8()+0.5f) / 127.5f;
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectShort()
|
||||
{
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[0] = DataReadU16();
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[1] = DataReadU16();
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[2] = DataReadU16();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
LOG_NORM16()
|
||||
// ((float*)VertexManager::s_pCurBufferPointer)[0] = ((float)(signed short)DataReadU16()+0.5f) / 32767.5f;
|
||||
// ((float*)VertexManager::s_pCurBufferPointer)[1] = ((float)(signed short)DataReadU16()+0.5f) / 32767.5f;
|
||||
// ((float*)VertexManager::s_pCurBufferPointer)[2] = ((float)(signed short)DataReadU16()+0.5f) / 32767.5f;
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectFloat()
|
||||
{
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = DataReadU32();
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = DataReadU32();
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = DataReadU32();
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORMF()
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectByte3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
*VertexManager::s_pCurBufferPointer++ = DataReadU8();
|
||||
*VertexManager::s_pCurBufferPointer++ = DataReadU8();
|
||||
*VertexManager::s_pCurBufferPointer++ = DataReadU8();
|
||||
VertexManager::s_pCurBufferPointer++;
|
||||
LOG_NORM8();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectShort3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[0] = DataReadU16();
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[1] = DataReadU16();
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[2] = DataReadU16();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
LOG_NORM16();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectFloat3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = DataReadU32();
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = DataReadU32();
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = DataReadU32();
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORMF();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// --- Index8 ---
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Byte()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+1);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+2);
|
||||
VertexManager::s_pCurBufferPointer++;
|
||||
// ((float*)VertexManager::s_pCurBufferPointer)[0] = ((float)(signed char)Memory_Read_U8(iAddress)+0.5f) / 127.5f;
|
||||
// ((float*)VertexManager::s_pCurBufferPointer)[1] = ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f;
|
||||
// ((float*)VertexManager::s_pCurBufferPointer)[2] = ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f;
|
||||
// VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORM8();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Short()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U16(iAddress);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U16(iAddress+2);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U16(iAddress+4);
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
LOG_NORM16();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Float()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress+4);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U32(iAddress+8);
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORMF();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Byte3_Indices1()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+1);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+2);
|
||||
VertexManager::s_pCurBufferPointer++;
|
||||
LOG_NORM8();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Short3_Indices1()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U16(iAddress);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U16(iAddress+2);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U16(iAddress+4);
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
LOG_NORM16();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Float3_Indices1()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress+4);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U32(iAddress+8);
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORMF();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Byte3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+1);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+2);
|
||||
*VertexManager::s_pCurBufferPointer++;
|
||||
LOG_NORM8();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Short3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U16(iAddress);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U16(iAddress+2);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U16(iAddress+4);
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
LOG_NORM16();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Float3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress+4);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U32(iAddress+8);
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORMF();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// --- Index16 ---
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Byte()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+1);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+2);
|
||||
VertexManager::s_pCurBufferPointer++;
|
||||
LOG_NORM8();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Short()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U16(iAddress);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U16(iAddress+2);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U16(iAddress+4);
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
LOG_NORM16();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Float()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress+4);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U32(iAddress+8);
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORMF();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Byte3_Indices1()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+1);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+2);
|
||||
VertexManager::s_pCurBufferPointer++;
|
||||
LOG_NORM8();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Short3_Indices1()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U16(iAddress);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U16(iAddress+2);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U16(iAddress+4);
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
LOG_NORM16();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Float3_Indices1()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress+4);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U32(iAddress+8);
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORMF();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Byte3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+1);
|
||||
*VertexManager::s_pCurBufferPointer++ = Memory_Read_U8(iAddress+2);
|
||||
VertexManager::s_pCurBufferPointer++;
|
||||
LOG_NORM8();
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Short3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U16(iAddress);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U16(iAddress+2);
|
||||
((u16*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U16(iAddress+4);
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
LOG_NORM16();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Float3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Memory_Read_U32(iAddress);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Memory_Read_U32(iAddress+4);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = Memory_Read_U32(iAddress+8);
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORMF();
|
||||
}
|
||||
}
|
||||
|
@ -1,241 +1,241 @@
|
||||
// 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);
|
||||
<two unpacks here to sign extend>
|
||||
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);
|
||||
<two unpacks here to sign extend>
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -1,379 +1,379 @@
|
||||
#include "Globals.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#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<u32, u32> > 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<u32, u32> &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<int, int>(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<u32, u32> >::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 <fstream>
|
||||
#include <vector>
|
||||
|
||||
#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<u32, u32> > 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<u32, u32> &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<int, int>(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<u32, u32> >::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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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
|
@ -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 <SDL.h>
|
||||
#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 <SDL.h>
|
||||
#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);
|
||||
}
|
||||
|
@ -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 <assert.h>
|
||||
|
||||
/*****************************************************************************
|
||||
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 <stddef.h>
|
||||
|
||||
// Inline assembly syntax for use with Visual C++
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#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 <memory.h>
|
||||
#include <string.h>
|
||||
|
||||
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 <assert.h>
|
||||
|
||||
/*****************************************************************************
|
||||
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 <stddef.h>
|
||||
|
||||
// Inline assembly syntax for use with Visual C++
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#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 <memory.h>
|
||||
#include <string.h>
|
||||
|
||||
void * memcpy_amd(void *dest, const void *src, size_t n)
|
||||
{
|
||||
memcpy(dest, src, n);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -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 <windows.h>
|
||||
#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 <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
#include <OpenGL/gl.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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 <OpenGL/gl.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user