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:
bushing
2008-12-08 05:25:12 +00:00
parent 9146b9b261
commit 901fe7c00f
142 changed files with 43834 additions and 43834 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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");
}

View File

@ -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();
}
}
// ==============

View File

@ -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

View File

@ -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());
}

View File

@ -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
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}
}