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

View File

@ -1,59 +1,59 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "IniFile.h"
#include "Config.h"
CConfig g_Config;
CConfig::CConfig()
{
Load();
}
void CConfig::LoadDefaults()
{
m_EnableHLEAudio = true;
m_EnableDTKMusic = true;
m_Interpolation = true;
}
void CConfig::Load()
{
// first load defaults
LoadDefaults();
IniFile file;
file.Load(FULL_CONFIG_DIR "DSP.ini");
file.Get("Config", "EnableHLEAudio", &m_EnableHLEAudio, true); // Sound Settings
file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true);
file.Get("Config", "EnableThrottle", &m_EnableThrottle, true);
file.Get("Config", "Interpolation", &m_Interpolation, true);
}
void CConfig::Save()
{
IniFile file;
file.Load(FULL_CONFIG_DIR "DSP.ini");
file.Set("Config", "EnableHLEAudio", m_EnableHLEAudio); // Sound Settings
file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic);
file.Set("Config", "EnableThrottle", m_EnableThrottle);
file.Set("Config", "Interpolation", m_Interpolation);
file.Save(FULL_CONFIG_DIR "DSP.ini");
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "IniFile.h"
#include "Config.h"
CConfig g_Config;
CConfig::CConfig()
{
Load();
}
void CConfig::LoadDefaults()
{
m_EnableHLEAudio = true;
m_EnableDTKMusic = true;
m_Interpolation = true;
}
void CConfig::Load()
{
// first load defaults
LoadDefaults();
IniFile file;
file.Load(FULL_CONFIG_DIR "DSP.ini");
file.Get("Config", "EnableHLEAudio", &m_EnableHLEAudio, true); // Sound Settings
file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true);
file.Get("Config", "EnableThrottle", &m_EnableThrottle, true);
file.Get("Config", "Interpolation", &m_Interpolation, true);
}
void CConfig::Save()
{
IniFile file;
file.Load(FULL_CONFIG_DIR "DSP.ini");
file.Set("Config", "EnableHLEAudio", m_EnableHLEAudio); // Sound Settings
file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic);
file.Set("Config", "EnableThrottle", m_EnableThrottle);
file.Set("Config", "Interpolation", m_Interpolation);
file.Save(FULL_CONFIG_DIR "DSP.ini");
}

View File

@ -1,85 +1,85 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "resource.h"
#include "Config.h"
#include "ConfigDlg.h"
LRESULT
CConfigDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
// Load config settings
g_Config.Load();
// Center window
//CenterWindow(this->GetParent());
CenterWindow(GetParent());
// Get button handles
m_buttonEnableHLEAudio = GetDlgItem(IDC_ENABLE_HLE_AUDIO);
m_buttonEnableDTKMusic = GetDlgItem(IDC_ENABLE_DTK_MUSIC);
m_buttonEnableThrottle = GetDlgItem(IDC_ENABLE_THROTTLE);
m_comboSampleRate = GetDlgItem(IDC_SAMPLERATE);
// Update checkboxes
m_buttonEnableHLEAudio.SetCheck(g_Config.m_EnableHLEAudio ? BST_CHECKED : BST_UNCHECKED);
m_buttonEnableDTKMusic.SetCheck(g_Config.m_EnableDTKMusic ? BST_CHECKED : BST_UNCHECKED);
m_buttonEnableThrottle.SetCheck(g_Config.m_EnableThrottle ? BST_CHECKED : BST_UNCHECKED);
m_comboSampleRate.AddString("44100");
m_comboSampleRate.AddString("48000");
m_comboSampleRate.SetCurSel(g_Config.m_SampleRate == 44100 ? 0 : 1);
// Add tooltips
CToolTipCtrl ToolTips;
ToolTips.Create(m_hWnd);
ToolTips.Activate(true);
ToolTips.SetMaxTipWidth(220); // limit the width
ToolTips.SetDelayTime(TTDT_AUTOPOP, 20 * 1000); // give us time to read it
CToolInfo tiHLE(TTF_SUBCLASS, m_buttonEnableHLEAudio, 0, NULL,
"This is the most common sound type");
CToolInfo tiDTK(TTF_SUBCLASS, m_buttonEnableDTKMusic, 0, NULL,
"This is sometimes used to play music tracks from the disc");
CToolInfo tiOther(TTF_SUBCLASS, m_buttonEnableThrottle, 0, NULL,
"This is sometimes used together with pre-rendered movies. Disabling this"
" also disables the speed throttle that is causes. Meaning that"
" there will be no upper limit on your FPS.");
ToolTips.AddTool(tiHLE);
ToolTips.AddTool(tiDTK);
ToolTips.AddTool(tiOther);
return(TRUE);
}
LRESULT
CConfigDlg::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
// Save settings
if (wID == IDOK)
{
g_Config.m_EnableHLEAudio = (m_buttonEnableHLEAudio.GetCheck() == BST_CHECKED) ? true : false;
g_Config.m_EnableDTKMusic = (m_buttonEnableDTKMusic.GetCheck() == BST_CHECKED) ? true : false;
g_Config.m_EnableThrottle = (m_buttonEnableThrottle.GetCheck() == BST_CHECKED) ? true : false;
g_Config.m_SampleRate = (m_comboSampleRate.GetCurSel() == 0 ? 44100 : 48000);
g_Config.Save();
}
EndDialog(wID);
g_Config.Save();
return(0);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "resource.h"
#include "Config.h"
#include "ConfigDlg.h"
LRESULT
CConfigDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
// Load config settings
g_Config.Load();
// Center window
//CenterWindow(this->GetParent());
CenterWindow(GetParent());
// Get button handles
m_buttonEnableHLEAudio = GetDlgItem(IDC_ENABLE_HLE_AUDIO);
m_buttonEnableDTKMusic = GetDlgItem(IDC_ENABLE_DTK_MUSIC);
m_buttonEnableThrottle = GetDlgItem(IDC_ENABLE_THROTTLE);
m_comboSampleRate = GetDlgItem(IDC_SAMPLERATE);
// Update checkboxes
m_buttonEnableHLEAudio.SetCheck(g_Config.m_EnableHLEAudio ? BST_CHECKED : BST_UNCHECKED);
m_buttonEnableDTKMusic.SetCheck(g_Config.m_EnableDTKMusic ? BST_CHECKED : BST_UNCHECKED);
m_buttonEnableThrottle.SetCheck(g_Config.m_EnableThrottle ? BST_CHECKED : BST_UNCHECKED);
m_comboSampleRate.AddString("44100");
m_comboSampleRate.AddString("48000");
m_comboSampleRate.SetCurSel(g_Config.m_SampleRate == 44100 ? 0 : 1);
// Add tooltips
CToolTipCtrl ToolTips;
ToolTips.Create(m_hWnd);
ToolTips.Activate(true);
ToolTips.SetMaxTipWidth(220); // limit the width
ToolTips.SetDelayTime(TTDT_AUTOPOP, 20 * 1000); // give us time to read it
CToolInfo tiHLE(TTF_SUBCLASS, m_buttonEnableHLEAudio, 0, NULL,
"This is the most common sound type");
CToolInfo tiDTK(TTF_SUBCLASS, m_buttonEnableDTKMusic, 0, NULL,
"This is sometimes used to play music tracks from the disc");
CToolInfo tiOther(TTF_SUBCLASS, m_buttonEnableThrottle, 0, NULL,
"This is sometimes used together with pre-rendered movies. Disabling this"
" also disables the speed throttle that is causes. Meaning that"
" there will be no upper limit on your FPS.");
ToolTips.AddTool(tiHLE);
ToolTips.AddTool(tiDTK);
ToolTips.AddTool(tiOther);
return(TRUE);
}
LRESULT
CConfigDlg::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
// Save settings
if (wID == IDOK)
{
g_Config.m_EnableHLEAudio = (m_buttonEnableHLEAudio.GetCheck() == BST_CHECKED) ? true : false;
g_Config.m_EnableDTKMusic = (m_buttonEnableDTKMusic.GetCheck() == BST_CHECKED) ? true : false;
g_Config.m_EnableThrottle = (m_buttonEnableThrottle.GetCheck() == BST_CHECKED) ? true : false;
g_Config.m_SampleRate = (m_comboSampleRate.GetCurSel() == 0 ? 44100 : 48000);
g_Config.Save();
}
EndDialog(wID);
g_Config.Save();
return(0);
}

View File

@ -1,90 +1,90 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifdef _WIN32
#include "PCHW/DSoundStream.h"
#endif
#include "DSPHandler.h"
CDSPHandler* CDSPHandler::m_pInstance = NULL;
CDSPHandler::CDSPHandler()
: m_pUCode(NULL),
m_bHalt(false),
m_bAssertInt(false)
{
SetUCode(UCODE_ROM);
m_DSPControl.DSPHalt = 1;
m_DSPControl.DSPInit = 1;
}
CDSPHandler::~CDSPHandler()
{
delete m_pUCode;
m_pUCode = NULL;
}
void CDSPHandler::Update()
{
if (m_pUCode != NULL)
m_pUCode->Update();
}
unsigned short CDSPHandler::WriteControlRegister(unsigned short _Value)
{
UDSPControl Temp(_Value);
if (Temp.DSPReset)
{
SetUCode(UCODE_ROM);
Temp.DSPReset = 0;
}
if (Temp.DSPInit == 0)
{
// copy 128 byte from ARAM 0x000000 to IMEM
SetUCode(UCODE_INIT_AUDIO_SYSTEM);
Temp.DSPInitCode = 0;
// MessageBox(NULL, "UCODE_INIT_AUDIO_SYSTEM", "DSP-HLE", MB_OK);
}
m_DSPControl.Hex = Temp.Hex;
return m_DSPControl.Hex;
}
unsigned short CDSPHandler::ReadControlRegister()
{
return m_DSPControl.Hex;
}
void CDSPHandler::SendMailToDSP(u32 _uMail)
{
if (m_pUCode != NULL)
m_pUCode->HandleMail(_uMail);
}
IUCode* CDSPHandler::GetUCode()
{
return m_pUCode;
}
void CDSPHandler::SetUCode(u32 _crc)
{
delete m_pUCode;
m_pUCode = NULL;
m_MailHandler.Clear();
m_pUCode = UCodeFactory(_crc, m_MailHandler);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifdef _WIN32
#include "PCHW/DSoundStream.h"
#endif
#include "DSPHandler.h"
CDSPHandler* CDSPHandler::m_pInstance = NULL;
CDSPHandler::CDSPHandler()
: m_pUCode(NULL),
m_bHalt(false),
m_bAssertInt(false)
{
SetUCode(UCODE_ROM);
m_DSPControl.DSPHalt = 1;
m_DSPControl.DSPInit = 1;
}
CDSPHandler::~CDSPHandler()
{
delete m_pUCode;
m_pUCode = NULL;
}
void CDSPHandler::Update()
{
if (m_pUCode != NULL)
m_pUCode->Update();
}
unsigned short CDSPHandler::WriteControlRegister(unsigned short _Value)
{
UDSPControl Temp(_Value);
if (Temp.DSPReset)
{
SetUCode(UCODE_ROM);
Temp.DSPReset = 0;
}
if (Temp.DSPInit == 0)
{
// copy 128 byte from ARAM 0x000000 to IMEM
SetUCode(UCODE_INIT_AUDIO_SYSTEM);
Temp.DSPInitCode = 0;
// MessageBox(NULL, "UCODE_INIT_AUDIO_SYSTEM", "DSP-HLE", MB_OK);
}
m_DSPControl.Hex = Temp.Hex;
return m_DSPControl.Hex;
}
unsigned short CDSPHandler::ReadControlRegister()
{
return m_DSPControl.Hex;
}
void CDSPHandler::SendMailToDSP(u32 _uMail)
{
if (m_pUCode != NULL)
m_pUCode->HandleMail(_uMail);
}
IUCode* CDSPHandler::GetUCode()
{
return m_pUCode;
}
void CDSPHandler::SetUCode(u32 _crc)
{
delete m_pUCode;
m_pUCode = NULL;
m_MailHandler.Clear();
m_pUCode = UCodeFactory(_crc, m_MailHandler);
}

View File

@ -1,85 +1,85 @@
//////////////////////////////////////////////////////////////////////////////////////////
//
// Licensetype: GNU General Public License (GPL)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
//
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
//
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//
//////////////////////////////////////////////////////////////////////////////////////////
// includes
#include <iostream>
#include <fstream>
#include <sstream>
#ifndef _WIN32
#include <stdlib.h>
#endif
#include "Debugger.h"
#include "PBView.h"
#include "IniFile.h"
#include "FileUtil.h"
#include "StringUtil.h"
#include "FileSearch.h"
#include "../Logging/Console.h" // open and close console
// Make the wxTextCtrls scroll with each other
void CDebugger::DoScrollBlocks()
{
// ShowPosition = in letters
// GetScrollPos = number of lines from the top
// GetLineLength = letters in one line
// SetScrollPos = only set the scrollbar, doesn't update the text,
// Update() or Refresh() doesn't help
double pos = m_bl95->GetScrollPos(wxVERTICAL)*(m_bl95->GetLineLength(0)+12.95); // annoying :(
m_bl0->ShowPosition((int)pos);
/*
if(GetAsyncKeyState(VK_NUMPAD1))
A -= 0.1;
else if(GetAsyncKeyState(VK_NUMPAD2))
A += 0.11;
wprintf("GetScrollPos:%i GetScrollRange:%i GetPosition:%i GetLastPosition:%i GetMaxWidth:%i \
GetLineLength:%i XYToPosition:%i\n \
GetScrollPos * GetLineLength + GetScrollRange:%i A:%f\n",
m_bl95->GetScrollPos(wxVERTICAL), m_bl95->GetScrollRange(wxVERTICAL),
m_bl95->GetPosition().y, m_bl95->GetLastPosition(), m_bl95->GetMaxWidth(),
m_bl95->GetLineLength(0), m_bl95->XYToPosition(0,25),
pos, A
);
for (int i = 0; i < 127; ++i)
{
m_bl0->AppendText(wxString::Format("%02i|68 : 01a70144\n", i));
m_bl95->AppendText(wxString::Format("%i Mouse\n", i));
}*/
}
void CDebugger::ScrollBlocksMouse(wxMouseEvent& event)
{
DoScrollBlocks();
event.Skip(); // otherwise we remove the regular behavior, for example scrolling
}
void CDebugger::ScrollBlocksCursor(wxScrollWinEvent& event)
{
DoScrollBlocks();
event.Skip(); // otherwise we remove the regular behavior, for example scrolling
}
// ==============
//////////////////////////////////////////////////////////////////////////////////////////
//
// Licensetype: GNU General Public License (GPL)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
//
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
//
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//
//////////////////////////////////////////////////////////////////////////////////////////
// includes
#include <iostream>
#include <fstream>
#include <sstream>
#ifndef _WIN32
#include <stdlib.h>
#endif
#include "Debugger.h"
#include "PBView.h"
#include "IniFile.h"
#include "FileUtil.h"
#include "StringUtil.h"
#include "FileSearch.h"
#include "../Logging/Console.h" // open and close console
// Make the wxTextCtrls scroll with each other
void CDebugger::DoScrollBlocks()
{
// ShowPosition = in letters
// GetScrollPos = number of lines from the top
// GetLineLength = letters in one line
// SetScrollPos = only set the scrollbar, doesn't update the text,
// Update() or Refresh() doesn't help
double pos = m_bl95->GetScrollPos(wxVERTICAL)*(m_bl95->GetLineLength(0)+12.95); // annoying :(
m_bl0->ShowPosition((int)pos);
/*
if(GetAsyncKeyState(VK_NUMPAD1))
A -= 0.1;
else if(GetAsyncKeyState(VK_NUMPAD2))
A += 0.11;
wprintf("GetScrollPos:%i GetScrollRange:%i GetPosition:%i GetLastPosition:%i GetMaxWidth:%i \
GetLineLength:%i XYToPosition:%i\n \
GetScrollPos * GetLineLength + GetScrollRange:%i A:%f\n",
m_bl95->GetScrollPos(wxVERTICAL), m_bl95->GetScrollRange(wxVERTICAL),
m_bl95->GetPosition().y, m_bl95->GetLastPosition(), m_bl95->GetMaxWidth(),
m_bl95->GetLineLength(0), m_bl95->XYToPosition(0,25),
pos, A
);
for (int i = 0; i < 127; ++i)
{
m_bl0->AppendText(wxString::Format("%02i|68 : 01a70144\n", i));
m_bl95->AppendText(wxString::Format("%i Mouse\n", i));
}*/
}
void CDebugger::ScrollBlocksMouse(wxMouseEvent& event)
{
DoScrollBlocks();
event.Skip(); // otherwise we remove the regular behavior, for example scrolling
}
void CDebugger::ScrollBlocksCursor(wxScrollWinEvent& event)
{
DoScrollBlocks();
event.Skip(); // otherwise we remove the regular behavior, for example scrolling
}
// ==============

File diff suppressed because it is too large Load Diff

View File

@ -1,288 +1,288 @@
//////////////////////////////////////////////////////////////////////////////////////////
//
// Licensetype: GNU General Public License (GPL)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
//
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
//
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//
//////////////////////////////////////////////////////////////////////////////////////////
// includes
#include <iostream>
#include <fstream>
#include <sstream>
#ifndef _WIN32
#include <stdlib.h>
#endif
#include "Debugger.h"
#include "PBView.h"
#include "IniFile.h"
#include "FileUtil.h"
#include "StringUtil.h"
#include "FileSearch.h"
#include "../Logging/Console.h" // open and close console
extern std::vector<std::string> sMailLog, sMailTime;
extern CDebugger* m_frame;
// =======================================================================================
// Update mail window
// --------------
void CDebugger::DoUpdateMail()
{
//wprintf("i %i %i\n", sFullMail.size(), sMailLog.size());
if(sFullMail.size() > 0 && sMailLog.size() > 0)
{
m_log->SetValue(wxString::FromAscii(sFullMail.at(m_RadioBox[3]->GetSelection()).c_str()));
m_log->SetDefaultStyle(wxTextAttr(*wxBLUE)); // doesn't work because of the current wx
m_log1->SetValue(wxString::FromAscii(sMailLog.at(m_RadioBox[3]->GetSelection()).c_str()));
m_log1->AppendText(wxT("\n\n"));
}
}
void CDebugger::UpdateMail(wxNotebookEvent& event)
{
DoUpdateMail();
/* This may be called before m_frame is fully created through the
EVT_NOTEBOOK_PAGE_CHANGED, in that case it will crash because this
is accessing members of it */
if(StoreMails && m_frame) ReadDir();
}
// Change mail from radio button change
void CDebugger::ChangeMail(wxCommandEvent& event)
{
//wprintf("abc");
DoUpdateMail();
//if(StoreMails) ReadDir();
}
// ==============
// =======================================================================================
// Read out mails from dir
// --------------
void CDebugger::ReadDir()
{
CFileSearch::XStringVector Directories;
//Directories.push_back("Logs/Mail");
Directories.push_back(FULL_MAIL_LOGS_DIR);
CFileSearch::XStringVector Extensions;
Extensions.push_back("*.log");
CFileSearch FileSearch(Extensions, Directories);
const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames();
//m_gc->Show(false);
//m_gc->Append(wxT("SSBM ffffix"));
//m_gc->Show(true);
// Clear in case we already did this earlier
all_all_files.clear();
if (rFilenames.size() > 0 && m_gc && m_wii)
{
for (u32 i = 0; i < rFilenames.size(); i++)
{
std::string FileName;
SplitPath(rFilenames[i], NULL, &FileName, NULL); // place the filename in FileName
//std::string FileName = StripSpaces(*FileName);
std::vector<std::string> pieces;
SplitString(FileName, "_sep", pieces); // split string
// Save all filenames heres
if(pieces[2] == "0") all_all_files.push_back(pieces[0]);
// Cut to size
std::string cut;
if(pieces[0].length() > 18)
cut = pieces[0].substr(0, 18) + "...";
else
cut = pieces[0];
//wprintf("%s %s %s\n", pieces[0].c_str(), pieces[1].c_str(),
// pieces[2].c_str(), pieces[3].c_str());
if (NoDuplicate(pieces[0]) && pieces.size() >= 3)
{
all_files.push_back(pieces[0]);
if (pieces[3] == "GC")
{
gc_files.push_back(pieces[0]);
m_gc->Append(wxString::FromAscii(cut.c_str()));
}
else
{
wii_files.push_back(pieces[0]);
m_wii->Append(wxString::FromAscii(cut.c_str()));
}
}
}
}
}
// =======================================================================================
// Check for duplicates and count files from all_all_files
// --------------
bool CDebugger::NoDuplicate(std::string FileName)
{
for (u32 i = 0; i < all_files.size(); i++)
{
if(all_files.at(i) == FileName)
return false;
}
return true;
}
// Count the number of files for each game
u32 CDebugger::CountFiles(std::string FileName)
{
int match = 0;
for (u32 i = 0; i < all_all_files.size(); i++)
{
//wprintf("CountFiles %i %s\n", i, all_all_files[i].c_str());
if(all_all_files[i] == FileName)
match++;
}
//wprintf("We found %i files for this game\n", match);
return match;
}
// ==============
// =======================================================================================
// Read file from harddrive
// --------------
std::string CDebugger::Readfile_(std::string FileName)
{
char c; // declare a char variable
FILE *file; // declare a FILE pointer
std::string sz = "";
if(File::Exists(FileName.c_str()))
file = fopen(FileName.c_str(), "r"); // open a text file for reading
else
return "";
if(file == NULL)
{
// file could not be opened
}
else
{
while(1) // looping through file
{
c = fgetc(file);
if(c != EOF)
sz += c; // print the file one character at a time
else
break; // break when EOF is reached
}
fclose(file);
}
return sz;
}
// Read file
void CDebugger::Readfile(std::string FileName, bool GC)
{
u32 n = CountFiles(FileName); // count how many mails we have
u32 curr_n = 0;
std::ifstream file;
for (u32 i = 0; i < m_RadioBox[3]->GetCount(); i++)
{
if(m_RadioBox[3]->IsItemEnabled(i)) curr_n++;
m_RadioBox[3]->Enable(i, false); // disable all
}
//wprintf("Disabled all: n %i\n", n);
for (u32 i = 0; i < n; i++)
{
m_RadioBox[3]->Enable(i, true); // then anble the right ones
//wprintf("m_RadioBox[3] enabled: %i\n", i);
std::string sz = "";
std::ostringstream ci;
ci << i;
std::string f0 = FULL_MAIL_LOGS_DIR + FileName + "_sep" + ci.str() + "_sep" + "0_sep" + (GC ? "GC" : "Wii") + "_sep.log";
std::string f1 = FULL_MAIL_LOGS_DIR + FileName + "_sep" + ci.str() + "_sep" + "1_sep" + (GC ? "GC" : "Wii") + "_sep.log";
//wprintf("ifstream %s %s\n", f0.c_str(), f1.c_str());
if(sFullMail.size() <= i) sFullMail.resize(sFullMail.size() + 1);
if(sMailLog.size() <= i) sMailLog.resize(sMailLog.size() + 1);
if(Readfile_(f0).length() > 0) sFullMail.at(i) = Readfile_(f0);
else sFullMail.at(i) = "";
if(Readfile_(f1).length() > 0) sMailLog.at(i) = Readfile_(f1);
else sMailLog.at(i) = "";
}
if(n < curr_n) m_RadioBox[3]->Select(n - 1);
//wprintf("Select: %i | n %i curr_n %i\n", n - 1, n, curr_n);
DoUpdateMail();
}
// ==============
// =======================================================================================
// Read the file to the text window
// ---------------
void CDebugger::OnGameChange(wxCommandEvent& event)
{
if(event.GetId() == 2006)
{
// Only allow one selected game at a time
for (u32 i = 0; i < m_gc->GetCount(); ++i)
if(i != (u32)event.GetInt()) m_gc->Check(i, false);
for (u32 i = 0; i < m_wii->GetCount(); ++i)
m_wii->Check(i, false);
Readfile(gc_files[event.GetInt()], true);
}
else
{
for (u32 i = 0; i < m_gc->GetCount(); ++i)
m_gc->Check(i, false);
for (u32 i = 0; i < m_wii->GetCount(); ++i)
if(i != (u32)event.GetInt()) m_wii->Check(i, false);
Readfile(wii_files[event.GetInt()], false);
}
}
// Settings
void CDebugger::MailSettings(wxCommandEvent& event)
{
//for (int i = 0; i < all_all_files.size(); ++i)
//wprintf("s: %s \n", all_all_files.at(i).c_str());
ScanMails = m_gcwiiset->IsChecked(0);
StoreMails = m_gcwiiset->IsChecked(1);
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Licensetype: GNU General Public License (GPL)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
//
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
//
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//
//////////////////////////////////////////////////////////////////////////////////////////
// includes
#include <iostream>
#include <fstream>
#include <sstream>
#ifndef _WIN32
#include <stdlib.h>
#endif
#include "Debugger.h"
#include "PBView.h"
#include "IniFile.h"
#include "FileUtil.h"
#include "StringUtil.h"
#include "FileSearch.h"
#include "../Logging/Console.h" // open and close console
extern std::vector<std::string> sMailLog, sMailTime;
extern CDebugger* m_frame;
// =======================================================================================
// Update mail window
// --------------
void CDebugger::DoUpdateMail()
{
//wprintf("i %i %i\n", sFullMail.size(), sMailLog.size());
if(sFullMail.size() > 0 && sMailLog.size() > 0)
{
m_log->SetValue(wxString::FromAscii(sFullMail.at(m_RadioBox[3]->GetSelection()).c_str()));
m_log->SetDefaultStyle(wxTextAttr(*wxBLUE)); // doesn't work because of the current wx
m_log1->SetValue(wxString::FromAscii(sMailLog.at(m_RadioBox[3]->GetSelection()).c_str()));
m_log1->AppendText(wxT("\n\n"));
}
}
void CDebugger::UpdateMail(wxNotebookEvent& event)
{
DoUpdateMail();
/* This may be called before m_frame is fully created through the
EVT_NOTEBOOK_PAGE_CHANGED, in that case it will crash because this
is accessing members of it */
if(StoreMails && m_frame) ReadDir();
}
// Change mail from radio button change
void CDebugger::ChangeMail(wxCommandEvent& event)
{
//wprintf("abc");
DoUpdateMail();
//if(StoreMails) ReadDir();
}
// ==============
// =======================================================================================
// Read out mails from dir
// --------------
void CDebugger::ReadDir()
{
CFileSearch::XStringVector Directories;
//Directories.push_back("Logs/Mail");
Directories.push_back(FULL_MAIL_LOGS_DIR);
CFileSearch::XStringVector Extensions;
Extensions.push_back("*.log");
CFileSearch FileSearch(Extensions, Directories);
const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames();
//m_gc->Show(false);
//m_gc->Append(wxT("SSBM ffffix"));
//m_gc->Show(true);
// Clear in case we already did this earlier
all_all_files.clear();
if (rFilenames.size() > 0 && m_gc && m_wii)
{
for (u32 i = 0; i < rFilenames.size(); i++)
{
std::string FileName;
SplitPath(rFilenames[i], NULL, &FileName, NULL); // place the filename in FileName
//std::string FileName = StripSpaces(*FileName);
std::vector<std::string> pieces;
SplitString(FileName, "_sep", pieces); // split string
// Save all filenames heres
if(pieces[2] == "0") all_all_files.push_back(pieces[0]);
// Cut to size
std::string cut;
if(pieces[0].length() > 18)
cut = pieces[0].substr(0, 18) + "...";
else
cut = pieces[0];
//wprintf("%s %s %s\n", pieces[0].c_str(), pieces[1].c_str(),
// pieces[2].c_str(), pieces[3].c_str());
if (NoDuplicate(pieces[0]) && pieces.size() >= 3)
{
all_files.push_back(pieces[0]);
if (pieces[3] == "GC")
{
gc_files.push_back(pieces[0]);
m_gc->Append(wxString::FromAscii(cut.c_str()));
}
else
{
wii_files.push_back(pieces[0]);
m_wii->Append(wxString::FromAscii(cut.c_str()));
}
}
}
}
}
// =======================================================================================
// Check for duplicates and count files from all_all_files
// --------------
bool CDebugger::NoDuplicate(std::string FileName)
{
for (u32 i = 0; i < all_files.size(); i++)
{
if(all_files.at(i) == FileName)
return false;
}
return true;
}
// Count the number of files for each game
u32 CDebugger::CountFiles(std::string FileName)
{
int match = 0;
for (u32 i = 0; i < all_all_files.size(); i++)
{
//wprintf("CountFiles %i %s\n", i, all_all_files[i].c_str());
if(all_all_files[i] == FileName)
match++;
}
//wprintf("We found %i files for this game\n", match);
return match;
}
// ==============
// =======================================================================================
// Read file from harddrive
// --------------
std::string CDebugger::Readfile_(std::string FileName)
{
char c; // declare a char variable
FILE *file; // declare a FILE pointer
std::string sz = "";
if(File::Exists(FileName.c_str()))
file = fopen(FileName.c_str(), "r"); // open a text file for reading
else
return "";
if(file == NULL)
{
// file could not be opened
}
else
{
while(1) // looping through file
{
c = fgetc(file);
if(c != EOF)
sz += c; // print the file one character at a time
else
break; // break when EOF is reached
}
fclose(file);
}
return sz;
}
// Read file
void CDebugger::Readfile(std::string FileName, bool GC)
{
u32 n = CountFiles(FileName); // count how many mails we have
u32 curr_n = 0;
std::ifstream file;
for (u32 i = 0; i < m_RadioBox[3]->GetCount(); i++)
{
if(m_RadioBox[3]->IsItemEnabled(i)) curr_n++;
m_RadioBox[3]->Enable(i, false); // disable all
}
//wprintf("Disabled all: n %i\n", n);
for (u32 i = 0; i < n; i++)
{
m_RadioBox[3]->Enable(i, true); // then anble the right ones
//wprintf("m_RadioBox[3] enabled: %i\n", i);
std::string sz = "";
std::ostringstream ci;
ci << i;
std::string f0 = FULL_MAIL_LOGS_DIR + FileName + "_sep" + ci.str() + "_sep" + "0_sep" + (GC ? "GC" : "Wii") + "_sep.log";
std::string f1 = FULL_MAIL_LOGS_DIR + FileName + "_sep" + ci.str() + "_sep" + "1_sep" + (GC ? "GC" : "Wii") + "_sep.log";
//wprintf("ifstream %s %s\n", f0.c_str(), f1.c_str());
if(sFullMail.size() <= i) sFullMail.resize(sFullMail.size() + 1);
if(sMailLog.size() <= i) sMailLog.resize(sMailLog.size() + 1);
if(Readfile_(f0).length() > 0) sFullMail.at(i) = Readfile_(f0);
else sFullMail.at(i) = "";
if(Readfile_(f1).length() > 0) sMailLog.at(i) = Readfile_(f1);
else sMailLog.at(i) = "";
}
if(n < curr_n) m_RadioBox[3]->Select(n - 1);
//wprintf("Select: %i | n %i curr_n %i\n", n - 1, n, curr_n);
DoUpdateMail();
}
// ==============
// =======================================================================================
// Read the file to the text window
// ---------------
void CDebugger::OnGameChange(wxCommandEvent& event)
{
if(event.GetId() == 2006)
{
// Only allow one selected game at a time
for (u32 i = 0; i < m_gc->GetCount(); ++i)
if(i != (u32)event.GetInt()) m_gc->Check(i, false);
for (u32 i = 0; i < m_wii->GetCount(); ++i)
m_wii->Check(i, false);
Readfile(gc_files[event.GetInt()], true);
}
else
{
for (u32 i = 0; i < m_gc->GetCount(); ++i)
m_gc->Check(i, false);
for (u32 i = 0; i < m_wii->GetCount(); ++i)
if(i != (u32)event.GetInt()) m_wii->Check(i, false);
Readfile(wii_files[event.GetInt()], false);
}
}
// Settings
void CDebugger::MailSettings(wxCommandEvent& event)
{
//for (int i = 0; i < all_all_files.size(); ++i)
//wprintf("s: %s \n", all_all_files.at(i).c_str());
ScanMails = m_gcwiiset->IsChecked(0);
StoreMails = m_gcwiiset->IsChecked(1);
}

View File

@ -1,168 +1,168 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "PBView.h"
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
// ---------------------------------------------------------------------------------------
// external declarations
extern const char* GetGRPName(unsigned int index);
// No buttons or events so far
BEGIN_EVENT_TABLE(CPBView, wxListCtrl)
END_EVENT_TABLE()
// ---------------------------------------------------------------------------------------
CPBView::CPBView(wxWindow* parent, const wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: wxListCtrl(parent, id, pos, size, style)
{
InsertColumn(1, wxT("upd4"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("upd3"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("upd2"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("upd1"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("upd0"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("r_lo"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("r_hi"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("ratio"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("frac"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("coef"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("src_t"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("form"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("isstr"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("yn2"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("yn1"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("pred_s"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("isloop"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("volr"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("voll"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("loopto"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("end"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(0, wxT("pos"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(0, wxT("run"), wxLIST_FORMAT_RIGHT, 50);
InsertColumn(0, wxT("Block"), wxLIST_FORMAT_CENTER, 40);
SetFont(wxFont(8, wxSWISS, wxNORMAL, wxNORMAL, false, wxT("Segoe UI")));
for (int i = 0; i < 64; i++)
{
// Print values from 0 to 63
char buffer [33];
sprintf(buffer, "%02i", i);
int Item = InsertItem(0, wxString::FromAscii(buffer));
wxListItem item;
item.SetId(Item);
item.SetBackgroundColour(0xFFFFFF);
item.SetData(i);
SetItem(item);
}
// This is a wx call that leads to MSWDrawSubItem
Refresh();
}
void
CPBView::Update()
{
Refresh();
}
bool
CPBView::MSWDrawSubItem(wxPaintDC& rPainDC, int item, int subitem)
{
bool Result = false;
// don't change 0, it has the block values
if(subitem > 0)
{
#ifdef __WXMSW__ // what's this? should I use that?
const wxChar* bgColor = _T("#ffffff");
wxBrush bgBrush(bgColor);
wxPen bgPen(bgColor);
wxRect SubItemRect;
this->GetSubItemRect(item, subitem, SubItemRect);
rPainDC.SetBrush(bgBrush);
rPainDC.SetPen(bgPen);
rPainDC.DrawRectangle(SubItemRect);
#endif
// A somewhat primitive attempt to show the playing history for a certain block.
wxString text;
if(subitem == 1)
{
char cbuff [33];
sprintf(cbuff, "%08i", m_CachedRegs[subitem][item]);
std::string c = cbuff;
int n[8];
for (int j = 0; j < 8; j++)
{
n[j] = atoi( c.substr(j, 1).c_str());
// 149 = dot, 160 = space
if (n[j] == 1){
n[j] = 149;} else {n[j] = 160;}
}
// pretty neat huh?
text.Printf(wxT("%c%c%c%c%c%c%c%c"), n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]);
}
else
{
text.Printf(wxT("0x%08x"), m_CachedRegs[subitem][item]);
}
#ifdef __WXMSW__
rPainDC.DrawText(text, SubItemRect.GetLeft() + 10, SubItemRect.GetTop() + 4);
#else
// May not show up pretty in !Win32
rPainDC.DrawText(text, 10, 4);
#endif
return(true);
}
else
{
// what does this mean?
return(Result);
}
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "PBView.h"
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
// ---------------------------------------------------------------------------------------
// external declarations
extern const char* GetGRPName(unsigned int index);
// No buttons or events so far
BEGIN_EVENT_TABLE(CPBView, wxListCtrl)
END_EVENT_TABLE()
// ---------------------------------------------------------------------------------------
CPBView::CPBView(wxWindow* parent, const wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: wxListCtrl(parent, id, pos, size, style)
{
InsertColumn(1, wxT("upd4"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("upd3"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("upd2"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("upd1"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("upd0"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("r_lo"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("r_hi"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("ratio"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("frac"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("coef"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("src_t"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("form"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("isstr"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("yn2"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("yn1"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("pred_s"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("isloop"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("volr"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("voll"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("loopto"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(1, wxT("end"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(0, wxT("pos"), wxLIST_FORMAT_LEFT, 90);
InsertColumn(0, wxT("run"), wxLIST_FORMAT_RIGHT, 50);
InsertColumn(0, wxT("Block"), wxLIST_FORMAT_CENTER, 40);
SetFont(wxFont(8, wxSWISS, wxNORMAL, wxNORMAL, false, wxT("Segoe UI")));
for (int i = 0; i < 64; i++)
{
// Print values from 0 to 63
char buffer [33];
sprintf(buffer, "%02i", i);
int Item = InsertItem(0, wxString::FromAscii(buffer));
wxListItem item;
item.SetId(Item);
item.SetBackgroundColour(0xFFFFFF);
item.SetData(i);
SetItem(item);
}
// This is a wx call that leads to MSWDrawSubItem
Refresh();
}
void
CPBView::Update()
{
Refresh();
}
bool
CPBView::MSWDrawSubItem(wxPaintDC& rPainDC, int item, int subitem)
{
bool Result = false;
// don't change 0, it has the block values
if(subitem > 0)
{
#ifdef __WXMSW__ // what's this? should I use that?
const wxChar* bgColor = _T("#ffffff");
wxBrush bgBrush(bgColor);
wxPen bgPen(bgColor);
wxRect SubItemRect;
this->GetSubItemRect(item, subitem, SubItemRect);
rPainDC.SetBrush(bgBrush);
rPainDC.SetPen(bgPen);
rPainDC.DrawRectangle(SubItemRect);
#endif
// A somewhat primitive attempt to show the playing history for a certain block.
wxString text;
if(subitem == 1)
{
char cbuff [33];
sprintf(cbuff, "%08i", m_CachedRegs[subitem][item]);
std::string c = cbuff;
int n[8];
for (int j = 0; j < 8; j++)
{
n[j] = atoi( c.substr(j, 1).c_str());
// 149 = dot, 160 = space
if (n[j] == 1){
n[j] = 149;} else {n[j] = 160;}
}
// pretty neat huh?
text.Printf(wxT("%c%c%c%c%c%c%c%c"), n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]);
}
else
{
text.Printf(wxT("0x%08x"), m_CachedRegs[subitem][item]);
}
#ifdef __WXMSW__
rPainDC.DrawText(text, SubItemRect.GetLeft() + 10, SubItemRect.GetTop() + 4);
#else
// May not show up pretty in !Win32
rPainDC.DrawText(text, 10, 4);
#endif
return(true);
}
else
{
// what does this mean?
return(Result);
}
}

View File

@ -1,85 +1,85 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <stdarg.h>
#include <stdio.h>
#include "Globals.h"
#include "Common.h"
void __Log(int, const char *fmt, ...)
{
DebugLog(fmt);
}
void __Log_(int v, const char *fmt, ...)
{
char Msg[512];
va_list ap;
va_start(ap, fmt);
vsprintf(Msg, fmt, ap);
va_end(ap);
g_dspInitialize.pLog(Msg, v);
}
void DebugLog(const char* _fmt, ...)
{
#if defined(_DEBUG) || defined(DEBUGFAST)
//if(strncmp (_fmt, "AX", 2)) // match = 0, in that case this is ignored
{
char Msg[512];
va_list ap;
va_start(ap, _fmt);
vsprintf(Msg, _fmt, ap);
va_end(ap);
g_dspInitialize.pLog(Msg, 0);
}
#endif
}
extern u8* g_pMemory;
// TODO: Wii support? Most likely audio data still must be in the old 24MB TRAM.
#define RAM_MASK 0x1FFFFFF
u8 Memory_Read_U8(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return g_pMemory[_uAddress];
}
u16 Memory_Read_U16(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return Common::swap16(*(u16*)&g_pMemory[_uAddress]);
}
u32 Memory_Read_U32(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return Common::swap32(*(u32*)&g_pMemory[_uAddress]);
}
float Memory_Read_Float(u32 _uAddress)
{
u32 uTemp = Memory_Read_U32(_uAddress);
return *(float*)&uTemp;
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <stdarg.h>
#include <stdio.h>
#include "Globals.h"
#include "Common.h"
void __Log(int, const char *fmt, ...)
{
DebugLog(fmt);
}
void __Log_(int v, const char *fmt, ...)
{
char Msg[512];
va_list ap;
va_start(ap, fmt);
vsprintf(Msg, fmt, ap);
va_end(ap);
g_dspInitialize.pLog(Msg, v);
}
void DebugLog(const char* _fmt, ...)
{
#if defined(_DEBUG) || defined(DEBUGFAST)
//if(strncmp (_fmt, "AX", 2)) // match = 0, in that case this is ignored
{
char Msg[512];
va_list ap;
va_start(ap, _fmt);
vsprintf(Msg, _fmt, ap);
va_end(ap);
g_dspInitialize.pLog(Msg, 0);
}
#endif
}
extern u8* g_pMemory;
// TODO: Wii support? Most likely audio data still must be in the old 24MB TRAM.
#define RAM_MASK 0x1FFFFFF
u8 Memory_Read_U8(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return g_pMemory[_uAddress];
}
u16 Memory_Read_U16(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return Common::swap16(*(u16*)&g_pMemory[_uAddress]);
}
u32 Memory_Read_U32(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return Common::swap32(*(u32*)&g_pMemory[_uAddress]);
}
float Memory_Read_Float(u32 _uAddress)
{
u32 uTemp = Memory_Read_U32(_uAddress);
return *(float*)&uTemp;
}

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/
// --------------------
// Includes
#include <string>
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#endif
#include "../Debugger/Debugger.h"
extern CDebugger* m_frame;
// --------------------
// On and off
bool g_consoleEnable = true;
//int gSaveFile = 0;
#define DEBUG_HLE
// --------------------
// Settings
int nFiles = 4;
// --------------------
// Create handles
#ifdef DEBUG_HLE
FILE* __fStdOut[4]; // you have to update this manually, we can't place a nFiles in there
#endif
#ifdef _WIN32
HANDLE __hStdOut = NULL;
#endif
// =======================================================================================
/* Start console window - width and height is the size of console window, if you specify
fname, the output will also be written to this file. TODO: Close the file pointer when the app
is closed */
// -------------
void startConsoleWin(int width, int height, char* fname)
{
#if defined(DEBUG_HLE) && defined(_WIN32)
AllocConsole();
SetConsoleTitle(fname);
__hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD co = {width,height};
SetConsoleScreenBufferSize(__hStdOut, co);
SMALL_RECT coo = {0,0,(width - 1),70}; // top, left, right, bottom
SetConsoleWindowInfo(__hStdOut, TRUE, &coo);
// ---------------------------------------------------------------------------------------
// Write to a file
if(fname)
{
for(int i = 0; i < nFiles; i++)
{
// Edit the log file name
std::string FileEnding = ".log";
std::string FileName = fname;
char buffer[33]; itoa(i, buffer, 10); // convert number to string
std::string FullFilename = (FileName + buffer + FileEnding);
__fStdOut[i] = fopen(FullFilename.c_str(), "w");
}
}
// ---------------
#endif
}
// ---------------------------------------------------------------------------------------
// File printf function
int aprintf(int a, char *fmt, ...)
{
#if defined(DEBUG_HLE) && defined(_WIN32)
if(m_frame->gSaveFile)
{
char s[5000]; // WARNING: mind this value
va_list argptr;
int cnt;
va_start(argptr, fmt);
cnt = vsnprintf(s, 5000, fmt, argptr); // remember to update this value to
va_end(argptr);
// ---------------------------------------------------------------------------------------
if(__fStdOut[a]) // TODO: make this work, we have to set all default values to NULL
//to make it work
fprintf(__fStdOut[a], s);
// -------------
return(cnt);
}
else
{
return 0;
}
#else
return 0;
#endif
}
// ---------------------------------------------------------------------------------------
// Printf to screen function
int wprintf(const char *fmt, ...)
{
#if defined(DEBUG_HLE) && defined(_WIN32)
char s[1024*20]; // Warning, mind this value
va_list argptr;
int cnt;
va_start(argptr, fmt);
cnt = vsnprintf(s, 1024*20, fmt, argptr);
va_end(argptr);
DWORD cCharsWritten;
// ---------------------------------------------------------------------------------------
if(__hStdOut)
{
WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL);
}
// -------------
return(cnt);
#else
return 0;
#endif
}
// ---------------------------------------------------------------------------------------
// Clear console screen
void ClearScreen()
{
#if defined(DEBUG_HLE) && defined(_WIN32)
if(g_consoleEnable)
{
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize,
coordScreen, &cCharsWritten);
GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize,
coordScreen, &cCharsWritten);
SetConsoleCursorPosition(hConsole, coordScreen);
}
#endif
}
// ---------------------------------------------------------------------------------------
// Get window handle of console window to be able to resize it
#if defined(DEBUG_HLE) && defined(_WIN32)
HWND GetConsoleHwnd(void)
{
#define MY_BUFSIZE 1024 // Buffer size for console window titles.
HWND hwndFound; // This is what is returned to the caller.
char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated
// WindowTitle.
char pszOldWindowTitle[MY_BUFSIZE]; // Contains original
// WindowTitle.
// Fetch current window title.
GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);
// Format a "unique" NewWindowTitle.
wsprintf(pszNewWindowTitle,"%d/%d",
GetTickCount(),
GetCurrentProcessId());
// Change current window title.
SetConsoleTitle(pszNewWindowTitle);
// Ensure window title has been updated.
Sleep(40);
// Look for NewWindowTitle.
hwndFound = FindWindow(NULL, pszNewWindowTitle);
// Restore original window title.
SetConsoleTitle(pszOldWindowTitle);
return(hwndFound);
}
#endif // win32
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// --------------------
// Includes
#include <string>
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#endif
#include "../Debugger/Debugger.h"
extern CDebugger* m_frame;
// --------------------
// On and off
bool g_consoleEnable = true;
//int gSaveFile = 0;
#define DEBUG_HLE
// --------------------
// Settings
int nFiles = 4;
// --------------------
// Create handles
#ifdef DEBUG_HLE
FILE* __fStdOut[4]; // you have to update this manually, we can't place a nFiles in there
#endif
#ifdef _WIN32
HANDLE __hStdOut = NULL;
#endif
// =======================================================================================
/* Start console window - width and height is the size of console window, if you specify
fname, the output will also be written to this file. TODO: Close the file pointer when the app
is closed */
// -------------
void startConsoleWin(int width, int height, char* fname)
{
#if defined(DEBUG_HLE) && defined(_WIN32)
AllocConsole();
SetConsoleTitle(fname);
__hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD co = {width,height};
SetConsoleScreenBufferSize(__hStdOut, co);
SMALL_RECT coo = {0,0,(width - 1),70}; // top, left, right, bottom
SetConsoleWindowInfo(__hStdOut, TRUE, &coo);
// ---------------------------------------------------------------------------------------
// Write to a file
if(fname)
{
for(int i = 0; i < nFiles; i++)
{
// Edit the log file name
std::string FileEnding = ".log";
std::string FileName = fname;
char buffer[33]; itoa(i, buffer, 10); // convert number to string
std::string FullFilename = (FileName + buffer + FileEnding);
__fStdOut[i] = fopen(FullFilename.c_str(), "w");
}
}
// ---------------
#endif
}
// ---------------------------------------------------------------------------------------
// File printf function
int aprintf(int a, char *fmt, ...)
{
#if defined(DEBUG_HLE) && defined(_WIN32)
if(m_frame->gSaveFile)
{
char s[5000]; // WARNING: mind this value
va_list argptr;
int cnt;
va_start(argptr, fmt);
cnt = vsnprintf(s, 5000, fmt, argptr); // remember to update this value to
va_end(argptr);
// ---------------------------------------------------------------------------------------
if(__fStdOut[a]) // TODO: make this work, we have to set all default values to NULL
//to make it work
fprintf(__fStdOut[a], s);
// -------------
return(cnt);
}
else
{
return 0;
}
#else
return 0;
#endif
}
// ---------------------------------------------------------------------------------------
// Printf to screen function
int wprintf(const char *fmt, ...)
{
#if defined(DEBUG_HLE) && defined(_WIN32)
char s[1024*20]; // Warning, mind this value
va_list argptr;
int cnt;
va_start(argptr, fmt);
cnt = vsnprintf(s, 1024*20, fmt, argptr);
va_end(argptr);
DWORD cCharsWritten;
// ---------------------------------------------------------------------------------------
if(__hStdOut)
{
WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL);
}
// -------------
return(cnt);
#else
return 0;
#endif
}
// ---------------------------------------------------------------------------------------
// Clear console screen
void ClearScreen()
{
#if defined(DEBUG_HLE) && defined(_WIN32)
if(g_consoleEnable)
{
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize,
coordScreen, &cCharsWritten);
GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize,
coordScreen, &cCharsWritten);
SetConsoleCursorPosition(hConsole, coordScreen);
}
#endif
}
// ---------------------------------------------------------------------------------------
// Get window handle of console window to be able to resize it
#if defined(DEBUG_HLE) && defined(_WIN32)
HWND GetConsoleHwnd(void)
{
#define MY_BUFSIZE 1024 // Buffer size for console window titles.
HWND hwndFound; // This is what is returned to the caller.
char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated
// WindowTitle.
char pszOldWindowTitle[MY_BUFSIZE]; // Contains original
// WindowTitle.
// Fetch current window title.
GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);
// Format a "unique" NewWindowTitle.
wsprintf(pszNewWindowTitle,"%d/%d",
GetTickCount(),
GetCurrentProcessId());
// Change current window title.
SetConsoleTitle(pszNewWindowTitle);
// Ensure window title has been updated.
Sleep(40);
// Look for NewWindowTitle.
hwndFound = FindWindow(NULL, pszNewWindowTitle);
// Restore original window title.
SetConsoleTitle(pszOldWindowTitle);
return(hwndFound);
}
#endif // win32

File diff suppressed because it is too large Load Diff

View File

@ -1,96 +1,96 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "MailHandler.h"
CMailHandler::CMailHandler()
{
}
CMailHandler::~CMailHandler()
{
Clear();
}
void CMailHandler::PushMail(u32 _Mail)
{
m_Mails.push(_Mail);
Update();
}
u16 CMailHandler::ReadDSPMailboxHigh()
{
// check if we have a mail for the core
if (!m_Mails.empty())
{
u16 result = (m_Mails.front() >> 16) & 0xFFFF;
Update();
return result;
}
return 0x00;
}
u16 CMailHandler::ReadDSPMailboxLow()
{
// check if we have a mail for the core
if (!m_Mails.empty())
{
u16 result = m_Mails.front() & 0xFFFF;
m_Mails.pop();
Update();
return(result);
}
return 0x00;
}
void CMailHandler::Clear()
{
while (!m_Mails.empty())
m_Mails.pop();
}
bool CMailHandler::IsEmpty()
{
return m_Mails.empty();
}
void CMailHandler::Halt(bool _Halt)
{
if (_Halt)
{
Clear();
m_Mails.push(0x80544348);
}
Update();
}
void CMailHandler::Update()
{
if (!IsEmpty())
{
// g_dspInitialize.pGenerateDSPInterrupt();
}
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "MailHandler.h"
CMailHandler::CMailHandler()
{
}
CMailHandler::~CMailHandler()
{
Clear();
}
void CMailHandler::PushMail(u32 _Mail)
{
m_Mails.push(_Mail);
Update();
}
u16 CMailHandler::ReadDSPMailboxHigh()
{
// check if we have a mail for the core
if (!m_Mails.empty())
{
u16 result = (m_Mails.front() >> 16) & 0xFFFF;
Update();
return result;
}
return 0x00;
}
u16 CMailHandler::ReadDSPMailboxLow()
{
// check if we have a mail for the core
if (!m_Mails.empty())
{
u16 result = m_Mails.front() & 0xFFFF;
m_Mails.pop();
Update();
return(result);
}
return 0x00;
}
void CMailHandler::Clear()
{
while (!m_Mails.empty())
m_Mails.pop();
}
bool CMailHandler::IsEmpty()
{
return m_Mails.empty();
}
void CMailHandler::Halt(bool _Halt)
{
if (_Halt)
{
Clear();
m_Mails.push(0x80544348);
}
Update();
}
void CMailHandler::Update()
{
if (!IsEmpty())
{
// g_dspInitialize.pGenerateDSPInterrupt();
}
}

View File

@ -1,248 +1,248 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
#include <mmsystem.h>
#include <dsound.h>
#include "DSoundStream.h"
namespace DSound
{
#define BUFSIZE 32768
#define MAXWAIT 70 //ms
CRITICAL_SECTION soundCriticalSection;
HANDLE soundSyncEvent;
HANDLE hThread;
StreamCallback callback;
IDirectSound8* ds;
IDirectSoundBuffer* dsBuffer;
int bufferSize; //i bytes
int totalRenderedBytes;
int sampleRate;
// playback position
int currentPos;
int lastPos;
short realtimeBuffer[1024 * 1024];
// We set this to shut down the sound thread.
// 0=keep playing, 1=stop playing NOW.
volatile int threadData;
inline int FIX128(int x)
{
return(x & (~127));
}
int DSound_GetSampleRate()
{
return(sampleRate);
}
bool CreateBuffer()
{
PCMWAVEFORMAT pcmwf;
DSBUFFERDESC dsbdesc;
memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
pcmwf.wf.nChannels = 2;
pcmwf.wf.nSamplesPerSec = sampleRate;
pcmwf.wf.nBlockAlign = 4;
pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
pcmwf.wBitsPerSample = 16;
//buffer description
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS; //VIKTIGT //DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
dsbdesc.dwBufferBytes = bufferSize = BUFSIZE;
dsbdesc.lpwfxFormat = (WAVEFORMATEX*)&pcmwf;
if (SUCCEEDED(ds->CreateSoundBuffer(&dsbdesc, &dsBuffer, NULL)))
{
dsBuffer->SetCurrentPosition(0);
return(true);
}
else
{
// Failed.
dsBuffer = NULL;
return(false);
}
}
bool WriteDataToBuffer(DWORD dwOffset, // Our own write cursor.
char* soundData, // Start of our data.
DWORD dwSoundBytes) // Size of block to copy.
{
void* ptr1, * ptr2;
DWORD numBytes1, numBytes2;
// Obtain memory address of write block. This will be in two parts if the block wraps around.
HRESULT hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0);
// If the buffer was lost, restore and retry lock.
if (DSERR_BUFFERLOST == hr)
{
dsBuffer->Restore();
hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0);
}
if (SUCCEEDED(hr))
{
memcpy(ptr1, soundData, numBytes1);
if (ptr2 != 0)
{
memcpy(ptr2, soundData + numBytes1, numBytes2);
}
// Release the data back to DirectSound.
dsBuffer->Unlock(ptr1, numBytes1, ptr2, numBytes2);
return(true);
}
return(false);
}
inline int ModBufferSize(int x)
{
return((x + bufferSize) % bufferSize);
}
// The audio thread.
DWORD WINAPI soundThread(void*)
{
currentPos = 0;
lastPos = 0;
// Prefill buffer?
//writeDataToBuffer(0,realtimeBuffer,bufferSize);
// dsBuffer->Lock(0, bufferSize, (void **)&p1, &num1, (void **)&p2, &num2, 0);
dsBuffer->Play(0, 0, DSBPLAY_LOOPING);
while (!threadData)
{
// No blocking inside the csection
EnterCriticalSection(&soundCriticalSection);
dsBuffer->GetCurrentPosition((DWORD*)&currentPos, 0);
int numBytesToRender = FIX128(ModBufferSize(currentPos - lastPos));
if (numBytesToRender >= 256)
{
if (numBytesToRender > sizeof(realtimeBuffer))
MessageBox(0,"soundThread: too big render call",0,0);
(*callback)(realtimeBuffer, numBytesToRender >> 2, 16, sampleRate, 2);
WriteDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender);
currentPos = ModBufferSize(lastPos + numBytesToRender);
totalRenderedBytes += numBytesToRender;
lastPos = currentPos;
}
LeaveCriticalSection(&soundCriticalSection);
WaitForSingleObject(soundSyncEvent, MAXWAIT);
}
dsBuffer->Stop();
return(0); //hurra!
}
bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback)
{
callback = _callback;
threadData = 0;
sampleRate = _sampleRate;
//no security attributes, automatic resetting, init state nonset, untitled
soundSyncEvent = CreateEvent(0, false, false, 0);
//vi initierar den...........
InitializeCriticalSection(&soundCriticalSection);
//vi vill ha access till DSOUND så...
if (FAILED(DirectSoundCreate8(0, &ds, 0)))
return false;
ds->SetCooperativeLevel(window, DSSCL_NORMAL);
if (!CreateBuffer())
{
return false;
}
DWORD num1;
short* p1;
dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0);
memset(p1, 0, num1);
dsBuffer->Unlock(p1, num1, 0, 0);
totalRenderedBytes = -bufferSize;
DWORD h;
hThread = CreateThread(0, 0, soundThread, 0, 0, &h);
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
return true;
}
void DSound_UpdateSound()
{
SetEvent(soundSyncEvent);
}
void DSound_StopSound()
{
EnterCriticalSection(&soundCriticalSection);
threadData = 1;
// kick the thread if it's waiting
SetEvent(soundSyncEvent);
LeaveCriticalSection(&soundCriticalSection);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
dsBuffer->Release();
ds->Release();
CloseHandle(soundSyncEvent);
soundSyncEvent = INVALID_HANDLE_VALUE;
hThread = INVALID_HANDLE_VALUE;
}
int DSound_GetCurSample()
{
EnterCriticalSection(&soundCriticalSection);
int playCursor;
dsBuffer->GetCurrentPosition((DWORD*)&playCursor, 0);
playCursor = ModBufferSize(playCursor - lastPos) + totalRenderedBytes;
LeaveCriticalSection(&soundCriticalSection);
return(playCursor);
}
float DSound_GetTimer()
{
return((float)DSound_GetCurSample() * (1.0f / (4.0f * sampleRate)));
}
} // namespace
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
#include <mmsystem.h>
#include <dsound.h>
#include "DSoundStream.h"
namespace DSound
{
#define BUFSIZE 32768
#define MAXWAIT 70 //ms
CRITICAL_SECTION soundCriticalSection;
HANDLE soundSyncEvent;
HANDLE hThread;
StreamCallback callback;
IDirectSound8* ds;
IDirectSoundBuffer* dsBuffer;
int bufferSize; //i bytes
int totalRenderedBytes;
int sampleRate;
// playback position
int currentPos;
int lastPos;
short realtimeBuffer[1024 * 1024];
// We set this to shut down the sound thread.
// 0=keep playing, 1=stop playing NOW.
volatile int threadData;
inline int FIX128(int x)
{
return(x & (~127));
}
int DSound_GetSampleRate()
{
return(sampleRate);
}
bool CreateBuffer()
{
PCMWAVEFORMAT pcmwf;
DSBUFFERDESC dsbdesc;
memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
pcmwf.wf.nChannels = 2;
pcmwf.wf.nSamplesPerSec = sampleRate;
pcmwf.wf.nBlockAlign = 4;
pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
pcmwf.wBitsPerSample = 16;
//buffer description
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS; //VIKTIGT //DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
dsbdesc.dwBufferBytes = bufferSize = BUFSIZE;
dsbdesc.lpwfxFormat = (WAVEFORMATEX*)&pcmwf;
if (SUCCEEDED(ds->CreateSoundBuffer(&dsbdesc, &dsBuffer, NULL)))
{
dsBuffer->SetCurrentPosition(0);
return(true);
}
else
{
// Failed.
dsBuffer = NULL;
return(false);
}
}
bool WriteDataToBuffer(DWORD dwOffset, // Our own write cursor.
char* soundData, // Start of our data.
DWORD dwSoundBytes) // Size of block to copy.
{
void* ptr1, * ptr2;
DWORD numBytes1, numBytes2;
// Obtain memory address of write block. This will be in two parts if the block wraps around.
HRESULT hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0);
// If the buffer was lost, restore and retry lock.
if (DSERR_BUFFERLOST == hr)
{
dsBuffer->Restore();
hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0);
}
if (SUCCEEDED(hr))
{
memcpy(ptr1, soundData, numBytes1);
if (ptr2 != 0)
{
memcpy(ptr2, soundData + numBytes1, numBytes2);
}
// Release the data back to DirectSound.
dsBuffer->Unlock(ptr1, numBytes1, ptr2, numBytes2);
return(true);
}
return(false);
}
inline int ModBufferSize(int x)
{
return((x + bufferSize) % bufferSize);
}
// The audio thread.
DWORD WINAPI soundThread(void*)
{
currentPos = 0;
lastPos = 0;
// Prefill buffer?
//writeDataToBuffer(0,realtimeBuffer,bufferSize);
// dsBuffer->Lock(0, bufferSize, (void **)&p1, &num1, (void **)&p2, &num2, 0);
dsBuffer->Play(0, 0, DSBPLAY_LOOPING);
while (!threadData)
{
// No blocking inside the csection
EnterCriticalSection(&soundCriticalSection);
dsBuffer->GetCurrentPosition((DWORD*)&currentPos, 0);
int numBytesToRender = FIX128(ModBufferSize(currentPos - lastPos));
if (numBytesToRender >= 256)
{
if (numBytesToRender > sizeof(realtimeBuffer))
MessageBox(0,"soundThread: too big render call",0,0);
(*callback)(realtimeBuffer, numBytesToRender >> 2, 16, sampleRate, 2);
WriteDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender);
currentPos = ModBufferSize(lastPos + numBytesToRender);
totalRenderedBytes += numBytesToRender;
lastPos = currentPos;
}
LeaveCriticalSection(&soundCriticalSection);
WaitForSingleObject(soundSyncEvent, MAXWAIT);
}
dsBuffer->Stop();
return(0); //hurra!
}
bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback)
{
callback = _callback;
threadData = 0;
sampleRate = _sampleRate;
//no security attributes, automatic resetting, init state nonset, untitled
soundSyncEvent = CreateEvent(0, false, false, 0);
//vi initierar den...........
InitializeCriticalSection(&soundCriticalSection);
//vi vill ha access till DSOUND så...
if (FAILED(DirectSoundCreate8(0, &ds, 0)))
return false;
ds->SetCooperativeLevel(window, DSSCL_NORMAL);
if (!CreateBuffer())
{
return false;
}
DWORD num1;
short* p1;
dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0);
memset(p1, 0, num1);
dsBuffer->Unlock(p1, num1, 0, 0);
totalRenderedBytes = -bufferSize;
DWORD h;
hThread = CreateThread(0, 0, soundThread, 0, 0, &h);
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
return true;
}
void DSound_UpdateSound()
{
SetEvent(soundSyncEvent);
}
void DSound_StopSound()
{
EnterCriticalSection(&soundCriticalSection);
threadData = 1;
// kick the thread if it's waiting
SetEvent(soundSyncEvent);
LeaveCriticalSection(&soundCriticalSection);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
dsBuffer->Release();
ds->Release();
CloseHandle(soundSyncEvent);
soundSyncEvent = INVALID_HANDLE_VALUE;
hThread = INVALID_HANDLE_VALUE;
}
int DSound_GetCurSample()
{
EnterCriticalSection(&soundCriticalSection);
int playCursor;
dsBuffer->GetCurrentPosition((DWORD*)&playCursor, 0);
playCursor = ModBufferSize(playCursor - lastPos) + totalRenderedBytes;
LeaveCriticalSection(&soundCriticalSection);
return(playCursor);
}
float DSound_GetTimer()
{
return((float)DSound_GetCurSample() * (1.0f / (4.0f * sampleRate)));
}
} // namespace

View File

@ -1,183 +1,183 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// This queue solution is temporary. I'll implement something more efficient later.
#include <queue>
#include "../Config.h"
#include "../Globals.h"
#include "../DSPHandler.h"
#include "../Logging/Console.h"
#include "Thread.h"
#include "Mixer.h"
#include "FixedSizeQueue.h"
#ifdef _WIN32
#include "../PCHW/DSoundStream.h"
#endif
namespace {
Common::CriticalSection push_sync;
// On real hardware, this fifo is much, much smaller. But timing is also tighter than under Windows, so...
const int queue_minlength = 1024 * 4;
const int queue_maxlength = 1024 * 28;
FixedSizeQueue<s16, queue_maxlength> sample_queue;
} // namespace
volatile bool mixer_HLEready = false;
volatile int queue_size = 0;
void Mixer(short *buffer, int numSamples, int bits, int rate, int channels)
{
// silence
memset(buffer, 0, numSamples * 2 * sizeof(short));
// first get the DTK Music
if (g_Config.m_EnableDTKMusic)
{
g_dspInitialize.pGetAudioStreaming(buffer, numSamples);
}
//if this was called directly from the HLE, and not by timeout
if (g_Config.m_EnableHLEAudio && mixer_HLEready)
{
IUCode* pUCode = CDSPHandler::GetInstance().GetUCode();
if (pUCode != NULL)
pUCode->MixAdd(buffer, numSamples);
}
push_sync.Enter();
int count = 0;
while (queue_size > queue_minlength && count < numSamples * 2) {
int x = buffer[count];
x += sample_queue.front();
if (x > 32767) x = 32767;
if (x < -32767) x = -32767;
buffer[count++] = x;
sample_queue.pop();
x = buffer[count];
x += sample_queue.front();
if (x > 32767) x = 32767;
if (x < -32767) x = -32767;
buffer[count++] = x;
sample_queue.pop();
queue_size-=2;
}
push_sync.Leave();
}
void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) {
// static FILE *f;
// if (!f)
// f = fopen("d:\\hello.raw", "wb");
// fwrite(buffer, num_stereo_samples * 4, 1, f);
if (queue_size == 0)
{
queue_size = queue_minlength;
for (int i = 0; i < queue_minlength; i++)
sample_queue.push((s16)0);
}
static int PV1l=0,PV2l=0,PV3l=0,PV4l=0;
static int PV1r=0,PV2r=0,PV3r=0,PV4r=0;
static int acc=0;
#ifdef _WIN32
if (! (GetAsyncKeyState(VK_TAB)) && g_Config.m_EnableThrottle) {
/* This is only needed for non-AX sound, currently directly streamed and
DTK sound. For AX we call DSound_UpdateSound in AXTask() for example. */
while (queue_size > queue_maxlength / 2) {
DSound::DSound_UpdateSound();
Sleep(0);
}
} else {
return;
}
#else
while (queue_size > queue_maxlength) {
sleep(0);
}
#endif
//convert into config option?
const int mode = 2;
push_sync.Enter();
while (num_stereo_samples)
{
acc += sample_rate;
while (num_stereo_samples && (acc >= 48000))
{
PV4l=PV3l;
PV3l=PV2l;
PV2l=PV1l;
PV1l=*(buffer++); //32bit processing
PV4r=PV3r;
PV3r=PV2r;
PV2r=PV1r;
PV1r=*(buffer++); //32bit processing
num_stereo_samples--;
acc-=48000;
}
// defaults to nearest
s32 DataL = PV1l;
s32 DataR = PV1r;
if (mode == 1) //linear
{
DataL = PV1l + ((PV2l - PV1l)*acc)/48000;
DataR = PV1r + ((PV2r - PV1r)*acc)/48000;
}
else if (mode == 2) //cubic
{
s32 a0l = PV1l - PV2l - PV4l + PV3l;
s32 a0r = PV1r - PV2r - PV4r + PV3r;
s32 a1l = PV4l - PV3l - a0l;
s32 a1r = PV4r - PV3r - a0r;
s32 a2l = PV1l - PV4l;
s32 a2r = PV1r - PV4r;
s32 a3l = PV2l;
s32 a3r = PV2r;
s32 t0l = ((a0l )*acc)/48000;
s32 t0r = ((a0r )*acc)/48000;
s32 t1l = ((t0l+a1l)*acc)/48000;
s32 t1r = ((t0r+a1r)*acc)/48000;
s32 t2l = ((t1l+a2l)*acc)/48000;
s32 t2r = ((t1r+a2r)*acc)/48000;
s32 t3l = ((t2l+a3l));
s32 t3r = ((t2r+a3r));
DataL = t3l;
DataR = t3r;
}
int l = DataL, r = DataR;
if (l < -32767) l = -32767;
if (r < -32767) r = -32767;
if (l > 32767) l = 32767;
if (r > 32767) r = 32767;
sample_queue.push(l);
sample_queue.push(r);
queue_size += 2;
}
push_sync.Leave();
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// This queue solution is temporary. I'll implement something more efficient later.
#include <queue>
#include "../Config.h"
#include "../Globals.h"
#include "../DSPHandler.h"
#include "../Logging/Console.h"
#include "Thread.h"
#include "Mixer.h"
#include "FixedSizeQueue.h"
#ifdef _WIN32
#include "../PCHW/DSoundStream.h"
#endif
namespace {
Common::CriticalSection push_sync;
// On real hardware, this fifo is much, much smaller. But timing is also tighter than under Windows, so...
const int queue_minlength = 1024 * 4;
const int queue_maxlength = 1024 * 28;
FixedSizeQueue<s16, queue_maxlength> sample_queue;
} // namespace
volatile bool mixer_HLEready = false;
volatile int queue_size = 0;
void Mixer(short *buffer, int numSamples, int bits, int rate, int channels)
{
// silence
memset(buffer, 0, numSamples * 2 * sizeof(short));
// first get the DTK Music
if (g_Config.m_EnableDTKMusic)
{
g_dspInitialize.pGetAudioStreaming(buffer, numSamples);
}
//if this was called directly from the HLE, and not by timeout
if (g_Config.m_EnableHLEAudio && mixer_HLEready)
{
IUCode* pUCode = CDSPHandler::GetInstance().GetUCode();
if (pUCode != NULL)
pUCode->MixAdd(buffer, numSamples);
}
push_sync.Enter();
int count = 0;
while (queue_size > queue_minlength && count < numSamples * 2) {
int x = buffer[count];
x += sample_queue.front();
if (x > 32767) x = 32767;
if (x < -32767) x = -32767;
buffer[count++] = x;
sample_queue.pop();
x = buffer[count];
x += sample_queue.front();
if (x > 32767) x = 32767;
if (x < -32767) x = -32767;
buffer[count++] = x;
sample_queue.pop();
queue_size-=2;
}
push_sync.Leave();
}
void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) {
// static FILE *f;
// if (!f)
// f = fopen("d:\\hello.raw", "wb");
// fwrite(buffer, num_stereo_samples * 4, 1, f);
if (queue_size == 0)
{
queue_size = queue_minlength;
for (int i = 0; i < queue_minlength; i++)
sample_queue.push((s16)0);
}
static int PV1l=0,PV2l=0,PV3l=0,PV4l=0;
static int PV1r=0,PV2r=0,PV3r=0,PV4r=0;
static int acc=0;
#ifdef _WIN32
if (! (GetAsyncKeyState(VK_TAB)) && g_Config.m_EnableThrottle) {
/* This is only needed for non-AX sound, currently directly streamed and
DTK sound. For AX we call DSound_UpdateSound in AXTask() for example. */
while (queue_size > queue_maxlength / 2) {
DSound::DSound_UpdateSound();
Sleep(0);
}
} else {
return;
}
#else
while (queue_size > queue_maxlength) {
sleep(0);
}
#endif
//convert into config option?
const int mode = 2;
push_sync.Enter();
while (num_stereo_samples)
{
acc += sample_rate;
while (num_stereo_samples && (acc >= 48000))
{
PV4l=PV3l;
PV3l=PV2l;
PV2l=PV1l;
PV1l=*(buffer++); //32bit processing
PV4r=PV3r;
PV3r=PV2r;
PV2r=PV1r;
PV1r=*(buffer++); //32bit processing
num_stereo_samples--;
acc-=48000;
}
// defaults to nearest
s32 DataL = PV1l;
s32 DataR = PV1r;
if (mode == 1) //linear
{
DataL = PV1l + ((PV2l - PV1l)*acc)/48000;
DataR = PV1r + ((PV2r - PV1r)*acc)/48000;
}
else if (mode == 2) //cubic
{
s32 a0l = PV1l - PV2l - PV4l + PV3l;
s32 a0r = PV1r - PV2r - PV4r + PV3r;
s32 a1l = PV4l - PV3l - a0l;
s32 a1r = PV4r - PV3r - a0r;
s32 a2l = PV1l - PV4l;
s32 a2r = PV1r - PV4r;
s32 a3l = PV2l;
s32 a3r = PV2r;
s32 t0l = ((a0l )*acc)/48000;
s32 t0r = ((a0r )*acc)/48000;
s32 t1l = ((t0l+a1l)*acc)/48000;
s32 t1r = ((t0r+a1r)*acc)/48000;
s32 t2l = ((t1l+a2l)*acc)/48000;
s32 t2r = ((t1r+a2r)*acc)/48000;
s32 t3l = ((t2l+a3l));
s32 t3r = ((t2r+a3r));
DataL = t3l;
DataR = t3r;
}
int l = DataL, r = DataR;
if (l < -32767) l = -32767;
if (r < -32767) r = -32767;
if (l > 32767) l = 32767;
if (r > 32767) r = 32767;
sample_queue.push(l);
sample_queue.push(r);
queue_size += 2;
}
push_sync.Leave();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,432 +1,432 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "StringUtil.h"
#include "../Debugger/Debugger.h"
#include "../Logging/Console.h" // for aprintf
#ifdef _WIN32
#include "../PCHW/DSoundStream.h"
#endif
#include "../PCHW/Mixer.h"
#include "../MailHandler.h"
#include "UCodes.h"
#include "UCode_AXStructs.h"
#include "UCode_AX.h" // for some functions in CUCode_AX
#include "UCode_AXWii.h"
#include "UCode_AX_Voice.h"
// ------------------------------------------------------------------
// Declarations
// -----------
extern bool gSequenced;
extern CDebugger * m_frame;
// -----------
CUCode_AXWii::CUCode_AXWii(CMailHandler& _rMailHandler, u32 l_CRC)
: IUCode(_rMailHandler)
, m_addressPBs(0xFFFFFFFF)
, _CRC(l_CRC)
{
// we got loaded
m_rMailHandler.PushMail(0xDCD10000);
m_rMailHandler.PushMail(0x80000000); // handshake ??? only (crc == 0xe2136399) needs it ...
templbuffer = new int[1024 * 1024];
temprbuffer = new int[1024 * 1024];
lCUCode_AX = new CUCode_AX(_rMailHandler);
lCUCode_AX->_CRC = l_CRC;
}
CUCode_AXWii::~CUCode_AXWii()
{
m_rMailHandler.Clear();
delete [] templbuffer;
delete [] temprbuffer;
}
void CUCode_AXWii::HandleMail(u32 _uMail)
{
if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST)
{
// a new List
}
else
{
AXTask(_uMail);
}
}
void CUCode_AXWii::MixAdd(short* _pBuffer, int _iSize)
{
if(_CRC == 0xfa450138)
{
AXParamBlockWii PBs[NUMBER_OF_PBS];
MixAdd_( _pBuffer, _iSize, PBs);
}
else
{
AXParamBlockWii_ PBs[NUMBER_OF_PBS];
MixAdd_(_pBuffer, _iSize, PBs);
}
}
template<class ParamBlockType>
void CUCode_AXWii::MixAdd_(short* _pBuffer, int _iSize, ParamBlockType &PBs)
{
//AXParamBlockWii PBs[NUMBER_OF_PBS];
// read out pbs
int numberOfPBs = ReadOutPBsWii(m_addressPBs, PBs, NUMBER_OF_PBS);
if (_iSize > 1024 * 1024)
_iSize = 1024 * 1024;
// write zeroes to the beginning of templbuffer
memset(templbuffer, 0, _iSize * sizeof(int));
memset(temprbuffer, 0, _iSize * sizeof(int));
// -------------------------------------------
// write logging data to debugger
if (m_frame)
{
lCUCode_AX->Logging(_pBuffer, _iSize, 0, true);
// -------------------------------------------
// Write the first block values
int p = numberOfPBs - 1;
if(numberOfPBs > p)
{
if(PBs[p].running && !m_frame->upd95)
{
const u32 blockAddr = (u32)(PBs[p].this_pb_hi<< 16) | PBs[p].this_pb_lo;
const short *pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr);
for (u32 i = 0; i < sizeof(AXParamBlockWii) / 2; i+=2)
{
if(i == 10 || i == 34 || i == 41 || i == 46 || i == 46 || i == 58 || i == 60
|| i == 68 || i == 88 || i == 95)
{m_frame->str0 += "\n"; m_frame->str95 += "\n";}
std::string line = StringFromFormat("%02i|%02i : %s : %s",
i/2, i,
m_frame->PBn[i].c_str(), m_frame->PBp[i].c_str()
);
for (u32 j = 0; j < 50 - line.length(); ++j)
line += " ";
m_frame->str0 += line;
m_frame->str0 += "\n";
m_frame->str95 += StringFromFormat(" : %02i|%02i : %04x%04x\n",
i/2, i,
Common::swap16(pSrc[i]), Common::swap16(pSrc[i+1]));
}
m_frame->m_bl95->AppendText(wxString::FromAscii(m_frame->str95.c_str()));
m_frame->m_bl0->AppendText(wxString::FromAscii(m_frame->str0.c_str()));
m_frame->upd95 = true;
}
}
}
// -----------------
// ---------------------------------------------------------------------------------------
/* Make the updates we are told to do. See comments to the GC version in UCode_AX.cpp */
// ------------
for (int i = 0; i < numberOfPBs; i++)
{
u16 *pDest = (u16 *)&PBs[i];
u16 upd0 = pDest[41]; u16 upd1 = pDest[42]; u16 upd2 = pDest[43]; // num_updates
u16 upd_hi = pDest[44]; // update addr
u16 upd_lo = pDest[45];
int numupd = upd0 + upd1 + upd2;
if(numupd > 64) numupd = 64; // prevent to high values
const u32 updaddr = (u32)(upd_hi << 16) | upd_lo;
int on = false, off = false;
for (int j = 0; j < numupd; j++) // make alll updates
{
const u16 updpar = Memory_Read_U16(updaddr);
const u16 upddata = Memory_Read_U16(updaddr + 2);
// some safety checks, I hope it's enough
if( ( (updaddr > 0x80000000 && updaddr < 0x817fffff)
|| (updaddr > 0x90000000 && updaddr < 0x93ffffff) )
&& updpar < 127 && updpar > 3 && upddata >= 0 // updpar > 3 because we don't want to change
// 0-3, those are important
//&& (upd0 || upd1 || upd2) // We should use these in some way to I think
// but I don't know how or when
&& gSequenced) // on and off option
{
//PanicAlert("Update %i: %i = %04x", i, updpar, upddata);
//DebugLog("Update: %i = %04x", updpar, upddata);
pDest[updpar] = upddata;
}
if (updpar == 7 && upddata == 1) on++;
if (updpar == 7 && upddata == 1) off++;
}
// hack: if we get both an on and an off select on rather than off
if (on > 0 && off > 0) pDest[7] = 1;
}
//aprintf(1, "%08x %04x %04x\n", updaddr, updpar, upddata);
// ------------
for (int i = 0; i < numberOfPBs; i++)
{
MixAddVoice(PBs[i], templbuffer, temprbuffer, _iSize, true);
}
WriteBackPBsWii(m_addressPBs, PBs, numberOfPBs);
// We write the sound to _pBuffer
for (int i = 0; i < _iSize; i++)
{
// Clamp into 16-bit. Maybe we should add a volume compressor here.
int left = templbuffer[i] + _pBuffer[0];
int right = temprbuffer[i] + _pBuffer[1];
if (left < -32767) left = -32767;
if (left > 32767) left = 32767;
if (right < -32767) right = -32767;
if (right > 32767) right = 32767;
*_pBuffer++ = left;
*_pBuffer++ = right;
}
// write logging data to debugger again after the update
if (m_frame)
{
lCUCode_AX->Logging(_pBuffer, _iSize, 1, true);
}
}
void CUCode_AXWii::Update()
{
// check if we have to sent something
if (!m_rMailHandler.IsEmpty())
{
g_dspInitialize.pGenerateDSPInterrupt();
}
}
// Shortcut
void CUCode_AXWii::SaveLog(const char* _fmt, ...)
{
va_list ap; va_start(ap, _fmt); if(m_frame) lCUCode_AX->SaveLog_(true, _fmt, ap); va_end(ap);
}
// AX seems to bootup one task only and waits for resume-callbacks
// everytime the DSP has "spare time" it sends a resume-mail to the CPU
// and the __DSPHandler calls a AX-Callback which generates a new AXFrame
bool CUCode_AXWii::AXTask(u32& _uMail)
{
u32 uAddress = _uMail;
SaveLog("Begin");
SaveLog("=====================================================================");
SaveLog("%08x: AXTask - AXCommandList-Addr", uAddress);
u32 Addr__AXStudio;
u32 Addr__AXOutSBuffer;
// u32 Addr__AXOutSBuffer_1;
// u32 Addr__AXOutSBuffer_2;
u32 Addr__A;
// u32 Addr__12;
u32 Addr__5_1;
u32 Addr__5_2;
u32 Addr__6;
// u32 Addr__9;
bool bExecuteList = true;
if(m_frame) lCUCode_AX->SaveMail(true, uAddress); // Save mail for debugging
if (false)
{
// PanicAlert("%i", sizeof(AXParamBlockWii)); // 252 ??
FILE *f = fopen("D:\\axdump.txt", "a");
if (!f)
f = fopen("D:\\axdump.txt", "w");
u32 addr = uAddress;
for (int i = 0; i < 100; i++) {
fprintf(f, "%02x\n", Memory_Read_U16(addr + i * 2));
}
fprintf(f, "===========------------------------------------------------=\n");
fclose(f);
}
else
{
// PanicAlert("%i", sizeof(AXParamBlock)); // 192
}
while (bExecuteList)
{
static int last_valid_command = 0;
u16 iCommand = Memory_Read_U16(uAddress);
uAddress += 2;
switch (iCommand)
{
case 0x0000: //00
Addr__AXStudio = Memory_Read_U32(uAddress);
uAddress += 4;
SaveLog("%08x : AXLIST studio address: %08x", uAddress, Addr__AXStudio);
break;
case 0x0001:
{
u32 address = Memory_Read_U32(uAddress);
uAddress += 4;
SaveLog("%08x : AXLIST 1: %08x", uAddress, address);
}
break;
case 0x0003:
{
u32 address = Memory_Read_U32(uAddress);
uAddress += 4;
SaveLog("%08x : AXLIST 3: %08x", uAddress, address);
}
break;
case 0x0004: // PBs are here now
m_addressPBs = Memory_Read_U32(uAddress);
lCUCode_AX->m_addressPBs = m_addressPBs; // for the sake of logging
mixer_HLEready = true;
SaveLog("%08x : AXLIST PB address: %08x", uAddress, m_addressPBs);
#ifdef _WIN32
//DebugLog("Update the SoundThread to be in sync");
DSound::DSound_UpdateSound(); //do it in this thread to avoid sync problems
#endif
uAddress += 4;
break;
case 0x0005:
if(Memory_Read_U16(uAddress) > 25) // this occured in Wii Sports
{
Addr__5_1 = Memory_Read_U32(uAddress);
uAddress += 4;
Addr__5_2 = Memory_Read_U32(uAddress);
uAddress += 4;
uAddress += 2;
SaveLog("%08x : AXLIST 5_1 5_2 addresses: %08x %08x", uAddress, Addr__5_1, Addr__5_2);
}
else
{
uAddress += 2;
SaveLog("%08x : AXLIST Empty 0x0005", uAddress);
}
break;
case 0x0006:
Addr__6 = Memory_Read_U32(uAddress);
uAddress += 10;
SaveLog("%08x : AXLIST 6 address: %08x", uAddress, Addr__6);
break;
/**/ case 0x0007: // AXLIST_SBUFFER
Addr__AXOutSBuffer = Memory_Read_U32(uAddress);
uAddress += 10;
// uAddress += 12;
SaveLog("%08x : AXLIST OutSBuffer (0x0007) address: %08x", uAddress, Addr__AXOutSBuffer);
break;
/* case 0x0009:
Addr__9 = Memory_Read_U32(uAddress);
uAddress += 4;
DebugLog("AXLIST 6 address: %08x", Addr__9);
break;*/
case 0x000a: // AXLIST_COMPRESSORTABLE
Addr__A = Memory_Read_U32(uAddress);
uAddress += 4;
//Addr__A = Memory_Read_U32(uAddress);
uAddress += 4;
SaveLog("%08x : AXLIST CompressorTable address: %08x", uAddress, Addr__A);
break;
case 0x000b:
uAddress += 2; // one 0x8000 in rabbids
uAddress += 4 * 2; // then two RAM addressses
break;
case 0x000c:
uAddress += 2; // one 0x8000 in rabbids
uAddress += 4 * 2; // then two RAM addressses
break;
case 0x000d:
uAddress += 4 * 4;
break;
case 0x000e:
// This is the end.
bExecuteList = false;
SaveLog("%08x : AXLIST end, wii stylee.", uAddress);
break;
default:
{
static bool bFirst = true;
if (bFirst == true)
{
// A little more descreet way to say that there is a problem, that also let you
// take a look at the mail (and possible previous mails) in the debugger
SaveLog("%08x : Unknown AX-Command 0x%04x", uAddress, iCommand);
bExecuteList = false;
break;
char szTemp[2048];
sprintf(szTemp, "Unknown AX-Command 0x%04x (address: 0x%08x). Last valid: %02x\n",
iCommand, uAddress - 2, last_valid_command);
int num = -32;
while (num < 64+32)
{
char szTemp2[128] = "";
sprintf(szTemp2, "%s0x%04x\n", num == 0 ? ">>" : " ", Memory_Read_U16(uAddress + num));
strcat(szTemp, szTemp2);
num += 2;
}
// Wii AX will always show this
PanicAlert(szTemp);
// bFirst = false;
}
// unknown command so stop the execution of this TaskList
bExecuteList = false;
}
break;
}
if (bExecuteList)
last_valid_command = iCommand;
}
SaveLog("AXTask - done, send resume");
SaveLog("=====================================================================");
SaveLog("End");
// i hope resume is okay AX
m_rMailHandler.PushMail(0xDCD10001);
return true;
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "StringUtil.h"
#include "../Debugger/Debugger.h"
#include "../Logging/Console.h" // for aprintf
#ifdef _WIN32
#include "../PCHW/DSoundStream.h"
#endif
#include "../PCHW/Mixer.h"
#include "../MailHandler.h"
#include "UCodes.h"
#include "UCode_AXStructs.h"
#include "UCode_AX.h" // for some functions in CUCode_AX
#include "UCode_AXWii.h"
#include "UCode_AX_Voice.h"
// ------------------------------------------------------------------
// Declarations
// -----------
extern bool gSequenced;
extern CDebugger * m_frame;
// -----------
CUCode_AXWii::CUCode_AXWii(CMailHandler& _rMailHandler, u32 l_CRC)
: IUCode(_rMailHandler)
, m_addressPBs(0xFFFFFFFF)
, _CRC(l_CRC)
{
// we got loaded
m_rMailHandler.PushMail(0xDCD10000);
m_rMailHandler.PushMail(0x80000000); // handshake ??? only (crc == 0xe2136399) needs it ...
templbuffer = new int[1024 * 1024];
temprbuffer = new int[1024 * 1024];
lCUCode_AX = new CUCode_AX(_rMailHandler);
lCUCode_AX->_CRC = l_CRC;
}
CUCode_AXWii::~CUCode_AXWii()
{
m_rMailHandler.Clear();
delete [] templbuffer;
delete [] temprbuffer;
}
void CUCode_AXWii::HandleMail(u32 _uMail)
{
if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST)
{
// a new List
}
else
{
AXTask(_uMail);
}
}
void CUCode_AXWii::MixAdd(short* _pBuffer, int _iSize)
{
if(_CRC == 0xfa450138)
{
AXParamBlockWii PBs[NUMBER_OF_PBS];
MixAdd_( _pBuffer, _iSize, PBs);
}
else
{
AXParamBlockWii_ PBs[NUMBER_OF_PBS];
MixAdd_(_pBuffer, _iSize, PBs);
}
}
template<class ParamBlockType>
void CUCode_AXWii::MixAdd_(short* _pBuffer, int _iSize, ParamBlockType &PBs)
{
//AXParamBlockWii PBs[NUMBER_OF_PBS];
// read out pbs
int numberOfPBs = ReadOutPBsWii(m_addressPBs, PBs, NUMBER_OF_PBS);
if (_iSize > 1024 * 1024)
_iSize = 1024 * 1024;
// write zeroes to the beginning of templbuffer
memset(templbuffer, 0, _iSize * sizeof(int));
memset(temprbuffer, 0, _iSize * sizeof(int));
// -------------------------------------------
// write logging data to debugger
if (m_frame)
{
lCUCode_AX->Logging(_pBuffer, _iSize, 0, true);
// -------------------------------------------
// Write the first block values
int p = numberOfPBs - 1;
if(numberOfPBs > p)
{
if(PBs[p].running && !m_frame->upd95)
{
const u32 blockAddr = (u32)(PBs[p].this_pb_hi<< 16) | PBs[p].this_pb_lo;
const short *pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr);
for (u32 i = 0; i < sizeof(AXParamBlockWii) / 2; i+=2)
{
if(i == 10 || i == 34 || i == 41 || i == 46 || i == 46 || i == 58 || i == 60
|| i == 68 || i == 88 || i == 95)
{m_frame->str0 += "\n"; m_frame->str95 += "\n";}
std::string line = StringFromFormat("%02i|%02i : %s : %s",
i/2, i,
m_frame->PBn[i].c_str(), m_frame->PBp[i].c_str()
);
for (u32 j = 0; j < 50 - line.length(); ++j)
line += " ";
m_frame->str0 += line;
m_frame->str0 += "\n";
m_frame->str95 += StringFromFormat(" : %02i|%02i : %04x%04x\n",
i/2, i,
Common::swap16(pSrc[i]), Common::swap16(pSrc[i+1]));
}
m_frame->m_bl95->AppendText(wxString::FromAscii(m_frame->str95.c_str()));
m_frame->m_bl0->AppendText(wxString::FromAscii(m_frame->str0.c_str()));
m_frame->upd95 = true;
}
}
}
// -----------------
// ---------------------------------------------------------------------------------------
/* Make the updates we are told to do. See comments to the GC version in UCode_AX.cpp */
// ------------
for (int i = 0; i < numberOfPBs; i++)
{
u16 *pDest = (u16 *)&PBs[i];
u16 upd0 = pDest[41]; u16 upd1 = pDest[42]; u16 upd2 = pDest[43]; // num_updates
u16 upd_hi = pDest[44]; // update addr
u16 upd_lo = pDest[45];
int numupd = upd0 + upd1 + upd2;
if(numupd > 64) numupd = 64; // prevent to high values
const u32 updaddr = (u32)(upd_hi << 16) | upd_lo;
int on = false, off = false;
for (int j = 0; j < numupd; j++) // make alll updates
{
const u16 updpar = Memory_Read_U16(updaddr);
const u16 upddata = Memory_Read_U16(updaddr + 2);
// some safety checks, I hope it's enough
if( ( (updaddr > 0x80000000 && updaddr < 0x817fffff)
|| (updaddr > 0x90000000 && updaddr < 0x93ffffff) )
&& updpar < 127 && updpar > 3 && upddata >= 0 // updpar > 3 because we don't want to change
// 0-3, those are important
//&& (upd0 || upd1 || upd2) // We should use these in some way to I think
// but I don't know how or when
&& gSequenced) // on and off option
{
//PanicAlert("Update %i: %i = %04x", i, updpar, upddata);
//DebugLog("Update: %i = %04x", updpar, upddata);
pDest[updpar] = upddata;
}
if (updpar == 7 && upddata == 1) on++;
if (updpar == 7 && upddata == 1) off++;
}
// hack: if we get both an on and an off select on rather than off
if (on > 0 && off > 0) pDest[7] = 1;
}
//aprintf(1, "%08x %04x %04x\n", updaddr, updpar, upddata);
// ------------
for (int i = 0; i < numberOfPBs; i++)
{
MixAddVoice(PBs[i], templbuffer, temprbuffer, _iSize, true);
}
WriteBackPBsWii(m_addressPBs, PBs, numberOfPBs);
// We write the sound to _pBuffer
for (int i = 0; i < _iSize; i++)
{
// Clamp into 16-bit. Maybe we should add a volume compressor here.
int left = templbuffer[i] + _pBuffer[0];
int right = temprbuffer[i] + _pBuffer[1];
if (left < -32767) left = -32767;
if (left > 32767) left = 32767;
if (right < -32767) right = -32767;
if (right > 32767) right = 32767;
*_pBuffer++ = left;
*_pBuffer++ = right;
}
// write logging data to debugger again after the update
if (m_frame)
{
lCUCode_AX->Logging(_pBuffer, _iSize, 1, true);
}
}
void CUCode_AXWii::Update()
{
// check if we have to sent something
if (!m_rMailHandler.IsEmpty())
{
g_dspInitialize.pGenerateDSPInterrupt();
}
}
// Shortcut
void CUCode_AXWii::SaveLog(const char* _fmt, ...)
{
va_list ap; va_start(ap, _fmt); if(m_frame) lCUCode_AX->SaveLog_(true, _fmt, ap); va_end(ap);
}
// AX seems to bootup one task only and waits for resume-callbacks
// everytime the DSP has "spare time" it sends a resume-mail to the CPU
// and the __DSPHandler calls a AX-Callback which generates a new AXFrame
bool CUCode_AXWii::AXTask(u32& _uMail)
{
u32 uAddress = _uMail;
SaveLog("Begin");
SaveLog("=====================================================================");
SaveLog("%08x: AXTask - AXCommandList-Addr", uAddress);
u32 Addr__AXStudio;
u32 Addr__AXOutSBuffer;
// u32 Addr__AXOutSBuffer_1;
// u32 Addr__AXOutSBuffer_2;
u32 Addr__A;
// u32 Addr__12;
u32 Addr__5_1;
u32 Addr__5_2;
u32 Addr__6;
// u32 Addr__9;
bool bExecuteList = true;
if(m_frame) lCUCode_AX->SaveMail(true, uAddress); // Save mail for debugging
if (false)
{
// PanicAlert("%i", sizeof(AXParamBlockWii)); // 252 ??
FILE *f = fopen("D:\\axdump.txt", "a");
if (!f)
f = fopen("D:\\axdump.txt", "w");
u32 addr = uAddress;
for (int i = 0; i < 100; i++) {
fprintf(f, "%02x\n", Memory_Read_U16(addr + i * 2));
}
fprintf(f, "===========------------------------------------------------=\n");
fclose(f);
}
else
{
// PanicAlert("%i", sizeof(AXParamBlock)); // 192
}
while (bExecuteList)
{
static int last_valid_command = 0;
u16 iCommand = Memory_Read_U16(uAddress);
uAddress += 2;
switch (iCommand)
{
case 0x0000: //00
Addr__AXStudio = Memory_Read_U32(uAddress);
uAddress += 4;
SaveLog("%08x : AXLIST studio address: %08x", uAddress, Addr__AXStudio);
break;
case 0x0001:
{
u32 address = Memory_Read_U32(uAddress);
uAddress += 4;
SaveLog("%08x : AXLIST 1: %08x", uAddress, address);
}
break;
case 0x0003:
{
u32 address = Memory_Read_U32(uAddress);
uAddress += 4;
SaveLog("%08x : AXLIST 3: %08x", uAddress, address);
}
break;
case 0x0004: // PBs are here now
m_addressPBs = Memory_Read_U32(uAddress);
lCUCode_AX->m_addressPBs = m_addressPBs; // for the sake of logging
mixer_HLEready = true;
SaveLog("%08x : AXLIST PB address: %08x", uAddress, m_addressPBs);
#ifdef _WIN32
//DebugLog("Update the SoundThread to be in sync");
DSound::DSound_UpdateSound(); //do it in this thread to avoid sync problems
#endif
uAddress += 4;
break;
case 0x0005:
if(Memory_Read_U16(uAddress) > 25) // this occured in Wii Sports
{
Addr__5_1 = Memory_Read_U32(uAddress);
uAddress += 4;
Addr__5_2 = Memory_Read_U32(uAddress);
uAddress += 4;
uAddress += 2;
SaveLog("%08x : AXLIST 5_1 5_2 addresses: %08x %08x", uAddress, Addr__5_1, Addr__5_2);
}
else
{
uAddress += 2;
SaveLog("%08x : AXLIST Empty 0x0005", uAddress);
}
break;
case 0x0006:
Addr__6 = Memory_Read_U32(uAddress);
uAddress += 10;
SaveLog("%08x : AXLIST 6 address: %08x", uAddress, Addr__6);
break;
/**/ case 0x0007: // AXLIST_SBUFFER
Addr__AXOutSBuffer = Memory_Read_U32(uAddress);
uAddress += 10;
// uAddress += 12;
SaveLog("%08x : AXLIST OutSBuffer (0x0007) address: %08x", uAddress, Addr__AXOutSBuffer);
break;
/* case 0x0009:
Addr__9 = Memory_Read_U32(uAddress);
uAddress += 4;
DebugLog("AXLIST 6 address: %08x", Addr__9);
break;*/
case 0x000a: // AXLIST_COMPRESSORTABLE
Addr__A = Memory_Read_U32(uAddress);
uAddress += 4;
//Addr__A = Memory_Read_U32(uAddress);
uAddress += 4;
SaveLog("%08x : AXLIST CompressorTable address: %08x", uAddress, Addr__A);
break;
case 0x000b:
uAddress += 2; // one 0x8000 in rabbids
uAddress += 4 * 2; // then two RAM addressses
break;
case 0x000c:
uAddress += 2; // one 0x8000 in rabbids
uAddress += 4 * 2; // then two RAM addressses
break;
case 0x000d:
uAddress += 4 * 4;
break;
case 0x000e:
// This is the end.
bExecuteList = false;
SaveLog("%08x : AXLIST end, wii stylee.", uAddress);
break;
default:
{
static bool bFirst = true;
if (bFirst == true)
{
// A little more descreet way to say that there is a problem, that also let you
// take a look at the mail (and possible previous mails) in the debugger
SaveLog("%08x : Unknown AX-Command 0x%04x", uAddress, iCommand);
bExecuteList = false;
break;
char szTemp[2048];
sprintf(szTemp, "Unknown AX-Command 0x%04x (address: 0x%08x). Last valid: %02x\n",
iCommand, uAddress - 2, last_valid_command);
int num = -32;
while (num < 64+32)
{
char szTemp2[128] = "";
sprintf(szTemp2, "%s0x%04x\n", num == 0 ? ">>" : " ", Memory_Read_U16(uAddress + num));
strcat(szTemp, szTemp2);
num += 2;
}
// Wii AX will always show this
PanicAlert(szTemp);
// bFirst = false;
}
// unknown command so stop the execution of this TaskList
bExecuteList = false;
}
break;
}
if (bExecuteList)
last_valid_command = iCommand;
}
SaveLog("AXTask - done, send resume");
SaveLog("=====================================================================");
SaveLog("End");
// i hope resume is okay AX
m_rMailHandler.PushMail(0xDCD10001);
return true;
}

View File

@ -1,62 +1,62 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../Globals.h"
#include "../DSPHandler.h"
#include "UCodes.h"
#include "UCode_CARD.h"
CUCode_CARD::CUCode_CARD(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
{
DebugLog("CUCode_CARD - initialized");
m_rMailHandler.PushMail(DSP_INIT);
}
CUCode_CARD::~CUCode_CARD()
{
m_rMailHandler.Clear();
}
void CUCode_CARD::Update()
{
// check if we have to sent something
if (!m_rMailHandler.IsEmpty())
{
g_dspInitialize.pGenerateDSPInterrupt();
}
}
void CUCode_CARD::HandleMail(u32 _uMail)
{
if (_uMail == 0xFF000000) // unlock card
{
// m_Mails.push(0x00000001); // ACK (actualy anything != 0)
}
else
{
DebugLog("CUCode_CARD - unknown cmd: %x (size %i)", _uMail);
}
m_rMailHandler.PushMail(DSP_DONE);
CDSPHandler::GetInstance().SetUCode(UCODE_ROM);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../Globals.h"
#include "../DSPHandler.h"
#include "UCodes.h"
#include "UCode_CARD.h"
CUCode_CARD::CUCode_CARD(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
{
DebugLog("CUCode_CARD - initialized");
m_rMailHandler.PushMail(DSP_INIT);
}
CUCode_CARD::~CUCode_CARD()
{
m_rMailHandler.Clear();
}
void CUCode_CARD::Update()
{
// check if we have to sent something
if (!m_rMailHandler.IsEmpty())
{
g_dspInitialize.pGenerateDSPInterrupt();
}
}
void CUCode_CARD::HandleMail(u32 _uMail)
{
if (_uMail == 0xFF000000) // unlock card
{
// m_Mails.push(0x00000001); // ACK (actualy anything != 0)
}
else
{
DebugLog("CUCode_CARD - unknown cmd: %x (size %i)", _uMail);
}
m_rMailHandler.PushMail(DSP_DONE);
CDSPHandler::GetInstance().SetUCode(UCODE_ROM);
}

View File

@ -1,53 +1,53 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../Globals.h"
#include "../DSPHandler.h"
#include "UCodes.h"
#include "UCode_InitAudioSystem.h"
CUCode_InitAudioSystem::CUCode_InitAudioSystem(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
, m_BootTask_numSteps(0)
, m_NextParameter(0)
, IsInitialized(false)
{
DebugLog("CUCode_InitAudioSystem - initialized");
}
CUCode_InitAudioSystem::~CUCode_InitAudioSystem()
{}
void CUCode_InitAudioSystem::Init()
{}
void CUCode_InitAudioSystem::Update()
{
if (m_rMailHandler.IsEmpty())
{
m_rMailHandler.PushMail(0x80544348);
// HALT
}
}
void CUCode_InitAudioSystem::HandleMail(u32 _uMail)
{}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../Globals.h"
#include "../DSPHandler.h"
#include "UCodes.h"
#include "UCode_InitAudioSystem.h"
CUCode_InitAudioSystem::CUCode_InitAudioSystem(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
, m_BootTask_numSteps(0)
, m_NextParameter(0)
, IsInitialized(false)
{
DebugLog("CUCode_InitAudioSystem - initialized");
}
CUCode_InitAudioSystem::~CUCode_InitAudioSystem()
{}
void CUCode_InitAudioSystem::Init()
{}
void CUCode_InitAudioSystem::Update()
{
if (m_rMailHandler.IsEmpty())
{
m_rMailHandler.PushMail(0x80544348);
// HALT
}
}
void CUCode_InitAudioSystem::HandleMail(u32 _uMail)
{}

View File

@ -1,161 +1,161 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../Globals.h"
#include "UCodes.h"
#include "UCode_Jac.h"
#include "../MailHandler.h"
CUCode_Jac::CUCode_Jac(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
, m_bListInProgress(false)
{
DebugLog("CUCode_Jac: init");
m_rMailHandler.PushMail(0xDCD10000);
m_rMailHandler.PushMail(0x80000000);
}
CUCode_Jac::~CUCode_Jac()
{
m_rMailHandler.Clear();
}
void CUCode_Jac::HandleMail(u32 _uMail)
{
// this is prolly totally bullshit and should work like the zelda one...
// but i am to lazy to change it atm
if (m_bListInProgress == false)
{
// get the command to find out how much steps it has
switch (_uMail & 0xFFFF)
{
// release halt
case 0x00:
// m_Mails.push(0x80000000);
g_dspInitialize.pGenerateDSPInterrupt();
break;
case 0x40:
m_step = 0;
((u32*)m_Buffer)[m_step++] = _uMail;
m_bListInProgress = true;
m_numSteps = 5;
break;
case 0x2000:
case 0x4000:
m_step = 0;
((u32*)m_Buffer)[m_step++] = _uMail;
m_bListInProgress = true;
m_numSteps = 3;
break;
default:
PanicAlert("UCode Jac");
DebugLog("UCode Jac - unknown cmd: %x", _uMail & 0xFFFF);
break;
}
}
else
{
((u32*)m_Buffer)[m_step] = _uMail;
m_step++;
if (m_step == m_numSteps)
{
ExecuteList();
m_bListInProgress = false;
}
}
}
void CUCode_Jac::Update()
{
// check if we have to sent something
/* if (!g_MailHandler.empty())
{
g_dspInitialize.pGenerateDSPInterrupt();
}*/
}
void CUCode_Jac::ExecuteList()
{
// begin with the list
m_readOffset = 0;
u16 cmd = Read16();
u16 sync = Read16();
DebugLog("==============================================================================");
DebugLog("UCode Jac - execute dlist (cmd: 0x%04x : sync: 0x%04x)", cmd, sync);
switch (cmd)
{
// ==============================================================================
// DsetupTable
// ==============================================================================
case 0x40:
{
u32 tmp[4];
tmp[0] = Read32();
tmp[1] = Read32();
tmp[2] = Read32();
tmp[3] = Read32();
DebugLog("DsetupTable");
DebugLog("???: 0x%08x", tmp[0]);
DebugLog("DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]);
DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]);
DebugLog("???: 0x%08x", tmp[3]);
}
break;
// ==============================================================================
// UpdateDSPChannel
// ==============================================================================
case 0x2000:
case 0x4000: // animal crossing
{
u32 tmp[3];
tmp[0] = Read32();
tmp[1] = Read32();
tmp[2] = Read32();
DebugLog("UpdateDSPChannel");
DebugLog("audiomemory: 0x%08x", tmp[0]);
DebugLog("audiomemory: 0x%08x", tmp[1]);
DebugLog("DSPADPCM_FILTER (size: 0x40): 0x%08x", tmp[2]);
}
break;
default:
PanicAlert("UCode Jac unknown cmd: %s (size %i)", cmd, m_numSteps);
DebugLog("Jac UCode - unknown cmd: %x (size %i)", cmd, m_numSteps);
break;
}
// sync, we are rdy
m_rMailHandler.PushMail(DSP_SYNC);
m_rMailHandler.PushMail(0xF3550000 | sync);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../Globals.h"
#include "UCodes.h"
#include "UCode_Jac.h"
#include "../MailHandler.h"
CUCode_Jac::CUCode_Jac(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
, m_bListInProgress(false)
{
DebugLog("CUCode_Jac: init");
m_rMailHandler.PushMail(0xDCD10000);
m_rMailHandler.PushMail(0x80000000);
}
CUCode_Jac::~CUCode_Jac()
{
m_rMailHandler.Clear();
}
void CUCode_Jac::HandleMail(u32 _uMail)
{
// this is prolly totally bullshit and should work like the zelda one...
// but i am to lazy to change it atm
if (m_bListInProgress == false)
{
// get the command to find out how much steps it has
switch (_uMail & 0xFFFF)
{
// release halt
case 0x00:
// m_Mails.push(0x80000000);
g_dspInitialize.pGenerateDSPInterrupt();
break;
case 0x40:
m_step = 0;
((u32*)m_Buffer)[m_step++] = _uMail;
m_bListInProgress = true;
m_numSteps = 5;
break;
case 0x2000:
case 0x4000:
m_step = 0;
((u32*)m_Buffer)[m_step++] = _uMail;
m_bListInProgress = true;
m_numSteps = 3;
break;
default:
PanicAlert("UCode Jac");
DebugLog("UCode Jac - unknown cmd: %x", _uMail & 0xFFFF);
break;
}
}
else
{
((u32*)m_Buffer)[m_step] = _uMail;
m_step++;
if (m_step == m_numSteps)
{
ExecuteList();
m_bListInProgress = false;
}
}
}
void CUCode_Jac::Update()
{
// check if we have to sent something
/* if (!g_MailHandler.empty())
{
g_dspInitialize.pGenerateDSPInterrupt();
}*/
}
void CUCode_Jac::ExecuteList()
{
// begin with the list
m_readOffset = 0;
u16 cmd = Read16();
u16 sync = Read16();
DebugLog("==============================================================================");
DebugLog("UCode Jac - execute dlist (cmd: 0x%04x : sync: 0x%04x)", cmd, sync);
switch (cmd)
{
// ==============================================================================
// DsetupTable
// ==============================================================================
case 0x40:
{
u32 tmp[4];
tmp[0] = Read32();
tmp[1] = Read32();
tmp[2] = Read32();
tmp[3] = Read32();
DebugLog("DsetupTable");
DebugLog("???: 0x%08x", tmp[0]);
DebugLog("DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]);
DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]);
DebugLog("???: 0x%08x", tmp[3]);
}
break;
// ==============================================================================
// UpdateDSPChannel
// ==============================================================================
case 0x2000:
case 0x4000: // animal crossing
{
u32 tmp[3];
tmp[0] = Read32();
tmp[1] = Read32();
tmp[2] = Read32();
DebugLog("UpdateDSPChannel");
DebugLog("audiomemory: 0x%08x", tmp[0]);
DebugLog("audiomemory: 0x%08x", tmp[1]);
DebugLog("DSPADPCM_FILTER (size: 0x40): 0x%08x", tmp[2]);
}
break;
default:
PanicAlert("UCode Jac unknown cmd: %s (size %i)", cmd, m_numSteps);
DebugLog("Jac UCode - unknown cmd: %x (size %i)", cmd, m_numSteps);
break;
}
// sync, we are rdy
m_rMailHandler.PushMail(DSP_SYNC);
m_rMailHandler.PushMail(0xF3550000 | sync);
}

View File

@ -1,112 +1,112 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../Globals.h"
#include "../DSPHandler.h"
#include "UCodes.h"
#include "UCode_ROM.h"
CUCode_Rom::CUCode_Rom(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
, m_BootTask_numSteps(0)
, m_NextParameter(0)
{
DebugLog("UCode_Rom - initialized");
m_rMailHandler.Clear();
m_rMailHandler.PushMail(0x8071FEED);
}
CUCode_Rom::~CUCode_Rom()
{}
void CUCode_Rom::Update()
{}
void CUCode_Rom::HandleMail(u32 _uMail)
{
if (m_NextParameter == 0)
{
// wait for beginning of UCode
if ((_uMail & 0xFFFF0000) != 0x80F30000)
{
u32 Message = 0xFEEE0000 | (_uMail & 0xFFFF);
m_rMailHandler.PushMail(Message);
}
else
{
m_NextParameter = _uMail;
}
}
else
{
switch (m_NextParameter)
{
case 0x80F3A001:
m_CurrentUCode.m_RAMAddress = _uMail;
break;
case 0x80F3A002:
m_CurrentUCode.m_Length = _uMail;
break;
case 0x80F3C002:
m_CurrentUCode.m_IMEMAddress = _uMail;
break;
case 0x80F3B002:
m_CurrentUCode.m_Unk = _uMail;
break;
case 0x80F3D001:
{
m_CurrentUCode.m_StartPC = _uMail;
BootUCode();
return; // FIXES THE OVERWRITE
}
break;
}
// THE GODDAMN OVERWRITE WAS HERE. Without the return above, since BootUCode may delete "this", well ...
m_NextParameter = 0;
}
}
void CUCode_Rom::BootUCode()
{
// simple non-scientific crc invented by ector :P
// too annoying to change now, and probably good enough anyway
u32 crc = 0;
for (u32 i = 0; i < m_CurrentUCode.m_Length; i++)
{
crc ^= Memory_Read_U8(m_CurrentUCode.m_RAMAddress + i);
//let's rol
crc = (crc << 3) | (crc >> 29);
}
DebugLog("CurrentUCode SOURCE Addr: 0x%08x", m_CurrentUCode.m_RAMAddress);
DebugLog("CurrentUCode Length: 0x%08x", m_CurrentUCode.m_Length);
DebugLog("CurrentUCode DEST Addr: 0x%08x", m_CurrentUCode.m_IMEMAddress);
DebugLog("CurrentUCode ???: 0x%08x", m_CurrentUCode.m_Unk);
DebugLog("CurrentUCode init_vector: 0x%08x", m_CurrentUCode.m_StartPC);
DebugLog("CurrentUCode CRC: 0x%08x", crc);
DebugLog("BootTask - done");
CDSPHandler::GetInstance().SetUCode(crc);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../Globals.h"
#include "../DSPHandler.h"
#include "UCodes.h"
#include "UCode_ROM.h"
CUCode_Rom::CUCode_Rom(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
, m_BootTask_numSteps(0)
, m_NextParameter(0)
{
DebugLog("UCode_Rom - initialized");
m_rMailHandler.Clear();
m_rMailHandler.PushMail(0x8071FEED);
}
CUCode_Rom::~CUCode_Rom()
{}
void CUCode_Rom::Update()
{}
void CUCode_Rom::HandleMail(u32 _uMail)
{
if (m_NextParameter == 0)
{
// wait for beginning of UCode
if ((_uMail & 0xFFFF0000) != 0x80F30000)
{
u32 Message = 0xFEEE0000 | (_uMail & 0xFFFF);
m_rMailHandler.PushMail(Message);
}
else
{
m_NextParameter = _uMail;
}
}
else
{
switch (m_NextParameter)
{
case 0x80F3A001:
m_CurrentUCode.m_RAMAddress = _uMail;
break;
case 0x80F3A002:
m_CurrentUCode.m_Length = _uMail;
break;
case 0x80F3C002:
m_CurrentUCode.m_IMEMAddress = _uMail;
break;
case 0x80F3B002:
m_CurrentUCode.m_Unk = _uMail;
break;
case 0x80F3D001:
{
m_CurrentUCode.m_StartPC = _uMail;
BootUCode();
return; // FIXES THE OVERWRITE
}
break;
}
// THE GODDAMN OVERWRITE WAS HERE. Without the return above, since BootUCode may delete "this", well ...
m_NextParameter = 0;
}
}
void CUCode_Rom::BootUCode()
{
// simple non-scientific crc invented by ector :P
// too annoying to change now, and probably good enough anyway
u32 crc = 0;
for (u32 i = 0; i < m_CurrentUCode.m_Length; i++)
{
crc ^= Memory_Read_U8(m_CurrentUCode.m_RAMAddress + i);
//let's rol
crc = (crc << 3) | (crc >> 29);
}
DebugLog("CurrentUCode SOURCE Addr: 0x%08x", m_CurrentUCode.m_RAMAddress);
DebugLog("CurrentUCode Length: 0x%08x", m_CurrentUCode.m_Length);
DebugLog("CurrentUCode DEST Addr: 0x%08x", m_CurrentUCode.m_IMEMAddress);
DebugLog("CurrentUCode ???: 0x%08x", m_CurrentUCode.m_Unk);
DebugLog("CurrentUCode init_vector: 0x%08x", m_CurrentUCode.m_StartPC);
DebugLog("CurrentUCode CRC: 0x%08x", crc);
DebugLog("BootTask - done");
CDSPHandler::GetInstance().SetUCode(crc);
}

View File

@ -1,181 +1,181 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Games that uses this UCode:
// Zelda: The Windwaker, Mario Sunshine, Mario Kart, Twilight Princess
#include "../Globals.h"
#include "UCodes.h"
#include "UCode_Zelda.h"
#include "../MailHandler.h"
#ifdef _WIN32
#include "../PCHW/DSoundStream.h"
#endif
#include "../PCHW/Mixer.h"
CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
, m_numSteps(0)
, m_bListInProgress(false)
, m_step(0)
, m_readOffset(0)
{
DebugLog("UCode_Zelda - add boot mails for handshake");
m_rMailHandler.PushMail(DSP_INIT);
m_rMailHandler.PushMail(0x80000000); // handshake
memset(m_Buffer, 0, sizeof(m_Buffer));
}
CUCode_Zelda::~CUCode_Zelda()
{
m_rMailHandler.Clear();
}
void CUCode_Zelda::Update()
{
// check if we have to sent something
if (!m_rMailHandler.IsEmpty())
g_dspInitialize.pGenerateDSPInterrupt();
}
void CUCode_Zelda::HandleMail(u32 _uMail)
{
if (m_bListInProgress == false)
{
m_bListInProgress = true;
m_numSteps = _uMail;
m_step = 0;
}
else
{
if (m_step < 0 || m_step >= sizeof(m_Buffer)/4)
PanicAlert("m_step out of range");
((u32*)m_Buffer)[m_step] = _uMail;
m_step++;
if (m_step == m_numSteps)
{
ExecuteList();
m_bListInProgress = false;
}
}
}
void CUCode_Zelda::MixAdd(short* buffer, int size)
{
//TODO(XK): Zelda UCode MixAdd?
}
void CUCode_Zelda::ExecuteList()
{
// begin with the list
m_readOffset = 0;
u32 Temp = Read32();
u32 Command = (Temp >> 24) & 0x7f;
u32 Sync = Temp >> 16;
DebugLog("==============================================================================");
DebugLog("Zelda UCode - execute dlist (cmd: 0x%04x : sync: 0x%04x)", Command, Sync);
switch (Command)
{
// DsetupTable ... zelda ww jumps to 0x0095
case 0x01:
{
u32 tmp[4];
tmp[0] = Read32();
tmp[1] = Read32();
tmp[2] = Read32();
tmp[3] = Read32();
DebugLog("DsetupTable");
DebugLog("???: 0x%08x", tmp[0]);
DebugLog("DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]);
DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]);
DebugLog("???: 0x%08x", tmp[3]);
}
break;
// SyncFrame ... zelda ww jumps to 0x0243
case 0x02:
{
u32 tmp[3];
tmp[0] = Read32();
tmp[1] = Read32();
tmp[2] = Read32();
// We're ready to mix
mixer_HLEready = true;
#ifdef _WIN32
DebugLog("Update the SoundThread to be in sync");
DSound::DSound_UpdateSound(); //do it in this thread to avoid sync problems
#endif
DebugLog("DsyncFrame");
DebugLog("???: 0x%08x", tmp[0]);
DebugLog("???: 0x%08x", tmp[1]);
DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]);
}
break;
/*
case 0x03: break; // dunno ... zelda ww jmps to 0x0073
case 0x04: break; // dunno ... zelda ww jmps to 0x0580
case 0x05: break; // dunno ... zelda ww jmps to 0x0592
case 0x06: break; // dunno ... zelda ww jmps to 0x0469
case 0x07: break; // dunno ... zelda ww jmps to 0x044d
case 0x08: break; // Mixer ... zelda ww jmps to 0x0485
case 0x09: break; // dunno ... zelda ww jmps to 0x044d
*/
// DsetDolbyDelay ... zelda ww jumps to 0x00b2
case 0x0d:
{
u32 tmp[2];
tmp[0] = Read32();
tmp[1] = Read32();
DebugLog("DSetDolbyDelay");
DebugLog("DOLBY2_DELAY_BUF (size 0x960): 0x%08x", tmp[0]);
DebugLog("DSPRES_FILTER (size 0x500): 0x%08x", tmp[1]);
}
break;
// Set VARAM
case 0x0e:
// MessageBox(NULL, "Zelda VARAM", "cmd", MB_OK);
break;
// default ... zelda ww jumps to 0x0043
default:
PanicAlert("Zelda UCode - unknown cmd: %x (size %i)", Command, m_numSteps);
break;
}
// sync, we are rdy
m_rMailHandler.PushMail(DSP_SYNC);
m_rMailHandler.PushMail(0xF3550000 | Sync);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Games that uses this UCode:
// Zelda: The Windwaker, Mario Sunshine, Mario Kart, Twilight Princess
#include "../Globals.h"
#include "UCodes.h"
#include "UCode_Zelda.h"
#include "../MailHandler.h"
#ifdef _WIN32
#include "../PCHW/DSoundStream.h"
#endif
#include "../PCHW/Mixer.h"
CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
, m_numSteps(0)
, m_bListInProgress(false)
, m_step(0)
, m_readOffset(0)
{
DebugLog("UCode_Zelda - add boot mails for handshake");
m_rMailHandler.PushMail(DSP_INIT);
m_rMailHandler.PushMail(0x80000000); // handshake
memset(m_Buffer, 0, sizeof(m_Buffer));
}
CUCode_Zelda::~CUCode_Zelda()
{
m_rMailHandler.Clear();
}
void CUCode_Zelda::Update()
{
// check if we have to sent something
if (!m_rMailHandler.IsEmpty())
g_dspInitialize.pGenerateDSPInterrupt();
}
void CUCode_Zelda::HandleMail(u32 _uMail)
{
if (m_bListInProgress == false)
{
m_bListInProgress = true;
m_numSteps = _uMail;
m_step = 0;
}
else
{
if (m_step < 0 || m_step >= sizeof(m_Buffer)/4)
PanicAlert("m_step out of range");
((u32*)m_Buffer)[m_step] = _uMail;
m_step++;
if (m_step == m_numSteps)
{
ExecuteList();
m_bListInProgress = false;
}
}
}
void CUCode_Zelda::MixAdd(short* buffer, int size)
{
//TODO(XK): Zelda UCode MixAdd?
}
void CUCode_Zelda::ExecuteList()
{
// begin with the list
m_readOffset = 0;
u32 Temp = Read32();
u32 Command = (Temp >> 24) & 0x7f;
u32 Sync = Temp >> 16;
DebugLog("==============================================================================");
DebugLog("Zelda UCode - execute dlist (cmd: 0x%04x : sync: 0x%04x)", Command, Sync);
switch (Command)
{
// DsetupTable ... zelda ww jumps to 0x0095
case 0x01:
{
u32 tmp[4];
tmp[0] = Read32();
tmp[1] = Read32();
tmp[2] = Read32();
tmp[3] = Read32();
DebugLog("DsetupTable");
DebugLog("???: 0x%08x", tmp[0]);
DebugLog("DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]);
DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]);
DebugLog("???: 0x%08x", tmp[3]);
}
break;
// SyncFrame ... zelda ww jumps to 0x0243
case 0x02:
{
u32 tmp[3];
tmp[0] = Read32();
tmp[1] = Read32();
tmp[2] = Read32();
// We're ready to mix
mixer_HLEready = true;
#ifdef _WIN32
DebugLog("Update the SoundThread to be in sync");
DSound::DSound_UpdateSound(); //do it in this thread to avoid sync problems
#endif
DebugLog("DsyncFrame");
DebugLog("???: 0x%08x", tmp[0]);
DebugLog("???: 0x%08x", tmp[1]);
DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]);
}
break;
/*
case 0x03: break; // dunno ... zelda ww jmps to 0x0073
case 0x04: break; // dunno ... zelda ww jmps to 0x0580
case 0x05: break; // dunno ... zelda ww jmps to 0x0592
case 0x06: break; // dunno ... zelda ww jmps to 0x0469
case 0x07: break; // dunno ... zelda ww jmps to 0x044d
case 0x08: break; // Mixer ... zelda ww jmps to 0x0485
case 0x09: break; // dunno ... zelda ww jmps to 0x044d
*/
// DsetDolbyDelay ... zelda ww jumps to 0x00b2
case 0x0d:
{
u32 tmp[2];
tmp[0] = Read32();
tmp[1] = Read32();
DebugLog("DSetDolbyDelay");
DebugLog("DOLBY2_DELAY_BUF (size 0x960): 0x%08x", tmp[0]);
DebugLog("DSPRES_FILTER (size 0x500): 0x%08x", tmp[1]);
}
break;
// Set VARAM
case 0x0e:
// MessageBox(NULL, "Zelda VARAM", "cmd", MB_OK);
break;
// default ... zelda ww jumps to 0x0043
default:
PanicAlert("Zelda UCode - unknown cmd: %x (size %i)", Command, m_numSteps);
break;
}
// sync, we are rdy
m_rMailHandler.PushMail(DSP_SYNC);
m_rMailHandler.PushMail(0xF3550000 | Sync);
}

View File

@ -1,90 +1,90 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../Globals.h"
#include "UCodes.h"
#include "UCode_AX.h"
#include "UCode_AXWii.h"
#include "UCode_Zelda.h"
#include "UCode_Jac.h"
#include "UCode_ROM.h"
#include "UCode_CARD.h"
#include "UCode_InitAudioSystem.h"
IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler)
{
switch (_CRC)
{
case UCODE_ROM:
return new CUCode_Rom(_rMailHandler);
case UCODE_INIT_AUDIO_SYSTEM:
return new CUCode_InitAudioSystem(_rMailHandler);
case 0x65d6cc6f: // CARD
return new CUCode_CARD(_rMailHandler);
case 0x088e38a5: // IPL - JAP
case 0xd73338cf: // IPL
case 0x42f64ac4: // Luigi (after fix)
case 0x4be6a5cb: // AC, Pikmin (after fix)
printf("JAC ucode chosen");
return new CUCode_Jac(_rMailHandler);
case 0x3ad3b7ac: // Naruto3
case 0x3daf59b9: // Alien Hominid
case 0x4e8a8b21: // spdemo, ctaxi, 18 wheeler, disney, monkeyball2,cubivore,puzzlecollection,wario,
// capcom vs snk, naruto2, lost kingdoms, star fox, mario party 4, mortal kombat,
// smugglers run warzone, smash brothers, sonic mega collection, ZooCube
// nddemo, starfox
case 0x07f88145: // bustamove, ikaruga, fzero, robotech battle cry, star soldier, soul calibur2,
// Zelda:OOT, Tony hawk, viewtiful joe
case 0xe2136399: // billy hatcher, dragonballz, mario party 5, TMNT, ava1080
printf("AX ucode chosen, yay!");
return new CUCode_AX(_rMailHandler);
case 0x6CA33A6D: // DK Jungle Beat
case 0x86840740: // zelda
case 0x56d36052: // mario
case 0x2fcdf1ec: // mariokart, zelda 4 swords
printf("Zelda ucode chosen");
return new CUCode_Zelda(_rMailHandler);
// WII CRCs
case 0x6c3f6f94: // zelda - PAL
case 0xd643001f: // mario galaxy - PAL
printf("Zelda Wii ucode chosen");
return new CUCode_Zelda(_rMailHandler);
case 0x5ef56da3: // AX demo
case 0x347112ba: // raving rabbits
case 0xfa450138: // wii sports - PAL
case 0xadbc06bd: // Elebits
printf("Wii - AXWii chosen");
return new CUCode_AXWii(_rMailHandler, _CRC);
default:
PanicAlert("Unknown ucode (CRC = %08x) - forcing AX", _CRC);
return new CUCode_AX(_rMailHandler);
}
return NULL;
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../Globals.h"
#include "UCodes.h"
#include "UCode_AX.h"
#include "UCode_AXWii.h"
#include "UCode_Zelda.h"
#include "UCode_Jac.h"
#include "UCode_ROM.h"
#include "UCode_CARD.h"
#include "UCode_InitAudioSystem.h"
IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler)
{
switch (_CRC)
{
case UCODE_ROM:
return new CUCode_Rom(_rMailHandler);
case UCODE_INIT_AUDIO_SYSTEM:
return new CUCode_InitAudioSystem(_rMailHandler);
case 0x65d6cc6f: // CARD
return new CUCode_CARD(_rMailHandler);
case 0x088e38a5: // IPL - JAP
case 0xd73338cf: // IPL
case 0x42f64ac4: // Luigi (after fix)
case 0x4be6a5cb: // AC, Pikmin (after fix)
printf("JAC ucode chosen");
return new CUCode_Jac(_rMailHandler);
case 0x3ad3b7ac: // Naruto3
case 0x3daf59b9: // Alien Hominid
case 0x4e8a8b21: // spdemo, ctaxi, 18 wheeler, disney, monkeyball2,cubivore,puzzlecollection,wario,
// capcom vs snk, naruto2, lost kingdoms, star fox, mario party 4, mortal kombat,
// smugglers run warzone, smash brothers, sonic mega collection, ZooCube
// nddemo, starfox
case 0x07f88145: // bustamove, ikaruga, fzero, robotech battle cry, star soldier, soul calibur2,
// Zelda:OOT, Tony hawk, viewtiful joe
case 0xe2136399: // billy hatcher, dragonballz, mario party 5, TMNT, ava1080
printf("AX ucode chosen, yay!");
return new CUCode_AX(_rMailHandler);
case 0x6CA33A6D: // DK Jungle Beat
case 0x86840740: // zelda
case 0x56d36052: // mario
case 0x2fcdf1ec: // mariokart, zelda 4 swords
printf("Zelda ucode chosen");
return new CUCode_Zelda(_rMailHandler);
// WII CRCs
case 0x6c3f6f94: // zelda - PAL
case 0xd643001f: // mario galaxy - PAL
printf("Zelda Wii ucode chosen");
return new CUCode_Zelda(_rMailHandler);
case 0x5ef56da3: // AX demo
case 0x347112ba: // raving rabbits
case 0xfa450138: // wii sports - PAL
case 0xadbc06bd: // Elebits
printf("Wii - AXWii chosen");
return new CUCode_AXWii(_rMailHandler, _CRC);
default:
PanicAlert("Unknown ucode (CRC = %08x) - forcing AX", _CRC);
return new CUCode_AX(_rMailHandler);
}
return NULL;
}

View File

@ -1,357 +1,357 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Debugger/Debugger.h" // for the CDebugger class
#include "ChunkFile.h"
#include "WaveFile.h"
#include "resource.h"
#ifdef _WIN32
#include "PCHW/DSoundStream.h"
#include "ConfigDlg.h"
#else
#include "PCHW/AOSoundStream.h"
#endif
#include "PCHW/Mixer.h"
#include "DSPHandler.h"
#include "Config.h"
#include "Logging/Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
DSPInitialize g_dspInitialize;
u8* g_pMemory;
extern std::vector<std::string> sMailLog, sMailTime;
std::string gpName;
// Set this if you want to log audio. search for log_ai in this file to see the filename.
static bool log_ai = false;
static WaveFileWriter g_wave_writer;
struct DSPState
{
u32 CPUMailbox;
bool CPUMailbox_Written[2];
u32 DSPMailbox;
bool DSPMailbox_Read[2];
DSPState()
{
CPUMailbox = 0x00000000;
CPUMailbox_Written[0] = false;
CPUMailbox_Written[1] = false;
DSPMailbox = 0x00000000;
DSPMailbox_Read[0] = true;
DSPMailbox_Read[1] = true;
}
};
DSPState g_dspState;
// ====================
//////////////////////////////////////////////////////////////////////////////////////////
// wxWidgets - Some kind of stuff wx needs
// ¯¯¯¯¯¯¯¯¯
class wxDLLApp : public wxApp
{
bool OnInit()
{
return true;
}
};
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
///////////////////
#ifdef _WIN32
HINSTANCE g_hInstance = NULL;
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
DWORD dwReason, // reason called
LPVOID lpvReserved) // reserved
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
// more stuff wx needs
wxSetInstance((HINSTANCE)hinstDLL);
int argc = 0;
char **argv = NULL;
wxEntryStart(argc, argv);
// This is for ?
if ( !wxTheApp || !wxTheApp->CallOnInit() )
return FALSE;
}
break;
case DLL_PROCESS_DETACH:
wxEntryCleanup(); // use this or get a crash
break;
default:
break;
}
g_hInstance = hinstDLL;
return(TRUE);
}
#endif
// =======================================================================================
// Open and close console
// -------------------
void OpenConsole()
{
#if defined (_WIN32)
startConsoleWin(155, 100, "Sound Debugging"); // give room for 100 rows
wprintf("OpenConsole > Console opened\n");
MoveWindow(GetConsoleHwnd(), 0,400, 1280,550, true); // move window, TODO: make this
// adjustable from the debugging window
#endif
}
void CloseConsole()
{
#if defined (_WIN32)
FreeConsole();
#endif
}
// ===================
// =======================================================================================
// Create debugging window - We could use use wxWindow win; new CDebugger(win) like nJoy but I don't
// know why it would be better. - There's a lockup problem with ShowModal(), but Show() doesn't work
// because then DLL_PROCESS_DETACH is called immediately after DLL_PROCESS_ATTACH.
// -------------------
CDebugger* m_frame;
void DllDebugger(HWND _hParent, bool Show)
{
if(m_frame && Show) // if we have created it, let us show it again
{
m_frame->DoShow();
}
else if(!m_frame && Show)
{
m_frame = new CDebugger(NULL);
m_frame->Show();
}
else if(m_frame && !Show)
{
m_frame->DoHide();
}
}
// ===================
void GetDllInfo(PLUGIN_INFO* _PluginInfo)
{
_PluginInfo->Version = 0x0100;
_PluginInfo->Type = PLUGIN_TYPE_DSP;
#ifdef DEBUGFAST
sprintf(_PluginInfo->Name, "Dolphin DSP-HLE Plugin (DebugFast) ");
#else
#ifndef _DEBUG
sprintf(_PluginInfo->Name, "Dolphin DSP-HLE Plugin ");
#else
sprintf(_PluginInfo ->Name, "Dolphin DSP-HLE Plugin (Debug) ");
#endif
#endif
}
void DllConfig(HWND _hParent)
{
#ifdef _WIN32
CConfigDlg configDlg;
configDlg.DoModal(_hParent);
#endif
}
void DSP_Initialize(DSPInitialize _dspInitialize)
{
g_Config.LoadDefaults();
g_Config.Load();
g_dspInitialize = _dspInitialize;
g_pMemory = g_dspInitialize.pGetMemoryPointer(0);
#if defined(_DEBUG) || defined(DEBUGFAST)
gpName = g_dspInitialize.pName(); // save the game name globally
for (int i = 0; i < gpName.length(); ++i) // and fix it
{
wprintf("%c", gpName[i]);
std::cout << gpName[i];
if (gpName[i] == ':') gpName[i] = ' ';
}
wprintf("\n");
#endif
CDSPHandler::CreateInstance();
#ifdef _WIN32
#ifdef _DEBUG
int tmpflag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
tmpflag |= _CRTDBG_DELAY_FREE_MEM_DF;
_CrtSetDbgFlag(tmpflag);
#endif
if (log_ai) {
g_wave_writer.Start("D:\\ai_log.wav");
g_wave_writer.SetSkipSilence(false);
}
DSound::DSound_StartSound((HWND)g_dspInitialize.hWnd, 48000, Mixer);
#else
AOSound::AOSound_StartSound(48000, Mixer);
#endif
}
void DSP_Shutdown()
{
if (log_ai)
g_wave_writer.Stop();
// delete the UCodes
#ifdef _WIN32
DSound::DSound_StopSound();
#else
AOSound::AOSound_StopSound();
#endif
CDSPHandler::Destroy();
// Reset mails
if(m_frame)
{
sMailLog.clear();
sMailTime.clear();
m_frame->sMail.clear();
m_frame->sMailEnd.clear();
}
}
void DSP_DoState(unsigned char **ptr, int mode) {
PointerWrap p(ptr, mode);
}
unsigned short DSP_ReadMailboxHigh(bool _CPUMailbox)
{
if (_CPUMailbox)
{
return (g_dspState.CPUMailbox >> 16) & 0xFFFF;
}
else
{
return CDSPHandler::GetInstance().AccessMailHandler().ReadDSPMailboxHigh();
}
}
unsigned short DSP_ReadMailboxLow(bool _CPUMailbox)
{
if (_CPUMailbox)
{
return g_dspState.CPUMailbox & 0xFFFF;
}
else
{
return CDSPHandler::GetInstance().AccessMailHandler().ReadDSPMailboxLow();
}
}
void Update_DSP_WriteRegister()
{
// check if the whole message is complete and if we can send it
if (g_dspState.CPUMailbox_Written[0] && g_dspState.CPUMailbox_Written[1])
{
CDSPHandler::GetInstance().SendMailToDSP(g_dspState.CPUMailbox);
g_dspState.CPUMailbox_Written[0] = g_dspState.CPUMailbox_Written[1] = false;
g_dspState.CPUMailbox = 0; // Mail sent so clear it to show that it is progressed
}
}
void DSP_WriteMailboxHigh(bool _CPUMailbox, unsigned short _Value)
{
if (_CPUMailbox)
{
g_dspState.CPUMailbox = (g_dspState.CPUMailbox & 0xFFFF) | (_Value << 16);
g_dspState.CPUMailbox_Written[0] = true;
Update_DSP_WriteRegister();
}
else
{
PanicAlert("CPU can't write %08x to DSP mailbox", _Value);
}
}
void DSP_WriteMailboxLow(bool _CPUMailbox, unsigned short _Value)
{
if (_CPUMailbox)
{
g_dspState.CPUMailbox = (g_dspState.CPUMailbox & 0xFFFF0000) | _Value;
g_dspState.CPUMailbox_Written[1] = true;
Update_DSP_WriteRegister();
}
else
{
PanicAlert("CPU can't write %08x to DSP mailbox", _Value);
}
}
unsigned short DSP_WriteControlRegister(unsigned short _Value)
{
return CDSPHandler::GetInstance().WriteControlRegister(_Value);
}
unsigned short DSP_ReadControlRegister()
{
return CDSPHandler::GetInstance().ReadControlRegister();
}
void DSP_Update(int cycles)
{
CDSPHandler::GetInstance().Update();
}
void DSP_SendAIBuffer(unsigned int address, int sample_rate)
{
short samples[16] = {0}; // interleaved stereo
if (address) {
for (int i = 0; i < 16; i++) {
samples[i] = Memory_Read_U16(address + i * 2);
}
if (log_ai)
g_wave_writer.AddStereoSamples(samples, 8);
}
Mixer_PushSamples(samples, 32 / 4, sample_rate);
static int counter = 0;
counter++;
#ifdef _WIN32
if ((counter & 255) == 0)
DSound::DSound_UpdateSound();
#endif
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Debugger/Debugger.h" // for the CDebugger class
#include "ChunkFile.h"
#include "WaveFile.h"
#include "resource.h"
#ifdef _WIN32
#include "PCHW/DSoundStream.h"
#include "ConfigDlg.h"
#else
#include "PCHW/AOSoundStream.h"
#endif
#include "PCHW/Mixer.h"
#include "DSPHandler.h"
#include "Config.h"
#include "Logging/Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
DSPInitialize g_dspInitialize;
u8* g_pMemory;
extern std::vector<std::string> sMailLog, sMailTime;
std::string gpName;
// Set this if you want to log audio. search for log_ai in this file to see the filename.
static bool log_ai = false;
static WaveFileWriter g_wave_writer;
struct DSPState
{
u32 CPUMailbox;
bool CPUMailbox_Written[2];
u32 DSPMailbox;
bool DSPMailbox_Read[2];
DSPState()
{
CPUMailbox = 0x00000000;
CPUMailbox_Written[0] = false;
CPUMailbox_Written[1] = false;
DSPMailbox = 0x00000000;
DSPMailbox_Read[0] = true;
DSPMailbox_Read[1] = true;
}
};
DSPState g_dspState;
// ====================
//////////////////////////////////////////////////////////////////////////////////////////
// wxWidgets - Some kind of stuff wx needs
// ¯¯¯¯¯¯¯¯¯
class wxDLLApp : public wxApp
{
bool OnInit()
{
return true;
}
};
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
///////////////////
#ifdef _WIN32
HINSTANCE g_hInstance = NULL;
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
DWORD dwReason, // reason called
LPVOID lpvReserved) // reserved
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
// more stuff wx needs
wxSetInstance((HINSTANCE)hinstDLL);
int argc = 0;
char **argv = NULL;
wxEntryStart(argc, argv);
// This is for ?
if ( !wxTheApp || !wxTheApp->CallOnInit() )
return FALSE;
}
break;
case DLL_PROCESS_DETACH:
wxEntryCleanup(); // use this or get a crash
break;
default:
break;
}
g_hInstance = hinstDLL;
return(TRUE);
}
#endif
// =======================================================================================
// Open and close console
// -------------------
void OpenConsole()
{
#if defined (_WIN32)
startConsoleWin(155, 100, "Sound Debugging"); // give room for 100 rows
wprintf("OpenConsole > Console opened\n");
MoveWindow(GetConsoleHwnd(), 0,400, 1280,550, true); // move window, TODO: make this
// adjustable from the debugging window
#endif
}
void CloseConsole()
{
#if defined (_WIN32)
FreeConsole();
#endif
}
// ===================
// =======================================================================================
// Create debugging window - We could use use wxWindow win; new CDebugger(win) like nJoy but I don't
// know why it would be better. - There's a lockup problem with ShowModal(), but Show() doesn't work
// because then DLL_PROCESS_DETACH is called immediately after DLL_PROCESS_ATTACH.
// -------------------
CDebugger* m_frame;
void DllDebugger(HWND _hParent, bool Show)
{
if(m_frame && Show) // if we have created it, let us show it again
{
m_frame->DoShow();
}
else if(!m_frame && Show)
{
m_frame = new CDebugger(NULL);
m_frame->Show();
}
else if(m_frame && !Show)
{
m_frame->DoHide();
}
}
// ===================
void GetDllInfo(PLUGIN_INFO* _PluginInfo)
{
_PluginInfo->Version = 0x0100;
_PluginInfo->Type = PLUGIN_TYPE_DSP;
#ifdef DEBUGFAST
sprintf(_PluginInfo->Name, "Dolphin DSP-HLE Plugin (DebugFast) ");
#else
#ifndef _DEBUG
sprintf(_PluginInfo->Name, "Dolphin DSP-HLE Plugin ");
#else
sprintf(_PluginInfo ->Name, "Dolphin DSP-HLE Plugin (Debug) ");
#endif
#endif
}
void DllConfig(HWND _hParent)
{
#ifdef _WIN32
CConfigDlg configDlg;
configDlg.DoModal(_hParent);
#endif
}
void DSP_Initialize(DSPInitialize _dspInitialize)
{
g_Config.LoadDefaults();
g_Config.Load();
g_dspInitialize = _dspInitialize;
g_pMemory = g_dspInitialize.pGetMemoryPointer(0);
#if defined(_DEBUG) || defined(DEBUGFAST)
gpName = g_dspInitialize.pName(); // save the game name globally
for (int i = 0; i < gpName.length(); ++i) // and fix it
{
wprintf("%c", gpName[i]);
std::cout << gpName[i];
if (gpName[i] == ':') gpName[i] = ' ';
}
wprintf("\n");
#endif
CDSPHandler::CreateInstance();
#ifdef _WIN32
#ifdef _DEBUG
int tmpflag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
tmpflag |= _CRTDBG_DELAY_FREE_MEM_DF;
_CrtSetDbgFlag(tmpflag);
#endif
if (log_ai) {
g_wave_writer.Start("D:\\ai_log.wav");
g_wave_writer.SetSkipSilence(false);
}
DSound::DSound_StartSound((HWND)g_dspInitialize.hWnd, 48000, Mixer);
#else
AOSound::AOSound_StartSound(48000, Mixer);
#endif
}
void DSP_Shutdown()
{
if (log_ai)
g_wave_writer.Stop();
// delete the UCodes
#ifdef _WIN32
DSound::DSound_StopSound();
#else
AOSound::AOSound_StopSound();
#endif
CDSPHandler::Destroy();
// Reset mails
if(m_frame)
{
sMailLog.clear();
sMailTime.clear();
m_frame->sMail.clear();
m_frame->sMailEnd.clear();
}
}
void DSP_DoState(unsigned char **ptr, int mode) {
PointerWrap p(ptr, mode);
}
unsigned short DSP_ReadMailboxHigh(bool _CPUMailbox)
{
if (_CPUMailbox)
{
return (g_dspState.CPUMailbox >> 16) & 0xFFFF;
}
else
{
return CDSPHandler::GetInstance().AccessMailHandler().ReadDSPMailboxHigh();
}
}
unsigned short DSP_ReadMailboxLow(bool _CPUMailbox)
{
if (_CPUMailbox)
{
return g_dspState.CPUMailbox & 0xFFFF;
}
else
{
return CDSPHandler::GetInstance().AccessMailHandler().ReadDSPMailboxLow();
}
}
void Update_DSP_WriteRegister()
{
// check if the whole message is complete and if we can send it
if (g_dspState.CPUMailbox_Written[0] && g_dspState.CPUMailbox_Written[1])
{
CDSPHandler::GetInstance().SendMailToDSP(g_dspState.CPUMailbox);
g_dspState.CPUMailbox_Written[0] = g_dspState.CPUMailbox_Written[1] = false;
g_dspState.CPUMailbox = 0; // Mail sent so clear it to show that it is progressed
}
}
void DSP_WriteMailboxHigh(bool _CPUMailbox, unsigned short _Value)
{
if (_CPUMailbox)
{
g_dspState.CPUMailbox = (g_dspState.CPUMailbox & 0xFFFF) | (_Value << 16);
g_dspState.CPUMailbox_Written[0] = true;
Update_DSP_WriteRegister();
}
else
{
PanicAlert("CPU can't write %08x to DSP mailbox", _Value);
}
}
void DSP_WriteMailboxLow(bool _CPUMailbox, unsigned short _Value)
{
if (_CPUMailbox)
{
g_dspState.CPUMailbox = (g_dspState.CPUMailbox & 0xFFFF0000) | _Value;
g_dspState.CPUMailbox_Written[1] = true;
Update_DSP_WriteRegister();
}
else
{
PanicAlert("CPU can't write %08x to DSP mailbox", _Value);
}
}
unsigned short DSP_WriteControlRegister(unsigned short _Value)
{
return CDSPHandler::GetInstance().WriteControlRegister(_Value);
}
unsigned short DSP_ReadControlRegister()
{
return CDSPHandler::GetInstance().ReadControlRegister();
}
void DSP_Update(int cycles)
{
CDSPHandler::GetInstance().Update();
}
void DSP_SendAIBuffer(unsigned int address, int sample_rate)
{
short samples[16] = {0}; // interleaved stereo
if (address) {
for (int i = 0; i < 16; i++) {
samples[i] = Memory_Read_U16(address + i * 2);
}
if (log_ai)
g_wave_writer.AddStereoSamples(samples, 8);
}
Mixer_PushSamples(samples, 32 / 4, sample_rate);
static int counter = 0;
counter++;
#ifdef _WIN32
if ((counter & 255) == 0)
DSound::DSound_UpdateSound();
#endif
}

View File

@ -1,19 +1,19 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"

View File

@ -1,280 +1,280 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
#include <mmsystem.h>
#include <dsound.h>
#include "DSoundStream.h"
namespace DSound
{
#define BUFSIZE 32768
#define MAXWAIT 70 //ms
//THE ROCK SOLID SYNCED DSOUND ENGINE :)
//våran kritiska sektion och vår syncevent-handle
CRITICAL_SECTION soundCriticalSection;
HANDLE soundSyncEvent;
HANDLE hThread;
StreamCallback callback;
//lite mojs
IDirectSound8* ds;
IDirectSoundBuffer* dsBuffer;
//tja.. behövs
int bufferSize; //i bytes
int totalRenderedBytes;
int sampleRate;
//med den här synkar vi stängning..
//0=vi spelar oväsen, 1=stäng tråden NU! 2=japp,tråden är stängd så fortsätt
volatile int threadData;
//ser till så X kan delas med 32
inline int FIX32(int x)
{
return(x & (~127));
}
int DSound_GetSampleRate()
{
return(sampleRate);
}
//Dags att skapa vår directsound buffert
bool createBuffer()
{
PCMWAVEFORMAT pcmwf;
DSBUFFERDESC dsbdesc;
//ljudformatet
memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
pcmwf.wf.nChannels = 2;
pcmwf.wf.nSamplesPerSec = sampleRate;
pcmwf.wf.nBlockAlign = 4;
pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
pcmwf.wBitsPerSample = 16;
//buffer description
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS; //VIKTIGT //DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
dsbdesc.dwBufferBytes = bufferSize = BUFSIZE; //FIX32(pcmwf.wf.nAvgBytesPerSec); //ändra för att ställa in bufferstorlek
dsbdesc.lpwfxFormat = (WAVEFORMATEX*)&pcmwf;
// nu skapar vi bufferjäveln
if (SUCCEEDED(ds->CreateSoundBuffer(&dsbdesc, &dsBuffer, NULL)))
{
dsBuffer->SetCurrentPosition(0);
return(true);
}
else
{
// Failed.
dsBuffer = NULL;
return(false);
}
}
bool writeDataToBuffer(DWORD dwOffset, // Our own write cursor.
char* soundData, // Start of our data.
DWORD dwSoundBytes) // Size of block to copy.
{
void* ptr1, * ptr2;
DWORD numBytes1, numBytes2;
// Obtain memory address of write block. This will be in two parts if the block wraps around.
HRESULT hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0);
// If the buffer was lost, restore and retry lock.
if (DSERR_BUFFERLOST == hr)
{
dsBuffer->Restore();
hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0);
}
if (SUCCEEDED(hr))
{
memcpy(ptr1, soundData, numBytes1);
if (ptr2 != 0)
{
memcpy(ptr2, soundData + numBytes1, numBytes2);
}
// Release the data back to DirectSound.
dsBuffer->Unlock(ptr1, numBytes1, ptr2, numBytes2);
return(true);
} /*
else
{
char temp[8];
sprintf(temp,"%i\n",hr);
OutputDebugString(temp);
}*/
return(false);
}
inline int ModBufferSize(int x)
{
return((x + bufferSize) % bufferSize);
}
int currentPos;
int lastPos;
short realtimeBuffer[1024 * 1024];
DWORD WINAPI soundThread(void*)
{
currentPos = 0;
lastPos = 0;
//writeDataToBuffer(0,realtimeBuffer,bufferSize);
// dsBuffer->Lock(0, bufferSize, (void **)&p1, &num1, (void **)&p2, &num2, 0);
dsBuffer->Play(0, 0, DSBPLAY_LOOPING);
while (!threadData)
{
EnterCriticalSection(&soundCriticalSection);
dsBuffer->GetCurrentPosition((DWORD*)&currentPos, 0);
int numBytesToRender = FIX32(ModBufferSize(currentPos - lastPos));
//renderStuff(numBytesToRender/2);
//if (numBytesToRender>bufferSize/2) numBytesToRender=0;
if (numBytesToRender >= 256)
{
(*callback)(realtimeBuffer, numBytesToRender >> 2, 16, 44100, 2);
writeDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender);
currentPos = ModBufferSize(lastPos + numBytesToRender);
totalRenderedBytes += numBytesToRender;
lastPos = currentPos;
}
LeaveCriticalSection(&soundCriticalSection);
WaitForSingleObject(soundSyncEvent, MAXWAIT);
}
dsBuffer->Stop();
threadData = 2;
return(0); //hurra!
}
bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback)
{
callback = _callback;
threadData = 0;
sampleRate = _sampleRate;
//no security attributes, automatic resetting, init state nonset, untitled
soundSyncEvent = CreateEvent(0, false, false, 0);
//vi initierar den...........
InitializeCriticalSection(&soundCriticalSection);
//vi vill ha access till DSOUND så...
if (FAILED(DirectSoundCreate8(0, &ds, 0)))
{
return(false);
}
//samarbetsvillig? nää :)
ds->SetCooperativeLevel(window, DSSCL_NORMAL); //DSSCL_PRIORITY?
//så.. skapa buffern
if (!createBuffer())
{
return(false);
}
//rensa den.. ?
DWORD num1;
short* p1;
dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0);
memset(p1, 0, num1);
dsBuffer->Unlock(p1, num1, 0, 0);
totalRenderedBytes = -bufferSize;
DWORD h;
hThread = CreateThread(0, 0, soundThread, 0, 0, &h);
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
return(true);
}
void DSound_UpdateSound()
{
SetEvent(soundSyncEvent);
}
void DSound_StopSound()
{
EnterCriticalSection(&soundCriticalSection);
threadData = 1;
//kick the thread if it's waiting
SetEvent(soundSyncEvent);
LeaveCriticalSection(&soundCriticalSection);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
dsBuffer->Release();
ds->Release();
CloseHandle(soundSyncEvent);
}
int DSound_GetCurSample()
{
EnterCriticalSection(&soundCriticalSection);
int playCursor;
dsBuffer->GetCurrentPosition((DWORD*)&playCursor, 0);
playCursor = ModBufferSize(playCursor - lastPos) + totalRenderedBytes;
LeaveCriticalSection(&soundCriticalSection);
return(playCursor);
}
float DSound_GetTimer()
{
return((float)DSound_GetCurSample() * (1.0f / (4.0f * 44100.0f)));
}
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
#include <mmsystem.h>
#include <dsound.h>
#include "DSoundStream.h"
namespace DSound
{
#define BUFSIZE 32768
#define MAXWAIT 70 //ms
//THE ROCK SOLID SYNCED DSOUND ENGINE :)
//våran kritiska sektion och vår syncevent-handle
CRITICAL_SECTION soundCriticalSection;
HANDLE soundSyncEvent;
HANDLE hThread;
StreamCallback callback;
//lite mojs
IDirectSound8* ds;
IDirectSoundBuffer* dsBuffer;
//tja.. behövs
int bufferSize; //i bytes
int totalRenderedBytes;
int sampleRate;
//med den här synkar vi stängning..
//0=vi spelar oväsen, 1=stäng tråden NU! 2=japp,tråden är stängd så fortsätt
volatile int threadData;
//ser till så X kan delas med 32
inline int FIX32(int x)
{
return(x & (~127));
}
int DSound_GetSampleRate()
{
return(sampleRate);
}
//Dags att skapa vår directsound buffert
bool createBuffer()
{
PCMWAVEFORMAT pcmwf;
DSBUFFERDESC dsbdesc;
//ljudformatet
memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
pcmwf.wf.nChannels = 2;
pcmwf.wf.nSamplesPerSec = sampleRate;
pcmwf.wf.nBlockAlign = 4;
pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
pcmwf.wBitsPerSample = 16;
//buffer description
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS; //VIKTIGT //DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
dsbdesc.dwBufferBytes = bufferSize = BUFSIZE; //FIX32(pcmwf.wf.nAvgBytesPerSec); //ändra för att ställa in bufferstorlek
dsbdesc.lpwfxFormat = (WAVEFORMATEX*)&pcmwf;
// nu skapar vi bufferjäveln
if (SUCCEEDED(ds->CreateSoundBuffer(&dsbdesc, &dsBuffer, NULL)))
{
dsBuffer->SetCurrentPosition(0);
return(true);
}
else
{
// Failed.
dsBuffer = NULL;
return(false);
}
}
bool writeDataToBuffer(DWORD dwOffset, // Our own write cursor.
char* soundData, // Start of our data.
DWORD dwSoundBytes) // Size of block to copy.
{
void* ptr1, * ptr2;
DWORD numBytes1, numBytes2;
// Obtain memory address of write block. This will be in two parts if the block wraps around.
HRESULT hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0);
// If the buffer was lost, restore and retry lock.
if (DSERR_BUFFERLOST == hr)
{
dsBuffer->Restore();
hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0);
}
if (SUCCEEDED(hr))
{
memcpy(ptr1, soundData, numBytes1);
if (ptr2 != 0)
{
memcpy(ptr2, soundData + numBytes1, numBytes2);
}
// Release the data back to DirectSound.
dsBuffer->Unlock(ptr1, numBytes1, ptr2, numBytes2);
return(true);
} /*
else
{
char temp[8];
sprintf(temp,"%i\n",hr);
OutputDebugString(temp);
}*/
return(false);
}
inline int ModBufferSize(int x)
{
return((x + bufferSize) % bufferSize);
}
int currentPos;
int lastPos;
short realtimeBuffer[1024 * 1024];
DWORD WINAPI soundThread(void*)
{
currentPos = 0;
lastPos = 0;
//writeDataToBuffer(0,realtimeBuffer,bufferSize);
// dsBuffer->Lock(0, bufferSize, (void **)&p1, &num1, (void **)&p2, &num2, 0);
dsBuffer->Play(0, 0, DSBPLAY_LOOPING);
while (!threadData)
{
EnterCriticalSection(&soundCriticalSection);
dsBuffer->GetCurrentPosition((DWORD*)&currentPos, 0);
int numBytesToRender = FIX32(ModBufferSize(currentPos - lastPos));
//renderStuff(numBytesToRender/2);
//if (numBytesToRender>bufferSize/2) numBytesToRender=0;
if (numBytesToRender >= 256)
{
(*callback)(realtimeBuffer, numBytesToRender >> 2, 16, 44100, 2);
writeDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender);
currentPos = ModBufferSize(lastPos + numBytesToRender);
totalRenderedBytes += numBytesToRender;
lastPos = currentPos;
}
LeaveCriticalSection(&soundCriticalSection);
WaitForSingleObject(soundSyncEvent, MAXWAIT);
}
dsBuffer->Stop();
threadData = 2;
return(0); //hurra!
}
bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback)
{
callback = _callback;
threadData = 0;
sampleRate = _sampleRate;
//no security attributes, automatic resetting, init state nonset, untitled
soundSyncEvent = CreateEvent(0, false, false, 0);
//vi initierar den...........
InitializeCriticalSection(&soundCriticalSection);
//vi vill ha access till DSOUND så...
if (FAILED(DirectSoundCreate8(0, &ds, 0)))
{
return(false);
}
//samarbetsvillig? nää :)
ds->SetCooperativeLevel(window, DSSCL_NORMAL); //DSSCL_PRIORITY?
//så.. skapa buffern
if (!createBuffer())
{
return(false);
}
//rensa den.. ?
DWORD num1;
short* p1;
dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0);
memset(p1, 0, num1);
dsBuffer->Unlock(p1, num1, 0, 0);
totalRenderedBytes = -bufferSize;
DWORD h;
hThread = CreateThread(0, 0, soundThread, 0, 0, &h);
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
return(true);
}
void DSound_UpdateSound()
{
SetEvent(soundSyncEvent);
}
void DSound_StopSound()
{
EnterCriticalSection(&soundCriticalSection);
threadData = 1;
//kick the thread if it's waiting
SetEvent(soundSyncEvent);
LeaveCriticalSection(&soundCriticalSection);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
dsBuffer->Release();
ds->Release();
CloseHandle(soundSyncEvent);
}
int DSound_GetCurSample()
{
EnterCriticalSection(&soundCriticalSection);
int playCursor;
dsBuffer->GetCurrentPosition((DWORD*)&playCursor, 0);
playCursor = ModBufferSize(playCursor - lastPos) + totalRenderedBytes;
LeaveCriticalSection(&soundCriticalSection);
return(playCursor);
}
float DSound_GetTimer()
{
return((float)DSound_GetCurSample() * (1.0f / (4.0f * 44100.0f)));
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,133 +1,133 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <iostream> // I hope this doesn't break anything
#include <stdio.h>
#include <stdarg.h>
#include "Common.h" // for Common::swap
#include "Globals.h"
#include "gdsp_interpreter.h"
// =======================================================================================
// This is to verbose, it has to be turned on manually for now
// --------------
void DebugLog(const char* _fmt, ...)
{
#if defined(_DEBUG) || defined(DEBUGFAST)
char Msg[512];
va_list ap;
va_start( ap, _fmt );
vsprintf( Msg, _fmt, ap );
va_end( ap );
// Only show certain messages
std::string sMsg = Msg;
if(sMsg.find("Mail") != -1 || sMsg.find("AX") != -1)
// no match = -1
{
OutputDebugString(Msg);
g_dspInitialize.pLog(Msg,0);
}
#endif
}
// =============
void ErrorLog(const char* _fmt, ...)
{
char Msg[512];
va_list ap;
va_start(ap, _fmt);
vsprintf(Msg, _fmt, ap);
va_end(ap);
g_dspInitialize.pLog(Msg,0);
#ifdef _WIN32
::MessageBox(NULL, Msg, "Error", MB_OK);
#endif
DSP_DebugBreak(); // NOTICE: we also break the emulation if this happens
}
// =======================================================================================
// For PB address detection
// --------------
u32 RAM_MASK = 0x1FFFFFF;
u16 Memory_Read_U16(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return Common::swap16(*(u16*)&g_dsp.cpu_ram[_uAddress]);
}
u32 Memory_Read_U32(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return Common::swap32(*(u32*)&g_dsp.cpu_ram[_uAddress]);
}
#if PROFILE
#define PROFILE_MAP_SIZE 0x10000
u64 g_profileMap[PROFILE_MAP_SIZE];
bool g_profile = false;
void ProfilerStart()
{
g_profile = true;
}
void ProfilerAddDelta(int _addr, int _delta)
{
if (g_profile)
{
g_profileMap[_addr] += _delta;
}
}
void ProfilerInit()
{
memset(g_profileMap, 0, sizeof(g_profileMap));
}
void ProfilerDump(uint64 count)
{
FILE* pFile = fopen("c:\\_\\DSP_Prof.txt", "wt");
if (pFile != NULL)
{
fprintf(pFile, "Number of DSP steps: %llu\n\n", count);
for (int i=0; i<PROFILE_MAP_SIZE;i++)
{
if (g_profileMap[i] > 0)
{
fprintf(pFile, "0x%04X: %llu\n", i, g_profileMap[i]);
}
}
fclose(pFile);
}
}
#endif
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <iostream> // I hope this doesn't break anything
#include <stdio.h>
#include <stdarg.h>
#include "Common.h" // for Common::swap
#include "Globals.h"
#include "gdsp_interpreter.h"
// =======================================================================================
// This is to verbose, it has to be turned on manually for now
// --------------
void DebugLog(const char* _fmt, ...)
{
#if defined(_DEBUG) || defined(DEBUGFAST)
char Msg[512];
va_list ap;
va_start( ap, _fmt );
vsprintf( Msg, _fmt, ap );
va_end( ap );
// Only show certain messages
std::string sMsg = Msg;
if(sMsg.find("Mail") != -1 || sMsg.find("AX") != -1)
// no match = -1
{
OutputDebugString(Msg);
g_dspInitialize.pLog(Msg,0);
}
#endif
}
// =============
void ErrorLog(const char* _fmt, ...)
{
char Msg[512];
va_list ap;
va_start(ap, _fmt);
vsprintf(Msg, _fmt, ap);
va_end(ap);
g_dspInitialize.pLog(Msg,0);
#ifdef _WIN32
::MessageBox(NULL, Msg, "Error", MB_OK);
#endif
DSP_DebugBreak(); // NOTICE: we also break the emulation if this happens
}
// =======================================================================================
// For PB address detection
// --------------
u32 RAM_MASK = 0x1FFFFFF;
u16 Memory_Read_U16(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return Common::swap16(*(u16*)&g_dsp.cpu_ram[_uAddress]);
}
u32 Memory_Read_U32(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return Common::swap32(*(u32*)&g_dsp.cpu_ram[_uAddress]);
}
#if PROFILE
#define PROFILE_MAP_SIZE 0x10000
u64 g_profileMap[PROFILE_MAP_SIZE];
bool g_profile = false;
void ProfilerStart()
{
g_profile = true;
}
void ProfilerAddDelta(int _addr, int _delta)
{
if (g_profile)
{
g_profileMap[_addr] += _delta;
}
}
void ProfilerInit()
{
memset(g_profileMap, 0, sizeof(g_profileMap));
}
void ProfilerDump(uint64 count)
{
FILE* pFile = fopen("c:\\_\\DSP_Prof.txt", "wt");
if (pFile != NULL)
{
fprintf(pFile, "Number of DSP steps: %llu\n\n", count);
for (int i=0; i<PROFILE_MAP_SIZE;i++)
{
if (g_profileMap[i] > 0)
{
fprintf(pFile, "0x%04X: %llu\n", i, g_profileMap[i]);
}
}
fclose(pFile);
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,37 +1,37 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifdef _WIN32
#include "stdafx.h"
#endif
#include "Globals.h"
#include "gdsp_interpreter.h"
#include "gdsp_memory.h"
#include "gdsp_opcodes_helper.h"
bool WriteDMEM(uint16 addr, uint16 val)
{
return dsp_dmem_write(addr, val);
}
uint16 ReadDMEM(uint16 addr)
{
return dsp_dmem_read(addr);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifdef _WIN32
#include "stdafx.h"
#endif
#include "Globals.h"
#include "gdsp_interpreter.h"
#include "gdsp_memory.h"
#include "gdsp_opcodes_helper.h"
bool WriteDMEM(uint16 addr, uint16 val)
{
return dsp_dmem_write(addr, val);
}
uint16 ReadDMEM(uint16 addr)
{
return dsp_dmem_read(addr);
}

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 "Common.h"
extern u32 m_addressPBs;
// =======================================================================================
// Get the parameter block location - Example SSBM: We get the addr 8049cf00, first we
// always get 0 and go to AXLIST_STUDIOADDR, then we end up at AXLIST_PBADDR.
// --------------
bool AXTask(u32& _uMail)
{
u32 uAddress = _uMail;
DebugLog("AXTask - ================================================================");
DebugLog("AXTask - AXCommandList-Addr: 0x%08x", uAddress);
bool bExecuteList = true;
while (bExecuteList)
{
// ---------------------------------------------------------------------------------------
// SSBM: We get the addr 8049cf00, first we always get 0
u16 iCommand = Memory_Read_U16(uAddress);
uAddress += 2;
// ---------------------------------------------------------------------------------------
switch (iCommand)
{
// ---------------------------------------------------------------------------------------
// ?
case 0: // AXLIST_STUDIOADDR: //00
{
uAddress += 4;
DebugLog("AXLIST AXLIST_SBUFFER: %08x", uAddress);
}
break;
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
case 2: // AXLIST_PBADDR: // 02
{
m_addressPBs = Memory_Read_U32(uAddress);
uAddress += 4;
DebugLog("AXLIST PB address: %08x", m_addressPBs);
bExecuteList = false;
}
break;
// ---------------------------------------------------------------------------------------
case 7: // AXLIST_SBUFFER: // 7
{
// Hopefully this is where in main ram to write.
uAddress += 4;
DebugLog("AXLIST AXLIST_SBUFFER: %08x", uAddress);
}
break;
default:
{
// ---------------------------------------------------------------------------------------
// Stop the execution of this TaskList
DebugLog("AXLIST default: %08x", uAddress);
bExecuteList = false;
// ---------------------------------------------------------------------------------------
}
break;
} // end of switch
}
DebugLog("AXTask - done, send resume");
DebugLog("AXTask - ================================================================");
// now resume
return true;
}
// =======================================================================================
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../Globals.h"
#include "Common.h"
extern u32 m_addressPBs;
// =======================================================================================
// Get the parameter block location - Example SSBM: We get the addr 8049cf00, first we
// always get 0 and go to AXLIST_STUDIOADDR, then we end up at AXLIST_PBADDR.
// --------------
bool AXTask(u32& _uMail)
{
u32 uAddress = _uMail;
DebugLog("AXTask - ================================================================");
DebugLog("AXTask - AXCommandList-Addr: 0x%08x", uAddress);
bool bExecuteList = true;
while (bExecuteList)
{
// ---------------------------------------------------------------------------------------
// SSBM: We get the addr 8049cf00, first we always get 0
u16 iCommand = Memory_Read_U16(uAddress);
uAddress += 2;
// ---------------------------------------------------------------------------------------
switch (iCommand)
{
// ---------------------------------------------------------------------------------------
// ?
case 0: // AXLIST_STUDIOADDR: //00
{
uAddress += 4;
DebugLog("AXLIST AXLIST_SBUFFER: %08x", uAddress);
}
break;
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
case 2: // AXLIST_PBADDR: // 02
{
m_addressPBs = Memory_Read_U32(uAddress);
uAddress += 4;
DebugLog("AXLIST PB address: %08x", m_addressPBs);
bExecuteList = false;
}
break;
// ---------------------------------------------------------------------------------------
case 7: // AXLIST_SBUFFER: // 7
{
// Hopefully this is where in main ram to write.
uAddress += 4;
DebugLog("AXLIST AXLIST_SBUFFER: %08x", uAddress);
}
break;
default:
{
// ---------------------------------------------------------------------------------------
// Stop the execution of this TaskList
DebugLog("AXLIST default: %08x", uAddress);
bExecuteList = false;
// ---------------------------------------------------------------------------------------
}
break;
} // end of switch
}
DebugLog("AXTask - done, send resume");
DebugLog("AXTask - ================================================================");
// now resume
return true;
}
// =======================================================================================

View File

@ -1,197 +1,197 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifdef _WIN32
// =======================================================================================
// Includes
// --------------
#include <string>
#include <stdio.h>
#include <windows.h>
// ---------------------------------------------------------------------------------------
// Defines and settings
// --------------
bool g_consoleEnable = true;
#define DEBUGG
//#define DEBUGG_FILEONLY
//#define DEBUGG_NOFILE
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// Handles
// --------------
#ifdef DEBUGG
FILE* __fStdOut = NULL;
#endif
#ifndef DEBUGG_FILEONLY
HANDLE __hStdOut = NULL;
#endif
// ==============
// =======================================================================================
// Width and height is the size of console window, if you specify fname,
// the output will also be writton to this file. The file pointer is automatically closed
// when you close the app
// --------------
void startConsoleWin(int width, int height, char* fname)
{
#ifdef DEBUGG
#ifndef DEBUGG_FILEONLY
AllocConsole();
SetConsoleTitle(fname);
__hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD co = {width,height};
SetConsoleScreenBufferSize(__hStdOut, co);
SMALL_RECT coo = {0,0,(width - 1),70}; // top, left, right, bottom
SetConsoleWindowInfo(__hStdOut, TRUE, &coo);
#endif
#ifndef DEBUGG_NOFILE
// ---------------------------------------------------------------------------------------
// Write to a file
if(fname)
{
// Edit the log file name
std::string FileEnding = ".log";
std::string FileName = fname;
std::string FullFilename = (FileName + FileEnding);
__fStdOut = fopen(FullFilename.c_str(), "w");
}
// -----------------
#endif
#endif
}
void ClearScreen();
int wprintf(char *fmt, ...)
{
#ifdef DEBUGG
char s[6000]; // WARNING: mind this value
va_list argptr;
int cnt;
va_start(argptr, fmt);
cnt = vsnprintf(s, 3000, fmt, argptr);
va_end(argptr);
DWORD cCharsWritten;
// ---------------------------------------------------------------------------------------
#ifndef DEBUGG_FILEONLY
if(__hStdOut)
{
WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL);
}
#endif
#ifndef DEBUGG_NOFILE
// ---------------------------------------------------------------------------------------
if(__fStdOut)
fprintf(__fStdOut, s);
// ---------------------------------------------------------------------------------------
#endif
return(cnt);
#else
return 0;
#endif
}
// =======================================================================================
// Clear screen
// --------------
void ClearScreen()
{
if(g_consoleEnable)
{
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
//HANDLE hConsole = __hStdOut;
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize,
coordScreen, &cCharsWritten);
GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize,
coordScreen, &cCharsWritten);
SetConsoleCursorPosition(hConsole, coordScreen);
}
}
// =======================================================================================
// Get console HWND to be able to use MoveWindow()
// --------------
HWND GetConsoleHwnd(void)
{
#define MY_BUFSIZE 1024 // Buffer size for console window titles.
HWND hwndFound; // This is what is returned to the caller.
char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated
// WindowTitle.
char pszOldWindowTitle[MY_BUFSIZE]; // Contains original
// WindowTitle.
// Fetch current window title.
GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);
// Format a "unique" NewWindowTitle.
wsprintf(pszNewWindowTitle,"%d/%d",
GetTickCount(),
GetCurrentProcessId());
// Change current window title.
SetConsoleTitle(pszNewWindowTitle);
// Ensure window title has been updated.
Sleep(40);
// Look for NewWindowTitle.
hwndFound = FindWindow(NULL, pszNewWindowTitle);
// Restore original window title.
SetConsoleTitle(pszOldWindowTitle);
return(hwndFound);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifdef _WIN32
// =======================================================================================
// Includes
// --------------
#include <string>
#include <stdio.h>
#include <windows.h>
// ---------------------------------------------------------------------------------------
// Defines and settings
// --------------
bool g_consoleEnable = true;
#define DEBUGG
//#define DEBUGG_FILEONLY
//#define DEBUGG_NOFILE
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// Handles
// --------------
#ifdef DEBUGG
FILE* __fStdOut = NULL;
#endif
#ifndef DEBUGG_FILEONLY
HANDLE __hStdOut = NULL;
#endif
// ==============
// =======================================================================================
// Width and height is the size of console window, if you specify fname,
// the output will also be writton to this file. The file pointer is automatically closed
// when you close the app
// --------------
void startConsoleWin(int width, int height, char* fname)
{
#ifdef DEBUGG
#ifndef DEBUGG_FILEONLY
AllocConsole();
SetConsoleTitle(fname);
__hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD co = {width,height};
SetConsoleScreenBufferSize(__hStdOut, co);
SMALL_RECT coo = {0,0,(width - 1),70}; // top, left, right, bottom
SetConsoleWindowInfo(__hStdOut, TRUE, &coo);
#endif
#ifndef DEBUGG_NOFILE
// ---------------------------------------------------------------------------------------
// Write to a file
if(fname)
{
// Edit the log file name
std::string FileEnding = ".log";
std::string FileName = fname;
std::string FullFilename = (FileName + FileEnding);
__fStdOut = fopen(FullFilename.c_str(), "w");
}
// -----------------
#endif
#endif
}
void ClearScreen();
int wprintf(char *fmt, ...)
{
#ifdef DEBUGG
char s[6000]; // WARNING: mind this value
va_list argptr;
int cnt;
va_start(argptr, fmt);
cnt = vsnprintf(s, 3000, fmt, argptr);
va_end(argptr);
DWORD cCharsWritten;
// ---------------------------------------------------------------------------------------
#ifndef DEBUGG_FILEONLY
if(__hStdOut)
{
WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL);
}
#endif
#ifndef DEBUGG_NOFILE
// ---------------------------------------------------------------------------------------
if(__fStdOut)
fprintf(__fStdOut, s);
// ---------------------------------------------------------------------------------------
#endif
return(cnt);
#else
return 0;
#endif
}
// =======================================================================================
// Clear screen
// --------------
void ClearScreen()
{
if(g_consoleEnable)
{
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
//HANDLE hConsole = __hStdOut;
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize,
coordScreen, &cCharsWritten);
GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize,
coordScreen, &cCharsWritten);
SetConsoleCursorPosition(hConsole, coordScreen);
}
}
// =======================================================================================
// Get console HWND to be able to use MoveWindow()
// --------------
HWND GetConsoleHwnd(void)
{
#define MY_BUFSIZE 1024 // Buffer size for console window titles.
HWND hwndFound; // This is what is returned to the caller.
char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated
// WindowTitle.
char pszOldWindowTitle[MY_BUFSIZE]; // Contains original
// WindowTitle.
// Fetch current window title.
GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);
// Format a "unique" NewWindowTitle.
wsprintf(pszNewWindowTitle,"%d/%d",
GetTickCount(),
GetCurrentProcessId());
// Change current window title.
SetConsoleTitle(pszNewWindowTitle);
// Ensure window title has been updated.
Sleep(40);
// Look for NewWindowTitle.
hwndFound = FindWindow(NULL, pszNewWindowTitle);
// Restore original window title.
SetConsoleTitle(pszOldWindowTitle);
return(hwndFound);
}
#endif

View File

@ -1,380 +1,380 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifdef _WIN32
// =======================================================================================
// Includes
// --------------
#include <iostream>
#include <vector>
#include <string> // So that we can test if std::string == abc
#include <windows.h>
#include "Common.h"
#include "UCode_AXStructs.h" // they are only in a virtual dir called UCodes AX
#include "Console.h" // For wprintf, ClearScreen
// ---------------------------------------------------------------------------------------
// Declarations
// --------------
#define NUMBER_OF_PBS 64 // Todo: move this to a logging class
// ---------------------------------------------------------------------------------------
// Externals
// --------------
extern u32 m_addressPBs;
float ratioFactor;
int globaliSize;
short globalpBuffer;
u32 gLastBlock;
// --------------
// ---------------------------------------------------------------------------------------
// Vectors and other stuff
// --------------
std::vector<u32> gloopPos(64);
std::vector<u32> gsampleEnd(64);
std::vector<u32> gsamplePos(64);
std::vector<u32> gratio(64);
std::vector<u32> gratiohi(64);
std::vector<u32> gratiolo(64);
std::vector<u32> gfrac(64);
std::vector<u32> gcoef(64);
// PBSampleRateConverter mixer
std::vector<u16> gvolume_left(64);
std::vector<u16> gvolume_right(64);
std::vector<u16> gmixer_control(64);
std::vector<u16> gcur_volume(64);
std::vector<u16> gcur_volume_delta(64);
std::vector<u16> gaudioFormat(64);
std::vector<u16> glooping(64);
std::vector<u16> gsrc_type(64);
std::vector<u16> gis_stream(64);
// loop
std::vector<u16> gloop1(64);
std::vector<u16> gloop2(64);
std::vector<u16> gloop3(64);
std::vector<u16> gadloop1(64);
std::vector<u16> gadloop2(64);
std::vector<u16> gadloop3(64);
// updates
std::vector<u16> gupdates1(64);
std::vector<u16> gupdates2(64);
std::vector<u16> gupdates3(64);
std::vector<u16> gupdates4(64);
std::vector<u16> gupdates5(64);
std::vector<u32> gupdates_addr(64);
// other stuff
std::vector<u16> Jump(64); // this is 1 or 0
std::vector<int> musicLength(64);
std::vector< std::vector<int> > vector1(64, std::vector<int>(100,0));
std::vector<int> numberRunning(64);
int j = 0;
int k = 0;
__int64 l = 0;
int iupd = 0;
bool iupdonce = false;
std::vector<u16> viupd(15); // the length of the update frequency bar
int vectorLength = 15; // the length of the playback history bar and how long
// old blocks are shown
std::vector<u16> vector62(vectorLength);
std::vector<u16> vector63(vectorLength);
int ReadOutPBs(AXParamBlock * _pPBs, int _num);
// ===========
// =======================================================================================
// Main logging function
// --------------
void Logging()
{
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// Control how often the screen is updated
j++;
l++;
if (j>1000000) // TODO: make the update frequency adjustable from the logging window
{
AXParamBlock PBs[NUMBER_OF_PBS];
int numberOfPBs = ReadOutPBs(PBs, NUMBER_OF_PBS);
// =======================================================================================
// Vector1 is a vector1[64][100] vector
/*
Move all items back like this
1 to 2
2 3
3 ...
*/
// ----------------
for (int i = 0; i < 64; i++)
{
for (int j = 1; j < vectorLength; j++)
{
vector1.at(i).at(j-1) = vector1.at(i).at(j);
}
}
// =================
// ---------------------------------------------------------------------------------------
// Enter the latest value
for (int i = 0; i < numberOfPBs; i++)
{
vector1.at(i).at(vectorLength-1) = PBs[i].running;
}
// -----------------
// ---------------------------------------------------------------------------------------
// Count how many blocks we have running now
int jj = 0;
for (int i = 0; i < 64; i++)
{
for (int j = 0; j < vectorLength-1; j++)
{
if (vector1.at(i).at(j) == 1)
{
jj++;
}
numberRunning.at(i) = jj;
}
}
// --------------
// ---------------------------------------------------------------------------------------
// Write the first row
char buffer [1000] = "";
std::string sbuff;
//sbuff = sbuff + " Nr | | frac ratio | old new \n"; // 5
sbuff = sbuff + " Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n";
// --------------
// ---------------------------------------------------------------------------------------
// Read out values for all blocks
for (int i = 0; i < numberOfPBs; i++)
{
if (numberRunning.at(i) > 0)
{
// =======================================================================================
// Write the playback bar
// -------------
for (int j = 0; j < vectorLength; j++)
{
if(vector1.at(i).at(j) == 0)
{
sbuff = sbuff + " ";
}
else
{
sprintf(buffer, "%c", 177);
sbuff = sbuff + buffer; strcpy(buffer, "");
}
}
// ==============
// ================================================================================================
int sampleJump;
int loopJump;
//if (PBs[i].running && PBs[i].adpcm_loop_info.yn1 && PBs[i].mixer.volume_left)
if (true)
{
// ---------------------------------------------------------------------------------------
// AXPB base
//int running = pb.running;
gcoef[i] = PBs[i].unknown1;
sampleJump = ((PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo) - gsamplePos[i];
loopJump = ((PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo) - gloopPos[i];
gloopPos[i] = (PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo;
gsampleEnd[i] = (PBs[i].audio_addr.end_addr_hi << 16) | PBs[i].audio_addr.end_addr_lo;
gsamplePos[i] = (PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo;
// PBSampleRateConverter src
gratio[i] = (u32)(((PBs[i].src.ratio_hi << 16) + PBs[i].src.ratio_lo) * ratioFactor);
gratiohi[i] = PBs[i].src.ratio_hi;
gratiolo[i] = PBs[i].src.ratio_lo;
gfrac[i] = PBs[i].src.cur_addr_frac;
// adpcm_loop_info
gadloop1[i] = PBs[i].adpcm.pred_scale;
gadloop2[i] = PBs[i].adpcm.yn1;
gadloop3[i] = PBs[i].adpcm.yn2;
gloop1[i] = PBs[i].adpcm_loop_info.pred_scale;
gloop2[i] = PBs[i].adpcm_loop_info.yn1;
gloop3[i] = PBs[i].adpcm_loop_info.yn2;
// updates
gupdates1[i] = PBs[i].updates.num_updates[0];
gupdates2[i] = PBs[i].updates.num_updates[1];
gupdates3[i] = PBs[i].updates.num_updates[2];
gupdates4[i] = PBs[i].updates.num_updates[3];
gupdates5[i] = PBs[i].updates.num_updates[4];
gupdates_addr[i] = (PBs[i].updates.data_hi << 16) | PBs[i].updates.data_lo;
gaudioFormat[i] = PBs[i].audio_addr.sample_format;
glooping[i] = PBs[i].audio_addr.looping;
gsrc_type[i] = PBs[i].src_type;
gis_stream[i] = PBs[i].is_stream;
// mixer
gvolume_left[i] = PBs[i].mixer.volume_left;
gvolume_right[i] = PBs[i].mixer.volume_right;
gmixer_control[i] = PBs[i].mixer_control;
gcur_volume[i] = PBs[i].vol_env.cur_volume;
gcur_volume_delta[i] = PBs[i].vol_env.cur_volume_delta;
// other stuff
Jump[i] = (gfrac[i] >> 16); // This is 1 or 0
musicLength[i] = gsampleEnd[i] - gloopPos[i];
}
// ================================================================================================
// =======================================================================================
// PRESETS
// ---------------------------------------------------------------------------------------
/*
/" Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n";
"---------------|00 12341234/12341234 12341234 | 00000 00000 00000 0000 00000 | 0[000 00000 00000] 0 | 00000 00000[0 00000] |
*/
sprintf(buffer,"%c%i %08i/%08i %08i | %05i %05i %05i %04i %05i | %i[%03i %05i %05i] %i | %05i %05i[%i %05i] | %i %i %i %i %i",
223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i],
gvolume_left[i], gvolume_right[i], gcur_volume[i], gcur_volume_delta[i], gmixer_control[i],
glooping[i], gloop1[i], gloop2[i], gloop3[i], gis_stream[i],
gfrac[i], gratio[i], gratiohi[i], gratiolo[i],
gupdates1[i], gupdates2[i], gupdates3[i], gupdates4[i], gupdates5[i]
);
// =======================================================================================
// write a new line
sbuff = sbuff + buffer; strcpy(buffer, "");
sbuff = sbuff + "\n";
} // end of if (true)
} // end of big loop - for (int i = 0; i < numberOfPBs; i++)
// =======================================================================================
// Write global values
sprintf(buffer, "\nParameter blocks span from %08x | to %08x | distance %i %i\n", m_addressPBs, gLastBlock, (gLastBlock-m_addressPBs), (gLastBlock-m_addressPBs) / 192);
sbuff = sbuff + buffer; strcpy(buffer, "");
// ==============
// =======================================================================================
// Show update frequency
// ---------------
sbuff = sbuff + "\n";
if(!iupdonce)
{
/*
for (int i = 0; i < 10; i++)
{
viupd.at(i) == 0;
}
*/
viupd.at(0) = 1;
viupd.at(1) = 1;
viupd.at(2) = 1;
iupdonce = true;
}
for (int i = 0; i < viupd.size(); i++) // 0, 1,..., 9
{
if (i < viupd.size()-1)
{
viupd.at(viupd.size()-i-1) = viupd.at(viupd.size()-i-2); // move all forward
}
else
{
viupd.at(0) = viupd.at(viupd.size()-1);
}
// Correction
if (viupd.at(viupd.size()-3) == 1 && viupd.at(viupd.size()-2) == 1 && viupd.at(viupd.size()-1) == 1)
{
viupd.at(0) = 0;
}
if(viupd.at(0) == 0 && viupd.at(1) == 1 && viupd.at(2) == 1 && viupd.at(3) == 0)
{
viupd.at(0) = 1;
}
}
for (int i = 0; i < viupd.size(); i++)
{
if(viupd.at(i) == 0)
sbuff = sbuff + " ";
else
sbuff = sbuff + ".";
}
// ================
// =======================================================================================
// Print
// ---------------
ClearScreen();
wprintf("%s", sbuff.c_str());
sbuff.clear(); strcpy(buffer, "");
// ---------------
k=0;
j=0;
// ---------------
}
// ---------------------------------------------------------------------------------------
}
// =======================================================================================
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifdef _WIN32
// =======================================================================================
// Includes
// --------------
#include <iostream>
#include <vector>
#include <string> // So that we can test if std::string == abc
#include <windows.h>
#include "Common.h"
#include "UCode_AXStructs.h" // they are only in a virtual dir called UCodes AX
#include "Console.h" // For wprintf, ClearScreen
// ---------------------------------------------------------------------------------------
// Declarations
// --------------
#define NUMBER_OF_PBS 64 // Todo: move this to a logging class
// ---------------------------------------------------------------------------------------
// Externals
// --------------
extern u32 m_addressPBs;
float ratioFactor;
int globaliSize;
short globalpBuffer;
u32 gLastBlock;
// --------------
// ---------------------------------------------------------------------------------------
// Vectors and other stuff
// --------------
std::vector<u32> gloopPos(64);
std::vector<u32> gsampleEnd(64);
std::vector<u32> gsamplePos(64);
std::vector<u32> gratio(64);
std::vector<u32> gratiohi(64);
std::vector<u32> gratiolo(64);
std::vector<u32> gfrac(64);
std::vector<u32> gcoef(64);
// PBSampleRateConverter mixer
std::vector<u16> gvolume_left(64);
std::vector<u16> gvolume_right(64);
std::vector<u16> gmixer_control(64);
std::vector<u16> gcur_volume(64);
std::vector<u16> gcur_volume_delta(64);
std::vector<u16> gaudioFormat(64);
std::vector<u16> glooping(64);
std::vector<u16> gsrc_type(64);
std::vector<u16> gis_stream(64);
// loop
std::vector<u16> gloop1(64);
std::vector<u16> gloop2(64);
std::vector<u16> gloop3(64);
std::vector<u16> gadloop1(64);
std::vector<u16> gadloop2(64);
std::vector<u16> gadloop3(64);
// updates
std::vector<u16> gupdates1(64);
std::vector<u16> gupdates2(64);
std::vector<u16> gupdates3(64);
std::vector<u16> gupdates4(64);
std::vector<u16> gupdates5(64);
std::vector<u32> gupdates_addr(64);
// other stuff
std::vector<u16> Jump(64); // this is 1 or 0
std::vector<int> musicLength(64);
std::vector< std::vector<int> > vector1(64, std::vector<int>(100,0));
std::vector<int> numberRunning(64);
int j = 0;
int k = 0;
__int64 l = 0;
int iupd = 0;
bool iupdonce = false;
std::vector<u16> viupd(15); // the length of the update frequency bar
int vectorLength = 15; // the length of the playback history bar and how long
// old blocks are shown
std::vector<u16> vector62(vectorLength);
std::vector<u16> vector63(vectorLength);
int ReadOutPBs(AXParamBlock * _pPBs, int _num);
// ===========
// =======================================================================================
// Main logging function
// --------------
void Logging()
{
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// Control how often the screen is updated
j++;
l++;
if (j>1000000) // TODO: make the update frequency adjustable from the logging window
{
AXParamBlock PBs[NUMBER_OF_PBS];
int numberOfPBs = ReadOutPBs(PBs, NUMBER_OF_PBS);
// =======================================================================================
// Vector1 is a vector1[64][100] vector
/*
Move all items back like this
1 to 2
2 3
3 ...
*/
// ----------------
for (int i = 0; i < 64; i++)
{
for (int j = 1; j < vectorLength; j++)
{
vector1.at(i).at(j-1) = vector1.at(i).at(j);
}
}
// =================
// ---------------------------------------------------------------------------------------
// Enter the latest value
for (int i = 0; i < numberOfPBs; i++)
{
vector1.at(i).at(vectorLength-1) = PBs[i].running;
}
// -----------------
// ---------------------------------------------------------------------------------------
// Count how many blocks we have running now
int jj = 0;
for (int i = 0; i < 64; i++)
{
for (int j = 0; j < vectorLength-1; j++)
{
if (vector1.at(i).at(j) == 1)
{
jj++;
}
numberRunning.at(i) = jj;
}
}
// --------------
// ---------------------------------------------------------------------------------------
// Write the first row
char buffer [1000] = "";
std::string sbuff;
//sbuff = sbuff + " Nr | | frac ratio | old new \n"; // 5
sbuff = sbuff + " Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n";
// --------------
// ---------------------------------------------------------------------------------------
// Read out values for all blocks
for (int i = 0; i < numberOfPBs; i++)
{
if (numberRunning.at(i) > 0)
{
// =======================================================================================
// Write the playback bar
// -------------
for (int j = 0; j < vectorLength; j++)
{
if(vector1.at(i).at(j) == 0)
{
sbuff = sbuff + " ";
}
else
{
sprintf(buffer, "%c", 177);
sbuff = sbuff + buffer; strcpy(buffer, "");
}
}
// ==============
// ================================================================================================
int sampleJump;
int loopJump;
//if (PBs[i].running && PBs[i].adpcm_loop_info.yn1 && PBs[i].mixer.volume_left)
if (true)
{
// ---------------------------------------------------------------------------------------
// AXPB base
//int running = pb.running;
gcoef[i] = PBs[i].unknown1;
sampleJump = ((PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo) - gsamplePos[i];
loopJump = ((PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo) - gloopPos[i];
gloopPos[i] = (PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo;
gsampleEnd[i] = (PBs[i].audio_addr.end_addr_hi << 16) | PBs[i].audio_addr.end_addr_lo;
gsamplePos[i] = (PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo;
// PBSampleRateConverter src
gratio[i] = (u32)(((PBs[i].src.ratio_hi << 16) + PBs[i].src.ratio_lo) * ratioFactor);
gratiohi[i] = PBs[i].src.ratio_hi;
gratiolo[i] = PBs[i].src.ratio_lo;
gfrac[i] = PBs[i].src.cur_addr_frac;
// adpcm_loop_info
gadloop1[i] = PBs[i].adpcm.pred_scale;
gadloop2[i] = PBs[i].adpcm.yn1;
gadloop3[i] = PBs[i].adpcm.yn2;
gloop1[i] = PBs[i].adpcm_loop_info.pred_scale;
gloop2[i] = PBs[i].adpcm_loop_info.yn1;
gloop3[i] = PBs[i].adpcm_loop_info.yn2;
// updates
gupdates1[i] = PBs[i].updates.num_updates[0];
gupdates2[i] = PBs[i].updates.num_updates[1];
gupdates3[i] = PBs[i].updates.num_updates[2];
gupdates4[i] = PBs[i].updates.num_updates[3];
gupdates5[i] = PBs[i].updates.num_updates[4];
gupdates_addr[i] = (PBs[i].updates.data_hi << 16) | PBs[i].updates.data_lo;
gaudioFormat[i] = PBs[i].audio_addr.sample_format;
glooping[i] = PBs[i].audio_addr.looping;
gsrc_type[i] = PBs[i].src_type;
gis_stream[i] = PBs[i].is_stream;
// mixer
gvolume_left[i] = PBs[i].mixer.volume_left;
gvolume_right[i] = PBs[i].mixer.volume_right;
gmixer_control[i] = PBs[i].mixer_control;
gcur_volume[i] = PBs[i].vol_env.cur_volume;
gcur_volume_delta[i] = PBs[i].vol_env.cur_volume_delta;
// other stuff
Jump[i] = (gfrac[i] >> 16); // This is 1 or 0
musicLength[i] = gsampleEnd[i] - gloopPos[i];
}
// ================================================================================================
// =======================================================================================
// PRESETS
// ---------------------------------------------------------------------------------------
/*
/" Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n";
"---------------|00 12341234/12341234 12341234 | 00000 00000 00000 0000 00000 | 0[000 00000 00000] 0 | 00000 00000[0 00000] |
*/
sprintf(buffer,"%c%i %08i/%08i %08i | %05i %05i %05i %04i %05i | %i[%03i %05i %05i] %i | %05i %05i[%i %05i] | %i %i %i %i %i",
223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i],
gvolume_left[i], gvolume_right[i], gcur_volume[i], gcur_volume_delta[i], gmixer_control[i],
glooping[i], gloop1[i], gloop2[i], gloop3[i], gis_stream[i],
gfrac[i], gratio[i], gratiohi[i], gratiolo[i],
gupdates1[i], gupdates2[i], gupdates3[i], gupdates4[i], gupdates5[i]
);
// =======================================================================================
// write a new line
sbuff = sbuff + buffer; strcpy(buffer, "");
sbuff = sbuff + "\n";
} // end of if (true)
} // end of big loop - for (int i = 0; i < numberOfPBs; i++)
// =======================================================================================
// Write global values
sprintf(buffer, "\nParameter blocks span from %08x | to %08x | distance %i %i\n", m_addressPBs, gLastBlock, (gLastBlock-m_addressPBs), (gLastBlock-m_addressPBs) / 192);
sbuff = sbuff + buffer; strcpy(buffer, "");
// ==============
// =======================================================================================
// Show update frequency
// ---------------
sbuff = sbuff + "\n";
if(!iupdonce)
{
/*
for (int i = 0; i < 10; i++)
{
viupd.at(i) == 0;
}
*/
viupd.at(0) = 1;
viupd.at(1) = 1;
viupd.at(2) = 1;
iupdonce = true;
}
for (int i = 0; i < viupd.size(); i++) // 0, 1,..., 9
{
if (i < viupd.size()-1)
{
viupd.at(viupd.size()-i-1) = viupd.at(viupd.size()-i-2); // move all forward
}
else
{
viupd.at(0) = viupd.at(viupd.size()-1);
}
// Correction
if (viupd.at(viupd.size()-3) == 1 && viupd.at(viupd.size()-2) == 1 && viupd.at(viupd.size()-1) == 1)
{
viupd.at(0) = 0;
}
if(viupd.at(0) == 0 && viupd.at(1) == 1 && viupd.at(2) == 1 && viupd.at(3) == 0)
{
viupd.at(0) = 1;
}
}
for (int i = 0; i < viupd.size(); i++)
{
if(viupd.at(i) == 0)
sbuff = sbuff + " ";
else
sbuff = sbuff + ".";
}
// ================
// =======================================================================================
// Print
// ---------------
ClearScreen();
wprintf("%s", sbuff.c_str());
sbuff.clear(); strcpy(buffer, "");
// ---------------
k=0;
j=0;
// ---------------
}
// ---------------------------------------------------------------------------------------
}
// =======================================================================================
#endif

View File

@ -1,115 +1,115 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Turn on and off logging modes
// --------------
//#define LOG1 // writes selected parameters only and with more readable formatting
//#define LOG2 // writes all parameters
#include "Common.h"
#include "../Globals.h"
#include "CommonTypes.h" // Pluginspecs
#include "UCode_AXStructs.h" // For the AXParamBlock structure
#include "Console.h" // For wprintf, ClearScreen
u32 m_addressPBs = 0;
extern u32 gLastBlock;
#ifdef _WIN32
int m = 0;
int n = 0;
#ifdef LOG2
bool logall = true;
#else
bool logall = false;
#endif
int ReadOutPBs(AXParamBlock * _pPBs, int _num)
{
int count = 0;
u32 blockAddr = m_addressPBs;
u32 OldblockAddr = blockAddr;
u32 paraAddr = blockAddr;
// reading and 'halfword' swap
n++;
if (n > 20 && logall) {ClearScreen();}
for (int i = 0; i < _num; i++)
{
// ---------------------------------------------------------------------------------------
// Check if there is something here.
const short * pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr);
// -------------
if (pSrc != NULL) // only read non-blank blocks
{
// ---------------------------------------------------------------------------------------
// Create a shortcut that let us update struct members
short * pDest = (short *) & _pPBs[i];
if (n > 20 && logall) {wprintf("%c%i:", 223, i);} // logging
// --------------
// Here we update the PB. We do it by going through all 192 / 2 = 96 u16 values
for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++)
{
paraAddr += 2;
if(pSrc != NULL)
{
if (pSrc[p] != 0 && n > 20 && logall)
{
wprintf("%i %04x | ", p, Common::swap16(pSrc[p]));
}
}
pDest[p] = Common::swap16(pSrc[p]);
}
if(n > 20 && logall) {wprintf("\n");} // logging
// --------------
// Here we update the block address to the starting point of the next PB
blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo;
// --------------
// save some values
count++;
gLastBlock = paraAddr; // blockAddr
// ============
}
else
{
break;
}
} // end of the big loop
if (n > 20) {n = 0;} // for logging
// return the number of readed PBs
return count;
}
// =======================================================================================
#endif
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Turn on and off logging modes
// --------------
//#define LOG1 // writes selected parameters only and with more readable formatting
//#define LOG2 // writes all parameters
#include "Common.h"
#include "../Globals.h"
#include "CommonTypes.h" // Pluginspecs
#include "UCode_AXStructs.h" // For the AXParamBlock structure
#include "Console.h" // For wprintf, ClearScreen
u32 m_addressPBs = 0;
extern u32 gLastBlock;
#ifdef _WIN32
int m = 0;
int n = 0;
#ifdef LOG2
bool logall = true;
#else
bool logall = false;
#endif
int ReadOutPBs(AXParamBlock * _pPBs, int _num)
{
int count = 0;
u32 blockAddr = m_addressPBs;
u32 OldblockAddr = blockAddr;
u32 paraAddr = blockAddr;
// reading and 'halfword' swap
n++;
if (n > 20 && logall) {ClearScreen();}
for (int i = 0; i < _num; i++)
{
// ---------------------------------------------------------------------------------------
// Check if there is something here.
const short * pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr);
// -------------
if (pSrc != NULL) // only read non-blank blocks
{
// ---------------------------------------------------------------------------------------
// Create a shortcut that let us update struct members
short * pDest = (short *) & _pPBs[i];
if (n > 20 && logall) {wprintf("%c%i:", 223, i);} // logging
// --------------
// Here we update the PB. We do it by going through all 192 / 2 = 96 u16 values
for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++)
{
paraAddr += 2;
if(pSrc != NULL)
{
if (pSrc[p] != 0 && n > 20 && logall)
{
wprintf("%i %04x | ", p, Common::swap16(pSrc[p]));
}
}
pDest[p] = Common::swap16(pSrc[p]);
}
if(n > 20 && logall) {wprintf("\n");} // logging
// --------------
// Here we update the block address to the starting point of the next PB
blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo;
// --------------
// save some values
count++;
gLastBlock = paraAddr; // blockAddr
// ============
}
else
{
break;
}
} // end of the big loop
if (n > 20) {n = 0;} // for logging
// return the number of readed PBs
return count;
}
// =======================================================================================
#endif

View File

@ -1,164 +1,164 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// This queue solution is temporary. I'll implement something more efficient later.
#include <queue>
#include "Thread.h"
#include "Mixer.h"
#include "FixedSizeQueue.h"
#ifdef _WIN32
#include "DSoundStream.h"
#else
#include <unistd.h>
#endif
namespace {
Common::CriticalSection push_sync;
// On real hardware, this fifo is much, much smaller. But timing is also tighter than under Windows, so...
const int queue_minlength = 1024 * 4;
const int queue_maxlength = 1024 * 28;
FixedSizeQueue<s16, queue_maxlength> sample_queue;
} // namespace
volatile bool mixer_HLEready = false;
volatile int queue_size = 0;
void Mixer(short *buffer, int numSamples, int bits, int rate, int channels)
{
// silence
memset(buffer, 0, numSamples * 2 * sizeof(short));
push_sync.Enter();
int count = 0;
while (queue_size > queue_minlength && count < numSamples * 2) {
int x = buffer[count];
x += sample_queue.front();
if (x > 32767) x = 32767;
if (x < -32767) x = -32767;
buffer[count++] = x;
sample_queue.pop();
x = buffer[count];
x += sample_queue.front();
if (x > 32767) x = 32767;
if (x < -32767) x = -32767;
buffer[count++] = x;
sample_queue.pop();
queue_size-=2;
}
push_sync.Leave();
}
void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) {
// static FILE *f;
// if (!f)
// f = fopen("d:\\hello.raw", "wb");
// fwrite(buffer, num_stereo_samples * 4, 1, f);
if (queue_size == 0)
{
queue_size = queue_minlength;
for (int i = 0; i < queue_minlength; i++)
sample_queue.push((s16)0);
}
static int PV1l=0,PV2l=0,PV3l=0,PV4l=0;
static int PV1r=0,PV2r=0,PV3r=0,PV4r=0;
static int acc=0;
#ifdef _WIN32
if (!GetAsyncKeyState(VK_TAB)) {
while (queue_size > queue_maxlength / 2) {
DSound::DSound_UpdateSound();
Sleep(0);
}
} else {
return;
}
#else
while (queue_size > queue_maxlength) {
sleep(0);
}
#endif
//convert into config option?
const int mode = 2;
push_sync.Enter();
while (num_stereo_samples)
{
acc += sample_rate;
while (num_stereo_samples && (acc >= 48000))
{
PV4l=PV3l;
PV3l=PV2l;
PV2l=PV1l;
PV1l=*(buffer++); //32bit processing
PV4r=PV3r;
PV3r=PV2r;
PV2r=PV1r;
PV1r=*(buffer++); //32bit processing
num_stereo_samples--;
acc-=48000;
}
// defaults to nearest
s32 DataL = PV1l;
s32 DataR = PV1r;
if (mode == 1) //linear
{
DataL = PV1l + ((PV2l - PV1l)*acc)/48000;
DataR = PV1r + ((PV2r - PV1r)*acc)/48000;
}
else if (mode == 2) //cubic
{
s32 a0l = PV1l - PV2l - PV4l + PV3l;
s32 a0r = PV1r - PV2r - PV4r + PV3r;
s32 a1l = PV4l - PV3l - a0l;
s32 a1r = PV4r - PV3r - a0r;
s32 a2l = PV1l - PV4l;
s32 a2r = PV1r - PV4r;
s32 a3l = PV2l;
s32 a3r = PV2r;
s32 t0l = ((a0l )*acc)/48000;
s32 t0r = ((a0r )*acc)/48000;
s32 t1l = ((t0l+a1l)*acc)/48000;
s32 t1r = ((t0r+a1r)*acc)/48000;
s32 t2l = ((t1l+a2l)*acc)/48000;
s32 t2r = ((t1r+a2r)*acc)/48000;
s32 t3l = ((t2l+a3l));
s32 t3r = ((t2r+a3r));
DataL = t3l;
DataR = t3r;
}
int l = DataL, r = DataR;
if (l < -32767) l = -32767;
if (r < -32767) r = -32767;
if (l > 32767) l = 32767;
if (r > 32767) r = 32767;
sample_queue.push(l);
sample_queue.push(r);
}
push_sync.Leave();
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// This queue solution is temporary. I'll implement something more efficient later.
#include <queue>
#include "Thread.h"
#include "Mixer.h"
#include "FixedSizeQueue.h"
#ifdef _WIN32
#include "DSoundStream.h"
#else
#include <unistd.h>
#endif
namespace {
Common::CriticalSection push_sync;
// On real hardware, this fifo is much, much smaller. But timing is also tighter than under Windows, so...
const int queue_minlength = 1024 * 4;
const int queue_maxlength = 1024 * 28;
FixedSizeQueue<s16, queue_maxlength> sample_queue;
} // namespace
volatile bool mixer_HLEready = false;
volatile int queue_size = 0;
void Mixer(short *buffer, int numSamples, int bits, int rate, int channels)
{
// silence
memset(buffer, 0, numSamples * 2 * sizeof(short));
push_sync.Enter();
int count = 0;
while (queue_size > queue_minlength && count < numSamples * 2) {
int x = buffer[count];
x += sample_queue.front();
if (x > 32767) x = 32767;
if (x < -32767) x = -32767;
buffer[count++] = x;
sample_queue.pop();
x = buffer[count];
x += sample_queue.front();
if (x > 32767) x = 32767;
if (x < -32767) x = -32767;
buffer[count++] = x;
sample_queue.pop();
queue_size-=2;
}
push_sync.Leave();
}
void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) {
// static FILE *f;
// if (!f)
// f = fopen("d:\\hello.raw", "wb");
// fwrite(buffer, num_stereo_samples * 4, 1, f);
if (queue_size == 0)
{
queue_size = queue_minlength;
for (int i = 0; i < queue_minlength; i++)
sample_queue.push((s16)0);
}
static int PV1l=0,PV2l=0,PV3l=0,PV4l=0;
static int PV1r=0,PV2r=0,PV3r=0,PV4r=0;
static int acc=0;
#ifdef _WIN32
if (!GetAsyncKeyState(VK_TAB)) {
while (queue_size > queue_maxlength / 2) {
DSound::DSound_UpdateSound();
Sleep(0);
}
} else {
return;
}
#else
while (queue_size > queue_maxlength) {
sleep(0);
}
#endif
//convert into config option?
const int mode = 2;
push_sync.Enter();
while (num_stereo_samples)
{
acc += sample_rate;
while (num_stereo_samples && (acc >= 48000))
{
PV4l=PV3l;
PV3l=PV2l;
PV2l=PV1l;
PV1l=*(buffer++); //32bit processing
PV4r=PV3r;
PV3r=PV2r;
PV2r=PV1r;
PV1r=*(buffer++); //32bit processing
num_stereo_samples--;
acc-=48000;
}
// defaults to nearest
s32 DataL = PV1l;
s32 DataR = PV1r;
if (mode == 1) //linear
{
DataL = PV1l + ((PV2l - PV1l)*acc)/48000;
DataR = PV1r + ((PV2r - PV1r)*acc)/48000;
}
else if (mode == 2) //cubic
{
s32 a0l = PV1l - PV2l - PV4l + PV3l;
s32 a0r = PV1r - PV2r - PV4r + PV3r;
s32 a1l = PV4l - PV3l - a0l;
s32 a1r = PV4r - PV3r - a0r;
s32 a2l = PV1l - PV4l;
s32 a2r = PV1r - PV4r;
s32 a3l = PV2l;
s32 a3r = PV2r;
s32 t0l = ((a0l )*acc)/48000;
s32 t0r = ((a0r )*acc)/48000;
s32 t1l = ((t0l+a1l)*acc)/48000;
s32 t1r = ((t0r+a1r)*acc)/48000;
s32 t2l = ((t1l+a2l)*acc)/48000;
s32 t2r = ((t1r+a2r)*acc)/48000;
s32 t3l = ((t2l+a3l));
s32 t3r = ((t2r+a3r));
DataL = t3l;
DataR = t3r;
}
int l = DataL, r = DataR;
if (l < -32767) l = -32767;
if (r < -32767) r = -32767;
if (l > 32767) l = 32767;
if (r > 32767) r = 32767;
sample_queue.push(l);
sample_queue.push(r);
}
push_sync.Leave();
}

View File

@ -1,274 +1,274 @@
// RegSettings.cpp
//
// Copyright (c) 2001 Magomed Abdurakhmanov
// maq@hotbox.ru, http://mickels.iwt.ru/en
//
//
//
// No warranties are given. Use at your own risk.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "RegSettings.h"
//////////////////////////////////////////////////////////////////////
// CWindowSettings
#define S_WINDOW_PLACEMENT_VAL _T("WindowPlacement")
CWindowSettings::CWindowSettings()
{
m_WindowPlacement.length = sizeof(m_WindowPlacement);
m_WindowPlacement.flags = 0;
m_WindowPlacement.ptMinPosition.x = 0;
m_WindowPlacement.ptMinPosition.y = 0;
m_WindowPlacement.ptMaxPosition.x = 0;
m_WindowPlacement.ptMaxPosition.y = 0;
CRect rc;
SystemParametersInfo(SPI_GETWORKAREA, 0, rc, 0);
rc.DeflateRect(100, 100);
m_WindowPlacement.rcNormalPosition = rc;
m_WindowPlacement.showCmd = SW_SHOWNORMAL;
}
bool CWindowSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/)
{
CRegKey reg;
DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ);
if (err == ERROR_SUCCESS)
{
DWORD dwType = NULL;
DWORD dwSize = sizeof(m_WindowPlacement);
err = RegQueryValueEx(reg.m_hKey, CString(szPrefix) + S_WINDOW_PLACEMENT_VAL, NULL, &dwType,
(LPBYTE)&m_WindowPlacement, &dwSize);
}
return(err == ERROR_SUCCESS);
}
bool CWindowSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const
{
CRegKey reg;
DWORD err = reg.Create(hkRootKey, szRegKey);
if (err == ERROR_SUCCESS)
{
err = RegSetValueEx(reg.m_hKey, CString(szPrefix) + S_WINDOW_PLACEMENT_VAL, NULL, REG_BINARY,
(LPBYTE)&m_WindowPlacement, sizeof(m_WindowPlacement));
}
return(err == ERROR_SUCCESS);
}
void CWindowSettings::GetFrom(CWindow& Wnd)
{
ATLASSERT(Wnd.IsWindow());
Wnd.GetWindowPlacement(&m_WindowPlacement);
}
void CWindowSettings::ApplyTo(CWindow& Wnd, int nCmdShow /* = SW_SHOWNORMAL*/) const
{
ATLASSERT(Wnd.IsWindow());
Wnd.SetWindowPlacement(&m_WindowPlacement);
if (SW_SHOWNORMAL != nCmdShow)
{
Wnd.ShowWindow(nCmdShow);
}
else
if (m_WindowPlacement.showCmd == SW_MINIMIZE || m_WindowPlacement.showCmd == SW_SHOWMINIMIZED)
{
Wnd.ShowWindow(SW_SHOWNORMAL);
}
}
//////////////////////////////////////////////////////////////////////
// CReBarSettings
#define S_BAR_BANDCOUNT _T("BandCount")
#define S_BAR_ID_VAL _T("ID")
#define S_BAR_CX_VAL _T("CX")
#define S_BAR_BREAKLINE_VAL _T("BreakLine")
CReBarSettings::CReBarSettings()
{
m_pBands = NULL;
m_cbBandCount = 0;
}
CReBarSettings::~CReBarSettings()
{
if (m_pBands != NULL)
{
delete[] m_pBands;
m_pBands = NULL;
}
}
bool CReBarSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/)
{
if (m_pBands != NULL)
{
delete[] m_pBands;
m_pBands = NULL;
}
m_pBands = NULL;
m_cbBandCount = 0;
CRegKey reg;
DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ);
if (err == ERROR_SUCCESS)
{
reg.QueryDWORDValue(CString(szPrefix) + S_BAR_BANDCOUNT, m_cbBandCount);
if (m_cbBandCount > 0)
{
m_pBands = new BandInfo[m_cbBandCount];
}
for (DWORD i = 0; i < m_cbBandCount; i++)
{
CString s;
s.Format(_T("%s%i_"), szPrefix, i);
reg.QueryDWORDValue(s + S_BAR_ID_VAL, m_pBands[i].ID);
reg.QueryDWORDValue(s + S_BAR_CX_VAL, m_pBands[i].cx);
DWORD dw;
reg.QueryDWORDValue(s + S_BAR_BREAKLINE_VAL, dw);
m_pBands[i].BreakLine = dw != 0;
}
}
return(err == ERROR_SUCCESS);
}
bool CReBarSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const
{
CRegKey reg;
DWORD err = reg.Create(hkRootKey, szRegKey);
if (err == ERROR_SUCCESS)
{
reg.SetDWORDValue(CString(szPrefix) + S_BAR_BANDCOUNT, m_cbBandCount);
for (DWORD i = 0; i < m_cbBandCount; i++)
{
CString s;
s.Format(_T("%s%i_"), szPrefix, i);
reg.SetDWORDValue(s + S_BAR_ID_VAL, m_pBands[i].ID);
reg.SetDWORDValue(s + S_BAR_CX_VAL, m_pBands[i].cx);
DWORD dw = m_pBands[i].BreakLine;
reg.SetDWORDValue(s + S_BAR_BREAKLINE_VAL, dw);
}
}
return(err == ERROR_SUCCESS);
}
void CReBarSettings::GetFrom(CReBarCtrl& ReBar)
{
ATLASSERT(ReBar.IsWindow());
if (m_pBands != NULL)
{
delete[] m_pBands;
}
m_pBands = NULL;
m_cbBandCount = ReBar.GetBandCount();
if (m_cbBandCount > 0)
{
m_pBands = new BandInfo[m_cbBandCount];
}
for (UINT i = 0; i < m_cbBandCount; i++)
{
REBARBANDINFO rbi;
rbi.cbSize = sizeof(rbi);
rbi.fMask = RBBIM_ID | RBBIM_SIZE | RBBIM_STYLE;
ReBar.GetBandInfo(i, &rbi);
m_pBands[i].ID = rbi.wID;
m_pBands[i].cx = rbi.cx;
m_pBands[i].BreakLine = (rbi.fStyle & RBBS_BREAK) != 0;
}
}
void CReBarSettings::ApplyTo(CReBarCtrl& ReBar) const
{
ATLASSERT(ReBar.IsWindow());
for (UINT i = 0; i < m_cbBandCount; i++)
{
ReBar.MoveBand(ReBar.IdToIndex(m_pBands[i].ID), i);
REBARBANDINFO rbi;
rbi.cbSize = sizeof(rbi);
rbi.fMask = RBBIM_ID | RBBIM_SIZE | RBBIM_STYLE;
ReBar.GetBandInfo(i, &rbi);
rbi.cx = m_pBands[i].cx;
if (m_pBands[i].BreakLine)
{
rbi.fStyle |= RBBS_BREAK;
}
else
{
rbi.fStyle &= (~RBBS_BREAK);
}
ReBar.SetBandInfo(i, &rbi);
}
}
//////////////////////////////////////////////////////////////////////
// CSplitterSettings
#define S_SPLITTER_POS _T("SplitterPos")
bool CSplitterSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/)
{
CRegKey reg;
DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ);
if (err == ERROR_SUCCESS)
{
reg.QueryDWORDValue(CString(szPrefix) + S_SPLITTER_POS, m_dwPos);
}
return(err == ERROR_SUCCESS);
}
bool CSplitterSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const
{
CRegKey reg;
DWORD err = reg.Create(hkRootKey, szRegKey);
if (err == ERROR_SUCCESS)
{
reg.SetDWORDValue(CString(szPrefix) + S_SPLITTER_POS, m_dwPos);
}
return(err == ERROR_SUCCESS);
}
// RegSettings.cpp
//
// Copyright (c) 2001 Magomed Abdurakhmanov
// maq@hotbox.ru, http://mickels.iwt.ru/en
//
//
//
// No warranties are given. Use at your own risk.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "RegSettings.h"
//////////////////////////////////////////////////////////////////////
// CWindowSettings
#define S_WINDOW_PLACEMENT_VAL _T("WindowPlacement")
CWindowSettings::CWindowSettings()
{
m_WindowPlacement.length = sizeof(m_WindowPlacement);
m_WindowPlacement.flags = 0;
m_WindowPlacement.ptMinPosition.x = 0;
m_WindowPlacement.ptMinPosition.y = 0;
m_WindowPlacement.ptMaxPosition.x = 0;
m_WindowPlacement.ptMaxPosition.y = 0;
CRect rc;
SystemParametersInfo(SPI_GETWORKAREA, 0, rc, 0);
rc.DeflateRect(100, 100);
m_WindowPlacement.rcNormalPosition = rc;
m_WindowPlacement.showCmd = SW_SHOWNORMAL;
}
bool CWindowSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/)
{
CRegKey reg;
DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ);
if (err == ERROR_SUCCESS)
{
DWORD dwType = NULL;
DWORD dwSize = sizeof(m_WindowPlacement);
err = RegQueryValueEx(reg.m_hKey, CString(szPrefix) + S_WINDOW_PLACEMENT_VAL, NULL, &dwType,
(LPBYTE)&m_WindowPlacement, &dwSize);
}
return(err == ERROR_SUCCESS);
}
bool CWindowSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const
{
CRegKey reg;
DWORD err = reg.Create(hkRootKey, szRegKey);
if (err == ERROR_SUCCESS)
{
err = RegSetValueEx(reg.m_hKey, CString(szPrefix) + S_WINDOW_PLACEMENT_VAL, NULL, REG_BINARY,
(LPBYTE)&m_WindowPlacement, sizeof(m_WindowPlacement));
}
return(err == ERROR_SUCCESS);
}
void CWindowSettings::GetFrom(CWindow& Wnd)
{
ATLASSERT(Wnd.IsWindow());
Wnd.GetWindowPlacement(&m_WindowPlacement);
}
void CWindowSettings::ApplyTo(CWindow& Wnd, int nCmdShow /* = SW_SHOWNORMAL*/) const
{
ATLASSERT(Wnd.IsWindow());
Wnd.SetWindowPlacement(&m_WindowPlacement);
if (SW_SHOWNORMAL != nCmdShow)
{
Wnd.ShowWindow(nCmdShow);
}
else
if (m_WindowPlacement.showCmd == SW_MINIMIZE || m_WindowPlacement.showCmd == SW_SHOWMINIMIZED)
{
Wnd.ShowWindow(SW_SHOWNORMAL);
}
}
//////////////////////////////////////////////////////////////////////
// CReBarSettings
#define S_BAR_BANDCOUNT _T("BandCount")
#define S_BAR_ID_VAL _T("ID")
#define S_BAR_CX_VAL _T("CX")
#define S_BAR_BREAKLINE_VAL _T("BreakLine")
CReBarSettings::CReBarSettings()
{
m_pBands = NULL;
m_cbBandCount = 0;
}
CReBarSettings::~CReBarSettings()
{
if (m_pBands != NULL)
{
delete[] m_pBands;
m_pBands = NULL;
}
}
bool CReBarSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/)
{
if (m_pBands != NULL)
{
delete[] m_pBands;
m_pBands = NULL;
}
m_pBands = NULL;
m_cbBandCount = 0;
CRegKey reg;
DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ);
if (err == ERROR_SUCCESS)
{
reg.QueryDWORDValue(CString(szPrefix) + S_BAR_BANDCOUNT, m_cbBandCount);
if (m_cbBandCount > 0)
{
m_pBands = new BandInfo[m_cbBandCount];
}
for (DWORD i = 0; i < m_cbBandCount; i++)
{
CString s;
s.Format(_T("%s%i_"), szPrefix, i);
reg.QueryDWORDValue(s + S_BAR_ID_VAL, m_pBands[i].ID);
reg.QueryDWORDValue(s + S_BAR_CX_VAL, m_pBands[i].cx);
DWORD dw;
reg.QueryDWORDValue(s + S_BAR_BREAKLINE_VAL, dw);
m_pBands[i].BreakLine = dw != 0;
}
}
return(err == ERROR_SUCCESS);
}
bool CReBarSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const
{
CRegKey reg;
DWORD err = reg.Create(hkRootKey, szRegKey);
if (err == ERROR_SUCCESS)
{
reg.SetDWORDValue(CString(szPrefix) + S_BAR_BANDCOUNT, m_cbBandCount);
for (DWORD i = 0; i < m_cbBandCount; i++)
{
CString s;
s.Format(_T("%s%i_"), szPrefix, i);
reg.SetDWORDValue(s + S_BAR_ID_VAL, m_pBands[i].ID);
reg.SetDWORDValue(s + S_BAR_CX_VAL, m_pBands[i].cx);
DWORD dw = m_pBands[i].BreakLine;
reg.SetDWORDValue(s + S_BAR_BREAKLINE_VAL, dw);
}
}
return(err == ERROR_SUCCESS);
}
void CReBarSettings::GetFrom(CReBarCtrl& ReBar)
{
ATLASSERT(ReBar.IsWindow());
if (m_pBands != NULL)
{
delete[] m_pBands;
}
m_pBands = NULL;
m_cbBandCount = ReBar.GetBandCount();
if (m_cbBandCount > 0)
{
m_pBands = new BandInfo[m_cbBandCount];
}
for (UINT i = 0; i < m_cbBandCount; i++)
{
REBARBANDINFO rbi;
rbi.cbSize = sizeof(rbi);
rbi.fMask = RBBIM_ID | RBBIM_SIZE | RBBIM_STYLE;
ReBar.GetBandInfo(i, &rbi);
m_pBands[i].ID = rbi.wID;
m_pBands[i].cx = rbi.cx;
m_pBands[i].BreakLine = (rbi.fStyle & RBBS_BREAK) != 0;
}
}
void CReBarSettings::ApplyTo(CReBarCtrl& ReBar) const
{
ATLASSERT(ReBar.IsWindow());
for (UINT i = 0; i < m_cbBandCount; i++)
{
ReBar.MoveBand(ReBar.IdToIndex(m_pBands[i].ID), i);
REBARBANDINFO rbi;
rbi.cbSize = sizeof(rbi);
rbi.fMask = RBBIM_ID | RBBIM_SIZE | RBBIM_STYLE;
ReBar.GetBandInfo(i, &rbi);
rbi.cx = m_pBands[i].cx;
if (m_pBands[i].BreakLine)
{
rbi.fStyle |= RBBS_BREAK;
}
else
{
rbi.fStyle &= (~RBBS_BREAK);
}
ReBar.SetBandInfo(i, &rbi);
}
}
//////////////////////////////////////////////////////////////////////
// CSplitterSettings
#define S_SPLITTER_POS _T("SplitterPos")
bool CSplitterSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/)
{
CRegKey reg;
DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ);
if (err == ERROR_SUCCESS)
{
reg.QueryDWORDValue(CString(szPrefix) + S_SPLITTER_POS, m_dwPos);
}
return(err == ERROR_SUCCESS);
}
bool CSplitterSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const
{
CRegKey reg;
DWORD err = reg.Create(hkRootKey, szRegKey);
if (err == ERROR_SUCCESS)
{
reg.SetDWORDValue(CString(szPrefix) + S_SPLITTER_POS, m_dwPos);
}
return(err == ERROR_SUCCESS);
}

View File

@ -1,207 +1,207 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../res/resource.h"
#include "RegisterDlg.h"
#include "disassemble.h"
#include "gdsp_interpreter.h"
#include "RegSettings.h"
CRegisterDlg::CRegisterDlg()
: m_CachedCounter(-1)
{}
BOOL CRegisterDlg::PreTranslateMessage(MSG* pMsg)
{
return(IsDialogMessage(pMsg));
}
BOOL CRegisterDlg::OnIdle()
{
return(FALSE);
}
LRESULT CRegisterDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CWindowSettings ws;
if (ws.Load("Software\\Dolphin\\DSP", "Register"))
{
ws.ApplyTo(CWindow(m_hWnd), SW_SHOW);
}
m_RegisterListViewCtrl.m_hWnd = GetDlgItem(IDC_DISASM_LIST);
UIAddChildWindowContainer(m_hWnd);
m_RegisterListViewCtrl.AddColumn(_T("General"), 0);
m_RegisterListViewCtrl.AddColumn(_T(" "), 1);
m_RegisterListViewCtrl.AddColumn(_T("Special"), 2);
m_RegisterListViewCtrl.AddColumn(_T("0"), 3);
m_RegisterListViewCtrl.SetColumnWidth(0, 50);
m_RegisterListViewCtrl.SetColumnWidth(1, 100);
m_RegisterListViewCtrl.SetColumnWidth(2, 60);
m_RegisterListViewCtrl.SetColumnWidth(3, 100);
m_RegisterListViewCtrl.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
m_RegisterListViewCtrl.SetTextBkColor(GetSysColor(COLOR_3DLIGHT));
for (uint16 i = 0; i < 16; i++)
{
// 0-15
int Item = m_RegisterListViewCtrl.AddItem(0, 0, gd_dis_get_reg_name(i));
// 16-31
m_RegisterListViewCtrl.AddItem(Item, 2, gd_dis_get_reg_name(16 + i));
// just for easy sort
m_RegisterListViewCtrl.SetItemData(Item, i);
}
m_RegisterListViewCtrl.SortItems(CompareFunc, (LPARAM) this);
UpdateRegisterListView();
return(TRUE);
}
LRESULT CRegisterDlg::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CWindowSettings ws;
ws.GetFrom(CWindow(m_hWnd));
ws.Save("Software\\Dolphin\\DSP", "Register");
return(0);
}
void CRegisterDlg::UpdateRegisterListView()
{
if (m_CachedCounter == g_dsp.step_counter)
{
return;
}
m_CachedCounter = g_dsp.step_counter;
char Temp[256];
for (uint16 i = 0; i < 16; i++)
{
// 0-15
if (m_CachedRegs[i] != g_dsp.r[i])
{
m_CachedRegHasChanged[i] = true;
}
else
{
m_CachedRegHasChanged[i] = false;
}
m_CachedRegs[i] = g_dsp.r[i];
sprintf_s(Temp, 256, "0x%04x", g_dsp.r[i]);
m_RegisterListViewCtrl.SetItemText(i, 1, Temp);
// 16-31
if (m_CachedRegs[16 + i] != g_dsp.r[16 + i])
{
m_CachedRegHasChanged[16 + i] = true;
}
else
{
m_CachedRegHasChanged[16 + i] = false;
}
m_CachedRegs[16 + i] = g_dsp.r[16 + i];
sprintf_s(Temp, 256, "0x%04x", g_dsp.r[16 + i]);
m_RegisterListViewCtrl.SetItemText(i, 3, Temp);
}
}
int CALLBACK CRegisterDlg::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
return(lParam1 > lParam2);
}
LRESULT CRegisterDlg::OnCustomDraw(int /*idCtrl*/, LPNMHDR pnmh, BOOL& _bHandled)
{
int result = CDRF_DODEFAULT;
NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pnmh);
switch (pLVCD->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
result = CDRF_NOTIFYITEMDRAW;
break;
case CDDS_ITEMPREPAINT:
result = CDRF_NOTIFYSUBITEMDRAW;
break;
case (CDDS_ITEMPREPAINT | CDDS_SUBITEM):
{
pLVCD->nmcd.uItemState &= ~(CDIS_SELECTED | CDIS_FOCUS);
int Offset = static_cast<int>(m_RegisterListViewCtrl.GetItemData((int)pLVCD->nmcd.dwItemSpec));
size_t Register = -1;
if (pLVCD->iSubItem == 1)
{
Register = Offset;
}
else if (pLVCD->iSubItem == 3)
{
Register = Offset + 16;
}
if (Register != -1)
{
if (m_CachedRegHasChanged[Register])
{
pLVCD->clrTextBk = RGB(0xFF, 192, 192);
}
else
{
pLVCD->clrTextBk = RGB(0xF0, 0xF0, 0xF0);
}
}
else
{
pLVCD->clrTextBk = RGB(192, 224, 192);
}
// uint16 CurrentAddress = static_cast<uint16>(m_DisAsmListViewCtrl.GetItemData((int)pLVCD->nmcd.dwItemSpec));
}
break;
}
return(result);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../res/resource.h"
#include "RegisterDlg.h"
#include "disassemble.h"
#include "gdsp_interpreter.h"
#include "RegSettings.h"
CRegisterDlg::CRegisterDlg()
: m_CachedCounter(-1)
{}
BOOL CRegisterDlg::PreTranslateMessage(MSG* pMsg)
{
return(IsDialogMessage(pMsg));
}
BOOL CRegisterDlg::OnIdle()
{
return(FALSE);
}
LRESULT CRegisterDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CWindowSettings ws;
if (ws.Load("Software\\Dolphin\\DSP", "Register"))
{
ws.ApplyTo(CWindow(m_hWnd), SW_SHOW);
}
m_RegisterListViewCtrl.m_hWnd = GetDlgItem(IDC_DISASM_LIST);
UIAddChildWindowContainer(m_hWnd);
m_RegisterListViewCtrl.AddColumn(_T("General"), 0);
m_RegisterListViewCtrl.AddColumn(_T(" "), 1);
m_RegisterListViewCtrl.AddColumn(_T("Special"), 2);
m_RegisterListViewCtrl.AddColumn(_T("0"), 3);
m_RegisterListViewCtrl.SetColumnWidth(0, 50);
m_RegisterListViewCtrl.SetColumnWidth(1, 100);
m_RegisterListViewCtrl.SetColumnWidth(2, 60);
m_RegisterListViewCtrl.SetColumnWidth(3, 100);
m_RegisterListViewCtrl.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
m_RegisterListViewCtrl.SetTextBkColor(GetSysColor(COLOR_3DLIGHT));
for (uint16 i = 0; i < 16; i++)
{
// 0-15
int Item = m_RegisterListViewCtrl.AddItem(0, 0, gd_dis_get_reg_name(i));
// 16-31
m_RegisterListViewCtrl.AddItem(Item, 2, gd_dis_get_reg_name(16 + i));
// just for easy sort
m_RegisterListViewCtrl.SetItemData(Item, i);
}
m_RegisterListViewCtrl.SortItems(CompareFunc, (LPARAM) this);
UpdateRegisterListView();
return(TRUE);
}
LRESULT CRegisterDlg::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CWindowSettings ws;
ws.GetFrom(CWindow(m_hWnd));
ws.Save("Software\\Dolphin\\DSP", "Register");
return(0);
}
void CRegisterDlg::UpdateRegisterListView()
{
if (m_CachedCounter == g_dsp.step_counter)
{
return;
}
m_CachedCounter = g_dsp.step_counter;
char Temp[256];
for (uint16 i = 0; i < 16; i++)
{
// 0-15
if (m_CachedRegs[i] != g_dsp.r[i])
{
m_CachedRegHasChanged[i] = true;
}
else
{
m_CachedRegHasChanged[i] = false;
}
m_CachedRegs[i] = g_dsp.r[i];
sprintf_s(Temp, 256, "0x%04x", g_dsp.r[i]);
m_RegisterListViewCtrl.SetItemText(i, 1, Temp);
// 16-31
if (m_CachedRegs[16 + i] != g_dsp.r[16 + i])
{
m_CachedRegHasChanged[16 + i] = true;
}
else
{
m_CachedRegHasChanged[16 + i] = false;
}
m_CachedRegs[16 + i] = g_dsp.r[16 + i];
sprintf_s(Temp, 256, "0x%04x", g_dsp.r[16 + i]);
m_RegisterListViewCtrl.SetItemText(i, 3, Temp);
}
}
int CALLBACK CRegisterDlg::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
return(lParam1 > lParam2);
}
LRESULT CRegisterDlg::OnCustomDraw(int /*idCtrl*/, LPNMHDR pnmh, BOOL& _bHandled)
{
int result = CDRF_DODEFAULT;
NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pnmh);
switch (pLVCD->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
result = CDRF_NOTIFYITEMDRAW;
break;
case CDDS_ITEMPREPAINT:
result = CDRF_NOTIFYSUBITEMDRAW;
break;
case (CDDS_ITEMPREPAINT | CDDS_SUBITEM):
{
pLVCD->nmcd.uItemState &= ~(CDIS_SELECTED | CDIS_FOCUS);
int Offset = static_cast<int>(m_RegisterListViewCtrl.GetItemData((int)pLVCD->nmcd.dwItemSpec));
size_t Register = -1;
if (pLVCD->iSubItem == 1)
{
Register = Offset;
}
else if (pLVCD->iSubItem == 3)
{
Register = Offset + 16;
}
if (Register != -1)
{
if (m_CachedRegHasChanged[Register])
{
pLVCD->clrTextBk = RGB(0xFF, 192, 192);
}
else
{
pLVCD->clrTextBk = RGB(0xF0, 0xF0, 0xF0);
}
}
else
{
pLVCD->clrTextBk = RGB(192, 224, 192);
}
// uint16 CurrentAddress = static_cast<uint16>(m_DisAsmListViewCtrl.GetItemData((int)pLVCD->nmcd.dwItemSpec));
}
break;
}
return(result);
}

View File

@ -1,93 +1,93 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <stdio.h>
#include <stdlib.h>
#include "Common.h"
#include "Globals.h"
#include "gdsp_interpreter.h"
bool DumpDSPCode(uint32 _Address, uint32 _Length, uint32 crc)
{
char szFilename[MAX_PATH];
sprintf(szFilename, "c:\\_\\DSP_UC_%08X.bin", crc);
FILE* pFile = fopen(szFilename, "wb");
if (pFile != NULL)
{
fwrite(g_dspInitialize.pGetMemoryPointer(_Address), _Length, 1, pFile);
fclose(pFile);
return(true);
}
else
{
PanicAlert("Cant open file (%s) to dump UCode!!", szFilename);
}
return(false);
}
uint32 GenerateCRC(const unsigned char* _pBuffer, int _pLength)
{
unsigned long CRC = 0xFFFFFFFF;
while (_pLength--)
{
unsigned long Temp = (unsigned long)((CRC & 0xFF) ^ *_pBuffer++);
for (int j = 0; j < 8; j++)
{
if (Temp & 0x1)
{
Temp = (Temp >> 1) ^ 0xEDB88320;
}
else
{
Temp >>= 1;
}
}
CRC = (CRC >> 8) ^ Temp;
}
return(CRC ^ 0xFFFFFFFF);
}
bool DumpCWCode(uint32 _Address, uint32 _Length)
{
FILE* pFile = fopen("d:\\DSP_UCode.bin", "wb");
if (pFile != NULL)
{
for (size_t i = _Address; i < _Address + _Length; i++)
{
uint16 val = Common::swap16(g_dsp.iram[i]);
fprintf(pFile, " cw 0x%04x \n", val);
}
fclose(pFile);
return(true);
}
return(false);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <stdio.h>
#include <stdlib.h>
#include "Common.h"
#include "Globals.h"
#include "gdsp_interpreter.h"
bool DumpDSPCode(uint32 _Address, uint32 _Length, uint32 crc)
{
char szFilename[MAX_PATH];
sprintf(szFilename, "c:\\_\\DSP_UC_%08X.bin", crc);
FILE* pFile = fopen(szFilename, "wb");
if (pFile != NULL)
{
fwrite(g_dspInitialize.pGetMemoryPointer(_Address), _Length, 1, pFile);
fclose(pFile);
return(true);
}
else
{
PanicAlert("Cant open file (%s) to dump UCode!!", szFilename);
}
return(false);
}
uint32 GenerateCRC(const unsigned char* _pBuffer, int _pLength)
{
unsigned long CRC = 0xFFFFFFFF;
while (_pLength--)
{
unsigned long Temp = (unsigned long)((CRC & 0xFF) ^ *_pBuffer++);
for (int j = 0; j < 8; j++)
{
if (Temp & 0x1)
{
Temp = (Temp >> 1) ^ 0xEDB88320;
}
else
{
Temp >>= 1;
}
}
CRC = (CRC >> 8) ^ Temp;
}
return(CRC ^ 0xFFFFFFFF);
}
bool DumpCWCode(uint32 _Address, uint32 _Length)
{
FILE* pFile = fopen("d:\\DSP_UCode.bin", "wb");
if (pFile != NULL)
{
for (size_t i = _Address; i < _Address + _Length; i++)
{
uint16 val = Common::swap16(g_dsp.iram[i]);
fprintf(pFile, " cw 0x%04x \n", val);
}
fclose(pFile);
return(true);
}
return(false);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,113 +1,113 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Globals.h"
#include "gdsp_interface.h"
extern uint16 dsp_swap16(uint16 x);
// The hardware adpcm decoder :)
sint16 ADPCM_Step(uint32& _rSamplePos, uint32 _BaseAddress)
{
sint16* pCoefTable = (sint16*)&gdsp_ifx_regs[DSP_COEF_A1_0];
if (((_rSamplePos) & 15) == 0)
{
gdsp_ifx_regs[DSP_PRED_SCALE] = g_dspInitialize.pARAM_Read_U8((_rSamplePos & ~15) >> 1);
_rSamplePos += 2;
}
int scale = 1 << (gdsp_ifx_regs[DSP_PRED_SCALE] & 0xF);
int coef_idx = gdsp_ifx_regs[DSP_PRED_SCALE] >> 4;
sint32 coef1 = pCoefTable[coef_idx * 2 + 0];
sint32 coef2 = pCoefTable[coef_idx * 2 + 1];
int temp = (_rSamplePos & 1) ?
(g_dspInitialize.pARAM_Read_U8(_rSamplePos >> 1) & 0xF) :
(g_dspInitialize.pARAM_Read_U8(_rSamplePos >> 1) >> 4);
if (temp >= 8)
temp -= 16;
// 0x400 = 0.5 in 11-bit fixed point
int val = (scale * temp) + ((0x400 + coef1 * (sint16)gdsp_ifx_regs[DSP_YN1] + coef2 * (sint16)gdsp_ifx_regs[DSP_YN2]) >> 11);
// Clamp values.
if (val > 0x7FFF)
val = 0x7FFF;
else if (val < -0x7FFF)
val = -0x7FFF;
gdsp_ifx_regs[DSP_YN2] = gdsp_ifx_regs[DSP_YN1];
gdsp_ifx_regs[DSP_YN1] = val;
_rSamplePos++;
// The advanced interpolation (linear, polyphase,...) is done by the UCode, so we don't
// need to bother with it here.
return val;
}
extern void gdsp_generate_exception(uint8 level);
uint16 dsp_read_aram()
{
// uint32 BaseAddress = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL];
uint32 EndAddress = (gdsp_ifx_regs[DSP_ACEAH] << 16) | gdsp_ifx_regs[DSP_ACEAL];
uint32 Address = (gdsp_ifx_regs[DSP_ACCAH] << 16) | gdsp_ifx_regs[DSP_ACCAL];
uint16 val;
// lets the "hardware" decode
switch (gdsp_ifx_regs[DSP_FORMAT])
{
case 0x00:
val = ADPCM_Step(Address, EndAddress);
break;
case 0x0A:
val = (g_dspInitialize.pARAM_Read_U8(Address) << 8) | g_dspInitialize.pARAM_Read_U8(Address + 1);
gdsp_ifx_regs[DSP_YN2] = gdsp_ifx_regs[DSP_YN1];
gdsp_ifx_regs[DSP_YN1] = val;
Address += 2;
break;
default:
val = (g_dspInitialize.pARAM_Read_U8(Address) << 8) | g_dspInitialize.pARAM_Read_U8(Address + 1);
Address += 2;
ErrorLog("Unknown DSP Format %i", gdsp_ifx_regs[DSP_FORMAT]);
break;
}
// check for loop
if (Address > EndAddress)
{
Address = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL];
gdsp_generate_exception(3);
gdsp_generate_exception(5);
// Somehow, YN1 and YN2 must be initialized with their "loop" values, so yeah,
// it seems likely that we should raise an exception to let the DSP program do that,
// at least if DSP_FORMAT == 0x0A.
}
gdsp_ifx_regs[DSP_ACCAH] = Address >> 16;
gdsp_ifx_regs[DSP_ACCAL] = Address & 0xffff;
return(val);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Globals.h"
#include "gdsp_interface.h"
extern uint16 dsp_swap16(uint16 x);
// The hardware adpcm decoder :)
sint16 ADPCM_Step(uint32& _rSamplePos, uint32 _BaseAddress)
{
sint16* pCoefTable = (sint16*)&gdsp_ifx_regs[DSP_COEF_A1_0];
if (((_rSamplePos) & 15) == 0)
{
gdsp_ifx_regs[DSP_PRED_SCALE] = g_dspInitialize.pARAM_Read_U8((_rSamplePos & ~15) >> 1);
_rSamplePos += 2;
}
int scale = 1 << (gdsp_ifx_regs[DSP_PRED_SCALE] & 0xF);
int coef_idx = gdsp_ifx_regs[DSP_PRED_SCALE] >> 4;
sint32 coef1 = pCoefTable[coef_idx * 2 + 0];
sint32 coef2 = pCoefTable[coef_idx * 2 + 1];
int temp = (_rSamplePos & 1) ?
(g_dspInitialize.pARAM_Read_U8(_rSamplePos >> 1) & 0xF) :
(g_dspInitialize.pARAM_Read_U8(_rSamplePos >> 1) >> 4);
if (temp >= 8)
temp -= 16;
// 0x400 = 0.5 in 11-bit fixed point
int val = (scale * temp) + ((0x400 + coef1 * (sint16)gdsp_ifx_regs[DSP_YN1] + coef2 * (sint16)gdsp_ifx_regs[DSP_YN2]) >> 11);
// Clamp values.
if (val > 0x7FFF)
val = 0x7FFF;
else if (val < -0x7FFF)
val = -0x7FFF;
gdsp_ifx_regs[DSP_YN2] = gdsp_ifx_regs[DSP_YN1];
gdsp_ifx_regs[DSP_YN1] = val;
_rSamplePos++;
// The advanced interpolation (linear, polyphase,...) is done by the UCode, so we don't
// need to bother with it here.
return val;
}
extern void gdsp_generate_exception(uint8 level);
uint16 dsp_read_aram()
{
// uint32 BaseAddress = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL];
uint32 EndAddress = (gdsp_ifx_regs[DSP_ACEAH] << 16) | gdsp_ifx_regs[DSP_ACEAL];
uint32 Address = (gdsp_ifx_regs[DSP_ACCAH] << 16) | gdsp_ifx_regs[DSP_ACCAL];
uint16 val;
// lets the "hardware" decode
switch (gdsp_ifx_regs[DSP_FORMAT])
{
case 0x00:
val = ADPCM_Step(Address, EndAddress);
break;
case 0x0A:
val = (g_dspInitialize.pARAM_Read_U8(Address) << 8) | g_dspInitialize.pARAM_Read_U8(Address + 1);
gdsp_ifx_regs[DSP_YN2] = gdsp_ifx_regs[DSP_YN1];
gdsp_ifx_regs[DSP_YN1] = val;
Address += 2;
break;
default:
val = (g_dspInitialize.pARAM_Read_U8(Address) << 8) | g_dspInitialize.pARAM_Read_U8(Address + 1);
Address += 2;
ErrorLog("Unknown DSP Format %i", gdsp_ifx_regs[DSP_FORMAT]);
break;
}
// check for loop
if (Address > EndAddress)
{
Address = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL];
gdsp_generate_exception(3);
gdsp_generate_exception(5);
// Somehow, YN1 and YN2 must be initialized with their "loop" values, so yeah,
// it seems likely that we should raise an exception to let the DSP program do that,
// at least if DSP_FORMAT == 0x0A.
}
gdsp_ifx_regs[DSP_ACCAH] = Address >> 16;
gdsp_ifx_regs[DSP_ACCAL] = Address & 0xffff;
return(val);
}

View File

@ -1,284 +1,284 @@
/*====================================================================
filename: opcodes.h
project: GameCube DSP Tool (gcdsp)
created: 2005.03.04
mail: duddie@walla.com
Copyright (c) 2005 Duddie
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
//
//
// At the moment just ls and sl are using the prolog
// perhaps all actions on r03 must be in the prolog
//
#include "Globals.h"
#include "gdsp_opcodes_helper.h"
//
void dsp_op_ext_r_epi(uint16 _Opcode)
{
uint8 op = (_Opcode >> 2) & 0x3;
uint8 reg = _Opcode & 0x3;
switch (op)
{
case 0x00:
ErrorLog("dsp_op_ext_r_epi");
break;
case 0x01:
g_dsp.r[reg]--;
break;
case 0x02:
g_dsp.r[reg]++;
break;
case 0x03:
g_dsp.r[reg] += g_dsp.r[reg + 4];
break;
}
}
void dsp_op_ext_mv(uint16 _Opcode)
{
uint8 sreg = _Opcode & 0x3;
uint8 dreg = ((_Opcode >> 2) & 0x3);
g_dsp.r[dreg + 0x18] = g_dsp.r[sreg + 0x1c];
}
void dsp_op_ext_s(uint16 _Opcode)
{
uint8 dreg = _Opcode & 0x3;
uint8 sreg = ((_Opcode >> 3) & 0x3) + 0x1c;
dsp_dmem_write(g_dsp.r[dreg], g_dsp.r[sreg]);
if (_Opcode & 0x04)
{
g_dsp.r[dreg] += g_dsp.r[dreg + 4];
}
else
{
g_dsp.r[dreg]++;
}
}
void dsp_op_ext_l(uint16 _Opcode)
{
uint8 sreg = _Opcode & 0x3;
uint8 dreg = ((_Opcode >> 3) & 0x7) + 0x18;
uint16 val = dsp_dmem_read(g_dsp.r[sreg]);
g_dsp.r[dreg] = val;
if (_Opcode & 0x04)
{
g_dsp.r[sreg] += g_dsp.r[sreg + 4];
}
else
{
g_dsp.r[sreg]++;
}
}
void dsp_op_ext_ls_pro(uint16 _Opcode)
{
uint8 areg = (_Opcode & 0x1) + 0x1e;
dsp_dmem_write(g_dsp.r[0x03], g_dsp.r[areg]);
if (_Opcode & 0x8)
{
g_dsp.r[0x03] += g_dsp.r[0x07];
}
else
{
g_dsp.r[0x03]++;
}
}
void dsp_op_ext_ls_epi(uint16 _Opcode)
{
uint8 dreg = ((_Opcode >> 4) & 0x3) + 0x18;
uint16 val = dsp_dmem_read(g_dsp.r[0x00]);
dsp_op_write_reg(dreg, val);
if (_Opcode & 0x4)
{
g_dsp.r[0x00] += g_dsp.r[0x04];
}
else
{
g_dsp.r[0x00]++;
}
}
void dsp_op_ext_sl_pro(uint16 _Opcode)
{
uint8 areg = (_Opcode & 0x1) + 0x1e;
dsp_dmem_write(g_dsp.r[0x00], g_dsp.r[areg]);
if (_Opcode & 0x4)
{
g_dsp.r[0x00] += g_dsp.r[0x04];
}
else
{
g_dsp.r[0x00]++;
}
}
void dsp_op_ext_sl_epi(uint16 _Opcode)
{
uint8 dreg = ((_Opcode >> 4) & 0x3) + 0x18;
uint16 val = dsp_dmem_read(g_dsp.r[0x03]);
dsp_op_write_reg(dreg, val);
if (_Opcode & 0x8)
{
g_dsp.r[0x03] += g_dsp.r[0x07];
}
else
{
g_dsp.r[0x03]++;
}
}
void dsp_op_ext_ld(uint16 _Opcode)
{
uint8 dreg1 = (((_Opcode >> 5) & 0x1) << 1) + 0x18;
uint8 dreg2 = (((_Opcode >> 4) & 0x1) << 1) + 0x19;
uint8 sreg = _Opcode & 0x3;
g_dsp.r[dreg1] = dsp_dmem_read(g_dsp.r[sreg]);
g_dsp.r[dreg2] = dsp_dmem_read(g_dsp.r[0x03]);
if (_Opcode & 0x04)
{
g_dsp.r[sreg] += g_dsp.r[sreg + 0x04];
}
else
{
g_dsp.r[sreg]++;
}
if (_Opcode & 0x08)
{
g_dsp.r[0x03] += g_dsp.r[0x07];
}
else
{
g_dsp.r[0x03]++;
}
}
// ================================================================================
//
//
//
// ================================================================================
void dsp_op_ext_ops_pro(uint16 _Opcode)
{
if ((_Opcode & 0xFF) == 0){return;}
switch ((_Opcode >> 4) & 0xf)
{
case 0x00:
dsp_op_ext_r_epi(_Opcode);
break;
case 0x01:
dsp_op_ext_mv(_Opcode);
break;
case 0x02:
case 0x03:
dsp_op_ext_s(_Opcode);
break;
case 0x04:
case 0x05:
case 0x06:
case 0x07:
dsp_op_ext_l(_Opcode);
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
if (_Opcode & 0x2)
{
dsp_op_ext_sl_pro(_Opcode);
}
else
{
dsp_op_ext_ls_pro(_Opcode);
}
return;
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
dsp_op_ext_ld(_Opcode);
break;
}
}
void dsp_op_ext_ops_epi(uint16 _Opcode)
{
if ((_Opcode & 0xFF) == 0){return;}
switch ((_Opcode >> 4) & 0xf)
{
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
if (_Opcode & 0x2)
{
dsp_op_ext_sl_epi(_Opcode);
}
else
{
dsp_op_ext_ls_epi(_Opcode);
}
return;
}
}
/*====================================================================
filename: opcodes.h
project: GameCube DSP Tool (gcdsp)
created: 2005.03.04
mail: duddie@walla.com
Copyright (c) 2005 Duddie
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
//
//
// At the moment just ls and sl are using the prolog
// perhaps all actions on r03 must be in the prolog
//
#include "Globals.h"
#include "gdsp_opcodes_helper.h"
//
void dsp_op_ext_r_epi(uint16 _Opcode)
{
uint8 op = (_Opcode >> 2) & 0x3;
uint8 reg = _Opcode & 0x3;
switch (op)
{
case 0x00:
ErrorLog("dsp_op_ext_r_epi");
break;
case 0x01:
g_dsp.r[reg]--;
break;
case 0x02:
g_dsp.r[reg]++;
break;
case 0x03:
g_dsp.r[reg] += g_dsp.r[reg + 4];
break;
}
}
void dsp_op_ext_mv(uint16 _Opcode)
{
uint8 sreg = _Opcode & 0x3;
uint8 dreg = ((_Opcode >> 2) & 0x3);
g_dsp.r[dreg + 0x18] = g_dsp.r[sreg + 0x1c];
}
void dsp_op_ext_s(uint16 _Opcode)
{
uint8 dreg = _Opcode & 0x3;
uint8 sreg = ((_Opcode >> 3) & 0x3) + 0x1c;
dsp_dmem_write(g_dsp.r[dreg], g_dsp.r[sreg]);
if (_Opcode & 0x04)
{
g_dsp.r[dreg] += g_dsp.r[dreg + 4];
}
else
{
g_dsp.r[dreg]++;
}
}
void dsp_op_ext_l(uint16 _Opcode)
{
uint8 sreg = _Opcode & 0x3;
uint8 dreg = ((_Opcode >> 3) & 0x7) + 0x18;
uint16 val = dsp_dmem_read(g_dsp.r[sreg]);
g_dsp.r[dreg] = val;
if (_Opcode & 0x04)
{
g_dsp.r[sreg] += g_dsp.r[sreg + 4];
}
else
{
g_dsp.r[sreg]++;
}
}
void dsp_op_ext_ls_pro(uint16 _Opcode)
{
uint8 areg = (_Opcode & 0x1) + 0x1e;
dsp_dmem_write(g_dsp.r[0x03], g_dsp.r[areg]);
if (_Opcode & 0x8)
{
g_dsp.r[0x03] += g_dsp.r[0x07];
}
else
{
g_dsp.r[0x03]++;
}
}
void dsp_op_ext_ls_epi(uint16 _Opcode)
{
uint8 dreg = ((_Opcode >> 4) & 0x3) + 0x18;
uint16 val = dsp_dmem_read(g_dsp.r[0x00]);
dsp_op_write_reg(dreg, val);
if (_Opcode & 0x4)
{
g_dsp.r[0x00] += g_dsp.r[0x04];
}
else
{
g_dsp.r[0x00]++;
}
}
void dsp_op_ext_sl_pro(uint16 _Opcode)
{
uint8 areg = (_Opcode & 0x1) + 0x1e;
dsp_dmem_write(g_dsp.r[0x00], g_dsp.r[areg]);
if (_Opcode & 0x4)
{
g_dsp.r[0x00] += g_dsp.r[0x04];
}
else
{
g_dsp.r[0x00]++;
}
}
void dsp_op_ext_sl_epi(uint16 _Opcode)
{
uint8 dreg = ((_Opcode >> 4) & 0x3) + 0x18;
uint16 val = dsp_dmem_read(g_dsp.r[0x03]);
dsp_op_write_reg(dreg, val);
if (_Opcode & 0x8)
{
g_dsp.r[0x03] += g_dsp.r[0x07];
}
else
{
g_dsp.r[0x03]++;
}
}
void dsp_op_ext_ld(uint16 _Opcode)
{
uint8 dreg1 = (((_Opcode >> 5) & 0x1) << 1) + 0x18;
uint8 dreg2 = (((_Opcode >> 4) & 0x1) << 1) + 0x19;
uint8 sreg = _Opcode & 0x3;
g_dsp.r[dreg1] = dsp_dmem_read(g_dsp.r[sreg]);
g_dsp.r[dreg2] = dsp_dmem_read(g_dsp.r[0x03]);
if (_Opcode & 0x04)
{
g_dsp.r[sreg] += g_dsp.r[sreg + 0x04];
}
else
{
g_dsp.r[sreg]++;
}
if (_Opcode & 0x08)
{
g_dsp.r[0x03] += g_dsp.r[0x07];
}
else
{
g_dsp.r[0x03]++;
}
}
// ================================================================================
//
//
//
// ================================================================================
void dsp_op_ext_ops_pro(uint16 _Opcode)
{
if ((_Opcode & 0xFF) == 0){return;}
switch ((_Opcode >> 4) & 0xf)
{
case 0x00:
dsp_op_ext_r_epi(_Opcode);
break;
case 0x01:
dsp_op_ext_mv(_Opcode);
break;
case 0x02:
case 0x03:
dsp_op_ext_s(_Opcode);
break;
case 0x04:
case 0x05:
case 0x06:
case 0x07:
dsp_op_ext_l(_Opcode);
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
if (_Opcode & 0x2)
{
dsp_op_ext_sl_pro(_Opcode);
}
else
{
dsp_op_ext_ls_pro(_Opcode);
}
return;
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
dsp_op_ext_ld(_Opcode);
break;
}
}
void dsp_op_ext_ops_epi(uint16 _Opcode)
{
if ((_Opcode & 0xFF) == 0){return;}
switch ((_Opcode >> 4) & 0xf)
{
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
if (_Opcode & 0x2)
{
dsp_op_ext_sl_epi(_Opcode);
}
else
{
dsp_op_ext_ls_epi(_Opcode);
}
return;
}
}

View File

@ -1,357 +1,357 @@
/*====================================================================
filename: gdsp_interface.h
project: GCemu
created: 2004-6-18
mail: duddie@walla.com
Copyright (c) 2005 Duddie & Tratax
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
#include <stdlib.h>
#include "Globals.h"
#include "Thread.h"
#include "gdsp_aram.h"
#include "gdsp_interpreter.h"
#include "gdsp_interface.h"
#include "Tools.h"
#ifndef NULL
#define NULL 0
#endif
#ifndef _WIN32
#undef WITH_DSP_ON_THREAD
//TODO FIX
#endif
const char* reg_names[] =
{
// a0
"COEF_A1_0", "COEF_A2_0", "COEF_A1_1", "COEF_A2_1", "COEF_A1_2", "COEF_A2_2", "COEF_A1_3", "COEF_A2_3",
"COEF_A1_4", "COEF_A2_4", "COEF_A1_5", "COEF_A2_5", "COEF_A1_6", "COEF_A2_6", "COEF_A1_7", "COEF_A2_7",
// b0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
// c0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, "DSCR", NULL, "DSBL", NULL, "DSPA", "DSMAH", "DSMAL",
// d0
NULL, "SampleFormat", NULL, NULL, "ACSAH", "ACSAL", "ACEAH", "ACEAL",
"ACCAH", "ACCAL", "PRED_SCALE", "YN1", "YN2", "ARAM", "GAIN", NULL,
// e0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, "AMDM",
// f0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, "DMBH", "DMBL", "CMBH", "CMBL",
};
void gdsp_dma();
#ifdef WITH_DSP_ON_THREAD
Common::CriticalSection g_CriticalSection;
#endif
static volatile uint16 gdsp_mbox[2][2];
uint16 gdsp_ifx_regs[256];
void gdsp_ifx_init()
{
int i;
for (i = 0; i < 256; i++)
{
gdsp_ifx_regs[i] = 0;
}
gdsp_mbox[0][0] = 0;
gdsp_mbox[0][1] = 0;
gdsp_mbox[1][0] = 0;
gdsp_mbox[1][1] = 0;
}
uint32 gdsp_mbox_peek(uint8 mbx)
{
#if WITH_DSP_ON_THREAD
g_CriticalSection.Enter();
#endif
uint32 value = ((gdsp_mbox[mbx][0] << 16) | gdsp_mbox[mbx][1]);
#if WITH_DSP_ON_THREAD
g_CriticalSection.Leave();
#endif
return value;
}
void gdsp_mbox_write_h(uint8 mbx, uint16 val)
{
#if WITH_DSP_ON_THREAD
g_CriticalSection.Enter();
#endif
gdsp_mbox[mbx][0] = val & 0x7fff;
#if WITH_DSP_ON_THREAD
g_CriticalSection.Leave();
#endif
}
void gdsp_mbox_write_l(uint8 mbx, uint16 val)
{
#if WITH_DSP_ON_THREAD
g_CriticalSection.Enter();
#endif
gdsp_mbox[mbx][1] = val;
gdsp_mbox[mbx][0] |= 0x8000;
#if WITH_DSP_ON_THREAD
g_CriticalSection.Leave();
#endif
if (mbx == GDSP_MBOX_DSP)
{
DebugLog("- Write DSP Mail: 0x%08x (pc=0x%04x)\n", gdsp_mbox_peek(GDSP_MBOX_DSP), g_dsp.err_pc);
}
}
uint16 gdsp_mbox_read_h(uint8 mbx)
{
return (gdsp_mbox[mbx][0]);
}
uint16 gdsp_mbox_read_l(uint8 mbx)
{
uint16 val;
#if WITH_DSP_ON_THREAD
g_CriticalSection.Enter();
#endif
val = gdsp_mbox[mbx][1];
gdsp_mbox[mbx][0] &= ~0x8000;
#if WITH_DSP_ON_THREAD
g_CriticalSection.Leave();
#endif
return(val);
}
void gdsp_ifx_write(uint16 addr, uint16 val)
{
addr &= 0xff;
switch (addr & 0xff)
{
case 0xfb: // DIRQ
if (val & 0x1)
{
g_dsp.irq_request();
}
break;
case 0xfc: // DMBH
gdsp_mbox_write_h(GDSP_MBOX_DSP, val);
break;
case 0xfd: // DMBL
gdsp_mbox_write_l(GDSP_MBOX_DSP, val);
break;
case 0xcb: // DSBL
gdsp_ifx_regs[addr] = val;
gdsp_dma();
gdsp_ifx_regs[DSP_DSCR] &= ~0x0004;
break;
case 0xcd:
case 0xce:
case 0xcf:
case 0xc9:
gdsp_ifx_regs[addr] = val;
break;
default:
/* if ((addr & 0xff) >= 0xa0 && reg_names[addr - 0xa0])
DebugLog("%04x MW %s (%04x)\n", g_dsp.pc, reg_names[addr - 0xa0], val);
else
DebugLog("%04x MW %04x (%04x)\n", g_dsp.pc, addr, val);*/
gdsp_ifx_regs[addr] = val;
break;
}
}
uint16 gdsp_ifx_read(uint16 addr)
{
uint16 val;
addr &= 0xff;
switch (addr & 0xff)
{
case 0xfc: // DMBH
val = gdsp_mbox_read_h(GDSP_MBOX_DSP);
break;
case 0xfe: // CMBH
val = gdsp_mbox_read_h(GDSP_MBOX_CPU);
break;
case 0xff: // CMBL
val = gdsp_mbox_read_l(GDSP_MBOX_CPU);
break;
case 0xc9:
val = gdsp_ifx_regs[addr];
break;
case 0xdd:
val = dsp_read_aram();
break;
default:
val = gdsp_ifx_regs[addr];
/* if ((addr & 0xff) >= 0xc0 && reg_names[addr & 0x3f])
printf("%04x MR %s (%04x)\n", g_dsp.pc, reg_names[addr & 0x3f], val);
else
printf("%04x MR %04x (%04x)\n", g_dsp.pc, addr, val);*/
break;
}
return(val);
}
void gdsp_idma_in(uint16 dsp_addr, uint32 addr, uint32 size)
{
uint8* dst = ((uint8*)g_dsp.iram);
for (uint32 i = 0; i < size; i += 2)
{
*(uint16*)&dst[dsp_addr + i] = *(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x0fffffff];
}
g_dsp.iram_crc = GenerateCRC(g_dsp.cpu_ram + (addr & 0x0fffffff), size);
DebugLog("*** Copy new UCode from 0x%08x to 0x%04x (crc: %8x)\n", addr, dsp_addr, g_dsp.iram_crc);
#if DUMP_DSP_IMEM
DumpDSPCode(addr, size, g_dsp.iram_crc );
#endif
}
void gdsp_idma_out(uint16 dsp_addr, uint32 addr, uint32 size)
{
ErrorLog("*** idma_out IRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)\n", dsp_addr / 2, addr, size);
}
void gdsp_ddma_in(uint16 dsp_addr, uint32 addr, uint32 size)
{
if ((addr & 0x7FFFFFFF) > 0x01FFFFFF)
{
ErrorLog("*** ddma_in read from invalid addr (0x%08x)\n", addr);
return;
}
uint8* dst = ((uint8*)g_dsp.dram);
for (uint32 i = 0; i < size; i += 2)
{
*(uint16*)&dst[dsp_addr + i] = *(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF];
}
DebugLog("*** ddma_in RAM (0x%08x) -> DRAM_DSP (0x%04x) : size (0x%08x)\n", addr, dsp_addr / 2, size);
}
void gdsp_ddma_out(uint16 dsp_addr, uint32 addr, uint32 size)
{
if ((addr & 0x7FFFFFFF) > 0x01FFFFFF)
{
ErrorLog("*** gdsp_ddma_out to invalid addr (0x%08x)\n", addr);
return;
}
uint8* src = ((uint8*)g_dsp.dram);
for (uint32 i = 0; i < size; i += 2)
{
*(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF] = *(uint16*)&src[dsp_addr + i];
}
DebugLog("*** ddma_out DRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)\n", dsp_addr / 2, addr, size);
}
#define DSP_CR_IMEM (2)
#define DSP_CR_DMEM (0)
#define DSP_CR_TO_CPU (1)
#define DSP_CR_FROM_CPU (0)
void gdsp_dma()
{
uint16 ctl;
uint32 addr;
uint16 dsp_addr;
uint16 len;
addr = (gdsp_ifx_regs[DSP_DSMAH] << 16) | gdsp_ifx_regs[DSP_DSMAL];
ctl = gdsp_ifx_regs[DSP_DSCR];
dsp_addr = gdsp_ifx_regs[DSP_DSPA] * 2;
len = gdsp_ifx_regs[DSP_DSBL];
if ((ctl > 3) || (len > 0x4000))
{
ErrorLog("DMA ERROR pc: %04x ctl: %04x addr: %08x da: %04x size: %04x\n", g_dsp.pc, ctl, addr, dsp_addr, len);
exit(0);
}
switch (ctl & 0x3)
{
case (DSP_CR_DMEM | DSP_CR_TO_CPU):
gdsp_ddma_out(dsp_addr, addr, len);
break;
case (DSP_CR_DMEM | DSP_CR_FROM_CPU):
gdsp_ddma_in(dsp_addr, addr, len);
break;
case (DSP_CR_IMEM | DSP_CR_TO_CPU):
gdsp_idma_out(dsp_addr, addr, len);
break;
case (DSP_CR_IMEM | DSP_CR_FROM_CPU):
gdsp_idma_in(dsp_addr, addr, len);
break;
}
}
/*====================================================================
filename: gdsp_interface.h
project: GCemu
created: 2004-6-18
mail: duddie@walla.com
Copyright (c) 2005 Duddie & Tratax
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
#include <stdlib.h>
#include "Globals.h"
#include "Thread.h"
#include "gdsp_aram.h"
#include "gdsp_interpreter.h"
#include "gdsp_interface.h"
#include "Tools.h"
#ifndef NULL
#define NULL 0
#endif
#ifndef _WIN32
#undef WITH_DSP_ON_THREAD
//TODO FIX
#endif
const char* reg_names[] =
{
// a0
"COEF_A1_0", "COEF_A2_0", "COEF_A1_1", "COEF_A2_1", "COEF_A1_2", "COEF_A2_2", "COEF_A1_3", "COEF_A2_3",
"COEF_A1_4", "COEF_A2_4", "COEF_A1_5", "COEF_A2_5", "COEF_A1_6", "COEF_A2_6", "COEF_A1_7", "COEF_A2_7",
// b0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
// c0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, "DSCR", NULL, "DSBL", NULL, "DSPA", "DSMAH", "DSMAL",
// d0
NULL, "SampleFormat", NULL, NULL, "ACSAH", "ACSAL", "ACEAH", "ACEAL",
"ACCAH", "ACCAL", "PRED_SCALE", "YN1", "YN2", "ARAM", "GAIN", NULL,
// e0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, "AMDM",
// f0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, "DMBH", "DMBL", "CMBH", "CMBL",
};
void gdsp_dma();
#ifdef WITH_DSP_ON_THREAD
Common::CriticalSection g_CriticalSection;
#endif
static volatile uint16 gdsp_mbox[2][2];
uint16 gdsp_ifx_regs[256];
void gdsp_ifx_init()
{
int i;
for (i = 0; i < 256; i++)
{
gdsp_ifx_regs[i] = 0;
}
gdsp_mbox[0][0] = 0;
gdsp_mbox[0][1] = 0;
gdsp_mbox[1][0] = 0;
gdsp_mbox[1][1] = 0;
}
uint32 gdsp_mbox_peek(uint8 mbx)
{
#if WITH_DSP_ON_THREAD
g_CriticalSection.Enter();
#endif
uint32 value = ((gdsp_mbox[mbx][0] << 16) | gdsp_mbox[mbx][1]);
#if WITH_DSP_ON_THREAD
g_CriticalSection.Leave();
#endif
return value;
}
void gdsp_mbox_write_h(uint8 mbx, uint16 val)
{
#if WITH_DSP_ON_THREAD
g_CriticalSection.Enter();
#endif
gdsp_mbox[mbx][0] = val & 0x7fff;
#if WITH_DSP_ON_THREAD
g_CriticalSection.Leave();
#endif
}
void gdsp_mbox_write_l(uint8 mbx, uint16 val)
{
#if WITH_DSP_ON_THREAD
g_CriticalSection.Enter();
#endif
gdsp_mbox[mbx][1] = val;
gdsp_mbox[mbx][0] |= 0x8000;
#if WITH_DSP_ON_THREAD
g_CriticalSection.Leave();
#endif
if (mbx == GDSP_MBOX_DSP)
{
DebugLog("- Write DSP Mail: 0x%08x (pc=0x%04x)\n", gdsp_mbox_peek(GDSP_MBOX_DSP), g_dsp.err_pc);
}
}
uint16 gdsp_mbox_read_h(uint8 mbx)
{
return (gdsp_mbox[mbx][0]);
}
uint16 gdsp_mbox_read_l(uint8 mbx)
{
uint16 val;
#if WITH_DSP_ON_THREAD
g_CriticalSection.Enter();
#endif
val = gdsp_mbox[mbx][1];
gdsp_mbox[mbx][0] &= ~0x8000;
#if WITH_DSP_ON_THREAD
g_CriticalSection.Leave();
#endif
return(val);
}
void gdsp_ifx_write(uint16 addr, uint16 val)
{
addr &= 0xff;
switch (addr & 0xff)
{
case 0xfb: // DIRQ
if (val & 0x1)
{
g_dsp.irq_request();
}
break;
case 0xfc: // DMBH
gdsp_mbox_write_h(GDSP_MBOX_DSP, val);
break;
case 0xfd: // DMBL
gdsp_mbox_write_l(GDSP_MBOX_DSP, val);
break;
case 0xcb: // DSBL
gdsp_ifx_regs[addr] = val;
gdsp_dma();
gdsp_ifx_regs[DSP_DSCR] &= ~0x0004;
break;
case 0xcd:
case 0xce:
case 0xcf:
case 0xc9:
gdsp_ifx_regs[addr] = val;
break;
default:
/* if ((addr & 0xff) >= 0xa0 && reg_names[addr - 0xa0])
DebugLog("%04x MW %s (%04x)\n", g_dsp.pc, reg_names[addr - 0xa0], val);
else
DebugLog("%04x MW %04x (%04x)\n", g_dsp.pc, addr, val);*/
gdsp_ifx_regs[addr] = val;
break;
}
}
uint16 gdsp_ifx_read(uint16 addr)
{
uint16 val;
addr &= 0xff;
switch (addr & 0xff)
{
case 0xfc: // DMBH
val = gdsp_mbox_read_h(GDSP_MBOX_DSP);
break;
case 0xfe: // CMBH
val = gdsp_mbox_read_h(GDSP_MBOX_CPU);
break;
case 0xff: // CMBL
val = gdsp_mbox_read_l(GDSP_MBOX_CPU);
break;
case 0xc9:
val = gdsp_ifx_regs[addr];
break;
case 0xdd:
val = dsp_read_aram();
break;
default:
val = gdsp_ifx_regs[addr];
/* if ((addr & 0xff) >= 0xc0 && reg_names[addr & 0x3f])
printf("%04x MR %s (%04x)\n", g_dsp.pc, reg_names[addr & 0x3f], val);
else
printf("%04x MR %04x (%04x)\n", g_dsp.pc, addr, val);*/
break;
}
return(val);
}
void gdsp_idma_in(uint16 dsp_addr, uint32 addr, uint32 size)
{
uint8* dst = ((uint8*)g_dsp.iram);
for (uint32 i = 0; i < size; i += 2)
{
*(uint16*)&dst[dsp_addr + i] = *(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x0fffffff];
}
g_dsp.iram_crc = GenerateCRC(g_dsp.cpu_ram + (addr & 0x0fffffff), size);
DebugLog("*** Copy new UCode from 0x%08x to 0x%04x (crc: %8x)\n", addr, dsp_addr, g_dsp.iram_crc);
#if DUMP_DSP_IMEM
DumpDSPCode(addr, size, g_dsp.iram_crc );
#endif
}
void gdsp_idma_out(uint16 dsp_addr, uint32 addr, uint32 size)
{
ErrorLog("*** idma_out IRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)\n", dsp_addr / 2, addr, size);
}
void gdsp_ddma_in(uint16 dsp_addr, uint32 addr, uint32 size)
{
if ((addr & 0x7FFFFFFF) > 0x01FFFFFF)
{
ErrorLog("*** ddma_in read from invalid addr (0x%08x)\n", addr);
return;
}
uint8* dst = ((uint8*)g_dsp.dram);
for (uint32 i = 0; i < size; i += 2)
{
*(uint16*)&dst[dsp_addr + i] = *(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF];
}
DebugLog("*** ddma_in RAM (0x%08x) -> DRAM_DSP (0x%04x) : size (0x%08x)\n", addr, dsp_addr / 2, size);
}
void gdsp_ddma_out(uint16 dsp_addr, uint32 addr, uint32 size)
{
if ((addr & 0x7FFFFFFF) > 0x01FFFFFF)
{
ErrorLog("*** gdsp_ddma_out to invalid addr (0x%08x)\n", addr);
return;
}
uint8* src = ((uint8*)g_dsp.dram);
for (uint32 i = 0; i < size; i += 2)
{
*(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF] = *(uint16*)&src[dsp_addr + i];
}
DebugLog("*** ddma_out DRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)\n", dsp_addr / 2, addr, size);
}
#define DSP_CR_IMEM (2)
#define DSP_CR_DMEM (0)
#define DSP_CR_TO_CPU (1)
#define DSP_CR_FROM_CPU (0)
void gdsp_dma()
{
uint16 ctl;
uint32 addr;
uint16 dsp_addr;
uint16 len;
addr = (gdsp_ifx_regs[DSP_DSMAH] << 16) | gdsp_ifx_regs[DSP_DSMAL];
ctl = gdsp_ifx_regs[DSP_DSCR];
dsp_addr = gdsp_ifx_regs[DSP_DSPA] * 2;
len = gdsp_ifx_regs[DSP_DSBL];
if ((ctl > 3) || (len > 0x4000))
{
ErrorLog("DMA ERROR pc: %04x ctl: %04x addr: %08x da: %04x size: %04x\n", g_dsp.pc, ctl, addr, dsp_addr, len);
exit(0);
}
switch (ctl & 0x3)
{
case (DSP_CR_DMEM | DSP_CR_TO_CPU):
gdsp_ddma_out(dsp_addr, addr, len);
break;
case (DSP_CR_DMEM | DSP_CR_FROM_CPU):
gdsp_ddma_in(dsp_addr, addr, len);
break;
case (DSP_CR_IMEM | DSP_CR_TO_CPU):
gdsp_idma_out(dsp_addr, addr, len);
break;
case (DSP_CR_IMEM | DSP_CR_FROM_CPU):
gdsp_idma_in(dsp_addr, addr, len);
break;
}
}

View File

@ -1,444 +1,444 @@
/*====================================================================
filename: gdsp_interpreter.cpp
project: GCemu
created: 2004-6-18
mail: duddie@walla.com
Copyright (c) 2005 Duddie & Tratax
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include "gdsp_interface.h"
#include "gdsp_opcodes_helper.h"
#include "Tools.h"
//-------------------------------------------------------------------------------
SDSP g_dsp;
uint16 SDSP::r[32];
uint16 SDSP::pc = 0;
uint16 SDSP::err_pc = 0;
uint16* SDSP::iram = 0;
uint16* SDSP::dram = 0;
uint16* SDSP::irom = 0;
uint16* SDSP::drom = 0;
uint16* SDSP::coef = 0;
uint8* SDSP::cpu_ram = 0;
uint16 SDSP::cr = 0;
uint8 SDSP::reg_stack_ptr[4];
// lets make stack depth to 32 for now
uint16 SDSP::reg_stack[4][DSP_STACK_DEPTH];
void (*SDSP::irq_request)() = NULL;
bool SDSP::exception_in_progress_hack = false;
// for debugger only
uint32 SDSP::iram_crc = 0;
uint64 SDSP::step_counter = 0;
//-------------------------------------------------------------------------------
static bool CR_HALT = true;
static bool CR_EXTERNAL_INT = false;
void UpdateCachedCR()
{
CR_HALT = (g_dsp.cr & 0x4) != 0;
CR_EXTERNAL_INT = (g_dsp.cr & 0x02) != 0;
}
//-------------------------------------------------------------------------------
void (*dsp_op[])(uint16 opc) =
{
dsp_op0, dsp_op1, dsp_op2, dsp_op3,
dsp_op4, dsp_op5, dsp_op6, dsp_op7,
dsp_op8, dsp_op9, dsp_opab, dsp_opab,
dsp_opcd, dsp_opcd, dsp_ope, dsp_opf,
};
void dbg_error(char* err_msg)
{
return;
}
void gdsp_init()
{
g_dsp.irom = (uint16*)malloc(DSP_IROM_SIZE * sizeof(uint16));
g_dsp.iram = (uint16*)malloc(DSP_IRAM_SIZE * sizeof(uint16));
g_dsp.drom = (uint16*)malloc(DSP_DROM_SIZE * sizeof(uint16));
g_dsp.dram = (uint16*)malloc(DSP_DRAM_SIZE * sizeof(uint16));
g_dsp.coef = (uint16*)malloc(DSP_COEF_SIZE * sizeof(uint16));
for (int i = 0; i < DSP_IRAM_SIZE; i++)
{
g_dsp.iram[i] = 0x0021; // HALT opcode
}
for (int i = 0; i < DSP_DRAM_SIZE; i++)
{
g_dsp.dram[i] = 0x0021; // HALT opcode
}
for (int i = 0; i < 32; i++)
{
g_dsp.r[i] = 0;
}
for (int i = 0; i < 4; i++)
{
g_dsp.reg_stack_ptr[i] = 0;
for (int j = 0; j < DSP_STACK_DEPTH; j++)
{
g_dsp.reg_stack[i][j] = 0;
}
}
// copied from a real console after the custom UCode has been loaded
g_dsp.r[0x08] = 0xffff;
g_dsp.r[0x09] = 0xffff;
g_dsp.r[0x0a] = 0xffff;
g_dsp.r[0x0b] = 0xffff;
g_dsp.cr = 0x804;
gdsp_ifx_init();
UpdateCachedCR();
}
void gdsp_reset()
{
// _assert_msg_(0, "gdsp_reset()");
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
g_dsp.pc = DSP_RESET_VECTOR;
g_dsp.exception_in_progress_hack = false;
}
uint8 gdsp_exceptions = 0;
void gdsp_generate_exception(uint8 level)
{
gdsp_exceptions |= 1 << level;
}
bool gdsp_load_rom(char* fname)
{
FILE* pFile = fopen(fname, "rb");
if (pFile)
{
fread(g_dsp.irom, 1, DSP_IRAM_SIZE, pFile);
fclose(pFile);
return(true);
}
return(false);
}
bool gdsp_load_coef(char* fname)
{
FILE* pFile = fopen(fname, "rb");
if (pFile)
{
fread(g_dsp.coef, 1, DSP_COEF_SIZE, pFile);
fclose(pFile);
return(true);
}
return(false);
}
void gdsp_write_cr(uint16 val)
{
// reset
if (val & 0x0001)
{
gdsp_reset();
}
val &= ~0x0001;
// update cr
g_dsp.cr = val;
UpdateCachedCR();
}
uint16 gdsp_read_cr()
{
if (g_dsp.pc & 0x8000)
{
g_dsp.cr |= 0x800;
}
else
{
g_dsp.cr &= ~0x800;
}
UpdateCachedCR();
return(g_dsp.cr);
}
// special loop step.. because exception in loop or loopi fails
// dunno how we have to fix it
// atm we execute this instructions directly inside the loop command
// so it cant be interrupted by an exception
void gdsp_loop_step()
{
g_dsp.err_pc = g_dsp.pc;
uint16 opc = dsp_fetch_code();
dsp_op[opc >> 12](opc);
}
u16 HLE_ROM_80E7_81F8();
void hacks();
void gdsp_step()
{
g_dsp.step_counter++;
if (g_dsp.pc == 0x80e7)
{
//g_dsp.pc = HLE_ROM_80E7_81F8();
}
g_dsp.err_pc = g_dsp.pc;
#if PROFILE
ProfilerAddDelta(g_dsp.err_pc, 1);
if (g_dsp.step_counter == 1)
{
ProfilerInit();
}
if ((g_dsp.step_counter & 0xFFFFF) == 0)
{
ProfilerDump(g_dsp.step_counter);
}
#endif
uint16 opc = dsp_fetch_code();
dsp_op[opc >> 12](opc);
uint16& rLoopCounter = g_dsp.r[DSP_REG_ST0 + 3];
if (rLoopCounter > 0)
{
const uint16& rCallAddress = g_dsp.r[DSP_REG_ST0 + 0];
const uint16& rLoopAddress = g_dsp.r[DSP_REG_ST0 + 2];
if (g_dsp.pc == (rLoopAddress + 1))
{
rLoopCounter--;
if (rLoopCounter > 0)
{
g_dsp.pc = rCallAddress;
}
else
{
// end of loop
dsp_reg_load_stack(0);
dsp_reg_load_stack(2);
dsp_reg_load_stack(3);
}
}
}
// check if there is an external interrupt
if (CR_EXTERNAL_INT)
{
if (dsp_SR_is_flag_set(FLAG_ENABLE_INTERUPT) && (g_dsp.exception_in_progress_hack == false))
{
// level 7 is the interrupt exception
gdsp_generate_exception(7);
g_dsp.cr &= ~0x0002;
UpdateCachedCR();
}
}
// check exceptions
if ((gdsp_exceptions > 0) && (!g_dsp.exception_in_progress_hack))
{
for (uint8 i=0; i<8; i++)
{
if (gdsp_exceptions & (1<<i))
{
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
dsp_reg_store_stack(DSP_STACK_D, g_dsp.r[R_SR]);
g_dsp.pc = i * 2;
gdsp_exceptions &= ~(1<<i);
g_dsp.exception_in_progress_hack = true;
break;
}
}
}
}
bool gdsp_running;
extern volatile uint32 dsp_running;
bool gdsp_run()
{
gdsp_running = true;
while (!CR_HALT)
{
gdsp_step();
}
gdsp_running = false;
return(true);
}
bool gdsp_runx(uint16 cnt)
{
gdsp_running = true;
while (!(g_dsp.cr & 0x4) && gdsp_running)
{
gdsp_step();
cnt--;
if (cnt == 0)
{
break;
}
}
gdsp_running = false;
return(true);
}
void gdsp_stop()
{
gdsp_running = false;
}
///////////////////////////////////////////////////////////////////////////////
//
// From fires for fires :)
//
//
#include "disassemble.h"
#include "WaveFile.h"
#include "Mixer.h"
uint16 r30 = 0, r31 = 0;
void PanicAlert(const char* text, ...);
extern WaveFileWriter g_wave_writer;
extern uint16 dsp_swap16(uint16 x);
void Hacks()
{
// if (g_wave_writer.GetAudioSize() > 1024*1024*1)
/* if (g_dsp.pc == 0x165)
{
PanicAlert("Opcode_06");
}
if (g_dsp.pc == 0x43b)
{
PanicAlert("Opcode_14");
}
if (g_dsp.pc == 0xb37)
{
PanicAlert("Opcode_08");
}*/
/* if (g_dsp.pc == 0x1bc)
{
r30 = g_dsp.r[30];
r31 = g_dsp.r[31];
}
else if (g_dsp.pc == 0x384)
{
// if ((r30 == 0x1bc) && (r31 == 0xaff))
{
//PanicAlert("%x, %x", r30, r31);
const int numSamples = 0x280;
static short Buffer[numSamples];
uint16 bufferAddr = 0x280; //dsp_dmem_read(0xe44);
for (int i=0; i<numSamples; i++)
{
Buffer[i] = dsp_dmem_read(bufferAddr+i);
}
g_wave_writer.AddStereoSamples(Buffer, numSamples/2); // 2 channels
if (g_wave_writer.GetAudioSize() > 1024*1024*2)
{
//PanicAlert("%x", bufferAddr);
g_wave_writer.Stop();
exit(1);
}
}
} */
if (g_dsp.pc == 0x468)
{
int numSamples = g_dsp.r[25] / 2;
uint16 bufferAddr = g_dsp.r[27];
// PanicAlert("%x %x", bufferAddr, numSamples);
short samples[1024];
for (int i=0; i<numSamples; i++)
{
samples[i] = dsp_dmem_read(bufferAddr+i);
}
Mixer_PushSamples(samples, numSamples / 2, 32000); //sample_rate);
g_wave_writer.AddStereoSamples(samples, numSamples/2); // 2 channels
if (g_wave_writer.GetAudioSize() > 1024*1024*2)
{
//PanicAlert("%x", bufferAddr);
g_wave_writer.Stop();
exit(1);
}
}
}
/*====================================================================
filename: gdsp_interpreter.cpp
project: GCemu
created: 2004-6-18
mail: duddie@walla.com
Copyright (c) 2005 Duddie & Tratax
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include "gdsp_interface.h"
#include "gdsp_opcodes_helper.h"
#include "Tools.h"
//-------------------------------------------------------------------------------
SDSP g_dsp;
uint16 SDSP::r[32];
uint16 SDSP::pc = 0;
uint16 SDSP::err_pc = 0;
uint16* SDSP::iram = 0;
uint16* SDSP::dram = 0;
uint16* SDSP::irom = 0;
uint16* SDSP::drom = 0;
uint16* SDSP::coef = 0;
uint8* SDSP::cpu_ram = 0;
uint16 SDSP::cr = 0;
uint8 SDSP::reg_stack_ptr[4];
// lets make stack depth to 32 for now
uint16 SDSP::reg_stack[4][DSP_STACK_DEPTH];
void (*SDSP::irq_request)() = NULL;
bool SDSP::exception_in_progress_hack = false;
// for debugger only
uint32 SDSP::iram_crc = 0;
uint64 SDSP::step_counter = 0;
//-------------------------------------------------------------------------------
static bool CR_HALT = true;
static bool CR_EXTERNAL_INT = false;
void UpdateCachedCR()
{
CR_HALT = (g_dsp.cr & 0x4) != 0;
CR_EXTERNAL_INT = (g_dsp.cr & 0x02) != 0;
}
//-------------------------------------------------------------------------------
void (*dsp_op[])(uint16 opc) =
{
dsp_op0, dsp_op1, dsp_op2, dsp_op3,
dsp_op4, dsp_op5, dsp_op6, dsp_op7,
dsp_op8, dsp_op9, dsp_opab, dsp_opab,
dsp_opcd, dsp_opcd, dsp_ope, dsp_opf,
};
void dbg_error(char* err_msg)
{
return;
}
void gdsp_init()
{
g_dsp.irom = (uint16*)malloc(DSP_IROM_SIZE * sizeof(uint16));
g_dsp.iram = (uint16*)malloc(DSP_IRAM_SIZE * sizeof(uint16));
g_dsp.drom = (uint16*)malloc(DSP_DROM_SIZE * sizeof(uint16));
g_dsp.dram = (uint16*)malloc(DSP_DRAM_SIZE * sizeof(uint16));
g_dsp.coef = (uint16*)malloc(DSP_COEF_SIZE * sizeof(uint16));
for (int i = 0; i < DSP_IRAM_SIZE; i++)
{
g_dsp.iram[i] = 0x0021; // HALT opcode
}
for (int i = 0; i < DSP_DRAM_SIZE; i++)
{
g_dsp.dram[i] = 0x0021; // HALT opcode
}
for (int i = 0; i < 32; i++)
{
g_dsp.r[i] = 0;
}
for (int i = 0; i < 4; i++)
{
g_dsp.reg_stack_ptr[i] = 0;
for (int j = 0; j < DSP_STACK_DEPTH; j++)
{
g_dsp.reg_stack[i][j] = 0;
}
}
// copied from a real console after the custom UCode has been loaded
g_dsp.r[0x08] = 0xffff;
g_dsp.r[0x09] = 0xffff;
g_dsp.r[0x0a] = 0xffff;
g_dsp.r[0x0b] = 0xffff;
g_dsp.cr = 0x804;
gdsp_ifx_init();
UpdateCachedCR();
}
void gdsp_reset()
{
// _assert_msg_(0, "gdsp_reset()");
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
g_dsp.pc = DSP_RESET_VECTOR;
g_dsp.exception_in_progress_hack = false;
}
uint8 gdsp_exceptions = 0;
void gdsp_generate_exception(uint8 level)
{
gdsp_exceptions |= 1 << level;
}
bool gdsp_load_rom(char* fname)
{
FILE* pFile = fopen(fname, "rb");
if (pFile)
{
fread(g_dsp.irom, 1, DSP_IRAM_SIZE, pFile);
fclose(pFile);
return(true);
}
return(false);
}
bool gdsp_load_coef(char* fname)
{
FILE* pFile = fopen(fname, "rb");
if (pFile)
{
fread(g_dsp.coef, 1, DSP_COEF_SIZE, pFile);
fclose(pFile);
return(true);
}
return(false);
}
void gdsp_write_cr(uint16 val)
{
// reset
if (val & 0x0001)
{
gdsp_reset();
}
val &= ~0x0001;
// update cr
g_dsp.cr = val;
UpdateCachedCR();
}
uint16 gdsp_read_cr()
{
if (g_dsp.pc & 0x8000)
{
g_dsp.cr |= 0x800;
}
else
{
g_dsp.cr &= ~0x800;
}
UpdateCachedCR();
return(g_dsp.cr);
}
// special loop step.. because exception in loop or loopi fails
// dunno how we have to fix it
// atm we execute this instructions directly inside the loop command
// so it cant be interrupted by an exception
void gdsp_loop_step()
{
g_dsp.err_pc = g_dsp.pc;
uint16 opc = dsp_fetch_code();
dsp_op[opc >> 12](opc);
}
u16 HLE_ROM_80E7_81F8();
void hacks();
void gdsp_step()
{
g_dsp.step_counter++;
if (g_dsp.pc == 0x80e7)
{
//g_dsp.pc = HLE_ROM_80E7_81F8();
}
g_dsp.err_pc = g_dsp.pc;
#if PROFILE
ProfilerAddDelta(g_dsp.err_pc, 1);
if (g_dsp.step_counter == 1)
{
ProfilerInit();
}
if ((g_dsp.step_counter & 0xFFFFF) == 0)
{
ProfilerDump(g_dsp.step_counter);
}
#endif
uint16 opc = dsp_fetch_code();
dsp_op[opc >> 12](opc);
uint16& rLoopCounter = g_dsp.r[DSP_REG_ST0 + 3];
if (rLoopCounter > 0)
{
const uint16& rCallAddress = g_dsp.r[DSP_REG_ST0 + 0];
const uint16& rLoopAddress = g_dsp.r[DSP_REG_ST0 + 2];
if (g_dsp.pc == (rLoopAddress + 1))
{
rLoopCounter--;
if (rLoopCounter > 0)
{
g_dsp.pc = rCallAddress;
}
else
{
// end of loop
dsp_reg_load_stack(0);
dsp_reg_load_stack(2);
dsp_reg_load_stack(3);
}
}
}
// check if there is an external interrupt
if (CR_EXTERNAL_INT)
{
if (dsp_SR_is_flag_set(FLAG_ENABLE_INTERUPT) && (g_dsp.exception_in_progress_hack == false))
{
// level 7 is the interrupt exception
gdsp_generate_exception(7);
g_dsp.cr &= ~0x0002;
UpdateCachedCR();
}
}
// check exceptions
if ((gdsp_exceptions > 0) && (!g_dsp.exception_in_progress_hack))
{
for (uint8 i=0; i<8; i++)
{
if (gdsp_exceptions & (1<<i))
{
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
dsp_reg_store_stack(DSP_STACK_D, g_dsp.r[R_SR]);
g_dsp.pc = i * 2;
gdsp_exceptions &= ~(1<<i);
g_dsp.exception_in_progress_hack = true;
break;
}
}
}
}
bool gdsp_running;
extern volatile uint32 dsp_running;
bool gdsp_run()
{
gdsp_running = true;
while (!CR_HALT)
{
gdsp_step();
}
gdsp_running = false;
return(true);
}
bool gdsp_runx(uint16 cnt)
{
gdsp_running = true;
while (!(g_dsp.cr & 0x4) && gdsp_running)
{
gdsp_step();
cnt--;
if (cnt == 0)
{
break;
}
}
gdsp_running = false;
return(true);
}
void gdsp_stop()
{
gdsp_running = false;
}
///////////////////////////////////////////////////////////////////////////////
//
// From fires for fires :)
//
//
#include "disassemble.h"
#include "WaveFile.h"
#include "Mixer.h"
uint16 r30 = 0, r31 = 0;
void PanicAlert(const char* text, ...);
extern WaveFileWriter g_wave_writer;
extern uint16 dsp_swap16(uint16 x);
void Hacks()
{
// if (g_wave_writer.GetAudioSize() > 1024*1024*1)
/* if (g_dsp.pc == 0x165)
{
PanicAlert("Opcode_06");
}
if (g_dsp.pc == 0x43b)
{
PanicAlert("Opcode_14");
}
if (g_dsp.pc == 0xb37)
{
PanicAlert("Opcode_08");
}*/
/* if (g_dsp.pc == 0x1bc)
{
r30 = g_dsp.r[30];
r31 = g_dsp.r[31];
}
else if (g_dsp.pc == 0x384)
{
// if ((r30 == 0x1bc) && (r31 == 0xaff))
{
//PanicAlert("%x, %x", r30, r31);
const int numSamples = 0x280;
static short Buffer[numSamples];
uint16 bufferAddr = 0x280; //dsp_dmem_read(0xe44);
for (int i=0; i<numSamples; i++)
{
Buffer[i] = dsp_dmem_read(bufferAddr+i);
}
g_wave_writer.AddStereoSamples(Buffer, numSamples/2); // 2 channels
if (g_wave_writer.GetAudioSize() > 1024*1024*2)
{
//PanicAlert("%x", bufferAddr);
g_wave_writer.Stop();
exit(1);
}
}
} */
if (g_dsp.pc == 0x468)
{
int numSamples = g_dsp.r[25] / 2;
uint16 bufferAddr = g_dsp.r[27];
// PanicAlert("%x %x", bufferAddr, numSamples);
short samples[1024];
for (int i=0; i<numSamples; i++)
{
samples[i] = dsp_dmem_read(bufferAddr+i);
}
Mixer_PushSamples(samples, numSamples / 2, 32000); //sample_rate);
g_wave_writer.AddStereoSamples(samples, numSamples/2); // 2 channels
if (g_wave_writer.GetAudioSize() > 1024*1024*2)
{
//PanicAlert("%x", bufferAddr);
g_wave_writer.Stop();
exit(1);
}
}
}

View File

@ -1,156 +1,156 @@
/*====================================================================
filename: gdsp_memory.cpp
project: GCemu
created: 2004-6-18
mail: duddie@walla.com
Copyright (c) 2005 Duddie & Tratax
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
#include <stdio.h>
#include "Globals.h"
#include "gdsp_interpreter.h"
#include "gdsp_memory.h"
#include "gdsp_ifx.h"
uint16 dsp_swap16(uint16 x)
{
return((x >> 8) | (x << 8));
}
uint16* gdsp_get_iram(void)
{
return(g_dsp.iram);
}
uint16* gdsp_get_irom(void)
{
return(g_dsp.irom);
}
uint16* gdsp_get_dram(void)
{
return(g_dsp.dram);
}
uint16* gdsp_get_drom(void)
{
return(g_dsp.drom);
}
uint16 dsp_imem_read(uint16 addr)
{
uint16 opc;
if (g_dsp.pc & 0x8000)
{
opc = g_dsp.irom[addr & DSP_IROM_MASK];
}
else
{
opc = g_dsp.iram[addr & DSP_IRAM_MASK];
}
return(dsp_swap16(opc));
}
uint16 dsp_dmem_read(uint16 addr)
{
uint16 val;
switch (addr >> 12)
{
case 0x0: // 0xxx DRAM
val = g_dsp.dram[addr & DSP_DRAM_MASK];
val = dsp_swap16(val);
break;
case 0x8: // 8xxx DROM
DebugLog("someone reads from ROM\n");
val = g_dsp.drom[addr & DSP_DROM_MASK];
val = dsp_swap16(val);
break;
case 0x1: // 1xxx COEF
val = g_dsp.coef[addr & DSP_DROM_MASK];
val = dsp_swap16(val);
break;
case 0xf: // Fxxx HW regs
val = gdsp_ifx_read(addr);
break;
default: // error
// ErrorLog("%04x DSP ERROR: Read from UNKNOWN (%04x) memory\n", g_dsp.pc, addr);
val = 0;
break;
}
return(val);
}
bool dsp_dmem_write(uint16 addr, uint16 val)
{
switch (addr >> 12)
{
case 0x8: // 8xxx DROM
DebugLog("someone writes to ROM\n");
/* val = dsp_swap16(val);
g_dsp.drom[addr & DSP_DROM_MASK] = val;*/
break;
case 0xf: // Fxxx HW regs
gdsp_ifx_write(addr, val);
break;
case 0x0: // 0xxx DRAM
val = dsp_swap16(val);
g_dsp.dram[addr & DSP_DRAM_MASK] = val;
break;
default: // error
DebugLog("%04x DSP ERROR: Write to UNKNOWN (%04x) memory\n", g_dsp.pc, addr);
break;
}
return(true);
}
uint16 dsp_fetch_code(void)
{
uint16 opc = dsp_imem_read(g_dsp.pc);
g_dsp.pc++;
return(opc);
}
uint16 dsp_peek_code(void)
{
return(dsp_imem_read(g_dsp.pc));
}
/*====================================================================
filename: gdsp_memory.cpp
project: GCemu
created: 2004-6-18
mail: duddie@walla.com
Copyright (c) 2005 Duddie & Tratax
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
#include <stdio.h>
#include "Globals.h"
#include "gdsp_interpreter.h"
#include "gdsp_memory.h"
#include "gdsp_ifx.h"
uint16 dsp_swap16(uint16 x)
{
return((x >> 8) | (x << 8));
}
uint16* gdsp_get_iram(void)
{
return(g_dsp.iram);
}
uint16* gdsp_get_irom(void)
{
return(g_dsp.irom);
}
uint16* gdsp_get_dram(void)
{
return(g_dsp.dram);
}
uint16* gdsp_get_drom(void)
{
return(g_dsp.drom);
}
uint16 dsp_imem_read(uint16 addr)
{
uint16 opc;
if (g_dsp.pc & 0x8000)
{
opc = g_dsp.irom[addr & DSP_IROM_MASK];
}
else
{
opc = g_dsp.iram[addr & DSP_IRAM_MASK];
}
return(dsp_swap16(opc));
}
uint16 dsp_dmem_read(uint16 addr)
{
uint16 val;
switch (addr >> 12)
{
case 0x0: // 0xxx DRAM
val = g_dsp.dram[addr & DSP_DRAM_MASK];
val = dsp_swap16(val);
break;
case 0x8: // 8xxx DROM
DebugLog("someone reads from ROM\n");
val = g_dsp.drom[addr & DSP_DROM_MASK];
val = dsp_swap16(val);
break;
case 0x1: // 1xxx COEF
val = g_dsp.coef[addr & DSP_DROM_MASK];
val = dsp_swap16(val);
break;
case 0xf: // Fxxx HW regs
val = gdsp_ifx_read(addr);
break;
default: // error
// ErrorLog("%04x DSP ERROR: Read from UNKNOWN (%04x) memory\n", g_dsp.pc, addr);
val = 0;
break;
}
return(val);
}
bool dsp_dmem_write(uint16 addr, uint16 val)
{
switch (addr >> 12)
{
case 0x8: // 8xxx DROM
DebugLog("someone writes to ROM\n");
/* val = dsp_swap16(val);
g_dsp.drom[addr & DSP_DROM_MASK] = val;*/
break;
case 0xf: // Fxxx HW regs
gdsp_ifx_write(addr, val);
break;
case 0x0: // 0xxx DRAM
val = dsp_swap16(val);
g_dsp.dram[addr & DSP_DRAM_MASK] = val;
break;
default: // error
DebugLog("%04x DSP ERROR: Write to UNKNOWN (%04x) memory\n", g_dsp.pc, addr);
break;
}
return(true);
}
uint16 dsp_fetch_code(void)
{
uint16 opc = dsp_imem_read(g_dsp.pc);
g_dsp.pc++;
return(opc);
}
uint16 dsp_peek_code(void)
{
return(dsp_imem_read(g_dsp.pc));
}

File diff suppressed because it is too large Load Diff

View File

@ -1,62 +1,62 @@
/*====================================================================
filename: gdsp_registers.cpp
project: GCemu
created: 2004-6-18
mail: duddie@walla.com
Copyright (c) 2005 Duddie & Tratax
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
#include "Globals.h"
#include "gdsp_registers.h"
#include "gdsp_interpreter.h"
void dsp_reg_stack_push(uint8 stack_reg)
{
g_dsp.reg_stack_ptr[stack_reg]++;
g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK;
g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]] = g_dsp.r[DSP_REG_ST0 + stack_reg];
}
void dsp_reg_stack_pop(uint8 stack_reg)
{
g_dsp.r[DSP_REG_ST0 + stack_reg] = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]];
g_dsp.reg_stack_ptr[stack_reg]--;
g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK;
}
void dsp_reg_store_stack(uint8 stack_reg, uint16 val)
{
dsp_reg_stack_push(stack_reg);
g_dsp.r[DSP_REG_ST0 + stack_reg] = val;
}
uint16 dsp_reg_load_stack(uint8 stack_reg)
{
uint16 val = g_dsp.r[DSP_REG_ST0 + stack_reg];
dsp_reg_stack_pop(stack_reg);
return(val);
}
/*====================================================================
filename: gdsp_registers.cpp
project: GCemu
created: 2004-6-18
mail: duddie@walla.com
Copyright (c) 2005 Duddie & Tratax
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
#include "Globals.h"
#include "gdsp_registers.h"
#include "gdsp_interpreter.h"
void dsp_reg_stack_push(uint8 stack_reg)
{
g_dsp.reg_stack_ptr[stack_reg]++;
g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK;
g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]] = g_dsp.r[DSP_REG_ST0 + stack_reg];
}
void dsp_reg_stack_pop(uint8 stack_reg)
{
g_dsp.r[DSP_REG_ST0 + stack_reg] = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]];
g_dsp.reg_stack_ptr[stack_reg]--;
g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK;
}
void dsp_reg_store_stack(uint8 stack_reg, uint16 val)
{
dsp_reg_stack_push(stack_reg);
g_dsp.r[DSP_REG_ST0 + stack_reg] = val;
}
uint16 dsp_reg_load_stack(uint8 stack_reg)
{
uint16 val = g_dsp.r[DSP_REG_ST0 + stack_reg];
dsp_reg_stack_pop(stack_reg);
return(val);
}

View File

@ -1,432 +1,432 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "Globals.h"
#include "WaveFile.h"
#include "CommonTypes.h"
#include "Mixer.h"
#include "gdsp_interpreter.h"
#include "gdsp_interface.h"
#include "disassemble.h"
#ifdef _WIN32
#include "DisAsmDlg.h"
#include "DSoundStream.h"
#include "Logging/Console.h" // For wprintf, ClearScreen
#include "Logging/Logging.h" // For Logging
HINSTANCE g_hInstance = NULL;
HANDLE g_hDSPThread = NULL;
CRITICAL_SECTION g_CriticalSection;
CDisAsmDlg g_Dialog;
#else
#define WINAPI
#define LPVOID void*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "AOSoundStream.h"
pthread_t g_hDSPThread = NULL;
#endif
#include "ChunkFile.h"
// =======================================================================================
// Globals
// --------------
DSPInitialize g_dspInitialize;
#define GDSP_MBOX_CPU 0
#define GDSP_MBOX_DSP 1
uint32 g_LastDMAAddress = 0;
uint32 g_LastDMASize = 0;
extern u32 m_addressPBs;
bool AXTask(u32& _uMail);
bool bCanWork = false;
// Set this if you want to log audio. search for log_ai in this file to see the filename.
static bool log_ai = false;
WaveFileWriter g_wave_writer;
// ==============
#ifdef _WIN32
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
DWORD dwReason, // reason called
LPVOID lpvReserved) // reserved
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
default:
break;
}
g_hInstance = hinstDLL;
return(TRUE);
}
#endif
void GetDllInfo(PLUGIN_INFO* _PluginInfo)
{
_PluginInfo->Version = 0x0100;
_PluginInfo->Type = PLUGIN_TYPE_DSP;
#ifdef DEBUGFAST
sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin (DebugFast)");
#else
#ifndef _DEBUG
sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin");
#else
sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin (Debug)");
#endif
#endif
}
void DllAbout(HWND _hParent)
{}
void DllConfig(HWND _hParent)
{}
void DSP_DoState(unsigned char **ptr, int mode) {
PointerWrap p(ptr, mode);
}
void DllDebugger(HWND _hParent, bool Show)
{
#ifdef _WIN32
#if defined (_DEBUG) || defined (DEBUGFAST)
g_Dialog.Create(NULL); //_hParent);
g_Dialog.ShowWindow(SW_SHOW);
MoveWindow(g_Dialog.m_hWnd, 450,0, 780,530, true);
// Open the console window
startConsoleWin(155, 100, "Sound Debugging"); // give room for 100 rows
wprintf("DllDebugger > Console opened\n");
// TODO: Make this adjustable from the Debugging window
MoveWindow(GetConsoleHwnd(), 0,400, 1280,500, true);
#else
MessageBox(0, "Can't open debugging window in Release build of this plugin.", "DSP LLE", 0);
#endif
#endif
}
// =======================================================================================
// Regular thread
// --------------
#ifdef _WIN32
DWORD WINAPI dsp_thread(LPVOID lpParameter)
#else
void* dsp_thread(void* lpParameter)
#endif
{
while (1)
{
if (!gdsp_run())
{
ErrorLog("*** DSP: CRITICAL ERROR ***\n");
//return 0;
exit(0);
}
}
}
// ==============
// =======================================================================================
// Debug thread
// --------------
#ifdef _WIN32
DWORD WINAPI dsp_thread_debug(LPVOID lpParameter)
#else
void* dsp_thread_debug(void* lpParameter)
#endif
{
//if (g_hDSPThread)
//{
// return NULL; // enable this to disable the plugin
//}
#ifdef _WIN32
while (1)
{
Logging(); // logging
if (g_Dialog.CanDoStep())
{
gdsp_runx(1);
}
else
{
Sleep(100);
}
}
#endif
return NULL;
}
// ==============
void DSP_DebugBreak()
{
#ifdef _WIN32
#if defined(_DEBUG) || defined(DEBUGFAST)
g_Dialog.DebugBreak();
#endif
#endif
}
void dspi_req_dsp_irq()
{
g_dspInitialize.pGenerateDSPInterrupt();
}
void DSP_Initialize(DSPInitialize _dspInitialize)
{
bCanWork = true;
g_dspInitialize = _dspInitialize;
gdsp_init();
g_dsp.step_counter = 0;
g_dsp.cpu_ram = g_dspInitialize.pGetMemoryPointer(0);
g_dsp.irq_request = dspi_req_dsp_irq;
gdsp_reset();
if (!gdsp_load_rom((char *)DSP_ROM_FILE))
{
bCanWork = false;
PanicAlert("No DSP ROM");
ErrorLog("Cannot load DSP ROM\n");
}
if (!gdsp_load_coef((char *)DSP_COEF_FILE))
{
bCanWork = false;
PanicAlert("No DSP COEF");
ErrorLog("Cannot load DSP COEF\n");
}
if(!bCanWork)
return; // TODO: Don't let it work
// ---------------------------------------------------------------------------------------
// First create DSP_UCode.bin by setting "#define DUMP_DSP_IMEM 1" in Globals.h. Then
// make the disassembled file here.
// --------------
// Dump UCode to file...
FILE* t = fopen("C:\\_\\DSP_UC_09CD143F.txt", "wb");
if (t != NULL)
{
gd_globals_t gdg;
gd_dis_file(&gdg, (char *)"C:\\_\\DSP_UC_09CD143F.bin", t);
fclose(t);
}
// --------------
#ifdef _WIN32
#if defined(_DEBUG) || defined(DEBUGFAST)
g_hDSPThread = CreateThread(NULL, 0, dsp_thread_debug, 0, 0, NULL);
#else
g_hDSPThread = CreateThread(NULL, 0, dsp_thread, 0, 0, NULL);
#endif // DEBUG
#else
#if _DEBUG
pthread_create(&g_hDSPThread, NULL, dsp_thread_debug, (void *)NULL);
#else
pthread_create(&g_hDSPThread, NULL, dsp_thread, (void *)NULL);
#endif // DEBUG
#endif // WIN32
if (log_ai) {
g_wave_writer.Start("C:\\_\\ai_log.wav");
g_wave_writer.SetSkipSilence(false);
}
#ifdef _WIN32
InitializeCriticalSection(&g_CriticalSection);
DSound::DSound_StartSound((HWND)g_dspInitialize.hWnd, 48000, Mixer);
#else
AOSound::AOSound_StartSound(48000, Mixer);
#endif
}
void DSP_Shutdown(void)
{
if (log_ai)
g_wave_writer.Stop();
#ifdef _WIN32
if (g_hDSPThread != NULL)
{
TerminateThread(g_hDSPThread, 0);
}
#else
pthread_cancel(g_hDSPThread);
#endif
}
u16 DSP_WriteControlRegister(u16 _uFlag)
{
gdsp_write_cr(_uFlag);
return(gdsp_read_cr());
}
u16 DSP_ReadControlRegister()
{
return(gdsp_read_cr());
}
u16 DSP_ReadMailboxHigh(bool _CPUMailbox)
{
if (_CPUMailbox)
{
return(gdsp_mbox_read_h(GDSP_MBOX_CPU));
}
else
{
return(gdsp_mbox_read_h(GDSP_MBOX_DSP));
}
}
u16 DSP_ReadMailboxLow(bool _CPUMailbox)
{
if (_CPUMailbox)
{
return(gdsp_mbox_read_l(GDSP_MBOX_CPU));
}
else
{
return(gdsp_mbox_read_l(GDSP_MBOX_DSP));
}
}
void DSP_WriteMailboxHigh(bool _CPUMailbox, u16 _uHighMail)
{
if (_CPUMailbox)
{
if (gdsp_mbox_peek(GDSP_MBOX_CPU) & 0x80000000)
{
ErrorLog("Mailbox isnt empty ... strange");
}
#if PROFILE
if ((_uHighMail) == 0xBABE)
{
ProfilerStart();
}
#endif
gdsp_mbox_write_h(GDSP_MBOX_CPU, _uHighMail);
}
else
{
ErrorLog("CPU cant write to DSP mailbox");
}
}
void DSP_WriteMailboxLow(bool _CPUMailbox, u16 _uLowMail)
{
if (_CPUMailbox)
{
gdsp_mbox_write_l(GDSP_MBOX_CPU, _uLowMail);
u32 uAddress = gdsp_mbox_peek(GDSP_MBOX_CPU);
u16 errpc = g_dsp.err_pc;
DebugLog("Write CPU Mail: 0x%08x (pc=0x%04x)\n", uAddress, errpc);
// ---------------------------------------------------------------------------------------
// I couldn't find any better way to detect the AX mails so this had to do. Please feel free
// to change it.
// --------------
if ((errpc == 0x0054 || errpc == 0x0055) && m_addressPBs == 0)
{
DebugLog("AXTask ======== 0x%08x (pc=0x%04x)", uAddress, errpc);
AXTask(uAddress);
}
}
else
{
ErrorLog("CPU cant write to DSP mailbox");
}
}
void DSP_Update(int cycles)
{
if (g_hDSPThread)
{
return;
}
#ifdef _WIN32
if (g_Dialog.CanDoStep())
{
gdsp_runx(100); // cycles
}
#endif
}
void DSP_SendAIBuffer(unsigned int address, int sample_rate)
{
short samples[16] = {0}; // interleaved stereo
if (address) {
for (int i = 0; i < 16; i++) {
samples[i] = Memory_Read_U16(address + i * 2);
}
if (log_ai)
g_wave_writer.AddStereoSamples(samples, 8);
}
Mixer_PushSamples(samples, 32 / 4, sample_rate);
static int counter = 0;
counter++;
#ifdef _WIN32
if ((counter & 255) == 0)
DSound::DSound_UpdateSound();
#endif
}
void __Log(int, const char *fmt, ...)
{
//DebugLog(fmt);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "Globals.h"
#include "WaveFile.h"
#include "CommonTypes.h"
#include "Mixer.h"
#include "gdsp_interpreter.h"
#include "gdsp_interface.h"
#include "disassemble.h"
#ifdef _WIN32
#include "DisAsmDlg.h"
#include "DSoundStream.h"
#include "Logging/Console.h" // For wprintf, ClearScreen
#include "Logging/Logging.h" // For Logging
HINSTANCE g_hInstance = NULL;
HANDLE g_hDSPThread = NULL;
CRITICAL_SECTION g_CriticalSection;
CDisAsmDlg g_Dialog;
#else
#define WINAPI
#define LPVOID void*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "AOSoundStream.h"
pthread_t g_hDSPThread = NULL;
#endif
#include "ChunkFile.h"
// =======================================================================================
// Globals
// --------------
DSPInitialize g_dspInitialize;
#define GDSP_MBOX_CPU 0
#define GDSP_MBOX_DSP 1
uint32 g_LastDMAAddress = 0;
uint32 g_LastDMASize = 0;
extern u32 m_addressPBs;
bool AXTask(u32& _uMail);
bool bCanWork = false;
// Set this if you want to log audio. search for log_ai in this file to see the filename.
static bool log_ai = false;
WaveFileWriter g_wave_writer;
// ==============
#ifdef _WIN32
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
DWORD dwReason, // reason called
LPVOID lpvReserved) // reserved
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
default:
break;
}
g_hInstance = hinstDLL;
return(TRUE);
}
#endif
void GetDllInfo(PLUGIN_INFO* _PluginInfo)
{
_PluginInfo->Version = 0x0100;
_PluginInfo->Type = PLUGIN_TYPE_DSP;
#ifdef DEBUGFAST
sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin (DebugFast)");
#else
#ifndef _DEBUG
sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin");
#else
sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin (Debug)");
#endif
#endif
}
void DllAbout(HWND _hParent)
{}
void DllConfig(HWND _hParent)
{}
void DSP_DoState(unsigned char **ptr, int mode) {
PointerWrap p(ptr, mode);
}
void DllDebugger(HWND _hParent, bool Show)
{
#ifdef _WIN32
#if defined (_DEBUG) || defined (DEBUGFAST)
g_Dialog.Create(NULL); //_hParent);
g_Dialog.ShowWindow(SW_SHOW);
MoveWindow(g_Dialog.m_hWnd, 450,0, 780,530, true);
// Open the console window
startConsoleWin(155, 100, "Sound Debugging"); // give room for 100 rows
wprintf("DllDebugger > Console opened\n");
// TODO: Make this adjustable from the Debugging window
MoveWindow(GetConsoleHwnd(), 0,400, 1280,500, true);
#else
MessageBox(0, "Can't open debugging window in Release build of this plugin.", "DSP LLE", 0);
#endif
#endif
}
// =======================================================================================
// Regular thread
// --------------
#ifdef _WIN32
DWORD WINAPI dsp_thread(LPVOID lpParameter)
#else
void* dsp_thread(void* lpParameter)
#endif
{
while (1)
{
if (!gdsp_run())
{
ErrorLog("*** DSP: CRITICAL ERROR ***\n");
//return 0;
exit(0);
}
}
}
// ==============
// =======================================================================================
// Debug thread
// --------------
#ifdef _WIN32
DWORD WINAPI dsp_thread_debug(LPVOID lpParameter)
#else
void* dsp_thread_debug(void* lpParameter)
#endif
{
//if (g_hDSPThread)
//{
// return NULL; // enable this to disable the plugin
//}
#ifdef _WIN32
while (1)
{
Logging(); // logging
if (g_Dialog.CanDoStep())
{
gdsp_runx(1);
}
else
{
Sleep(100);
}
}
#endif
return NULL;
}
// ==============
void DSP_DebugBreak()
{
#ifdef _WIN32
#if defined(_DEBUG) || defined(DEBUGFAST)
g_Dialog.DebugBreak();
#endif
#endif
}
void dspi_req_dsp_irq()
{
g_dspInitialize.pGenerateDSPInterrupt();
}
void DSP_Initialize(DSPInitialize _dspInitialize)
{
bCanWork = true;
g_dspInitialize = _dspInitialize;
gdsp_init();
g_dsp.step_counter = 0;
g_dsp.cpu_ram = g_dspInitialize.pGetMemoryPointer(0);
g_dsp.irq_request = dspi_req_dsp_irq;
gdsp_reset();
if (!gdsp_load_rom((char *)DSP_ROM_FILE))
{
bCanWork = false;
PanicAlert("No DSP ROM");
ErrorLog("Cannot load DSP ROM\n");
}
if (!gdsp_load_coef((char *)DSP_COEF_FILE))
{
bCanWork = false;
PanicAlert("No DSP COEF");
ErrorLog("Cannot load DSP COEF\n");
}
if(!bCanWork)
return; // TODO: Don't let it work
// ---------------------------------------------------------------------------------------
// First create DSP_UCode.bin by setting "#define DUMP_DSP_IMEM 1" in Globals.h. Then
// make the disassembled file here.
// --------------
// Dump UCode to file...
FILE* t = fopen("C:\\_\\DSP_UC_09CD143F.txt", "wb");
if (t != NULL)
{
gd_globals_t gdg;
gd_dis_file(&gdg, (char *)"C:\\_\\DSP_UC_09CD143F.bin", t);
fclose(t);
}
// --------------
#ifdef _WIN32
#if defined(_DEBUG) || defined(DEBUGFAST)
g_hDSPThread = CreateThread(NULL, 0, dsp_thread_debug, 0, 0, NULL);
#else
g_hDSPThread = CreateThread(NULL, 0, dsp_thread, 0, 0, NULL);
#endif // DEBUG
#else
#if _DEBUG
pthread_create(&g_hDSPThread, NULL, dsp_thread_debug, (void *)NULL);
#else
pthread_create(&g_hDSPThread, NULL, dsp_thread, (void *)NULL);
#endif // DEBUG
#endif // WIN32
if (log_ai) {
g_wave_writer.Start("C:\\_\\ai_log.wav");
g_wave_writer.SetSkipSilence(false);
}
#ifdef _WIN32
InitializeCriticalSection(&g_CriticalSection);
DSound::DSound_StartSound((HWND)g_dspInitialize.hWnd, 48000, Mixer);
#else
AOSound::AOSound_StartSound(48000, Mixer);
#endif
}
void DSP_Shutdown(void)
{
if (log_ai)
g_wave_writer.Stop();
#ifdef _WIN32
if (g_hDSPThread != NULL)
{
TerminateThread(g_hDSPThread, 0);
}
#else
pthread_cancel(g_hDSPThread);
#endif
}
u16 DSP_WriteControlRegister(u16 _uFlag)
{
gdsp_write_cr(_uFlag);
return(gdsp_read_cr());
}
u16 DSP_ReadControlRegister()
{
return(gdsp_read_cr());
}
u16 DSP_ReadMailboxHigh(bool _CPUMailbox)
{
if (_CPUMailbox)
{
return(gdsp_mbox_read_h(GDSP_MBOX_CPU));
}
else
{
return(gdsp_mbox_read_h(GDSP_MBOX_DSP));
}
}
u16 DSP_ReadMailboxLow(bool _CPUMailbox)
{
if (_CPUMailbox)
{
return(gdsp_mbox_read_l(GDSP_MBOX_CPU));
}
else
{
return(gdsp_mbox_read_l(GDSP_MBOX_DSP));
}
}
void DSP_WriteMailboxHigh(bool _CPUMailbox, u16 _uHighMail)
{
if (_CPUMailbox)
{
if (gdsp_mbox_peek(GDSP_MBOX_CPU) & 0x80000000)
{
ErrorLog("Mailbox isnt empty ... strange");
}
#if PROFILE
if ((_uHighMail) == 0xBABE)
{
ProfilerStart();
}
#endif
gdsp_mbox_write_h(GDSP_MBOX_CPU, _uHighMail);
}
else
{
ErrorLog("CPU cant write to DSP mailbox");
}
}
void DSP_WriteMailboxLow(bool _CPUMailbox, u16 _uLowMail)
{
if (_CPUMailbox)
{
gdsp_mbox_write_l(GDSP_MBOX_CPU, _uLowMail);
u32 uAddress = gdsp_mbox_peek(GDSP_MBOX_CPU);
u16 errpc = g_dsp.err_pc;
DebugLog("Write CPU Mail: 0x%08x (pc=0x%04x)\n", uAddress, errpc);
// ---------------------------------------------------------------------------------------
// I couldn't find any better way to detect the AX mails so this had to do. Please feel free
// to change it.
// --------------
if ((errpc == 0x0054 || errpc == 0x0055) && m_addressPBs == 0)
{
DebugLog("AXTask ======== 0x%08x (pc=0x%04x)", uAddress, errpc);
AXTask(uAddress);
}
}
else
{
ErrorLog("CPU cant write to DSP mailbox");
}
}
void DSP_Update(int cycles)
{
if (g_hDSPThread)
{
return;
}
#ifdef _WIN32
if (g_Dialog.CanDoStep())
{
gdsp_runx(100); // cycles
}
#endif
}
void DSP_SendAIBuffer(unsigned int address, int sample_rate)
{
short samples[16] = {0}; // interleaved stereo
if (address) {
for (int i = 0; i < 16; i++) {
samples[i] = Memory_Read_U16(address + i * 2);
}
if (log_ai)
g_wave_writer.AddStereoSamples(samples, 8);
}
Mixer_PushSamples(samples, 32 / 4, sample_rate);
static int counter = 0;
counter++;
#ifdef _WIN32
if ((counter & 255) == 0)
DSound::DSound_UpdateSound();
#endif
}
void __Log(int, const char *fmt, ...)
{
//DebugLog(fmt);
}

View File

@ -1,237 +1,237 @@
/*====================================================================
filename: opcodes.cpp
project: GameCube DSP Tool (gcdsp)
created: 2005.03.04
mail: duddie@walla.com
Copyright (c) 2005 Duddie
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
#include "Globals.h"
#include "opcodes.h"
opc_t opcodes[] =
{
{"NOP", 0x0000, 0xffff, 1, 0, {},},
{"HALT", 0x0021, 0xffff, 1, 0, {},},
{"RET", 0x02df, 0xffff, 1, 0, {},},
{"RETEQ", 0x02d5, 0xffff, 1, 0, {},},
{"RETNZ", 0x02dd, 0xffff, 1, 0, {},},
{"RTI", 0x02ff, 0xffff, 1, 0, {},},
{"CALL", 0x02bf, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"CALLNE", 0x02b4, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"IF_0", 0x0270, 0xffff, 1, 0, {},},
{"IF_1", 0x0271, 0xffff, 1, 0, {},},
{"IF_2", 0x0272, 0xffff, 1, 0, {},},
{"IF_3", 0x0273, 0xffff, 1, 0, {},},
{"IF_E", 0x0274, 0xffff, 1, 0, {},},
{"IF_Q", 0x0275, 0xffff, 1, 0, {},},
{"IF_R", 0x027c, 0xffff, 1, 0, {},},
{"IF_Z", 0x027d, 0xffff, 1, 0, {},},
{"IF_P", 0x027f, 0xffff, 1, 0, {},},
{"JX0", 0x0290, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JX1", 0x0291, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JX2", 0x0292, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JX3", 0x0293, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JNE", 0x0294, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JEQ", 0x0295, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JZR", 0x029c, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JNZ", 0x029d, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JMP", 0x029f, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"DAR", 0x0004, 0xfffc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"IAR", 0x0008, 0xfffc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"CALLR", 0x171f, 0xff1f, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}},},
{"JMPR", 0x170f, 0xff1f, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}},},
{"SBCLR", 0x1200, 0xfff8, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}},},
{"SBSET", 0x1300, 0xfff8, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}},},
{"LSL", 0x1400, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}},},
{"LSR", 0x1440, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}},},
{"ASL", 0x1480, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x007f}},},
{"ASR", 0x14c0, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x007f}},},
{"LRI", 0x0080, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_IMM, 2, 1, 0, 0xffff}},},
{"LR", 0x00c0, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_MEM, 2, 1, 0, 0xffff}},},
{"SR", 0x00e0, 0xffe0, 2, 2, {{P_MEM, 2, 1, 0, 0xffff}, {P_REG, 1, 0, 0, 0x001f}},},
{"MRR", 0x1c00, 0xfc00, 1, 2, {{P_REG, 1, 0, 5, 0x03e0}, {P_REG, 1, 0, 0, 0x001f}},},
{"SI", 0x1600, 0xff00, 2, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_IMM, 2, 1, 0, 0xffff}},},
{"LRS", 0x2000, 0xf800, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_MEM, 1, 0, 0, 0x00ff}},},
{"SRS", 0x2800, 0xf800, 1, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_REG18, 1, 0, 8, 0x0700}},},
{"LRIS", 0x0800, 0xf800, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_IMM, 1, 0, 0, 0x00ff}},},
{"ADDIS", 0x0400, 0xfe00, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}},},
{"CMPIS", 0x0600, 0xfe00, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}},},
{"ANDI", 0x0240, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ANDF", 0x02c0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"XORI", 0x0220, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ANDCF", 0x02a0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ORI", 0x0260, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ORF", 0x02e0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ADDI", 0x0200, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, // missing S64
{"CMPI", 0x0280, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, // missing S64
{"ILRR", 0x0210, 0xfedc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},},
{"ILRRI", 0x0218, 0xfedc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},},
// load and store value pointed by indexing reg and increment; LRR/SRR variants
{"LRRI", 0x1900, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},},
{"LRRD", 0x1880, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},},
{"LRRN", 0x1980, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},},
{"LRR", 0x1800, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},},
{"SRRI", 0x1b00, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},},
{"SRRD", 0x1a80, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},},
{"SRRN", 0x1b80, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},},
{"SRR", 0x1a00, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},},
{"LOOPI", 0x1000, 0xff00, 1, 1, {{P_IMM, 1, 0, 0, 0x00ff}},},
{"BLOOPI", 0x1100, 0xff00, 2, 2, {{P_IMM, 1, 0, 0, 0x00ff}, {P_VAL, 2, 1, 0, 0xffff}},},
{"LOOP", 0x0040, 0xffe0, 1, 1, {{P_REG, 1, 0, 0, 0x001f}},},
{"BLOOP", 0x0060, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_VAL, 2, 1, 0, 0xffff}},},
// opcodes that can be extended
// extended opcodes, note size of opcode will be set to 0
{"NX", 0x8000, 0xffff, 1 | P_EXT, 0, {},},
{"S40", 0x8e00, 0xffff, 1 | P_EXT, 0, {},},
{"S16", 0x8f00, 0xffff, 1 | P_EXT, 0, {},},
{"M2", 0x8a00, 0xffff, 1 | P_EXT, 0, {},},
{"M0", 0x8b00, 0xffff, 1 | P_EXT, 0, {},},
{"CLR15", 0x8c00, 0xffff, 1 | P_EXT, 0, {},},
{"SET15", 0x8d00, 0xffff, 1 | P_EXT, 0, {},},
{"DECM", 0x7800, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"INCM", 0x7400, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"DEC", 0x7a00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"INC", 0x7600, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"NEG", 0x7c00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"TST", 0xb100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},},
{"TSTAXH", 0x8600, 0xfeff, 1 | P_EXT, 1, {{P_REG1A, 1, 0, 8, 0x0100}},},
{"CMP", 0x8200, 0xffff, 1 | P_EXT, 0, {},},
{"CMPAXH", 0xc100, 0xe7ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}},},
{"CLR", 0x8100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},},
{"CLRP", 0x8400, 0xffff, 1 | P_EXT, 0, {},},
{"MOV", 0x6c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},},
{"MOVAX", 0x6800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},},
{"MOVR", 0x6000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},},
{"MOVP", 0x6e00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"MOVPZ", 0xfe00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"ADDPAXZ", 0xf800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG1A, 1, 0, 8, 0x0100}},},
{"ADDP", 0x4e00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"LSL16", 0xf000, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"LSR16", 0xf400, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"ASR16", 0x9100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},},
{"XORR", 0x3000, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},},
{"ANDR", 0x3400, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},},
{"ORR", 0x3800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},},
{"ANDC", 0x3C00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"ORC", 0x3E00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"MULX", 0xa000, 0xe7ff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}},},
{"MULXAC", 0xa400, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULXMV", 0xa600, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULXMVZ", 0xa200, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MUL", 0x9000, 0xf7ff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}},},
{"MULAC", 0x9400, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULMV", 0x9600, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULMVZ", 0x9200, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULC", 0xc000, 0xe7ff, 1 | P_EXT, 2, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}},},
{"MULCAC", 0xc400, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULCMV", 0xc600, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULCMVZ", 0xc200, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"ADDR", 0x4000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},},
{"ADDAX", 0x4800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},},
{"ADD", 0x4c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},},
{"ADDAXL", 0x7000, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},},
{"SUBR", 0x5000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},},
{"SUBAX", 0x5800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},},
{"SUB", 0x5c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},},
{"MADD", 0xf200, 0xfeff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}},},
{"MSUB", 0xf600, 0xfeff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}},},
{"MADDX", 0xe000, 0xfcff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},},
{"MSUBX", 0xe400, 0xfcff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},},
{"MADDC", 0xe800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},},
{"MSUBC", 0xec00, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},},
// assemble CW
{"CW", 0x0000, 0xffff, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}},},
// unknown opcode for disassemble
{"CW", 0x0000, 0x0000, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}},},
};
opc_t opcodes_ext[] =
{
{"L", 0x0040, 0x00c4, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LN", 0x0044, 0x00c4, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LS", 0x0080, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},},
{"LSN", 0x0084, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},},
{"LSM", 0x0088, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},},
{"LSNM", 0x008c, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},},
{"SL", 0x0082, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},},
{"SLN", 0x0086, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},},
{"SLM", 0x008a, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},},
{"SLNM", 0x008e, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},},
{"S", 0x0020, 0x00e4, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}},},
{"SN", 0x0024, 0x00e4, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}},},
{"LDX", 0x00c0, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},},
{"LDXN", 0x00c4, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},},
{"LDXM", 0x00c8, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},},
{"LDXNM", 0x00cc, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},},
{"LD", 0x00c0, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LDN", 0x00c4, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LDM", 0x00c8, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LDNM", 0x00cc, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},},
{"MV", 0x0010, 0x00f0, 1, 2, {{P_REG18, 1, 0, 2, 0x000c}, {P_REG1C, 1, 0, 0, 0x0003}},},
{"DR", 0x0004, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"IR", 0x0008, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"NR", 0x000c, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"XXX", 0x0000, 0x0000, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}},},
};
const uint32 opcodes_size = sizeof(opcodes) / sizeof(opc_t);
const uint32 opcodes_ext_size = sizeof(opcodes_ext) / sizeof(opc_t);
/*====================================================================
filename: opcodes.cpp
project: GameCube DSP Tool (gcdsp)
created: 2005.03.04
mail: duddie@walla.com
Copyright (c) 2005 Duddie
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
#include "Globals.h"
#include "opcodes.h"
opc_t opcodes[] =
{
{"NOP", 0x0000, 0xffff, 1, 0, {},},
{"HALT", 0x0021, 0xffff, 1, 0, {},},
{"RET", 0x02df, 0xffff, 1, 0, {},},
{"RETEQ", 0x02d5, 0xffff, 1, 0, {},},
{"RETNZ", 0x02dd, 0xffff, 1, 0, {},},
{"RTI", 0x02ff, 0xffff, 1, 0, {},},
{"CALL", 0x02bf, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"CALLNE", 0x02b4, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"IF_0", 0x0270, 0xffff, 1, 0, {},},
{"IF_1", 0x0271, 0xffff, 1, 0, {},},
{"IF_2", 0x0272, 0xffff, 1, 0, {},},
{"IF_3", 0x0273, 0xffff, 1, 0, {},},
{"IF_E", 0x0274, 0xffff, 1, 0, {},},
{"IF_Q", 0x0275, 0xffff, 1, 0, {},},
{"IF_R", 0x027c, 0xffff, 1, 0, {},},
{"IF_Z", 0x027d, 0xffff, 1, 0, {},},
{"IF_P", 0x027f, 0xffff, 1, 0, {},},
{"JX0", 0x0290, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JX1", 0x0291, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JX2", 0x0292, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JX3", 0x0293, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JNE", 0x0294, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JEQ", 0x0295, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JZR", 0x029c, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JNZ", 0x029d, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JMP", 0x029f, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"DAR", 0x0004, 0xfffc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"IAR", 0x0008, 0xfffc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"CALLR", 0x171f, 0xff1f, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}},},
{"JMPR", 0x170f, 0xff1f, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}},},
{"SBCLR", 0x1200, 0xfff8, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}},},
{"SBSET", 0x1300, 0xfff8, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}},},
{"LSL", 0x1400, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}},},
{"LSR", 0x1440, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}},},
{"ASL", 0x1480, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x007f}},},
{"ASR", 0x14c0, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x007f}},},
{"LRI", 0x0080, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_IMM, 2, 1, 0, 0xffff}},},
{"LR", 0x00c0, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_MEM, 2, 1, 0, 0xffff}},},
{"SR", 0x00e0, 0xffe0, 2, 2, {{P_MEM, 2, 1, 0, 0xffff}, {P_REG, 1, 0, 0, 0x001f}},},
{"MRR", 0x1c00, 0xfc00, 1, 2, {{P_REG, 1, 0, 5, 0x03e0}, {P_REG, 1, 0, 0, 0x001f}},},
{"SI", 0x1600, 0xff00, 2, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_IMM, 2, 1, 0, 0xffff}},},
{"LRS", 0x2000, 0xf800, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_MEM, 1, 0, 0, 0x00ff}},},
{"SRS", 0x2800, 0xf800, 1, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_REG18, 1, 0, 8, 0x0700}},},
{"LRIS", 0x0800, 0xf800, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_IMM, 1, 0, 0, 0x00ff}},},
{"ADDIS", 0x0400, 0xfe00, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}},},
{"CMPIS", 0x0600, 0xfe00, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}},},
{"ANDI", 0x0240, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ANDF", 0x02c0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"XORI", 0x0220, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ANDCF", 0x02a0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ORI", 0x0260, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ORF", 0x02e0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ADDI", 0x0200, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, // missing S64
{"CMPI", 0x0280, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, // missing S64
{"ILRR", 0x0210, 0xfedc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},},
{"ILRRI", 0x0218, 0xfedc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},},
// load and store value pointed by indexing reg and increment; LRR/SRR variants
{"LRRI", 0x1900, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},},
{"LRRD", 0x1880, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},},
{"LRRN", 0x1980, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},},
{"LRR", 0x1800, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},},
{"SRRI", 0x1b00, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},},
{"SRRD", 0x1a80, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},},
{"SRRN", 0x1b80, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},},
{"SRR", 0x1a00, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},},
{"LOOPI", 0x1000, 0xff00, 1, 1, {{P_IMM, 1, 0, 0, 0x00ff}},},
{"BLOOPI", 0x1100, 0xff00, 2, 2, {{P_IMM, 1, 0, 0, 0x00ff}, {P_VAL, 2, 1, 0, 0xffff}},},
{"LOOP", 0x0040, 0xffe0, 1, 1, {{P_REG, 1, 0, 0, 0x001f}},},
{"BLOOP", 0x0060, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_VAL, 2, 1, 0, 0xffff}},},
// opcodes that can be extended
// extended opcodes, note size of opcode will be set to 0
{"NX", 0x8000, 0xffff, 1 | P_EXT, 0, {},},
{"S40", 0x8e00, 0xffff, 1 | P_EXT, 0, {},},
{"S16", 0x8f00, 0xffff, 1 | P_EXT, 0, {},},
{"M2", 0x8a00, 0xffff, 1 | P_EXT, 0, {},},
{"M0", 0x8b00, 0xffff, 1 | P_EXT, 0, {},},
{"CLR15", 0x8c00, 0xffff, 1 | P_EXT, 0, {},},
{"SET15", 0x8d00, 0xffff, 1 | P_EXT, 0, {},},
{"DECM", 0x7800, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"INCM", 0x7400, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"DEC", 0x7a00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"INC", 0x7600, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"NEG", 0x7c00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"TST", 0xb100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},},
{"TSTAXH", 0x8600, 0xfeff, 1 | P_EXT, 1, {{P_REG1A, 1, 0, 8, 0x0100}},},
{"CMP", 0x8200, 0xffff, 1 | P_EXT, 0, {},},
{"CMPAXH", 0xc100, 0xe7ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}},},
{"CLR", 0x8100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},},
{"CLRP", 0x8400, 0xffff, 1 | P_EXT, 0, {},},
{"MOV", 0x6c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},},
{"MOVAX", 0x6800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},},
{"MOVR", 0x6000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},},
{"MOVP", 0x6e00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"MOVPZ", 0xfe00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"ADDPAXZ", 0xf800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG1A, 1, 0, 8, 0x0100}},},
{"ADDP", 0x4e00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"LSL16", 0xf000, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"LSR16", 0xf400, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"ASR16", 0x9100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},},
{"XORR", 0x3000, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},},
{"ANDR", 0x3400, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},},
{"ORR", 0x3800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},},
{"ANDC", 0x3C00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"ORC", 0x3E00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"MULX", 0xa000, 0xe7ff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}},},
{"MULXAC", 0xa400, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULXMV", 0xa600, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULXMVZ", 0xa200, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MUL", 0x9000, 0xf7ff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}},},
{"MULAC", 0x9400, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULMV", 0x9600, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULMVZ", 0x9200, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULC", 0xc000, 0xe7ff, 1 | P_EXT, 2, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}},},
{"MULCAC", 0xc400, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULCMV", 0xc600, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULCMVZ", 0xc200, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"ADDR", 0x4000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},},
{"ADDAX", 0x4800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},},
{"ADD", 0x4c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},},
{"ADDAXL", 0x7000, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},},
{"SUBR", 0x5000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},},
{"SUBAX", 0x5800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},},
{"SUB", 0x5c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},},
{"MADD", 0xf200, 0xfeff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}},},
{"MSUB", 0xf600, 0xfeff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}},},
{"MADDX", 0xe000, 0xfcff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},},
{"MSUBX", 0xe400, 0xfcff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},},
{"MADDC", 0xe800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},},
{"MSUBC", 0xec00, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},},
// assemble CW
{"CW", 0x0000, 0xffff, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}},},
// unknown opcode for disassemble
{"CW", 0x0000, 0x0000, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}},},
};
opc_t opcodes_ext[] =
{
{"L", 0x0040, 0x00c4, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LN", 0x0044, 0x00c4, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LS", 0x0080, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},},
{"LSN", 0x0084, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},},
{"LSM", 0x0088, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},},
{"LSNM", 0x008c, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},},
{"SL", 0x0082, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},},
{"SLN", 0x0086, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},},
{"SLM", 0x008a, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},},
{"SLNM", 0x008e, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},},
{"S", 0x0020, 0x00e4, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}},},
{"SN", 0x0024, 0x00e4, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}},},
{"LDX", 0x00c0, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},},
{"LDXN", 0x00c4, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},},
{"LDXM", 0x00c8, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},},
{"LDXNM", 0x00cc, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},},
{"LD", 0x00c0, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LDN", 0x00c4, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LDM", 0x00c8, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LDNM", 0x00cc, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},},
{"MV", 0x0010, 0x00f0, 1, 2, {{P_REG18, 1, 0, 2, 0x000c}, {P_REG1C, 1, 0, 0, 0x0003}},},
{"DR", 0x0004, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"IR", 0x0008, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"NR", 0x000c, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"XXX", 0x0000, 0x0000, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}},},
};
const uint32 opcodes_size = sizeof(opcodes) / sizeof(opc_t);
const uint32 opcodes_ext_size = sizeof(opcodes_ext) / sizeof(opc_t);

View File

@ -1,19 +1,19 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"

View File

@ -1,86 +1,86 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DSPHandler.h"
CDSPHandler* CDSPHandler::m_pInstance = NULL;
CDSPHandler::CDSPHandler()
: m_pUCode(NULL),
m_bHalt(false),
m_bAssertInt(false)
{
SetUCode(UCODE_ROM);
m_DSPControl.DSPHalt = 1;
m_DSPControl.DSPInit = 1;
}
CDSPHandler::~CDSPHandler()
{
delete m_pUCode;
m_pUCode = NULL;
}
void CDSPHandler::Update()
{
if (m_pUCode != NULL)
m_pUCode->Update();
}
unsigned short CDSPHandler::WriteControlRegister(unsigned short _Value)
{
UDSPControl Temp(_Value);
if (Temp.DSPReset)
{
SetUCode(UCODE_ROM);
Temp.DSPReset = 0;
}
if (Temp.DSPInit == 0)
{
// copy 128 byte from ARAM 0x000000 to IMEM
SetUCode(UCODE_INIT_AUDIO_SYSTEM);
Temp.DSPInitCode = 0;
// MessageBox(NULL, "UCODE_INIT_AUDIO_SYSTEM", "DSP-HLE", MB_OK);
}
m_DSPControl.Hex = Temp.Hex;
return m_DSPControl.Hex;
}
unsigned short CDSPHandler::ReadControlRegister()
{
return m_DSPControl.Hex;
}
void CDSPHandler::SendMailToDSP(u32 _uMail)
{
if (m_pUCode != NULL)
m_pUCode->HandleMail(_uMail);
}
IUCode* CDSPHandler::GetUCode()
{
return m_pUCode;
}
void CDSPHandler::SetUCode(u32 _crc)
{
delete m_pUCode;
m_pUCode = NULL;
m_MailHandler.Clear();
m_pUCode = UCodeFactory(_crc, m_MailHandler);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DSPHandler.h"
CDSPHandler* CDSPHandler::m_pInstance = NULL;
CDSPHandler::CDSPHandler()
: m_pUCode(NULL),
m_bHalt(false),
m_bAssertInt(false)
{
SetUCode(UCODE_ROM);
m_DSPControl.DSPHalt = 1;
m_DSPControl.DSPInit = 1;
}
CDSPHandler::~CDSPHandler()
{
delete m_pUCode;
m_pUCode = NULL;
}
void CDSPHandler::Update()
{
if (m_pUCode != NULL)
m_pUCode->Update();
}
unsigned short CDSPHandler::WriteControlRegister(unsigned short _Value)
{
UDSPControl Temp(_Value);
if (Temp.DSPReset)
{
SetUCode(UCODE_ROM);
Temp.DSPReset = 0;
}
if (Temp.DSPInit == 0)
{
// copy 128 byte from ARAM 0x000000 to IMEM
SetUCode(UCODE_INIT_AUDIO_SYSTEM);
Temp.DSPInitCode = 0;
// MessageBox(NULL, "UCODE_INIT_AUDIO_SYSTEM", "DSP-HLE", MB_OK);
}
m_DSPControl.Hex = Temp.Hex;
return m_DSPControl.Hex;
}
unsigned short CDSPHandler::ReadControlRegister()
{
return m_DSPControl.Hex;
}
void CDSPHandler::SendMailToDSP(u32 _uMail)
{
if (m_pUCode != NULL)
m_pUCode->HandleMail(_uMail);
}
IUCode* CDSPHandler::GetUCode()
{
return m_pUCode;
}
void CDSPHandler::SetUCode(u32 _crc)
{
delete m_pUCode;
m_pUCode = NULL;
m_MailHandler.Clear();
m_pUCode = UCodeFactory(_crc, m_MailHandler);
}

View File

@ -1,53 +1,53 @@
#include <stdarg.h>
#include <stdio.h>
#include "Common.h"
#include "Globals.h"
void __Log(int, const char *fmt, ...)
{
DebugLog(fmt);
}
void DebugLog(const char* _fmt, ...)
{
#ifdef _DEBUG
char Msg[512];
va_list ap;
va_start(ap, _fmt);
vsprintf(Msg, _fmt, ap);
va_end(ap);
g_dspInitialize.pLog(Msg, FALSE);
#endif
}
extern u8* g_pMemory;
// TODO: Wii support? Most likely audio data still must be in the old 24MB TRAM.
#define RAM_MASK 0x1FFFFFF
u8 Memory_Read_U8(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return g_pMemory[_uAddress];
}
u16 Memory_Read_U16(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return Common::swap16(*(u16*)&g_pMemory[_uAddress]);
}
u32 Memory_Read_U32(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return Common::swap32(*(u32*)&g_pMemory[_uAddress]);
}
float Memory_Read_Float(u32 _uAddress)
{
u32 uTemp = Memory_Read_U32(_uAddress);
return *(float*)&uTemp;
}
#include <stdarg.h>
#include <stdio.h>
#include "Common.h"
#include "Globals.h"
void __Log(int, const char *fmt, ...)
{
DebugLog(fmt);
}
void DebugLog(const char* _fmt, ...)
{
#ifdef _DEBUG
char Msg[512];
va_list ap;
va_start(ap, _fmt);
vsprintf(Msg, _fmt, ap);
va_end(ap);
g_dspInitialize.pLog(Msg, FALSE);
#endif
}
extern u8* g_pMemory;
// TODO: Wii support? Most likely audio data still must be in the old 24MB TRAM.
#define RAM_MASK 0x1FFFFFF
u8 Memory_Read_U8(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return g_pMemory[_uAddress];
}
u16 Memory_Read_U16(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return Common::swap16(*(u16*)&g_pMemory[_uAddress]);
}
u32 Memory_Read_U32(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return Common::swap32(*(u32*)&g_pMemory[_uAddress]);
}
float Memory_Read_Float(u32 _uAddress)
{
u32 uTemp = Memory_Read_U32(_uAddress);
return *(float*)&uTemp;
}

View File

@ -1,96 +1,96 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "MailHandler.h"
CMailHandler::CMailHandler()
{
}
CMailHandler::~CMailHandler()
{
Clear();
}
void CMailHandler::PushMail(u32 _Mail)
{
m_Mails.push(_Mail);
Update();
}
u16 CMailHandler::ReadDSPMailboxHigh()
{
// check if we have a mail for the core
if (!m_Mails.empty())
{
u16 result = (m_Mails.front() >> 16) & 0xFFFF;
Update();
return result;
}
return 0x00;
}
u16 CMailHandler::ReadDSPMailboxLow()
{
// check if we have a mail for the core
if (!m_Mails.empty())
{
u16 result = m_Mails.front() & 0xFFFF;
m_Mails.pop();
Update();
return(result);
}
return 0x00;
}
void CMailHandler::Clear()
{
while (!m_Mails.empty())
m_Mails.pop();
}
bool CMailHandler::IsEmpty()
{
return m_Mails.empty();
}
void CMailHandler::Halt(bool _Halt)
{
if (_Halt)
{
Clear();
m_Mails.push(0x80544348);
}
Update();
}
void CMailHandler::Update()
{
if (!IsEmpty())
{
// g_dspInitialize.pGenerateDSPInterrupt();
}
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "MailHandler.h"
CMailHandler::CMailHandler()
{
}
CMailHandler::~CMailHandler()
{
Clear();
}
void CMailHandler::PushMail(u32 _Mail)
{
m_Mails.push(_Mail);
Update();
}
u16 CMailHandler::ReadDSPMailboxHigh()
{
// check if we have a mail for the core
if (!m_Mails.empty())
{
u16 result = (m_Mails.front() >> 16) & 0xFFFF;
Update();
return result;
}
return 0x00;
}
u16 CMailHandler::ReadDSPMailboxLow()
{
// check if we have a mail for the core
if (!m_Mails.empty())
{
u16 result = m_Mails.front() & 0xFFFF;
m_Mails.pop();
Update();
return(result);
}
return 0x00;
}
void CMailHandler::Clear()
{
while (!m_Mails.empty())
m_Mails.pop();
}
bool CMailHandler::IsEmpty()
{
return m_Mails.empty();
}
void CMailHandler::Halt(bool _Halt)
{
if (_Halt)
{
Clear();
m_Mails.push(0x80544348);
}
Update();
}
void CMailHandler::Update()
{
if (!IsEmpty())
{
// g_dspInitialize.pGenerateDSPInterrupt();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,63 +1,63 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "../Globals.h"
#include "../DSPHandler.h"
#include "UCodes.h"
#include "UCode_CARD.h"
CUCode_CARD::CUCode_CARD(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
{
DebugLog("CUCode_CARD - initialized");
m_rMailHandler.PushMail(DSP_INIT);
}
CUCode_CARD::~CUCode_CARD()
{
m_rMailHandler.Clear();
}
void CUCode_CARD::Update()
{
// check if we have to sent something
if (!m_rMailHandler.IsEmpty())
{
g_dspInitialize.pGenerateDSPInterrupt();
}
}
void CUCode_CARD::HandleMail(u32 _uMail)
{
if (_uMail == 0xFF000000) // unlock card
{
// m_Mails.push(0x00000001); // ACK (actualy anything != 0)
}
else
{
DebugLog("CUCode_CARD - unknown cmd: %x (size %i)", _uMail);
}
m_rMailHandler.PushMail(DSP_DONE);
CDSPHandler::GetInstance().SetUCode(UCODE_ROM);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "../Globals.h"
#include "../DSPHandler.h"
#include "UCodes.h"
#include "UCode_CARD.h"
CUCode_CARD::CUCode_CARD(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
{
DebugLog("CUCode_CARD - initialized");
m_rMailHandler.PushMail(DSP_INIT);
}
CUCode_CARD::~CUCode_CARD()
{
m_rMailHandler.Clear();
}
void CUCode_CARD::Update()
{
// check if we have to sent something
if (!m_rMailHandler.IsEmpty())
{
g_dspInitialize.pGenerateDSPInterrupt();
}
}
void CUCode_CARD::HandleMail(u32 _uMail)
{
if (_uMail == 0xFF000000) // unlock card
{
// m_Mails.push(0x00000001); // ACK (actualy anything != 0)
}
else
{
DebugLog("CUCode_CARD - unknown cmd: %x (size %i)", _uMail);
}
m_rMailHandler.PushMail(DSP_DONE);
CDSPHandler::GetInstance().SetUCode(UCODE_ROM);
}

View File

@ -1,54 +1,54 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "../Globals.h"
#include "../DSPHandler.h"
#include "UCodes.h"
#include "UCode_InitAudioSystem.h"
CUCode_InitAudioSystem::CUCode_InitAudioSystem(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
, m_BootTask_numSteps(0)
, m_NextParameter(0)
, IsInitialized(false)
{
DebugLog("CUCode_InitAudioSystem - initialized");
}
CUCode_InitAudioSystem::~CUCode_InitAudioSystem()
{}
void CUCode_InitAudioSystem::Init()
{}
void CUCode_InitAudioSystem::Update()
{
if (m_rMailHandler.IsEmpty())
{
m_rMailHandler.PushMail(0x80544348);
// HALT
}
}
void CUCode_InitAudioSystem::HandleMail(u32 _uMail)
{}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "../Globals.h"
#include "../DSPHandler.h"
#include "UCodes.h"
#include "UCode_InitAudioSystem.h"
CUCode_InitAudioSystem::CUCode_InitAudioSystem(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
, m_BootTask_numSteps(0)
, m_NextParameter(0)
, IsInitialized(false)
{
DebugLog("CUCode_InitAudioSystem - initialized");
}
CUCode_InitAudioSystem::~CUCode_InitAudioSystem()
{}
void CUCode_InitAudioSystem::Init()
{}
void CUCode_InitAudioSystem::Update()
{
if (m_rMailHandler.IsEmpty())
{
m_rMailHandler.PushMail(0x80544348);
// HALT
}
}
void CUCode_InitAudioSystem::HandleMail(u32 _uMail)
{}

View File

@ -1,162 +1,162 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "../Globals.h"
#include "UCodes.h"
#include "UCode_Jac.h"
#include "../MailHandler.h"
CUCode_Jac::CUCode_Jac(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
, m_bListInProgress(false)
{
DebugLog("CUCode_Jac: init");
m_rMailHandler.PushMail(0xDCD10000);
m_rMailHandler.PushMail(0x80000000);
}
CUCode_Jac::~CUCode_Jac()
{
m_rMailHandler.Clear();
}
void CUCode_Jac::HandleMail(u32 _uMail)
{
// this is prolly totally bullshit and should work like the zelda one...
// but i am to lazy to change it atm
if (m_bListInProgress == false)
{
// get the command to find out how much steps it has
switch (_uMail & 0xFFFF)
{
// release halt
case 0x00:
// m_Mails.push(0x80000000);
g_dspInitialize.pGenerateDSPInterrupt();
break;
case 0x40:
m_step = 0;
((u32*)m_Buffer)[m_step++] = _uMail;
m_bListInProgress = true;
m_numSteps = 5;
break;
case 0x2000:
case 0x4000:
m_step = 0;
((u32*)m_Buffer)[m_step++] = _uMail;
m_bListInProgress = true;
m_numSteps = 3;
break;
default:
PanicAlert("UCode Jac");
DebugLog("UCode Jac - unknown cmd: %x", _uMail & 0xFFFF);
break;
}
}
else
{
((u32*)m_Buffer)[m_step] = _uMail;
m_step++;
if (m_step == m_numSteps)
{
ExecuteList();
m_bListInProgress = false;
}
}
}
void CUCode_Jac::Update()
{
// check if we have to sent something
/* if (!g_MailHandler.empty())
{
g_dspInitialize.pGenerateDSPInterrupt();
}*/
}
void CUCode_Jac::ExecuteList()
{
// begin with the list
m_readOffset = 0;
u16 cmd = Read16();
u16 sync = Read16();
DebugLog("==============================================================================");
DebugLog("UCode Jac - execute dlist (cmd: 0x%04x : sync: 0x%04x)", cmd, sync);
switch (cmd)
{
// ==============================================================================
// DsetupTable
// ==============================================================================
case 0x40:
{
u32 tmp[4];
tmp[0] = Read32();
tmp[1] = Read32();
tmp[2] = Read32();
tmp[3] = Read32();
DebugLog("DsetupTable");
DebugLog("???: 0x%08x", tmp[0]);
DebugLog("DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]);
DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]);
DebugLog("???: 0x%08x", tmp[3]);
}
break;
// ==============================================================================
// UpdateDSPChannel
// ==============================================================================
case 0x2000:
case 0x4000: // animal crossing
{
u32 tmp[3];
tmp[0] = Read32();
tmp[1] = Read32();
tmp[2] = Read32();
DebugLog("UpdateDSPChannel");
DebugLog("audiomemory: 0x%08x", tmp[0]);
DebugLog("audiomemory: 0x%08x", tmp[1]);
DebugLog("DSPADPCM_FILTER (size: 0x40): 0x%08x", tmp[2]);
}
break;
default:
PanicAlert("UCode Jac unknown cmd: %s (size %)", cmd, m_numSteps);
DebugLog("Jac UCode - unknown cmd: %x (size %i)", cmd, m_numSteps);
break;
}
// sync, we are rdy
m_rMailHandler.PushMail(DSP_SYNC);
m_rMailHandler.PushMail(0xF3550000 | sync);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "../Globals.h"
#include "UCodes.h"
#include "UCode_Jac.h"
#include "../MailHandler.h"
CUCode_Jac::CUCode_Jac(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
, m_bListInProgress(false)
{
DebugLog("CUCode_Jac: init");
m_rMailHandler.PushMail(0xDCD10000);
m_rMailHandler.PushMail(0x80000000);
}
CUCode_Jac::~CUCode_Jac()
{
m_rMailHandler.Clear();
}
void CUCode_Jac::HandleMail(u32 _uMail)
{
// this is prolly totally bullshit and should work like the zelda one...
// but i am to lazy to change it atm
if (m_bListInProgress == false)
{
// get the command to find out how much steps it has
switch (_uMail & 0xFFFF)
{
// release halt
case 0x00:
// m_Mails.push(0x80000000);
g_dspInitialize.pGenerateDSPInterrupt();
break;
case 0x40:
m_step = 0;
((u32*)m_Buffer)[m_step++] = _uMail;
m_bListInProgress = true;
m_numSteps = 5;
break;
case 0x2000:
case 0x4000:
m_step = 0;
((u32*)m_Buffer)[m_step++] = _uMail;
m_bListInProgress = true;
m_numSteps = 3;
break;
default:
PanicAlert("UCode Jac");
DebugLog("UCode Jac - unknown cmd: %x", _uMail & 0xFFFF);
break;
}
}
else
{
((u32*)m_Buffer)[m_step] = _uMail;
m_step++;
if (m_step == m_numSteps)
{
ExecuteList();
m_bListInProgress = false;
}
}
}
void CUCode_Jac::Update()
{
// check if we have to sent something
/* if (!g_MailHandler.empty())
{
g_dspInitialize.pGenerateDSPInterrupt();
}*/
}
void CUCode_Jac::ExecuteList()
{
// begin with the list
m_readOffset = 0;
u16 cmd = Read16();
u16 sync = Read16();
DebugLog("==============================================================================");
DebugLog("UCode Jac - execute dlist (cmd: 0x%04x : sync: 0x%04x)", cmd, sync);
switch (cmd)
{
// ==============================================================================
// DsetupTable
// ==============================================================================
case 0x40:
{
u32 tmp[4];
tmp[0] = Read32();
tmp[1] = Read32();
tmp[2] = Read32();
tmp[3] = Read32();
DebugLog("DsetupTable");
DebugLog("???: 0x%08x", tmp[0]);
DebugLog("DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]);
DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]);
DebugLog("???: 0x%08x", tmp[3]);
}
break;
// ==============================================================================
// UpdateDSPChannel
// ==============================================================================
case 0x2000:
case 0x4000: // animal crossing
{
u32 tmp[3];
tmp[0] = Read32();
tmp[1] = Read32();
tmp[2] = Read32();
DebugLog("UpdateDSPChannel");
DebugLog("audiomemory: 0x%08x", tmp[0]);
DebugLog("audiomemory: 0x%08x", tmp[1]);
DebugLog("DSPADPCM_FILTER (size: 0x40): 0x%08x", tmp[2]);
}
break;
default:
PanicAlert("UCode Jac unknown cmd: %s (size %)", cmd, m_numSteps);
DebugLog("Jac UCode - unknown cmd: %x (size %i)", cmd, m_numSteps);
break;
}
// sync, we are rdy
m_rMailHandler.PushMail(DSP_SYNC);
m_rMailHandler.PushMail(0xF3550000 | sync);
}

View File

@ -1,113 +1,113 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "../Globals.h"
#include "../DSPHandler.h"
#include "UCodes.h"
#include "UCode_ROM.h"
CUCode_Rom::CUCode_Rom(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
, m_BootTask_numSteps(0)
, m_NextParameter(0)
{
DebugLog("UCode_Rom - initialized");
m_rMailHandler.Clear();
m_rMailHandler.PushMail(0x8071FEED);
}
CUCode_Rom::~CUCode_Rom()
{}
void CUCode_Rom::Update()
{}
void CUCode_Rom::HandleMail(u32 _uMail)
{
if (m_NextParameter == 0)
{
// wait for beginning of UCode
if ((_uMail & 0xFFFF0000) != 0x80F30000)
{
u32 Message = 0xFEEE0000 | (_uMail & 0xFFFF);
m_rMailHandler.PushMail(Message);
}
else
{
m_NextParameter = _uMail;
}
}
else
{
switch (m_NextParameter)
{
case 0x80F3A001:
m_CurrentUCode.m_RAMAddress = _uMail;
break;
case 0x80F3A002:
m_CurrentUCode.m_Length = _uMail;
break;
case 0x80F3C002:
m_CurrentUCode.m_IMEMAddress = _uMail;
break;
case 0x80F3B002:
m_CurrentUCode.m_Unk = _uMail;
break;
case 0x80F3D001:
{
m_CurrentUCode.m_StartPC = _uMail;
BootUCode();
return; // FIXES THE OVERWRITE
}
break;
}
// THE GODDAMN OVERWRITE WAS HERE. Without the return above, since BootUCode may delete "this", well ...
m_NextParameter = 0;
}
}
void CUCode_Rom::BootUCode()
{
// simple non-scientific crc invented by ector :P
// too annoying to change now, and probably good enough anyway
u32 crc = 0;
for (u32 i = 0; i < m_CurrentUCode.m_Length; i++)
{
crc ^= Memory_Read_U8(m_CurrentUCode.m_RAMAddress + i);
//let's rol
crc = (crc << 3) | (crc >> 29);
}
DebugLog("CurrentUCode SOURCE Addr: 0x%08x", m_CurrentUCode.m_RAMAddress);
DebugLog("CurrentUCode Length: 0x%08x", m_CurrentUCode.m_Length);
DebugLog("CurrentUCode DEST Addr: 0x%08x", m_CurrentUCode.m_IMEMAddress);
DebugLog("CurrentUCode ???: 0x%08x", m_CurrentUCode.m_Unk);
DebugLog("CurrentUCode init_vector: 0x%08x", m_CurrentUCode.m_StartPC);
DebugLog("CurrentUCode CRC: 0x%08x", crc);
DebugLog("BootTask - done");
CDSPHandler::GetInstance().SetUCode(crc);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "../Globals.h"
#include "../DSPHandler.h"
#include "UCodes.h"
#include "UCode_ROM.h"
CUCode_Rom::CUCode_Rom(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
, m_BootTask_numSteps(0)
, m_NextParameter(0)
{
DebugLog("UCode_Rom - initialized");
m_rMailHandler.Clear();
m_rMailHandler.PushMail(0x8071FEED);
}
CUCode_Rom::~CUCode_Rom()
{}
void CUCode_Rom::Update()
{}
void CUCode_Rom::HandleMail(u32 _uMail)
{
if (m_NextParameter == 0)
{
// wait for beginning of UCode
if ((_uMail & 0xFFFF0000) != 0x80F30000)
{
u32 Message = 0xFEEE0000 | (_uMail & 0xFFFF);
m_rMailHandler.PushMail(Message);
}
else
{
m_NextParameter = _uMail;
}
}
else
{
switch (m_NextParameter)
{
case 0x80F3A001:
m_CurrentUCode.m_RAMAddress = _uMail;
break;
case 0x80F3A002:
m_CurrentUCode.m_Length = _uMail;
break;
case 0x80F3C002:
m_CurrentUCode.m_IMEMAddress = _uMail;
break;
case 0x80F3B002:
m_CurrentUCode.m_Unk = _uMail;
break;
case 0x80F3D001:
{
m_CurrentUCode.m_StartPC = _uMail;
BootUCode();
return; // FIXES THE OVERWRITE
}
break;
}
// THE GODDAMN OVERWRITE WAS HERE. Without the return above, since BootUCode may delete "this", well ...
m_NextParameter = 0;
}
}
void CUCode_Rom::BootUCode()
{
// simple non-scientific crc invented by ector :P
// too annoying to change now, and probably good enough anyway
u32 crc = 0;
for (u32 i = 0; i < m_CurrentUCode.m_Length; i++)
{
crc ^= Memory_Read_U8(m_CurrentUCode.m_RAMAddress + i);
//let's rol
crc = (crc << 3) | (crc >> 29);
}
DebugLog("CurrentUCode SOURCE Addr: 0x%08x", m_CurrentUCode.m_RAMAddress);
DebugLog("CurrentUCode Length: 0x%08x", m_CurrentUCode.m_Length);
DebugLog("CurrentUCode DEST Addr: 0x%08x", m_CurrentUCode.m_IMEMAddress);
DebugLog("CurrentUCode ???: 0x%08x", m_CurrentUCode.m_Unk);
DebugLog("CurrentUCode init_vector: 0x%08x", m_CurrentUCode.m_StartPC);
DebugLog("CurrentUCode CRC: 0x%08x", crc);
DebugLog("BootTask - done");
CDSPHandler::GetInstance().SetUCode(crc);
}

View File

@ -1,166 +1,166 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Games that uses this UCode:
// Zelda: The Windwaker, Mario Sunshine, Mario Kart
#include "Common.h"
#include "../Globals.h"
#include "UCodes.h"
#include "UCode_Zelda.h"
#include "../MailHandler.h"
CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
, m_numSteps(0)
, m_bListInProgress(false)
, m_step(0)
, m_readOffset(0)
{
DebugLog("UCode_Zelda - add boot mails for handshake");
m_rMailHandler.PushMail(DSP_INIT);
m_rMailHandler.PushMail(0x80000000); // handshake
memset(m_Buffer, 0, sizeof(m_Buffer));
}
CUCode_Zelda::~CUCode_Zelda()
{
m_rMailHandler.Clear();
}
void CUCode_Zelda::Update()
{
// check if we have to sent something
if (!m_rMailHandler.IsEmpty())
g_dspInitialize.pGenerateDSPInterrupt();
}
void CUCode_Zelda::HandleMail(u32 _uMail)
{
if (m_bListInProgress == false)
{
m_bListInProgress = true;
m_numSteps = _uMail;
m_step = 0;
}
else
{
if (m_step < 0 || m_step >= sizeof(m_Buffer)/4)
PanicAlert("m_step out of range");
((u32*)m_Buffer)[m_step] = _uMail;
m_step++;
if (m_step == m_numSteps)
{
ExecuteList();
m_bListInProgress = false;
}
}
}
void CUCode_Zelda::ExecuteList()
{
// begin with the list
m_readOffset = 0;
u32 Temp = Read32();
u32 Command = (Temp >> 24) & 0x7f;
u32 Sync = Temp >> 16;
DebugLog("==============================================================================");
DebugLog("Zelda UCode - execute dlist (cmd: 0x%04x : sync: 0x%04x)", Command, Sync);
switch (Command)
{
// DsetupTable ... zelda ww jumps to 0x0095
case 0x01:
{
u32 tmp[4];
tmp[0] = Read32();
tmp[1] = Read32();
tmp[2] = Read32();
tmp[3] = Read32();
DebugLog("DsetupTable");
DebugLog("???: 0x%08x", tmp[0]);
DebugLog("DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]);
DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]);
DebugLog("???: 0x%08x", tmp[3]);
}
break;
// SyncFrame ... zelda ww jumps to 0x0243
case 0x02:
{
u32 tmp[3];
tmp[0] = Read32();
tmp[1] = Read32();
tmp[2] = Read32();
DebugLog("DsyncFrame");
DebugLog("???: 0x%08x", tmp[0]);
DebugLog("???: 0x%08x", tmp[1]);
DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]);
}
break;
/*
case 0x03: break; // dunno ... zelda ww jmps to 0x0073
case 0x04: break; // dunno ... zelda ww jmps to 0x0580
case 0x05: break; // dunno ... zelda ww jmps to 0x0592
case 0x06: break; // dunno ... zelda ww jmps to 0x0469
case 0x07: break; // dunno ... zelda ww jmps to 0x044d
case 0x08: break; // Mixer ... zelda ww jmps to 0x0485
case 0x09: break; // dunno ... zelda ww jmps to 0x044d
*/
// DsetDolbyDelay ... zelda ww jumps to 0x00b2
case 0x0d:
{
u32 tmp[2];
tmp[0] = Read32();
tmp[1] = Read32();
DebugLog("DSetDolbyDelay");
DebugLog("DOLBY2_DELAY_BUF (size 0x960): 0x%08x", tmp[0]);
DebugLog("DSPRES_FILTER (size 0x500): 0x%08x", tmp[1]);
}
break;
// Set VARAM
case 0x0e:
// MessageBox(NULL, "Zelda VARAM", "cmd", MB_OK);
break;
// default ... zelda ww jumps to 0x0043
default:
PanicAlert("Zelda UCode - unknown cmd: %x (size %i)", Command, m_numSteps);
break;
}
// sync, we are rdy
m_rMailHandler.PushMail(DSP_SYNC);
m_rMailHandler.PushMail(0xF3550000 | Sync);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Games that uses this UCode:
// Zelda: The Windwaker, Mario Sunshine, Mario Kart
#include "Common.h"
#include "../Globals.h"
#include "UCodes.h"
#include "UCode_Zelda.h"
#include "../MailHandler.h"
CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler)
: IUCode(_rMailHandler)
, m_numSteps(0)
, m_bListInProgress(false)
, m_step(0)
, m_readOffset(0)
{
DebugLog("UCode_Zelda - add boot mails for handshake");
m_rMailHandler.PushMail(DSP_INIT);
m_rMailHandler.PushMail(0x80000000); // handshake
memset(m_Buffer, 0, sizeof(m_Buffer));
}
CUCode_Zelda::~CUCode_Zelda()
{
m_rMailHandler.Clear();
}
void CUCode_Zelda::Update()
{
// check if we have to sent something
if (!m_rMailHandler.IsEmpty())
g_dspInitialize.pGenerateDSPInterrupt();
}
void CUCode_Zelda::HandleMail(u32 _uMail)
{
if (m_bListInProgress == false)
{
m_bListInProgress = true;
m_numSteps = _uMail;
m_step = 0;
}
else
{
if (m_step < 0 || m_step >= sizeof(m_Buffer)/4)
PanicAlert("m_step out of range");
((u32*)m_Buffer)[m_step] = _uMail;
m_step++;
if (m_step == m_numSteps)
{
ExecuteList();
m_bListInProgress = false;
}
}
}
void CUCode_Zelda::ExecuteList()
{
// begin with the list
m_readOffset = 0;
u32 Temp = Read32();
u32 Command = (Temp >> 24) & 0x7f;
u32 Sync = Temp >> 16;
DebugLog("==============================================================================");
DebugLog("Zelda UCode - execute dlist (cmd: 0x%04x : sync: 0x%04x)", Command, Sync);
switch (Command)
{
// DsetupTable ... zelda ww jumps to 0x0095
case 0x01:
{
u32 tmp[4];
tmp[0] = Read32();
tmp[1] = Read32();
tmp[2] = Read32();
tmp[3] = Read32();
DebugLog("DsetupTable");
DebugLog("???: 0x%08x", tmp[0]);
DebugLog("DSPRES_FILTER (size: 0x40): 0x%08x", tmp[1]);
DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]);
DebugLog("???: 0x%08x", tmp[3]);
}
break;
// SyncFrame ... zelda ww jumps to 0x0243
case 0x02:
{
u32 tmp[3];
tmp[0] = Read32();
tmp[1] = Read32();
tmp[2] = Read32();
DebugLog("DsyncFrame");
DebugLog("???: 0x%08x", tmp[0]);
DebugLog("???: 0x%08x", tmp[1]);
DebugLog("DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]);
}
break;
/*
case 0x03: break; // dunno ... zelda ww jmps to 0x0073
case 0x04: break; // dunno ... zelda ww jmps to 0x0580
case 0x05: break; // dunno ... zelda ww jmps to 0x0592
case 0x06: break; // dunno ... zelda ww jmps to 0x0469
case 0x07: break; // dunno ... zelda ww jmps to 0x044d
case 0x08: break; // Mixer ... zelda ww jmps to 0x0485
case 0x09: break; // dunno ... zelda ww jmps to 0x044d
*/
// DsetDolbyDelay ... zelda ww jumps to 0x00b2
case 0x0d:
{
u32 tmp[2];
tmp[0] = Read32();
tmp[1] = Read32();
DebugLog("DSetDolbyDelay");
DebugLog("DOLBY2_DELAY_BUF (size 0x960): 0x%08x", tmp[0]);
DebugLog("DSPRES_FILTER (size 0x500): 0x%08x", tmp[1]);
}
break;
// Set VARAM
case 0x0e:
// MessageBox(NULL, "Zelda VARAM", "cmd", MB_OK);
break;
// default ... zelda ww jumps to 0x0043
default:
PanicAlert("Zelda UCode - unknown cmd: %x (size %i)", Command, m_numSteps);
break;
}
// sync, we are rdy
m_rMailHandler.PushMail(DSP_SYNC);
m_rMailHandler.PushMail(0xF3550000 | Sync);
}

View File

@ -1,87 +1,87 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "../Globals.h"
#include "UCodes.h"
#include "UCode_AX.h"
#include "UCode_Zelda.h"
#include "UCode_Jac.h"
#include "UCode_ROM.h"
#include "UCode_CARD.h"
#include "UCode_InitAudioSystem.h"
IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler)
{
switch (_CRC)
{
case UCODE_ROM:
return new CUCode_Rom(_rMailHandler);
case UCODE_INIT_AUDIO_SYSTEM:
return new CUCode_InitAudioSystem(_rMailHandler);
case 0x65d6cc6f: // CARD
return new CUCode_CARD(_rMailHandler);
case 0x088e38a5: // IPL - JAP
case 0xd73338cf: // IPL
case 0x42f64ac4: // Luigi (after fix)
case 0x4be6a5cb: // AC, Pikmin (after fix)
DebugLog("JAC ucode chosen");
return new CUCode_Jac(_rMailHandler);
case 0x3ad3b7ac: // Naruto3
case 0x3daf59b9: // Alien Hominid
case 0x4e8a8b21: // spdemo, ctaxi, 18 wheeler, disney, monkeyball2,cubivore,puzzlecollection,wario,
// capcom vs snk, naruto2, lost kingdoms, star fox, mario party 4, mortal kombat,
// smugglers run warzone, smash brothers, sonic mega collection, ZooCube
// nddemo, starfox
case 0x07f88145: // bustamove, ikaruga, fzero, robotech battle cry, star soldier, soul calibur2,
// Zelda:OOT, Tony hawk, viewtiful joe
case 0xe2136399: // billy hatcher, dragonballz, mario party 5, TMNT, ava1080
DebugLog("AX ucode chosen, yay!");
return new CUCode_AX(_rMailHandler);
case 0x6CA33A6D: // DK Jungle Beat
case 0x86840740: // zelda
case 0x56d36052: // mario
case 0x2fcdf1ec: // mariokart, zelda 4 swords
DebugLog("Zelda ucode chosen");
return new CUCode_Zelda(_rMailHandler);
// WII CRCs
case 0x6c3f6f94: // zelda - PAL
case 0xd643001f: // mario galaxy - PAL
DebugLog("Zelda Wii ucode chosen");
return new CUCode_Zelda(_rMailHandler);
case 0x347112ba: // raving rabbits
DebugLog("Wii - AX chosen");
return new CUCode_AX(_rMailHandler, true);
default:
PanicAlert("Unknown ucode (CRC = %08x) - forcing AX", _CRC);
return new CUCode_AX(_rMailHandler);
}
return NULL;
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "../Globals.h"
#include "UCodes.h"
#include "UCode_AX.h"
#include "UCode_Zelda.h"
#include "UCode_Jac.h"
#include "UCode_ROM.h"
#include "UCode_CARD.h"
#include "UCode_InitAudioSystem.h"
IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler)
{
switch (_CRC)
{
case UCODE_ROM:
return new CUCode_Rom(_rMailHandler);
case UCODE_INIT_AUDIO_SYSTEM:
return new CUCode_InitAudioSystem(_rMailHandler);
case 0x65d6cc6f: // CARD
return new CUCode_CARD(_rMailHandler);
case 0x088e38a5: // IPL - JAP
case 0xd73338cf: // IPL
case 0x42f64ac4: // Luigi (after fix)
case 0x4be6a5cb: // AC, Pikmin (after fix)
DebugLog("JAC ucode chosen");
return new CUCode_Jac(_rMailHandler);
case 0x3ad3b7ac: // Naruto3
case 0x3daf59b9: // Alien Hominid
case 0x4e8a8b21: // spdemo, ctaxi, 18 wheeler, disney, monkeyball2,cubivore,puzzlecollection,wario,
// capcom vs snk, naruto2, lost kingdoms, star fox, mario party 4, mortal kombat,
// smugglers run warzone, smash brothers, sonic mega collection, ZooCube
// nddemo, starfox
case 0x07f88145: // bustamove, ikaruga, fzero, robotech battle cry, star soldier, soul calibur2,
// Zelda:OOT, Tony hawk, viewtiful joe
case 0xe2136399: // billy hatcher, dragonballz, mario party 5, TMNT, ava1080
DebugLog("AX ucode chosen, yay!");
return new CUCode_AX(_rMailHandler);
case 0x6CA33A6D: // DK Jungle Beat
case 0x86840740: // zelda
case 0x56d36052: // mario
case 0x2fcdf1ec: // mariokart, zelda 4 swords
DebugLog("Zelda ucode chosen");
return new CUCode_Zelda(_rMailHandler);
// WII CRCs
case 0x6c3f6f94: // zelda - PAL
case 0xd643001f: // mario galaxy - PAL
DebugLog("Zelda Wii ucode chosen");
return new CUCode_Zelda(_rMailHandler);
case 0x347112ba: // raving rabbits
DebugLog("Wii - AX chosen");
return new CUCode_AX(_rMailHandler, true);
default:
PanicAlert("Unknown ucode (CRC = %08x) - forcing AX", _CRC);
return new CUCode_AX(_rMailHandler);
}
return NULL;
}

View File

@ -1,203 +1,203 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//#include "Common.h"
#include "ChunkFile.h"
#include "pluginspecs_dsp.h"
#include "DSPHandler.h"
DSPInitialize g_dspInitialize;
u8* g_pMemory;
struct DSPState
{
u32 CPUMailbox;
bool CPUMailbox_Written[2];
u32 DSPMailbox;
bool DSPMailbox_Read[2];
DSPState()
{
CPUMailbox = 0x00000000;
CPUMailbox_Written[0] = false;
CPUMailbox_Written[1] = false;
DSPMailbox = 0x00000000;
DSPMailbox_Read[0] = true;
DSPMailbox_Read[1] = true;
}
};
DSPState g_dspState;
#ifdef _WIN32
HINSTANCE g_hInstance = NULL;
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
DWORD dwReason, // reason called
LPVOID lpvReserved) // reserved
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
default:
break;
}
g_hInstance = hinstDLL;
return(TRUE);
}
#endif
void DllDebugger(HWND _hParent)
{
// TODO: implement
}
void GetDllInfo(PLUGIN_INFO* _PluginInfo)
{
_PluginInfo->Version = 0x0100;
_PluginInfo->Type = PLUGIN_TYPE_DSP;
#ifdef DEBUGFAST
sprintf(_PluginInfo->Name, "Dolphin DSP-NULL Plugin (DebugFast) ");
#else
#ifndef _DEBUG
sprintf(_PluginInfo->Name, "Dolphin DSP-NULL Plugin ");
#else
sprintf(_PluginInfo->Name, "Dolphin DSP-NULL Plugin (Debug) ");
#endif
#endif
}
void DllAbout(HWND _hParent)
{
}
void DllConfig(HWND _hParent)
{
}
void DSP_Initialize(DSPInitialize _dspInitialize)
{
g_dspInitialize = _dspInitialize;
g_pMemory = g_dspInitialize.pGetMemoryPointer(0);
CDSPHandler::CreateInstance();
}
void DSP_Shutdown()
{
CDSPHandler::Destroy();
}
void DSP_DoState(unsigned char **ptr, int mode) {
PointerWrap p(ptr, mode);
}
unsigned short DSP_ReadMailboxHigh(bool _CPUMailbox)
{
if (_CPUMailbox)
{
return (g_dspState.CPUMailbox >> 16) & 0xFFFF;
}
else
{
return CDSPHandler::GetInstance().AccessMailHandler().ReadDSPMailboxHigh();
}
}
unsigned short DSP_ReadMailboxLow(bool _CPUMailbox)
{
if (_CPUMailbox)
{
return g_dspState.CPUMailbox & 0xFFFF;
}
else
{
return CDSPHandler::GetInstance().AccessMailHandler().ReadDSPMailboxLow();
}
}
void Update_DSP_WriteRegister()
{
// check if the whole message is complete and if we can send it
if (g_dspState.CPUMailbox_Written[0] && g_dspState.CPUMailbox_Written[1])
{
CDSPHandler::GetInstance().SendMailToDSP(g_dspState.CPUMailbox);
g_dspState.CPUMailbox_Written[0] = g_dspState.CPUMailbox_Written[1] = false;
g_dspState.CPUMailbox = 0; // Mail sent so clear it to show that it is progressed
}
}
void DSP_WriteMailboxHigh(bool _CPUMailbox, unsigned short _Value)
{
if (_CPUMailbox)
{
g_dspState.CPUMailbox = (g_dspState.CPUMailbox & 0xFFFF) | (_Value << 16);
g_dspState.CPUMailbox_Written[0] = true;
Update_DSP_WriteRegister();
}
else
{
PanicAlert("CPU can't write %08x to DSP mailbox", _Value);
}
}
void DSP_WriteMailboxLow(bool _CPUMailbox, unsigned short _Value)
{
if (_CPUMailbox)
{
g_dspState.CPUMailbox = (g_dspState.CPUMailbox & 0xFFFF0000) | _Value;
g_dspState.CPUMailbox_Written[1] = true;
Update_DSP_WriteRegister();
}
else
{
PanicAlert("CPU can't write %08x to DSP mailbox", _Value);
}
}
unsigned short DSP_WriteControlRegister(unsigned short _Value)
{
return CDSPHandler::GetInstance().WriteControlRegister(_Value);
}
unsigned short DSP_ReadControlRegister()
{
return CDSPHandler::GetInstance().ReadControlRegister();
}
void DSP_Update(int cycles)
{
CDSPHandler::GetInstance().Update();
}
void DSP_SendAIBuffer(unsigned int address, int sample_rate)
{
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//#include "Common.h"
#include "ChunkFile.h"
#include "pluginspecs_dsp.h"
#include "DSPHandler.h"
DSPInitialize g_dspInitialize;
u8* g_pMemory;
struct DSPState
{
u32 CPUMailbox;
bool CPUMailbox_Written[2];
u32 DSPMailbox;
bool DSPMailbox_Read[2];
DSPState()
{
CPUMailbox = 0x00000000;
CPUMailbox_Written[0] = false;
CPUMailbox_Written[1] = false;
DSPMailbox = 0x00000000;
DSPMailbox_Read[0] = true;
DSPMailbox_Read[1] = true;
}
};
DSPState g_dspState;
#ifdef _WIN32
HINSTANCE g_hInstance = NULL;
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
DWORD dwReason, // reason called
LPVOID lpvReserved) // reserved
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
default:
break;
}
g_hInstance = hinstDLL;
return(TRUE);
}
#endif
void DllDebugger(HWND _hParent)
{
// TODO: implement
}
void GetDllInfo(PLUGIN_INFO* _PluginInfo)
{
_PluginInfo->Version = 0x0100;
_PluginInfo->Type = PLUGIN_TYPE_DSP;
#ifdef DEBUGFAST
sprintf(_PluginInfo->Name, "Dolphin DSP-NULL Plugin (DebugFast) ");
#else
#ifndef _DEBUG
sprintf(_PluginInfo->Name, "Dolphin DSP-NULL Plugin ");
#else
sprintf(_PluginInfo->Name, "Dolphin DSP-NULL Plugin (Debug) ");
#endif
#endif
}
void DllAbout(HWND _hParent)
{
}
void DllConfig(HWND _hParent)
{
}
void DSP_Initialize(DSPInitialize _dspInitialize)
{
g_dspInitialize = _dspInitialize;
g_pMemory = g_dspInitialize.pGetMemoryPointer(0);
CDSPHandler::CreateInstance();
}
void DSP_Shutdown()
{
CDSPHandler::Destroy();
}
void DSP_DoState(unsigned char **ptr, int mode) {
PointerWrap p(ptr, mode);
}
unsigned short DSP_ReadMailboxHigh(bool _CPUMailbox)
{
if (_CPUMailbox)
{
return (g_dspState.CPUMailbox >> 16) & 0xFFFF;
}
else
{
return CDSPHandler::GetInstance().AccessMailHandler().ReadDSPMailboxHigh();
}
}
unsigned short DSP_ReadMailboxLow(bool _CPUMailbox)
{
if (_CPUMailbox)
{
return g_dspState.CPUMailbox & 0xFFFF;
}
else
{
return CDSPHandler::GetInstance().AccessMailHandler().ReadDSPMailboxLow();
}
}
void Update_DSP_WriteRegister()
{
// check if the whole message is complete and if we can send it
if (g_dspState.CPUMailbox_Written[0] && g_dspState.CPUMailbox_Written[1])
{
CDSPHandler::GetInstance().SendMailToDSP(g_dspState.CPUMailbox);
g_dspState.CPUMailbox_Written[0] = g_dspState.CPUMailbox_Written[1] = false;
g_dspState.CPUMailbox = 0; // Mail sent so clear it to show that it is progressed
}
}
void DSP_WriteMailboxHigh(bool _CPUMailbox, unsigned short _Value)
{
if (_CPUMailbox)
{
g_dspState.CPUMailbox = (g_dspState.CPUMailbox & 0xFFFF) | (_Value << 16);
g_dspState.CPUMailbox_Written[0] = true;
Update_DSP_WriteRegister();
}
else
{
PanicAlert("CPU can't write %08x to DSP mailbox", _Value);
}
}
void DSP_WriteMailboxLow(bool _CPUMailbox, unsigned short _Value)
{
if (_CPUMailbox)
{
g_dspState.CPUMailbox = (g_dspState.CPUMailbox & 0xFFFF0000) | _Value;
g_dspState.CPUMailbox_Written[1] = true;
Update_DSP_WriteRegister();
}
else
{
PanicAlert("CPU can't write %08x to DSP mailbox", _Value);
}
}
unsigned short DSP_WriteControlRegister(unsigned short _Value)
{
return CDSPHandler::GetInstance().WriteControlRegister(_Value);
}
unsigned short DSP_ReadControlRegister()
{
return CDSPHandler::GetInstance().ReadControlRegister();
}
void DSP_Update(int cycles)
{
CDSPHandler::GetInstance().Update();
}
void DSP_SendAIBuffer(unsigned int address, int sample_rate)
{
}

View File

@ -1,189 +1,189 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
#include "DirectInputBase.h"
DInput::DInput()
: g_pDI(NULL),
g_pKeyboard(NULL)
{}
DInput::~DInput()
{
Free();
}
void DInput::DIKToString(unsigned int keycode, char *keyStr)
{
switch(keycode) {
case DIK_RETURN:
sprintf(keyStr, "Enter");
break;
case DIK_UP:
sprintf(keyStr, "Up");
break;
case DIK_DOWN:
sprintf(keyStr, "Down");
break;
case DIK_LEFT:
sprintf(keyStr, "Left");
break;
case DIK_RIGHT:
sprintf(keyStr, "Right");
break;
case DIK_HOME:
strcpy(keyStr, "Home");
break;
case DIK_END:
strcpy(keyStr, "End");
break;
case DIK_INSERT:
strcpy(keyStr, "Ins");
break;
case DIK_DELETE:
strcpy(keyStr, "Del");
break;
case DIK_PGUP:
strcpy(keyStr, "PgUp");
break;
case DIK_PGDN:
strcpy(keyStr, "PgDn");
break;
case DIK_NUMPAD0:
strcpy(keyStr, "Num 0");
break;
case DIK_NUMPAD1:
strcpy(keyStr, "Num 1");
break;
case DIK_NUMPAD2:
strcpy(keyStr, "Num 2");
break;
case DIK_NUMPAD3:
strcpy(keyStr, "Num 3");
break;
case DIK_NUMPAD4:
strcpy(keyStr, "Num 4");
break;
case DIK_NUMPAD5:
strcpy(keyStr, "Num 5");
break;
case DIK_NUMPAD6:
strcpy(keyStr, "Num 6");
break;
case DIK_NUMPAD7:
strcpy(keyStr, "Num 7");
break;
case DIK_NUMPAD8:
strcpy(keyStr, "Num 8");
break;
case DIK_NUMPAD9:
strcpy(keyStr, "Num 9");
break;
case DIK_NUMPADSLASH:
strcpy(keyStr, "Num /");
break;
default:
GetKeyNameText(keycode << 16, keyStr, 64);
break;
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
#include "DirectInputBase.h"
DInput::DInput()
: g_pDI(NULL),
g_pKeyboard(NULL)
{}
DInput::~DInput()
{
Free();
}
void DInput::DIKToString(unsigned int keycode, char *keyStr)
{
switch(keycode) {
case DIK_RETURN:
sprintf(keyStr, "Enter");
break;
case DIK_UP:
sprintf(keyStr, "Up");
break;
case DIK_DOWN:
sprintf(keyStr, "Down");
break;
case DIK_LEFT:
sprintf(keyStr, "Left");
break;
case DIK_RIGHT:
sprintf(keyStr, "Right");
break;
case DIK_HOME:
strcpy(keyStr, "Home");
break;
case DIK_END:
strcpy(keyStr, "End");
break;
case DIK_INSERT:
strcpy(keyStr, "Ins");
break;
case DIK_DELETE:
strcpy(keyStr, "Del");
break;
case DIK_PGUP:
strcpy(keyStr, "PgUp");
break;
case DIK_PGDN:
strcpy(keyStr, "PgDn");
break;
case DIK_NUMPAD0:
strcpy(keyStr, "Num 0");
break;
case DIK_NUMPAD1:
strcpy(keyStr, "Num 1");
break;
case DIK_NUMPAD2:
strcpy(keyStr, "Num 2");
break;
case DIK_NUMPAD3:
strcpy(keyStr, "Num 3");
break;
case DIK_NUMPAD4:
strcpy(keyStr, "Num 4");
break;
case DIK_NUMPAD5:
strcpy(keyStr, "Num 5");
break;
case DIK_NUMPAD6:
strcpy(keyStr, "Num 6");
break;
case DIK_NUMPAD7:
strcpy(keyStr, "Num 7");
break;
case DIK_NUMPAD8:
strcpy(keyStr, "Num 8");
break;
case DIK_NUMPAD9:
strcpy(keyStr, "Num 9");
break;
case DIK_NUMPADSLASH:
strcpy(keyStr, "Num /");
break;
default:
GetKeyNameText(keycode << 16, keyStr, 64);
break;
}
}
HRESULT DInput::Init(HWND hWnd)
{
HRESULT hr;
DWORD dwCoopFlags;
dwCoopFlags = DISCL_FOREGROUND | DISCL_NOWINKEY;
// Create a DInput object
if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
IID_IDirectInput8, (VOID* *)&g_pDI, NULL)))
{
MessageBox(0, "Direct Input Create Failed", 0, MB_ICONERROR);
return(hr);
}
if (FAILED(hr = g_pDI->CreateDevice(GUID_SysKeyboard, &g_pKeyboard, NULL)))
{
MessageBox(0, "Couldn't access keyboard", 0, MB_ICONERROR);
Free();
return(hr);
}
g_pKeyboard->SetDataFormat(&c_dfDIKeyboard);
g_pKeyboard->SetCooperativeLevel(hWnd, dwCoopFlags);
g_pKeyboard->Acquire();
return(S_OK);
}
void DInput::Free()
{
if (g_pKeyboard)
{
g_pKeyboard->Unacquire();
g_pKeyboard->Release();
g_pKeyboard = 0;
}
if (g_pDI)
{
g_pDI->Release();
g_pDI = 0;
}
}
// Desc: Read the input device's state when in immediate mode and display it.
HRESULT DInput::Read()
{
HRESULT hr;
if (NULL == g_pKeyboard)
{
return(S_OK);
}
// Get the input's device state, and put the state in dims
ZeroMemory(diks, sizeof(diks));
hr = g_pKeyboard->GetDeviceState(sizeof(diks), diks);
//for (int i=0; i<256; i++)
// if (diks[i])MessageBox(0,"DSFJDKSF|",0,0);
if (FAILED(hr))
{
// DirectInput may be telling us that the input stream has been
// interrupted. We aren't tracking any state between polls, so
// we don't have any special reset that needs to be done.
// We just re-acquire and try again.
// If input is lost then acquire and keep trying
hr = g_pKeyboard->Acquire();
while (hr == DIERR_INPUTLOST)
{
hr = g_pKeyboard->Acquire();
}
// hr may be DIERR_OTHERAPPHASPRIO or other errors. This
// may occur when the app is minimized or in the process of
// switching, so just try again later
return(S_OK);
}
return(S_OK);
}
}
HRESULT DInput::Init(HWND hWnd)
{
HRESULT hr;
DWORD dwCoopFlags;
dwCoopFlags = DISCL_FOREGROUND | DISCL_NOWINKEY;
// Create a DInput object
if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
IID_IDirectInput8, (VOID* *)&g_pDI, NULL)))
{
MessageBox(0, "Direct Input Create Failed", 0, MB_ICONERROR);
return(hr);
}
if (FAILED(hr = g_pDI->CreateDevice(GUID_SysKeyboard, &g_pKeyboard, NULL)))
{
MessageBox(0, "Couldn't access keyboard", 0, MB_ICONERROR);
Free();
return(hr);
}
g_pKeyboard->SetDataFormat(&c_dfDIKeyboard);
g_pKeyboard->SetCooperativeLevel(hWnd, dwCoopFlags);
g_pKeyboard->Acquire();
return(S_OK);
}
void DInput::Free()
{
if (g_pKeyboard)
{
g_pKeyboard->Unacquire();
g_pKeyboard->Release();
g_pKeyboard = 0;
}
if (g_pDI)
{
g_pDI->Release();
g_pDI = 0;
}
}
// Desc: Read the input device's state when in immediate mode and display it.
HRESULT DInput::Read()
{
HRESULT hr;
if (NULL == g_pKeyboard)
{
return(S_OK);
}
// Get the input's device state, and put the state in dims
ZeroMemory(diks, sizeof(diks));
hr = g_pKeyboard->GetDeviceState(sizeof(diks), diks);
//for (int i=0; i<256; i++)
// if (diks[i])MessageBox(0,"DSFJDKSF|",0,0);
if (FAILED(hr))
{
// DirectInput may be telling us that the input stream has been
// interrupted. We aren't tracking any state between polls, so
// we don't have any special reset that needs to be done.
// We just re-acquire and try again.
// If input is lost then acquire and keep trying
hr = g_pKeyboard->Acquire();
while (hr == DIERR_INPUTLOST)
{
hr = g_pKeyboard->Acquire();
}
// hr may be DIERR_OTHERAPPHASPRIO or other errors. This
// may occur when the app is minimized or in the process of
// switching, so just try again later
return(S_OK);
}
return(S_OK);
}

View File

@ -1,339 +1,339 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "ConfigDlg.h"
#include "../PadSimple.h"
#ifdef _WIN32
#include "XInput.h"
#include "../DirectInputBase.h"
DInput m_dinput;
#endif
BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
EVT_CLOSE(ConfigDialog::OnClose)
EVT_BUTTON(ID_CLOSE,ConfigDialog::OnCloseClick)
EVT_BUTTON(ID_PAD_ABOUT,ConfigDialog::DllAbout)
EVT_CHECKBOX(ID_ATTACHED,ConfigDialog::ControllerSettingsChanged)
EVT_CHECKBOX(ID_X360PAD,ConfigDialog::ControllerSettingsChanged)
EVT_CHOICE(ID_X360PAD_CHOICE,ConfigDialog::ControllerSettingsChanged)
EVT_CHECKBOX(ID_RUMBLE,ConfigDialog::ControllerSettingsChanged)
EVT_CHECKBOX(ID_DISABLE,ConfigDialog::ControllerSettingsChanged)
EVT_BUTTON(CTL_A,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_B,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_X,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_Y,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_Z,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_START,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_L,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_R,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_MAINUP,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_MAINDOWN,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_MAINLEFT,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_MAINRIGHT,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_SUBUP,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_SUBDOWN,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_SUBLEFT,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_SUBRIGHT,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_DPADUP,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_DPADDOWN,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_DPADLEFT,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_DPADRIGHT,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_HALFPRESS,ConfigDialog::OnButtonClick)
END_EVENT_TABLE()
ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
: wxDialog(parent, id, title, position, size, style)
{
#ifdef _WIN32
m_dinput.Init((HWND)parent);
#endif
clickedButton = NULL;
CreateGUIControls();
Fit();
}
ConfigDialog::~ConfigDialog()
{
}
inline void AddControl(wxPanel *pan, wxButton **button, wxStaticBoxSizer *sizer,
const char *name, int ctl, int controller)
{
wxBoxSizer *hButton = new wxBoxSizer(wxHORIZONTAL);
char keyStr[10] = {0};
hButton->Add(new wxStaticText(pan, 0, wxString::FromAscii(name),
wxDefaultPosition, wxDefaultSize), 0,
wxALIGN_CENTER_VERTICAL|wxALL);
#ifdef _WIN32
DInput::DIKToString(pad[controller].keyForControl[ctl], keyStr);
#else
XKeyToString(pad[controller].keyForControl[ctl], keyStr);
#endif
*button = new wxButton(pan, ctl, wxString::FromAscii(keyStr),
wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS);
hButton->Add(*button, 0, wxALIGN_RIGHT|wxALL);
sizer->Add(hButton, 0, wxALIGN_RIGHT|wxALL);
}
void ConfigDialog::CreateGUIControls()
{
// Notebook
m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize);
// Controller pages
m_Controller[0] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE1, wxDefaultPosition, wxDefaultSize);
m_Notebook->AddPage(m_Controller[0], wxT("Controller 1"));
m_Controller[1] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE2, wxDefaultPosition, wxDefaultSize);
m_Notebook->AddPage(m_Controller[1], wxT("Controller 2"));
m_Controller[2] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE3, wxDefaultPosition, wxDefaultSize);
m_Notebook->AddPage(m_Controller[2], wxT("Controller 3"));
m_Controller[3] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE4, wxDefaultPosition, wxDefaultSize);
m_Notebook->AddPage(m_Controller[3], wxT("Controller 4"));
// Standard buttons
m_Close = new wxButton(this, ID_CLOSE, wxT("Close"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_About = new wxButton(this, ID_PAD_ABOUT, wxT("About"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
// Put notebook and standard buttons in sizers
wxBoxSizer* sSButtons;
sSButtons = new wxBoxSizer(wxHORIZONTAL);
sSButtons->Add(m_About,0,wxALL, 5);
sSButtons->Add(0, 0, 1, wxEXPAND, 5);
sSButtons->Add(m_Close, 0, wxALL, 5);
wxBoxSizer* sMain;
sMain = new wxBoxSizer(wxVERTICAL);
sMain->Add(m_Notebook, 1, wxEXPAND|wxALL, 5);
sMain->Add(sSButtons, 0, wxEXPAND, 5);
this->SetSizer(sMain);
this->Layout();
#ifdef _WIN32
// Add connected XPads
for (int x = 0; x < 4; x++)
{
XINPUT_STATE xstate;
DWORD xresult = XInputGetState(x, &xstate);
if (xresult == ERROR_SUCCESS)
{
arrayStringFor_X360Pad.Add(wxString::Format("%i", x+1));
}
}
#endif
for(int i = 0; i < 4; i++)
{
sbDevice[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Controller Settings"));
sDevice[i] = new wxBoxSizer(wxHORIZONTAL);
m_Attached[i] = new wxCheckBox(m_Controller[i], ID_ATTACHED, wxT("Controller attached"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
#ifdef _WIN32
m_X360Pad[i] = new wxCheckBox(m_Controller[i], ID_X360PAD, wxT("Enable X360Pad"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_X360PadC[i] = new wxChoice(m_Controller[i], ID_X360PAD_CHOICE, wxDefaultPosition, wxDefaultSize, arrayStringFor_X360Pad, 0, wxDefaultValidator);
m_Rumble[i] = new wxCheckBox(m_Controller[i], ID_RUMBLE, wxT("Enable rumble"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
#endif
m_Disable[i] = new wxCheckBox(m_Controller[i], ID_DISABLE, wxT("Disable when Dolphin is not in focus"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_Attached[i]->SetValue(pad[i].bAttached);
#ifdef _WIN32
if (arrayStringFor_X360Pad.IsEmpty())
{
m_X360Pad[i]->SetLabel(wxT("Enable X360Pad - No pad connected"));
m_X360Pad[i]->SetValue(false);
m_X360Pad[i]->Enable(false);
pad[i].bEnableXPad = false;
m_X360PadC[i]->Hide();
m_Rumble[i]->Hide();
}
else
{
m_X360Pad[i]->SetValue(pad[i].bEnableXPad);
m_X360PadC[i]->SetSelection(pad[i].XPadPlayer);
m_X360PadC[i]->Enable(m_X360Pad[i]->IsChecked());
m_Rumble[i]->SetValue(pad[i].bRumble);
m_Rumble[i]->Enable(m_X360Pad[i]->IsChecked());
}
#endif
m_Disable[i]->SetValue(pad[i].bDisable);
sDevice[i]->Add(m_Attached[i], 0, wxEXPAND|wxALL, 1);
sDevice[i]->AddStretchSpacer();
#ifdef _WIN32
sDevice[i]->Add(m_X360Pad[i], 0, wxEXPAND|wxALL, 1);
sDevice[i]->Add(m_X360PadC[i], 0, wxEXPAND|wxALL, 1);
sDevice[i]->Add(m_Rumble[i], 0, wxEXPAND|wxALL, 1);
sDevice[i]->AddStretchSpacer();
#endif
sDevice[i]->Add(m_Disable[i], 0, wxEXPAND|wxALL, 1);
sbDevice[i]->Add(sDevice[i], 0, wxEXPAND|wxALL, 1);
sButtons[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Buttons"));
AddControl(m_Controller[i], &(m_ButtonA[i]), sButtons[i], "A: ", CTL_A, i);
AddControl(m_Controller[i], &(m_ButtonB[i]), sButtons[i], "B: ", CTL_B, i);
AddControl(m_Controller[i], &(m_ButtonX[i]), sButtons[i], "X: ", CTL_X, i);
AddControl(m_Controller[i], &(m_ButtonY[i]), sButtons[i], "Y: ", CTL_Y, i);
AddControl(m_Controller[i], &(m_ButtonZ[i]), sButtons[i], "Z: ", CTL_Z, i);
AddControl(m_Controller[i], &(m_ButtonStart[i]), sButtons[i], "Start: ", CTL_START, i);
sTriggers[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Triggers"));
AddControl(m_Controller[i], &(m_ButtonL[i]), sTriggers[i], " L: ", CTL_L, i);
AddControl(m_Controller[i], &(m_ButtonR[i]), sTriggers[i], " R: ", CTL_R, i);
sModifiers[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Modifiers"));
AddControl(m_Controller[i], &(m_HalfPress[i]), sModifiers[i], "1/2 Press: ", CTL_HALFPRESS, i);
sStick[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Main Stick"));
AddControl(m_Controller[i], &(m_StickUp[i]), sStick[i], "Up: ", CTL_MAINUP, i);
AddControl(m_Controller[i], &(m_StickDown[i]), sStick[i], "Down: ", CTL_MAINDOWN, i);
AddControl(m_Controller[i], &(m_StickLeft[i]), sStick[i], "Left: ", CTL_MAINLEFT, i);
AddControl(m_Controller[i], &(m_StickRight[i]), sStick[i], "Right: ", CTL_MAINRIGHT, i);
sDPad[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("D-Pad"));
AddControl(m_Controller[i], &(m_DPadUp[i]), sDPad[i], "Up: ", CTL_DPADUP, i);
AddControl(m_Controller[i], &(m_DPadDown[i]), sDPad[i], "Down: ", CTL_DPADDOWN, i);
AddControl(m_Controller[i], &(m_DPadLeft[i]), sDPad[i], "Left: ", CTL_DPADLEFT, i);
AddControl(m_Controller[i], &(m_DPadRight[i]), sDPad[i], "Right: ", CTL_DPADRIGHT, i);
sCStick[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("C-Stick"));
AddControl(m_Controller[i], &(m_CStickUp[i]), sCStick[i], "Up: ", CTL_SUBUP, i);
AddControl(m_Controller[i], &(m_CStickDown[i]), sCStick[i], "Down: ", CTL_SUBDOWN, i);
AddControl(m_Controller[i], &(m_CStickLeft[i]), sCStick[i], "Left: ", CTL_SUBLEFT, i);
AddControl(m_Controller[i], &(m_CStickRight[i]), sCStick[i], "Right: ", CTL_SUBRIGHT, i);
sPage[i] = new wxGridBagSizer(0, 0);
sPage[i]->SetFlexibleDirection(wxBOTH);
sPage[i]->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
sPage[i]->Add(sbDevice[i], wxGBPosition(0, 0), wxGBSpan(1, 5), wxEXPAND|wxALL, 1);
sPage[i]->Add(sButtons[i], wxGBPosition(1, 0), wxGBSpan(2, 1), wxALL, 1);
sPage[i]->Add(sTriggers[i], wxGBPosition(1, 1), wxGBSpan(1, 1), wxEXPAND|wxALL, 1);
sPage[i]->Add(sModifiers[i], wxGBPosition(2, 1), wxGBSpan(1, 1), wxALL, 1);
sPage[i]->Add(sStick[i], wxGBPosition(1, 2), wxGBSpan(2, 1), wxALL, 1);
sPage[i]->Add(sDPad[i], wxGBPosition(1, 3), wxGBSpan(2, 1), wxALL, 1);
sPage[i]->Add(sCStick[i], wxGBPosition(1, 4), wxGBSpan(2, 1), wxALL, 1);
m_Controller[i]->SetSizer(sPage[i]);
sPage[i]->Layout();
}
}
void ConfigDialog::OnClose(wxCloseEvent& event)
{
#ifdef _WIN32
m_dinput.Free();
#endif
EndModal(0);
}
void ConfigDialog::OnKeyDown(wxKeyEvent& event)
{
if(clickedButton != NULL)
{
int page = m_Notebook->GetSelection();
#ifdef _WIN32
m_dinput.Read();
for(int i = 0; i < 255; i++)
{
if(m_dinput.diks[i])
{
char keyStr[10] = {0};
pad[page].keyForControl[clickedButton->GetId()] = i;
DInput::DIKToString(i, keyStr);
clickedButton->SetLabel(wxString::FromAscii(keyStr));
break;
}
}
#else
pad[page].keyForControl[clickedButton->GetId()] = wxCharCodeWXToX(event.GetKeyCode());
clickedButton->SetLabel(wxString::Format(_T("%c"), event.GetKeyCode()));
#endif
clickedButton->Disconnect();
}
clickedButton = NULL;
event.Skip();
}
void ConfigDialog::OnCloseClick(wxCommandEvent& event)
{
Close();
}
void ConfigDialog::ControllerSettingsChanged(wxCommandEvent& event)
{
int page = m_Notebook->GetSelection();
switch (event.GetId())
{
case ID_ATTACHED:
pad[page].bAttached = m_Attached[page]->GetValue();
break;
case ID_X360PAD:
pad[page].bEnableXPad = event.IsChecked();
m_Rumble[page]->Enable(event.IsChecked());
m_X360PadC[page]->Enable(event.IsChecked());
break;
case ID_X360PAD_CHOICE:
pad[page].XPadPlayer = event.GetSelection();
break;
case ID_RUMBLE:
pad[page].bRumble = m_Rumble[page]->GetValue();
break;
case ID_DISABLE:
pad[page].bDisable = m_Disable[page]->GetValue();
break;
}
}
void ConfigDialog::OnButtonClick(wxCommandEvent& event)
{
if(clickedButton)
{
clickedButton->SetLabel(oldLabel);
}
clickedButton = (wxButton *)event.GetEventObject();
oldLabel = clickedButton->GetLabel();
clickedButton->SetLabel(_("Press Key"));
clickedButton->Connect(wxID_ANY, wxEVT_KEY_DOWN,
wxKeyEventHandler(ConfigDialog::OnKeyDown),
(wxObject*)NULL, this);
}
void ConfigDialog::DllAbout(wxCommandEvent& event)
{
wxString message;
#ifdef _WIN32
message = _("A simple keyboard and XInput plugin for dolphin.");
#else
message = _("A simple keyboard plugin for dolphin.");
#endif
wxMessageBox(_T("Dolphin PadSimple Plugin\nBy ector and F|RES\n\n" + message),
_T("Dolphin PadSimple"), wxOK, this);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "ConfigDlg.h"
#include "../PadSimple.h"
#ifdef _WIN32
#include "XInput.h"
#include "../DirectInputBase.h"
DInput m_dinput;
#endif
BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
EVT_CLOSE(ConfigDialog::OnClose)
EVT_BUTTON(ID_CLOSE,ConfigDialog::OnCloseClick)
EVT_BUTTON(ID_PAD_ABOUT,ConfigDialog::DllAbout)
EVT_CHECKBOX(ID_ATTACHED,ConfigDialog::ControllerSettingsChanged)
EVT_CHECKBOX(ID_X360PAD,ConfigDialog::ControllerSettingsChanged)
EVT_CHOICE(ID_X360PAD_CHOICE,ConfigDialog::ControllerSettingsChanged)
EVT_CHECKBOX(ID_RUMBLE,ConfigDialog::ControllerSettingsChanged)
EVT_CHECKBOX(ID_DISABLE,ConfigDialog::ControllerSettingsChanged)
EVT_BUTTON(CTL_A,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_B,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_X,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_Y,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_Z,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_START,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_L,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_R,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_MAINUP,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_MAINDOWN,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_MAINLEFT,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_MAINRIGHT,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_SUBUP,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_SUBDOWN,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_SUBLEFT,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_SUBRIGHT,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_DPADUP,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_DPADDOWN,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_DPADLEFT,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_DPADRIGHT,ConfigDialog::OnButtonClick)
EVT_BUTTON(CTL_HALFPRESS,ConfigDialog::OnButtonClick)
END_EVENT_TABLE()
ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
: wxDialog(parent, id, title, position, size, style)
{
#ifdef _WIN32
m_dinput.Init((HWND)parent);
#endif
clickedButton = NULL;
CreateGUIControls();
Fit();
}
ConfigDialog::~ConfigDialog()
{
}
inline void AddControl(wxPanel *pan, wxButton **button, wxStaticBoxSizer *sizer,
const char *name, int ctl, int controller)
{
wxBoxSizer *hButton = new wxBoxSizer(wxHORIZONTAL);
char keyStr[10] = {0};
hButton->Add(new wxStaticText(pan, 0, wxString::FromAscii(name),
wxDefaultPosition, wxDefaultSize), 0,
wxALIGN_CENTER_VERTICAL|wxALL);
#ifdef _WIN32
DInput::DIKToString(pad[controller].keyForControl[ctl], keyStr);
#else
XKeyToString(pad[controller].keyForControl[ctl], keyStr);
#endif
*button = new wxButton(pan, ctl, wxString::FromAscii(keyStr),
wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS);
hButton->Add(*button, 0, wxALIGN_RIGHT|wxALL);
sizer->Add(hButton, 0, wxALIGN_RIGHT|wxALL);
}
void ConfigDialog::CreateGUIControls()
{
// Notebook
m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize);
// Controller pages
m_Controller[0] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE1, wxDefaultPosition, wxDefaultSize);
m_Notebook->AddPage(m_Controller[0], wxT("Controller 1"));
m_Controller[1] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE2, wxDefaultPosition, wxDefaultSize);
m_Notebook->AddPage(m_Controller[1], wxT("Controller 2"));
m_Controller[2] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE3, wxDefaultPosition, wxDefaultSize);
m_Notebook->AddPage(m_Controller[2], wxT("Controller 3"));
m_Controller[3] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE4, wxDefaultPosition, wxDefaultSize);
m_Notebook->AddPage(m_Controller[3], wxT("Controller 4"));
// Standard buttons
m_Close = new wxButton(this, ID_CLOSE, wxT("Close"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_About = new wxButton(this, ID_PAD_ABOUT, wxT("About"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
// Put notebook and standard buttons in sizers
wxBoxSizer* sSButtons;
sSButtons = new wxBoxSizer(wxHORIZONTAL);
sSButtons->Add(m_About,0,wxALL, 5);
sSButtons->Add(0, 0, 1, wxEXPAND, 5);
sSButtons->Add(m_Close, 0, wxALL, 5);
wxBoxSizer* sMain;
sMain = new wxBoxSizer(wxVERTICAL);
sMain->Add(m_Notebook, 1, wxEXPAND|wxALL, 5);
sMain->Add(sSButtons, 0, wxEXPAND, 5);
this->SetSizer(sMain);
this->Layout();
#ifdef _WIN32
// Add connected XPads
for (int x = 0; x < 4; x++)
{
XINPUT_STATE xstate;
DWORD xresult = XInputGetState(x, &xstate);
if (xresult == ERROR_SUCCESS)
{
arrayStringFor_X360Pad.Add(wxString::Format("%i", x+1));
}
}
#endif
for(int i = 0; i < 4; i++)
{
sbDevice[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Controller Settings"));
sDevice[i] = new wxBoxSizer(wxHORIZONTAL);
m_Attached[i] = new wxCheckBox(m_Controller[i], ID_ATTACHED, wxT("Controller attached"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
#ifdef _WIN32
m_X360Pad[i] = new wxCheckBox(m_Controller[i], ID_X360PAD, wxT("Enable X360Pad"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_X360PadC[i] = new wxChoice(m_Controller[i], ID_X360PAD_CHOICE, wxDefaultPosition, wxDefaultSize, arrayStringFor_X360Pad, 0, wxDefaultValidator);
m_Rumble[i] = new wxCheckBox(m_Controller[i], ID_RUMBLE, wxT("Enable rumble"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
#endif
m_Disable[i] = new wxCheckBox(m_Controller[i], ID_DISABLE, wxT("Disable when Dolphin is not in focus"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_Attached[i]->SetValue(pad[i].bAttached);
#ifdef _WIN32
if (arrayStringFor_X360Pad.IsEmpty())
{
m_X360Pad[i]->SetLabel(wxT("Enable X360Pad - No pad connected"));
m_X360Pad[i]->SetValue(false);
m_X360Pad[i]->Enable(false);
pad[i].bEnableXPad = false;
m_X360PadC[i]->Hide();
m_Rumble[i]->Hide();
}
else
{
m_X360Pad[i]->SetValue(pad[i].bEnableXPad);
m_X360PadC[i]->SetSelection(pad[i].XPadPlayer);
m_X360PadC[i]->Enable(m_X360Pad[i]->IsChecked());
m_Rumble[i]->SetValue(pad[i].bRumble);
m_Rumble[i]->Enable(m_X360Pad[i]->IsChecked());
}
#endif
m_Disable[i]->SetValue(pad[i].bDisable);
sDevice[i]->Add(m_Attached[i], 0, wxEXPAND|wxALL, 1);
sDevice[i]->AddStretchSpacer();
#ifdef _WIN32
sDevice[i]->Add(m_X360Pad[i], 0, wxEXPAND|wxALL, 1);
sDevice[i]->Add(m_X360PadC[i], 0, wxEXPAND|wxALL, 1);
sDevice[i]->Add(m_Rumble[i], 0, wxEXPAND|wxALL, 1);
sDevice[i]->AddStretchSpacer();
#endif
sDevice[i]->Add(m_Disable[i], 0, wxEXPAND|wxALL, 1);
sbDevice[i]->Add(sDevice[i], 0, wxEXPAND|wxALL, 1);
sButtons[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Buttons"));
AddControl(m_Controller[i], &(m_ButtonA[i]), sButtons[i], "A: ", CTL_A, i);
AddControl(m_Controller[i], &(m_ButtonB[i]), sButtons[i], "B: ", CTL_B, i);
AddControl(m_Controller[i], &(m_ButtonX[i]), sButtons[i], "X: ", CTL_X, i);
AddControl(m_Controller[i], &(m_ButtonY[i]), sButtons[i], "Y: ", CTL_Y, i);
AddControl(m_Controller[i], &(m_ButtonZ[i]), sButtons[i], "Z: ", CTL_Z, i);
AddControl(m_Controller[i], &(m_ButtonStart[i]), sButtons[i], "Start: ", CTL_START, i);
sTriggers[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Triggers"));
AddControl(m_Controller[i], &(m_ButtonL[i]), sTriggers[i], " L: ", CTL_L, i);
AddControl(m_Controller[i], &(m_ButtonR[i]), sTriggers[i], " R: ", CTL_R, i);
sModifiers[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Modifiers"));
AddControl(m_Controller[i], &(m_HalfPress[i]), sModifiers[i], "1/2 Press: ", CTL_HALFPRESS, i);
sStick[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Main Stick"));
AddControl(m_Controller[i], &(m_StickUp[i]), sStick[i], "Up: ", CTL_MAINUP, i);
AddControl(m_Controller[i], &(m_StickDown[i]), sStick[i], "Down: ", CTL_MAINDOWN, i);
AddControl(m_Controller[i], &(m_StickLeft[i]), sStick[i], "Left: ", CTL_MAINLEFT, i);
AddControl(m_Controller[i], &(m_StickRight[i]), sStick[i], "Right: ", CTL_MAINRIGHT, i);
sDPad[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("D-Pad"));
AddControl(m_Controller[i], &(m_DPadUp[i]), sDPad[i], "Up: ", CTL_DPADUP, i);
AddControl(m_Controller[i], &(m_DPadDown[i]), sDPad[i], "Down: ", CTL_DPADDOWN, i);
AddControl(m_Controller[i], &(m_DPadLeft[i]), sDPad[i], "Left: ", CTL_DPADLEFT, i);
AddControl(m_Controller[i], &(m_DPadRight[i]), sDPad[i], "Right: ", CTL_DPADRIGHT, i);
sCStick[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("C-Stick"));
AddControl(m_Controller[i], &(m_CStickUp[i]), sCStick[i], "Up: ", CTL_SUBUP, i);
AddControl(m_Controller[i], &(m_CStickDown[i]), sCStick[i], "Down: ", CTL_SUBDOWN, i);
AddControl(m_Controller[i], &(m_CStickLeft[i]), sCStick[i], "Left: ", CTL_SUBLEFT, i);
AddControl(m_Controller[i], &(m_CStickRight[i]), sCStick[i], "Right: ", CTL_SUBRIGHT, i);
sPage[i] = new wxGridBagSizer(0, 0);
sPage[i]->SetFlexibleDirection(wxBOTH);
sPage[i]->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
sPage[i]->Add(sbDevice[i], wxGBPosition(0, 0), wxGBSpan(1, 5), wxEXPAND|wxALL, 1);
sPage[i]->Add(sButtons[i], wxGBPosition(1, 0), wxGBSpan(2, 1), wxALL, 1);
sPage[i]->Add(sTriggers[i], wxGBPosition(1, 1), wxGBSpan(1, 1), wxEXPAND|wxALL, 1);
sPage[i]->Add(sModifiers[i], wxGBPosition(2, 1), wxGBSpan(1, 1), wxALL, 1);
sPage[i]->Add(sStick[i], wxGBPosition(1, 2), wxGBSpan(2, 1), wxALL, 1);
sPage[i]->Add(sDPad[i], wxGBPosition(1, 3), wxGBSpan(2, 1), wxALL, 1);
sPage[i]->Add(sCStick[i], wxGBPosition(1, 4), wxGBSpan(2, 1), wxALL, 1);
m_Controller[i]->SetSizer(sPage[i]);
sPage[i]->Layout();
}
}
void ConfigDialog::OnClose(wxCloseEvent& event)
{
#ifdef _WIN32
m_dinput.Free();
#endif
EndModal(0);
}
void ConfigDialog::OnKeyDown(wxKeyEvent& event)
{
if(clickedButton != NULL)
{
int page = m_Notebook->GetSelection();
#ifdef _WIN32
m_dinput.Read();
for(int i = 0; i < 255; i++)
{
if(m_dinput.diks[i])
{
char keyStr[10] = {0};
pad[page].keyForControl[clickedButton->GetId()] = i;
DInput::DIKToString(i, keyStr);
clickedButton->SetLabel(wxString::FromAscii(keyStr));
break;
}
}
#else
pad[page].keyForControl[clickedButton->GetId()] = wxCharCodeWXToX(event.GetKeyCode());
clickedButton->SetLabel(wxString::Format(_T("%c"), event.GetKeyCode()));
#endif
clickedButton->Disconnect();
}
clickedButton = NULL;
event.Skip();
}
void ConfigDialog::OnCloseClick(wxCommandEvent& event)
{
Close();
}
void ConfigDialog::ControllerSettingsChanged(wxCommandEvent& event)
{
int page = m_Notebook->GetSelection();
switch (event.GetId())
{
case ID_ATTACHED:
pad[page].bAttached = m_Attached[page]->GetValue();
break;
case ID_X360PAD:
pad[page].bEnableXPad = event.IsChecked();
m_Rumble[page]->Enable(event.IsChecked());
m_X360PadC[page]->Enable(event.IsChecked());
break;
case ID_X360PAD_CHOICE:
pad[page].XPadPlayer = event.GetSelection();
break;
case ID_RUMBLE:
pad[page].bRumble = m_Rumble[page]->GetValue();
break;
case ID_DISABLE:
pad[page].bDisable = m_Disable[page]->GetValue();
break;
}
}
void ConfigDialog::OnButtonClick(wxCommandEvent& event)
{
if(clickedButton)
{
clickedButton->SetLabel(oldLabel);
}
clickedButton = (wxButton *)event.GetEventObject();
oldLabel = clickedButton->GetLabel();
clickedButton->SetLabel(_("Press Key"));
clickedButton->Connect(wxID_ANY, wxEVT_KEY_DOWN,
wxKeyEventHandler(ConfigDialog::OnKeyDown),
(wxObject*)NULL, this);
}
void ConfigDialog::DllAbout(wxCommandEvent& event)
{
wxString message;
#ifdef _WIN32
message = _("A simple keyboard and XInput plugin for dolphin.");
#else
message = _("A simple keyboard plugin for dolphin.");
#endif
wxMessageBox(_T("Dolphin PadSimple Plugin\nBy ector and F|RES\n\n" + message),
_T("Dolphin PadSimple"), wxOK, this);
}

View File

@ -1,18 +1,18 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"

File diff suppressed because it is too large Load Diff

View File

@ -1,76 +1,76 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <stdio.h>
#include "CPStructs.h"
#include "XFStructs.h"
#include "TransformEngine.h"
#include "VertexManager.h"
#include "VertexLoader.h"
// PROBLEM - matrix switching within vbuffers may be stateful!
void CPUpdateMatricesA()
{
float *flipmem = (float *)xfmem;
CTransformEngine::SetPosNormalMatrix(
flipmem + MatrixIndexA.PosNormalMtxIdx * 4, //CHECK
flipmem + 0x400 + 3 * (MatrixIndexA.PosNormalMtxIdx & 31)); //CHECK
CTransformEngine::SetTexMatrix(0,flipmem + MatrixIndexA.Tex0MtxIdx * 4);
CTransformEngine::SetTexMatrix(1,flipmem + MatrixIndexA.Tex1MtxIdx * 4);
CTransformEngine::SetTexMatrix(2,flipmem + MatrixIndexA.Tex2MtxIdx * 4);
CTransformEngine::SetTexMatrix(3,flipmem + MatrixIndexA.Tex3MtxIdx * 4);
}
void CPUpdateMatricesB()
{
float *flipmem = (float *)xfmem;
CTransformEngine::SetTexMatrix(4,flipmem + MatrixIndexB.Tex4MtxIdx * 4);
CTransformEngine::SetTexMatrix(5,flipmem + MatrixIndexB.Tex5MtxIdx * 4);
CTransformEngine::SetTexMatrix(6,flipmem + MatrixIndexB.Tex6MtxIdx * 4);
CTransformEngine::SetTexMatrix(7,flipmem + MatrixIndexB.Tex7MtxIdx * 4);
}
void LoadCPReg(u32 SubCmd, u32 Value)
{
switch (SubCmd & 0xF0)
{
case 0x30:
MatrixIndexA.Hex = Value;
CPUpdateMatricesA();
break;
case 0x40:
MatrixIndexB.Hex = Value;
CPUpdateMatricesB();
break;
case 0x50:
VertexManager::Flush(); VertexLoader::SetVtxDesc_Lo(Value);
break;
case 0x60:
VertexManager::Flush(); VertexLoader::SetVtxDesc_Hi(Value);
break;
case 0x70: g_VertexLoaders[SubCmd & 7].SetVAT_group0(Value); _assert_((SubCmd & 0x0F) < 8); break;
case 0x80: g_VertexLoaders[SubCmd & 7].SetVAT_group1(Value); _assert_((SubCmd & 0x0F) < 8); break;
case 0x90: g_VertexLoaders[SubCmd & 7].SetVAT_group2(Value); _assert_((SubCmd & 0x0F) < 8); break;
case 0xA0: arraybases[SubCmd & 0xF] = Value & 0xFFFFFFFF; break;
case 0xB0: arraystrides[SubCmd & 0xF] = Value & 0xFF; break;
}
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <stdio.h>
#include "CPStructs.h"
#include "XFStructs.h"
#include "TransformEngine.h"
#include "VertexManager.h"
#include "VertexLoader.h"
// PROBLEM - matrix switching within vbuffers may be stateful!
void CPUpdateMatricesA()
{
float *flipmem = (float *)xfmem;
CTransformEngine::SetPosNormalMatrix(
flipmem + MatrixIndexA.PosNormalMtxIdx * 4, //CHECK
flipmem + 0x400 + 3 * (MatrixIndexA.PosNormalMtxIdx & 31)); //CHECK
CTransformEngine::SetTexMatrix(0,flipmem + MatrixIndexA.Tex0MtxIdx * 4);
CTransformEngine::SetTexMatrix(1,flipmem + MatrixIndexA.Tex1MtxIdx * 4);
CTransformEngine::SetTexMatrix(2,flipmem + MatrixIndexA.Tex2MtxIdx * 4);
CTransformEngine::SetTexMatrix(3,flipmem + MatrixIndexA.Tex3MtxIdx * 4);
}
void CPUpdateMatricesB()
{
float *flipmem = (float *)xfmem;
CTransformEngine::SetTexMatrix(4,flipmem + MatrixIndexB.Tex4MtxIdx * 4);
CTransformEngine::SetTexMatrix(5,flipmem + MatrixIndexB.Tex5MtxIdx * 4);
CTransformEngine::SetTexMatrix(6,flipmem + MatrixIndexB.Tex6MtxIdx * 4);
CTransformEngine::SetTexMatrix(7,flipmem + MatrixIndexB.Tex7MtxIdx * 4);
}
void LoadCPReg(u32 SubCmd, u32 Value)
{
switch (SubCmd & 0xF0)
{
case 0x30:
MatrixIndexA.Hex = Value;
CPUpdateMatricesA();
break;
case 0x40:
MatrixIndexB.Hex = Value;
CPUpdateMatricesB();
break;
case 0x50:
VertexManager::Flush(); VertexLoader::SetVtxDesc_Lo(Value);
break;
case 0x60:
VertexManager::Flush(); VertexLoader::SetVtxDesc_Hi(Value);
break;
case 0x70: g_VertexLoaders[SubCmd & 7].SetVAT_group0(Value); _assert_((SubCmd & 0x0F) < 8); break;
case 0x80: g_VertexLoaders[SubCmd & 7].SetVAT_group1(Value); _assert_((SubCmd & 0x0F) < 8); break;
case 0x90: g_VertexLoaders[SubCmd & 7].SetVAT_group2(Value); _assert_((SubCmd & 0x0F) < 8); break;
case 0xA0: arraybases[SubCmd & 0xF] = Value & 0xFFFFFFFF; break;
case 0xB0: arraystrides[SubCmd & 0xF] = Value & 0xFF; break;
}
}

View File

@ -1,82 +1,82 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Config.h"
#include "IniFile.h"
Config g_Config;
Config::Config()
{
}
void Config::Load()
{
IniFile iniFile;
iniFile.Load(FULL_CONFIG_DIR "gfx_dx9.ini");
iniFile.Get("Hardware", "Adapter", &iAdapter, 0);
iniFile.Get("Hardware", "WindowedRes", &iWindowedRes, 0);
iniFile.Get("Hardware", "FullscreenRes", &iFSResolution, 0);
iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0);
iniFile.Get("Hardware", "RenderInMainframe", &renderToMainframe, false);
iniFile.Get("Hardware", "VSync", &bVsync, 0);
if (iAdapter == -1)
iAdapter = 0;
iniFile.Get("Settings", "OverlayStats", &bOverlayStats, false);
iniFile.Get("Settings", "Postprocess", &iPostprocessEffect, 0);
iniFile.Get("Settings", "DLOptimize", &iCompileDLsLevel, 0);
iniFile.Get("Settings", "DumpTextures", &bDumpTextures, 0);
iniFile.Get("Settings", "ShowShaderErrors", &bShowShaderErrors, 0);
iniFile.Get("Settings", "Multisample", &iMultisampleMode, 0);
iniFile.Get("Settings", "TexDumpPath", &texDumpPath, 0);
iniFile.Get("Settings", "TexFmtOverlayEnable", &bTexFmtOverlayEnable, 0);
iniFile.Get("Settings", "TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0);
iniFile.Get("Enhancements", "ForceFiltering", &bForceFiltering, 0);
iniFile.Get("Enhancements", "ForceMaxAniso", &bForceMaxAniso, 0);
}
void Config::Save()
{
IniFile iniFile;
iniFile.Load(FULL_CONFIG_DIR "gfx_dx9.ini");
iniFile.Set("Hardware", "Adapter", iAdapter);
iniFile.Set("Hardware", "WindowedRes", iWindowedRes);
iniFile.Set("Hardware", "FullscreenRes", iFSResolution);
iniFile.Set("Hardware", "Fullscreen", bFullscreen);
iniFile.Set("Hardware", "VSync", bVsync);
iniFile.Set("Hardware", "RenderInMainframe", renderToMainframe);
iniFile.Set("Settings", "OverlayStats", bOverlayStats);
iniFile.Set("Settings", "OverlayStats", bOverlayStats);
iniFile.Set("Settings", "Postprocess", iPostprocessEffect);
iniFile.Set("Settings", "DLOptimize", iCompileDLsLevel);
iniFile.Set("Settings", "DumpTextures", bDumpTextures);
iniFile.Set("Settings", "ShowShaderErrors", bShowShaderErrors);
iniFile.Set("Settings", "Multisample", iMultisampleMode);
iniFile.Set("Settings", "TexDumpPath", texDumpPath);
iniFile.Set("Settings", "TexFmtOverlayEnable", bTexFmtOverlayEnable);
iniFile.Set("Settings", "TexFmtOverlayCenter", bTexFmtOverlayCenter);
iniFile.Set("Enhancements", "ForceFiltering", bForceFiltering);
iniFile.Set("Enhancements", "ForceMaxAniso", bForceMaxAniso);
iniFile.Save(FULL_CONFIG_DIR "gfx_dx9.ini");
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Config.h"
#include "IniFile.h"
Config g_Config;
Config::Config()
{
}
void Config::Load()
{
IniFile iniFile;
iniFile.Load(FULL_CONFIG_DIR "gfx_dx9.ini");
iniFile.Get("Hardware", "Adapter", &iAdapter, 0);
iniFile.Get("Hardware", "WindowedRes", &iWindowedRes, 0);
iniFile.Get("Hardware", "FullscreenRes", &iFSResolution, 0);
iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0);
iniFile.Get("Hardware", "RenderInMainframe", &renderToMainframe, false);
iniFile.Get("Hardware", "VSync", &bVsync, 0);
if (iAdapter == -1)
iAdapter = 0;
iniFile.Get("Settings", "OverlayStats", &bOverlayStats, false);
iniFile.Get("Settings", "Postprocess", &iPostprocessEffect, 0);
iniFile.Get("Settings", "DLOptimize", &iCompileDLsLevel, 0);
iniFile.Get("Settings", "DumpTextures", &bDumpTextures, 0);
iniFile.Get("Settings", "ShowShaderErrors", &bShowShaderErrors, 0);
iniFile.Get("Settings", "Multisample", &iMultisampleMode, 0);
iniFile.Get("Settings", "TexDumpPath", &texDumpPath, 0);
iniFile.Get("Settings", "TexFmtOverlayEnable", &bTexFmtOverlayEnable, 0);
iniFile.Get("Settings", "TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0);
iniFile.Get("Enhancements", "ForceFiltering", &bForceFiltering, 0);
iniFile.Get("Enhancements", "ForceMaxAniso", &bForceMaxAniso, 0);
}
void Config::Save()
{
IniFile iniFile;
iniFile.Load(FULL_CONFIG_DIR "gfx_dx9.ini");
iniFile.Set("Hardware", "Adapter", iAdapter);
iniFile.Set("Hardware", "WindowedRes", iWindowedRes);
iniFile.Set("Hardware", "FullscreenRes", iFSResolution);
iniFile.Set("Hardware", "Fullscreen", bFullscreen);
iniFile.Set("Hardware", "VSync", bVsync);
iniFile.Set("Hardware", "RenderInMainframe", renderToMainframe);
iniFile.Set("Settings", "OverlayStats", bOverlayStats);
iniFile.Set("Settings", "OverlayStats", bOverlayStats);
iniFile.Set("Settings", "Postprocess", iPostprocessEffect);
iniFile.Set("Settings", "DLOptimize", iCompileDLsLevel);
iniFile.Set("Settings", "DumpTextures", bDumpTextures);
iniFile.Set("Settings", "ShowShaderErrors", bShowShaderErrors);
iniFile.Set("Settings", "Multisample", iMultisampleMode);
iniFile.Set("Settings", "TexDumpPath", texDumpPath);
iniFile.Set("Settings", "TexFmtOverlayEnable", bTexFmtOverlayEnable);
iniFile.Set("Settings", "TexFmtOverlayCenter", bTexFmtOverlayCenter);
iniFile.Set("Enhancements", "ForceFiltering", bForceFiltering);
iniFile.Set("Enhancements", "ForceMaxAniso", bForceMaxAniso);
iniFile.Save(FULL_CONFIG_DIR "gfx_dx9.ini");
}

View File

@ -1,389 +1,389 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "D3DBase.h"
#include "Render.h"
namespace D3D
{
bool fullScreen = false, nextFullScreen=false;
LPDIRECT3D9 D3D = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9 dev = NULL; // Our rendering device
LPDIRECT3DSURFACE9 backBuffer;
D3DCAPS9 caps;
int multisample;
int resolution;
#define VENDOR_NVIDIA 4318
RECT client;
HWND hWnd;
int xres, yres;
int cur_adapter;
Shader Ps;
Shader Vs;
bool bFrameInProgress = false;
//enum shit
Adapter adapters[4];
int numAdapters;
void Enumerate();
int GetNumAdapters()
{
return numAdapters;
}
const Adapter &GetAdapter(int i)
{
return adapters[i];
}
const Adapter &GetCurAdapter()
{
return adapters[cur_adapter];
}
HRESULT Init()
{
// Create the D3D object, which is needed to create the D3DDevice.
if( NULL == ( D3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;
Enumerate();
return S_OK;
}
void EnableAlphaToCoverage()
{
// dev->SetRenderState(D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C'));
Renderer::SetRenderState( D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C') );
}
void InitPP(int adapter, int resolution, int aa_mode, D3DPRESENT_PARAMETERS *pp)
{
int FSResX = adapters[adapter].resolutions[resolution].xres;
int FSResY = adapters[adapter].resolutions[resolution].yres;
ZeroMemory(pp, sizeof(D3DPRESENT_PARAMETERS));
pp->hDeviceWindow = hWnd;
pp->EnableAutoDepthStencil = TRUE;
pp->AutoDepthStencilFormat = D3DFMT_D24S8;
pp->BackBufferFormat = D3DFMT_A8R8G8B8;
if (aa_mode >= (int)adapters[adapter].aa_levels.size())
aa_mode = 0;
pp->MultiSampleType = adapters[adapter].aa_levels[aa_mode].ms_setting;
pp->MultiSampleQuality = adapters[adapter].aa_levels[aa_mode].qual_setting;
pp->Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
//D3DPRESENTFLAG_LOCKABLE_BACKBUFFER
if (fullScreen)
{
xres = pp->BackBufferWidth = FSResX;
yres = pp->BackBufferHeight = FSResY;
pp->SwapEffect = D3DSWAPEFFECT_DISCARD;
pp->Windowed = FALSE;
}
else
{
GetClientRect(hWnd, &client);
xres = pp->BackBufferWidth = client.right - client.left;
yres = pp->BackBufferHeight = client.bottom - client.top;
pp->SwapEffect = D3DSWAPEFFECT_DISCARD;
pp->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
pp->Windowed = TRUE;
}
}
void Enumerate()
{
numAdapters = D3D::D3D->GetAdapterCount();
for (int i=0; i<numAdapters; i++)
{
Adapter &a = adapters[i];
D3D::D3D->GetAdapterIdentifier(i, 0, &a.ident);
bool isNvidia = a.ident.VendorId == VENDOR_NVIDIA;
// Add multisample modes
a.aa_levels.push_back(AALevel("None", D3DMULTISAMPLE_NONE, 0));
DWORD qlevels = 0;
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels))
if (qlevels > 0)
a.aa_levels.push_back(AALevel("2x MSAA", D3DMULTISAMPLE_2_SAMPLES, 0));
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels))
if (qlevels > 0)
a.aa_levels.push_back(AALevel("4x MSAA", D3DMULTISAMPLE_4_SAMPLES, 0));
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
if (qlevels > 0)
a.aa_levels.push_back(AALevel("8x MSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
if (isNvidia)
{
// CSAA support
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_4_SAMPLES, &qlevels))
{
if (qlevels > 2)
{
// 8x, 8xQ are available
// See http://developer.nvidia.com/object/coverage-sampled-aa.html
a.aa_levels.push_back(AALevel("8x CSAA", D3DMULTISAMPLE_4_SAMPLES, 2));
a.aa_levels.push_back(AALevel("8xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
}
}
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
{
if (qlevels > 2)
{
// 8x, 8xQ are available
// See http://developer.nvidia.com/object/coverage-sampled-aa.html
a.aa_levels.push_back(AALevel("16x CSAA", D3DMULTISAMPLE_4_SAMPLES, 4));
a.aa_levels.push_back(AALevel("16xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 2));
}
}
}
if (a.aa_levels.size() == 1)
{
strcpy(a.aa_levels[0].name, "(Not supported on this device)");
}
int numModes = D3D::D3D->GetAdapterModeCount(i, D3DFMT_X8R8G8B8);
for (int m = 0; m < numModes; m++)
{
D3DDISPLAYMODE mode;
D3D::D3D->EnumAdapterModes(i, D3DFMT_X8R8G8B8, m, &mode);
int found = -1;
for (int x = 0; x < (int)a.resolutions.size(); x++)
{
if (a.resolutions[x].xres == mode.Width && a.resolutions[x].yres == mode.Height)
{
found = x;
break;
}
}
Resolution temp;
Resolution &r = found==-1 ? temp : a.resolutions[found];
sprintf(r.name, "%ix%i", mode.Width, mode.Height);
r.bitdepths.insert(mode.Format);
r.refreshes.insert(mode.RefreshRate);
if (found == -1 && mode.Width >= 640 && mode.Height >= 480)
{
r.xres = mode.Width;
r.yres = mode.Height;
a.resolutions.push_back(r);
}
}
}
}
HRESULT Create(int adapter, HWND wnd, bool _fullscreen, int _resolution, int aa_mode)
{
hWnd = wnd;
fullScreen = _fullscreen;
nextFullScreen = _fullscreen;
multisample = aa_mode;
resolution = _resolution;
cur_adapter = adapter;
D3DPRESENT_PARAMETERS d3dpp;
InitPP(adapter, resolution, aa_mode, &d3dpp);
if( FAILED( D3D->CreateDevice(
adapter,
D3DDEVTYPE_HAL,
wnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,
// |D3DCREATE_MULTITHREADED /* | D3DCREATE_PUREDEVICE*/,
//D3DCREATE_SOFTWARE_VERTEXPROCESSING ,
&d3dpp, &dev ) ) )
{
MessageBox(wnd,
"Sorry, but it looks like your 3D accelerator is too old,\n"
"or doesn't support features that Dolphin requires.\n"
"Falling back to software vertex processing.\n",
"Dolphin Direct3D plugin", MB_OK | MB_ICONERROR);
if( FAILED( D3D->CreateDevice(
adapter,
D3DDEVTYPE_HAL,
wnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,
// |D3DCREATE_MULTITHREADED /* | D3DCREATE_PUREDEVICE*/,
//D3DCREATE_SOFTWARE_VERTEXPROCESSING ,
&d3dpp, &dev ) ) )
{
MessageBox(wnd,
"Software VP failed too. Upgrade your graphics card.",
"Dolphin Direct3D plugin", MB_OK | MB_ICONERROR);
return E_FAIL;
}
}
dev->GetDeviceCaps(&caps);
dev->GetRenderTarget(0,&backBuffer);
Ps.Major = (D3D::caps.PixelShaderVersion >> 8) & 0xFF;
Ps.Minor = (D3D::caps.PixelShaderVersion) & 0xFF;
Vs.Major = (D3D::caps.VertexShaderVersion >>8) & 0xFF;
Vs.Minor = (D3D::caps.VertexShaderVersion) & 0xFF;
// Device state would normally be set here
return S_OK;
}
ShaderVersion GetShaderVersion()
{
if (Ps.Major < 2)
{
return PSNONE;
}
//good enough estimate - we really only
//care about zero shader vs ps20
return (ShaderVersion)Ps.Major;
}
void Close()
{
dev->Release();
dev = 0;
}
void Shutdown()
{
D3D->Release();
D3D = 0;
}
const D3DCAPS9 &GetCaps()
{
return caps;
}
LPDIRECT3DSURFACE9 GetBackBufferSurface()
{
return backBuffer;
}
void ShowD3DError(HRESULT err)
{
switch (err)
{
case D3DERR_DEVICELOST:
MessageBox(0, "Device Lost", "D3D ERROR", 0);
break;
case D3DERR_INVALIDCALL:
MessageBox(0, "Invalid Call", "D3D ERROR", 0);
break;
case D3DERR_DRIVERINTERNALERROR:
MessageBox(0, "Driver Internal Error", "D3D ERROR", 0);
break;
case D3DERR_OUTOFVIDEOMEMORY:
MessageBox(0, "Out of vid mem", "D3D ERROR", 0);
break;
default:
// MessageBox(0,"Other error or success","ERROR",0);
break;
}
}
void Reset()
{
if (dev)
{
D3DPRESENT_PARAMETERS d3dpp;
InitPP(cur_adapter, resolution, multisample, &d3dpp);
HRESULT hr = dev->Reset(&d3dpp);
ShowD3DError(hr);
}
}
bool IsFullscreen()
{
return fullScreen;
}
int GetDisplayWidth()
{
return xres;
}
int GetDisplayHeight()
{
return yres;
}
void SwitchFullscreen(bool fullscreen)
{
nextFullScreen = fullscreen;
}
bool BeginFrame(bool clear, u32 color, float z)
{
if (bFrameInProgress)
{
return false;
}
bFrameInProgress = true;
if (dev)
{
if (clear)
dev->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, (DWORD)color, z, 0 );
dev->BeginScene();
return true;
}
else
return false;
}
void EndFrame()
{
if (!bFrameInProgress)
return;
bFrameInProgress = false;
if (dev)
{
dev->EndScene();
dev->Present( NULL, NULL, NULL, NULL );
}
if (fullScreen != nextFullScreen)
{
fullScreen = nextFullScreen;
Reset();
}
}
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "D3DBase.h"
#include "Render.h"
namespace D3D
{
bool fullScreen = false, nextFullScreen=false;
LPDIRECT3D9 D3D = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9 dev = NULL; // Our rendering device
LPDIRECT3DSURFACE9 backBuffer;
D3DCAPS9 caps;
int multisample;
int resolution;
#define VENDOR_NVIDIA 4318
RECT client;
HWND hWnd;
int xres, yres;
int cur_adapter;
Shader Ps;
Shader Vs;
bool bFrameInProgress = false;
//enum shit
Adapter adapters[4];
int numAdapters;
void Enumerate();
int GetNumAdapters()
{
return numAdapters;
}
const Adapter &GetAdapter(int i)
{
return adapters[i];
}
const Adapter &GetCurAdapter()
{
return adapters[cur_adapter];
}
HRESULT Init()
{
// Create the D3D object, which is needed to create the D3DDevice.
if( NULL == ( D3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;
Enumerate();
return S_OK;
}
void EnableAlphaToCoverage()
{
// dev->SetRenderState(D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C'));
Renderer::SetRenderState( D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C') );
}
void InitPP(int adapter, int resolution, int aa_mode, D3DPRESENT_PARAMETERS *pp)
{
int FSResX = adapters[adapter].resolutions[resolution].xres;
int FSResY = adapters[adapter].resolutions[resolution].yres;
ZeroMemory(pp, sizeof(D3DPRESENT_PARAMETERS));
pp->hDeviceWindow = hWnd;
pp->EnableAutoDepthStencil = TRUE;
pp->AutoDepthStencilFormat = D3DFMT_D24S8;
pp->BackBufferFormat = D3DFMT_A8R8G8B8;
if (aa_mode >= (int)adapters[adapter].aa_levels.size())
aa_mode = 0;
pp->MultiSampleType = adapters[adapter].aa_levels[aa_mode].ms_setting;
pp->MultiSampleQuality = adapters[adapter].aa_levels[aa_mode].qual_setting;
pp->Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
//D3DPRESENTFLAG_LOCKABLE_BACKBUFFER
if (fullScreen)
{
xres = pp->BackBufferWidth = FSResX;
yres = pp->BackBufferHeight = FSResY;
pp->SwapEffect = D3DSWAPEFFECT_DISCARD;
pp->Windowed = FALSE;
}
else
{
GetClientRect(hWnd, &client);
xres = pp->BackBufferWidth = client.right - client.left;
yres = pp->BackBufferHeight = client.bottom - client.top;
pp->SwapEffect = D3DSWAPEFFECT_DISCARD;
pp->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
pp->Windowed = TRUE;
}
}
void Enumerate()
{
numAdapters = D3D::D3D->GetAdapterCount();
for (int i=0; i<numAdapters; i++)
{
Adapter &a = adapters[i];
D3D::D3D->GetAdapterIdentifier(i, 0, &a.ident);
bool isNvidia = a.ident.VendorId == VENDOR_NVIDIA;
// Add multisample modes
a.aa_levels.push_back(AALevel("None", D3DMULTISAMPLE_NONE, 0));
DWORD qlevels = 0;
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels))
if (qlevels > 0)
a.aa_levels.push_back(AALevel("2x MSAA", D3DMULTISAMPLE_2_SAMPLES, 0));
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels))
if (qlevels > 0)
a.aa_levels.push_back(AALevel("4x MSAA", D3DMULTISAMPLE_4_SAMPLES, 0));
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
if (qlevels > 0)
a.aa_levels.push_back(AALevel("8x MSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
if (isNvidia)
{
// CSAA support
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_4_SAMPLES, &qlevels))
{
if (qlevels > 2)
{
// 8x, 8xQ are available
// See http://developer.nvidia.com/object/coverage-sampled-aa.html
a.aa_levels.push_back(AALevel("8x CSAA", D3DMULTISAMPLE_4_SAMPLES, 2));
a.aa_levels.push_back(AALevel("8xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
}
}
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
{
if (qlevels > 2)
{
// 8x, 8xQ are available
// See http://developer.nvidia.com/object/coverage-sampled-aa.html
a.aa_levels.push_back(AALevel("16x CSAA", D3DMULTISAMPLE_4_SAMPLES, 4));
a.aa_levels.push_back(AALevel("16xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 2));
}
}
}
if (a.aa_levels.size() == 1)
{
strcpy(a.aa_levels[0].name, "(Not supported on this device)");
}
int numModes = D3D::D3D->GetAdapterModeCount(i, D3DFMT_X8R8G8B8);
for (int m = 0; m < numModes; m++)
{
D3DDISPLAYMODE mode;
D3D::D3D->EnumAdapterModes(i, D3DFMT_X8R8G8B8, m, &mode);
int found = -1;
for (int x = 0; x < (int)a.resolutions.size(); x++)
{
if (a.resolutions[x].xres == mode.Width && a.resolutions[x].yres == mode.Height)
{
found = x;
break;
}
}
Resolution temp;
Resolution &r = found==-1 ? temp : a.resolutions[found];
sprintf(r.name, "%ix%i", mode.Width, mode.Height);
r.bitdepths.insert(mode.Format);
r.refreshes.insert(mode.RefreshRate);
if (found == -1 && mode.Width >= 640 && mode.Height >= 480)
{
r.xres = mode.Width;
r.yres = mode.Height;
a.resolutions.push_back(r);
}
}
}
}
HRESULT Create(int adapter, HWND wnd, bool _fullscreen, int _resolution, int aa_mode)
{
hWnd = wnd;
fullScreen = _fullscreen;
nextFullScreen = _fullscreen;
multisample = aa_mode;
resolution = _resolution;
cur_adapter = adapter;
D3DPRESENT_PARAMETERS d3dpp;
InitPP(adapter, resolution, aa_mode, &d3dpp);
if( FAILED( D3D->CreateDevice(
adapter,
D3DDEVTYPE_HAL,
wnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,
// |D3DCREATE_MULTITHREADED /* | D3DCREATE_PUREDEVICE*/,
//D3DCREATE_SOFTWARE_VERTEXPROCESSING ,
&d3dpp, &dev ) ) )
{
MessageBox(wnd,
"Sorry, but it looks like your 3D accelerator is too old,\n"
"or doesn't support features that Dolphin requires.\n"
"Falling back to software vertex processing.\n",
"Dolphin Direct3D plugin", MB_OK | MB_ICONERROR);
if( FAILED( D3D->CreateDevice(
adapter,
D3DDEVTYPE_HAL,
wnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,
// |D3DCREATE_MULTITHREADED /* | D3DCREATE_PUREDEVICE*/,
//D3DCREATE_SOFTWARE_VERTEXPROCESSING ,
&d3dpp, &dev ) ) )
{
MessageBox(wnd,
"Software VP failed too. Upgrade your graphics card.",
"Dolphin Direct3D plugin", MB_OK | MB_ICONERROR);
return E_FAIL;
}
}
dev->GetDeviceCaps(&caps);
dev->GetRenderTarget(0,&backBuffer);
Ps.Major = (D3D::caps.PixelShaderVersion >> 8) & 0xFF;
Ps.Minor = (D3D::caps.PixelShaderVersion) & 0xFF;
Vs.Major = (D3D::caps.VertexShaderVersion >>8) & 0xFF;
Vs.Minor = (D3D::caps.VertexShaderVersion) & 0xFF;
// Device state would normally be set here
return S_OK;
}
ShaderVersion GetShaderVersion()
{
if (Ps.Major < 2)
{
return PSNONE;
}
//good enough estimate - we really only
//care about zero shader vs ps20
return (ShaderVersion)Ps.Major;
}
void Close()
{
dev->Release();
dev = 0;
}
void Shutdown()
{
D3D->Release();
D3D = 0;
}
const D3DCAPS9 &GetCaps()
{
return caps;
}
LPDIRECT3DSURFACE9 GetBackBufferSurface()
{
return backBuffer;
}
void ShowD3DError(HRESULT err)
{
switch (err)
{
case D3DERR_DEVICELOST:
MessageBox(0, "Device Lost", "D3D ERROR", 0);
break;
case D3DERR_INVALIDCALL:
MessageBox(0, "Invalid Call", "D3D ERROR", 0);
break;
case D3DERR_DRIVERINTERNALERROR:
MessageBox(0, "Driver Internal Error", "D3D ERROR", 0);
break;
case D3DERR_OUTOFVIDEOMEMORY:
MessageBox(0, "Out of vid mem", "D3D ERROR", 0);
break;
default:
// MessageBox(0,"Other error or success","ERROR",0);
break;
}
}
void Reset()
{
if (dev)
{
D3DPRESENT_PARAMETERS d3dpp;
InitPP(cur_adapter, resolution, multisample, &d3dpp);
HRESULT hr = dev->Reset(&d3dpp);
ShowD3DError(hr);
}
}
bool IsFullscreen()
{
return fullScreen;
}
int GetDisplayWidth()
{
return xres;
}
int GetDisplayHeight()
{
return yres;
}
void SwitchFullscreen(bool fullscreen)
{
nextFullScreen = fullscreen;
}
bool BeginFrame(bool clear, u32 color, float z)
{
if (bFrameInProgress)
{
return false;
}
bFrameInProgress = true;
if (dev)
{
if (clear)
dev->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, (DWORD)color, z, 0 );
dev->BeginScene();
return true;
}
else
return false;
}
void EndFrame()
{
if (!bFrameInProgress)
return;
bFrameInProgress = false;
if (dev)
{
dev->EndScene();
dev->Present( NULL, NULL, NULL, NULL );
}
if (fullScreen != nextFullScreen)
{
fullScreen = nextFullScreen;
Reset();
}
}
}

View File

@ -1,294 +1,294 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "D3DBase.h"
#include "D3DTexture.h"
#include "D3DUtil.h"
#include "Config.h"
#include "Render.h"
using namespace D3D;
namespace Postprocess
{
LPDIRECT3DSURFACE9 displayColorBuffer;
LPDIRECT3DSURFACE9 displayZStencilBuffer;
LPDIRECT3DTEXTURE9 mainColorBufferTexture;
LPDIRECT3DSURFACE9 mainColorBuffer;
LPDIRECT3DSURFACE9 mainZStencilBuffer;
const int numScratch = 2;
LPDIRECT3DTEXTURE9 scratch[numScratch];
LPDIRECT3DSURFACE9 scratchSurface[numScratch];
const int mainWidth = 640, mainHeight=480;
const int scratchWidth = 256, scratchHeight=256;
int displayWidth, displayHeight;
bool initialized;
int GetWidth() {
return initialized ? mainWidth : displayWidth;
}
int GetHeight() {
return initialized ? mainHeight : displayHeight;
}
void CreateStuff()
{
mainColorBufferTexture = D3D::CreateRenderTarget(mainWidth,mainHeight);
mainColorBufferTexture->GetSurfaceLevel(0,&mainColorBuffer);
mainZStencilBuffer = D3D::CreateDepthStencilSurface(mainWidth,mainHeight);
for (int i=0; i<numScratch; i++)
{
scratch[i]=D3D::CreateRenderTarget(scratchWidth,scratchHeight);
scratch[i]->GetSurfaceLevel(0,&(scratchSurface[i]));
}
initialized=true;
}
void DestroyStuff()
{
SAFE_RELEASE(mainColorBuffer);
SAFE_RELEASE(mainColorBufferTexture);
SAFE_RELEASE(mainZStencilBuffer);
for (int i=0; i<numScratch; i++)
{
SAFE_RELEASE(scratch[i]);
SAFE_RELEASE(scratchSurface[i]);
}
initialized=false;
}
void Initialize()
{
dev->GetRenderTarget(0,&displayColorBuffer);
dev->GetDepthStencilSurface(&displayZStencilBuffer);
D3DSURFACE_DESC desc;
displayColorBuffer->GetDesc(&desc);
displayWidth = desc.Width;
displayHeight = desc.Height;
if (g_Config.iPostprocessEffect)
CreateStuff();
}
void Cleanup()
{
DestroyStuff();
SAFE_RELEASE(displayColorBuffer);
SAFE_RELEASE(displayZStencilBuffer);
}
void BeginFrame()
{
if (g_Config.iPostprocessEffect)
{
if (!initialized)
CreateStuff();
dev->SetRenderTarget(0,mainColorBuffer);
dev->SetDepthStencilSurface(mainZStencilBuffer);
// dev->SetRenderState(D3DRS_ZENABLE,TRUE);
Renderer::SetRenderState( D3DRS_ZENABLE, TRUE );
dev->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,0,1,0);
}
else
{
if (initialized)
{
dev->SetRenderTarget(0,displayColorBuffer);
dev->SetDepthStencilSurface(displayZStencilBuffer);
DestroyStuff();
}
// dev->SetRenderState(D3DRS_ZENABLE,TRUE);
Renderer::SetRenderState( D3DRS_ZENABLE, TRUE );
}
}
int filterKernel[8] = {0x40,0x80,0xc0,0xFF,0xFF,0xc0,0x80,0x40}; //good looking almost Gaussian
//int filterKernel[8] = {0xFF,0xc0,0x80,0x40,0x40,0x80,0xc0,0xFF,}; //crazy filter
void NightGlow(bool intense, bool original)
{
// dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SUBTRACT);
// dev->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
// dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
// dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SUBTRACT );
Renderer::SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
dev->SetDepthStencilSurface(0);
//dev->SetTexture(0,mainColorBufferTexture);
Renderer::SetTexture( 0, mainColorBufferTexture );
dev->SetRenderTarget(0,scratchSurface[0]);
dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_CLAMP);
dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_CLAMP);
dev->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
dev->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
dev->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR);
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
POINT pt;
GetCursorPos(&pt);
//dev->SetSamplerState(0,D3DSAMP_MIPMAPLODBIAS,1.0f);
#define QOFF(xoff,yoff,col) quad2d(-0.0f,-0.0f,scratchWidth-0.0f,scratchHeight-0.0f,col,0+xoff,0+yoff,1+xoff,1+yoff);
float f=0.008f;
QOFF(0,0,0xa0a0a0a0);
// dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
//dev->SetTexture(0,scratch[0]);
Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
Renderer::SetTexture( 0, scratch[0] );
dev->SetRenderTarget(0,scratchSurface[1]);
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
float yMul = 1.33333333333f;
for (int i=0; i<8; i++)
{
DWORD c=filterKernel[i]/2;
c|=c<<8;
c|=c<<16;
QOFF(0,(i-3.5f) * f * yMul,c);
}
//dev->SetTexture(0,scratch[1]);
Renderer::SetTexture( 0, scratch[1] );
dev->SetRenderTarget(0,scratchSurface[0]);
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
for (int i=0; i<8; i++)
{
DWORD c=filterKernel[i]/(intense?3:2);
c|=c<<8;
c|=c<<16;
QOFF((i-3.5f) * f,0,c);
}
// dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
if (intense)
{
// dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
// dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_SRCALPHA);
Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCALPHA );
}
else
{
// dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_INVDESTCOLOR);
// dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR );
Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
}
// dev->SetTexture(0,scratch[0]);
Renderer::SetTexture( 0, scratch[0] );
dev->SetRenderTarget(0,mainColorBuffer);
quad2d(0,0,(float)mainWidth,(float)mainHeight,original?0xCFFFFFFF:0xFFFFFFFF,0,0,1,1);
// dev->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
Renderer::SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_WRAP);
dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_WRAP);
//dev->SetSamplerState(0,D3DSAMP_MIPMAPLODBIAS,0);
}
const char **GetPostprocessingNames()
{
static const char *names[] = {
"None",
"Night Glow 1",
"Night Glow 2",
"Night Glow 3",
0,
};
return names;
}
void FinalizeFrame()
{
if (initialized)
{
// dev->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
// dev->SetRenderState(D3DRS_ZENABLE,FALSE);
// dev->SetRenderState(D3DRS_FOGENABLE,FALSE);
// dev->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
// dev->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
// dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
// dev->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
// dev->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE);
// dev->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2);
Renderer::SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
Renderer::SetRenderState( D3DRS_ZENABLE, FALSE );
Renderer::SetRenderState( D3DRS_FOGENABLE, FALSE );
Renderer::SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
Renderer::SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
Renderer::SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
Renderer::SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
Renderer::SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE);
Renderer::SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2);
switch(g_Config.iPostprocessEffect) {
case 1:
NightGlow(true,true);
case 2:
NightGlow(false,true);
break;
case 3:
NightGlow(false,false);
break;
}
dev->SetRenderTarget(0,displayColorBuffer);
dev->SetDepthStencilSurface(displayZStencilBuffer);
// dev->SetTexture(0,mainColorBufferTexture);
Renderer::SetTexture( 0, mainColorBufferTexture );
quad2d(0, 0, (float)displayWidth, (float)displayHeight, 0xFFFFFFFF);
}
}
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "D3DBase.h"
#include "D3DTexture.h"
#include "D3DUtil.h"
#include "Config.h"
#include "Render.h"
using namespace D3D;
namespace Postprocess
{
LPDIRECT3DSURFACE9 displayColorBuffer;
LPDIRECT3DSURFACE9 displayZStencilBuffer;
LPDIRECT3DTEXTURE9 mainColorBufferTexture;
LPDIRECT3DSURFACE9 mainColorBuffer;
LPDIRECT3DSURFACE9 mainZStencilBuffer;
const int numScratch = 2;
LPDIRECT3DTEXTURE9 scratch[numScratch];
LPDIRECT3DSURFACE9 scratchSurface[numScratch];
const int mainWidth = 640, mainHeight=480;
const int scratchWidth = 256, scratchHeight=256;
int displayWidth, displayHeight;
bool initialized;
int GetWidth() {
return initialized ? mainWidth : displayWidth;
}
int GetHeight() {
return initialized ? mainHeight : displayHeight;
}
void CreateStuff()
{
mainColorBufferTexture = D3D::CreateRenderTarget(mainWidth,mainHeight);
mainColorBufferTexture->GetSurfaceLevel(0,&mainColorBuffer);
mainZStencilBuffer = D3D::CreateDepthStencilSurface(mainWidth,mainHeight);
for (int i=0; i<numScratch; i++)
{
scratch[i]=D3D::CreateRenderTarget(scratchWidth,scratchHeight);
scratch[i]->GetSurfaceLevel(0,&(scratchSurface[i]));
}
initialized=true;
}
void DestroyStuff()
{
SAFE_RELEASE(mainColorBuffer);
SAFE_RELEASE(mainColorBufferTexture);
SAFE_RELEASE(mainZStencilBuffer);
for (int i=0; i<numScratch; i++)
{
SAFE_RELEASE(scratch[i]);
SAFE_RELEASE(scratchSurface[i]);
}
initialized=false;
}
void Initialize()
{
dev->GetRenderTarget(0,&displayColorBuffer);
dev->GetDepthStencilSurface(&displayZStencilBuffer);
D3DSURFACE_DESC desc;
displayColorBuffer->GetDesc(&desc);
displayWidth = desc.Width;
displayHeight = desc.Height;
if (g_Config.iPostprocessEffect)
CreateStuff();
}
void Cleanup()
{
DestroyStuff();
SAFE_RELEASE(displayColorBuffer);
SAFE_RELEASE(displayZStencilBuffer);
}
void BeginFrame()
{
if (g_Config.iPostprocessEffect)
{
if (!initialized)
CreateStuff();
dev->SetRenderTarget(0,mainColorBuffer);
dev->SetDepthStencilSurface(mainZStencilBuffer);
// dev->SetRenderState(D3DRS_ZENABLE,TRUE);
Renderer::SetRenderState( D3DRS_ZENABLE, TRUE );
dev->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,0,1,0);
}
else
{
if (initialized)
{
dev->SetRenderTarget(0,displayColorBuffer);
dev->SetDepthStencilSurface(displayZStencilBuffer);
DestroyStuff();
}
// dev->SetRenderState(D3DRS_ZENABLE,TRUE);
Renderer::SetRenderState( D3DRS_ZENABLE, TRUE );
}
}
int filterKernel[8] = {0x40,0x80,0xc0,0xFF,0xFF,0xc0,0x80,0x40}; //good looking almost Gaussian
//int filterKernel[8] = {0xFF,0xc0,0x80,0x40,0x40,0x80,0xc0,0xFF,}; //crazy filter
void NightGlow(bool intense, bool original)
{
// dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SUBTRACT);
// dev->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
// dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
// dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SUBTRACT );
Renderer::SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
dev->SetDepthStencilSurface(0);
//dev->SetTexture(0,mainColorBufferTexture);
Renderer::SetTexture( 0, mainColorBufferTexture );
dev->SetRenderTarget(0,scratchSurface[0]);
dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_CLAMP);
dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_CLAMP);
dev->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
dev->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
dev->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR);
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
POINT pt;
GetCursorPos(&pt);
//dev->SetSamplerState(0,D3DSAMP_MIPMAPLODBIAS,1.0f);
#define QOFF(xoff,yoff,col) quad2d(-0.0f,-0.0f,scratchWidth-0.0f,scratchHeight-0.0f,col,0+xoff,0+yoff,1+xoff,1+yoff);
float f=0.008f;
QOFF(0,0,0xa0a0a0a0);
// dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
//dev->SetTexture(0,scratch[0]);
Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
Renderer::SetTexture( 0, scratch[0] );
dev->SetRenderTarget(0,scratchSurface[1]);
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
float yMul = 1.33333333333f;
for (int i=0; i<8; i++)
{
DWORD c=filterKernel[i]/2;
c|=c<<8;
c|=c<<16;
QOFF(0,(i-3.5f) * f * yMul,c);
}
//dev->SetTexture(0,scratch[1]);
Renderer::SetTexture( 0, scratch[1] );
dev->SetRenderTarget(0,scratchSurface[0]);
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
for (int i=0; i<8; i++)
{
DWORD c=filterKernel[i]/(intense?3:2);
c|=c<<8;
c|=c<<16;
QOFF((i-3.5f) * f,0,c);
}
// dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
if (intense)
{
// dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
// dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_SRCALPHA);
Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCALPHA );
}
else
{
// dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_INVDESTCOLOR);
// dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR );
Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
}
// dev->SetTexture(0,scratch[0]);
Renderer::SetTexture( 0, scratch[0] );
dev->SetRenderTarget(0,mainColorBuffer);
quad2d(0,0,(float)mainWidth,(float)mainHeight,original?0xCFFFFFFF:0xFFFFFFFF,0,0,1,1);
// dev->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
Renderer::SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_WRAP);
dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_WRAP);
//dev->SetSamplerState(0,D3DSAMP_MIPMAPLODBIAS,0);
}
const char **GetPostprocessingNames()
{
static const char *names[] = {
"None",
"Night Glow 1",
"Night Glow 2",
"Night Glow 3",
0,
};
return names;
}
void FinalizeFrame()
{
if (initialized)
{
// dev->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
// dev->SetRenderState(D3DRS_ZENABLE,FALSE);
// dev->SetRenderState(D3DRS_FOGENABLE,FALSE);
// dev->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
// dev->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
// dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
// dev->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
// dev->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE);
// dev->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2);
Renderer::SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
Renderer::SetRenderState( D3DRS_ZENABLE, FALSE );
Renderer::SetRenderState( D3DRS_FOGENABLE, FALSE );
Renderer::SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
Renderer::SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
Renderer::SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
Renderer::SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
Renderer::SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE);
Renderer::SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2);
switch(g_Config.iPostprocessEffect) {
case 1:
NightGlow(true,true);
case 2:
NightGlow(false,true);
break;
case 3:
NightGlow(false,false);
break;
}
dev->SetRenderTarget(0,displayColorBuffer);
dev->SetDepthStencilSurface(displayZStencilBuffer);
// dev->SetTexture(0,mainColorBufferTexture);
Renderer::SetTexture( 0, mainColorBufferTexture );
quad2d(0, 0, (float)displayWidth, (float)displayHeight, 0xFFFFFFFF);
}
}
}

View File

@ -1,108 +1,108 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <d3dx9.h>
#include <string>
#include "Config.h"
#include "D3DShader.h"
namespace D3D
{
LPDIRECT3DVERTEXSHADER9 CompileVShader(const char *code, int len)
{
//try to compile
LPD3DXBUFFER shaderBuffer = 0, errorBuffer = 0;
LPDIRECT3DVERTEXSHADER9 vShader = 0;
HRESULT hr = D3DXCompileShader(code,len,0,0,"main","vs_1_1",0,&shaderBuffer,&errorBuffer,0);
if (FAILED(hr))
{
//let's try 2.0
hr = D3DXCompileShader(code,len,0,0,"main","vs_2_0",0,&shaderBuffer,&errorBuffer,0);
}
if (FAILED(hr))
{
//compilation error
std::string hello = (char*)errorBuffer->GetBufferPointer();
hello += "\n\n";
hello += code;
if (g_Config.bShowShaderErrors)
MessageBox(0, hello.c_str(), "Error compiling vertex shader", MB_ICONERROR);
vShader = 0;
}
else if (SUCCEEDED(hr))
{
//create it
HRESULT hr = E_FAIL;
if (shaderBuffer)
hr = D3D::dev->CreateVertexShader((DWORD *)shaderBuffer->GetBufferPointer(), &vShader);
if (FAILED(hr) || vShader == 0)
{
if (g_Config.bShowShaderErrors)
MessageBox(0,code,(char*)errorBuffer->GetBufferPointer(),MB_ICONERROR);
}
}
//cleanup
if (shaderBuffer)
shaderBuffer->Release();
if (errorBuffer)
errorBuffer->Release();
return vShader;
}
LPDIRECT3DPIXELSHADER9 CompilePShader(const char *code, int len)
{
LPD3DXBUFFER shaderBuffer = 0, errorBuffer = 0;
LPDIRECT3DPIXELSHADER9 pShader = 0;
static char *versions[6] = {"ERROR","ps_1_1","ps_1_4","ps_2_0","ps_3_0","ps_4_0"};
HRESULT hr = D3DXCompileShader(code,len,0,0,
"main","ps_2_0", // Pixel Shader 2.0 is enough for all we do
0,&shaderBuffer,&errorBuffer,0);
if (FAILED(hr))
{
std::string hello = (char*)errorBuffer->GetBufferPointer();
hello += "\n\n";
hello += code;
if (g_Config.bShowShaderErrors)
MessageBox(0, hello.c_str(), "Error compiling pixel shader", MB_ICONERROR);
pShader = 0;
}
else
{
//create it
HRESULT hr = D3D::dev->CreatePixelShader((DWORD *)shaderBuffer->GetBufferPointer(), &pShader);
if (FAILED(hr) || pShader == 0)
{
if (g_Config.bShowShaderErrors)
MessageBox(0,"damn","error creating pixelshader",MB_ICONERROR);
}
}
//cleanup
if (shaderBuffer)
shaderBuffer->Release();
if (errorBuffer)
errorBuffer->Release();
return pShader;
}
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <d3dx9.h>
#include <string>
#include "Config.h"
#include "D3DShader.h"
namespace D3D
{
LPDIRECT3DVERTEXSHADER9 CompileVShader(const char *code, int len)
{
//try to compile
LPD3DXBUFFER shaderBuffer = 0, errorBuffer = 0;
LPDIRECT3DVERTEXSHADER9 vShader = 0;
HRESULT hr = D3DXCompileShader(code,len,0,0,"main","vs_1_1",0,&shaderBuffer,&errorBuffer,0);
if (FAILED(hr))
{
//let's try 2.0
hr = D3DXCompileShader(code,len,0,0,"main","vs_2_0",0,&shaderBuffer,&errorBuffer,0);
}
if (FAILED(hr))
{
//compilation error
std::string hello = (char*)errorBuffer->GetBufferPointer();
hello += "\n\n";
hello += code;
if (g_Config.bShowShaderErrors)
MessageBox(0, hello.c_str(), "Error compiling vertex shader", MB_ICONERROR);
vShader = 0;
}
else if (SUCCEEDED(hr))
{
//create it
HRESULT hr = E_FAIL;
if (shaderBuffer)
hr = D3D::dev->CreateVertexShader((DWORD *)shaderBuffer->GetBufferPointer(), &vShader);
if (FAILED(hr) || vShader == 0)
{
if (g_Config.bShowShaderErrors)
MessageBox(0,code,(char*)errorBuffer->GetBufferPointer(),MB_ICONERROR);
}
}
//cleanup
if (shaderBuffer)
shaderBuffer->Release();
if (errorBuffer)
errorBuffer->Release();
return vShader;
}
LPDIRECT3DPIXELSHADER9 CompilePShader(const char *code, int len)
{
LPD3DXBUFFER shaderBuffer = 0, errorBuffer = 0;
LPDIRECT3DPIXELSHADER9 pShader = 0;
static char *versions[6] = {"ERROR","ps_1_1","ps_1_4","ps_2_0","ps_3_0","ps_4_0"};
HRESULT hr = D3DXCompileShader(code,len,0,0,
"main","ps_2_0", // Pixel Shader 2.0 is enough for all we do
0,&shaderBuffer,&errorBuffer,0);
if (FAILED(hr))
{
std::string hello = (char*)errorBuffer->GetBufferPointer();
hello += "\n\n";
hello += code;
if (g_Config.bShowShaderErrors)
MessageBox(0, hello.c_str(), "Error compiling pixel shader", MB_ICONERROR);
pShader = 0;
}
else
{
//create it
HRESULT hr = D3D::dev->CreatePixelShader((DWORD *)shaderBuffer->GetBufferPointer(), &pShader);
if (FAILED(hr) || pShader == 0)
{
if (g_Config.bShowShaderErrors)
MessageBox(0,"damn","error creating pixelshader",MB_ICONERROR);
}
}
//cleanup
if (shaderBuffer)
shaderBuffer->Release();
if (errorBuffer)
errorBuffer->Release();
return pShader;
}
}

View File

@ -1,115 +1,115 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "D3DBase.h"
#include "D3DTexture.h"
namespace D3D
{
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height,const int pitch, D3DFORMAT fmt)
{
u32* pBuffer = (u32*)buffer;
LPDIRECT3DTEXTURE9 pTexture;
// crazy bitmagic
bool isPow2 = !((width&(width-1)) || (height&(height-1)));
HRESULT hr;
// TODO(ector): allow mipmaps for non-pow textures on newer cards?
if (!isPow2)
hr = dev->CreateTexture(width, height, 1, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
else
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
if(FAILED(hr))
return 0;
int level = 0;
D3DLOCKED_RECT Lock;
pTexture->LockRect(level, &Lock, NULL, 0 );
u32* pIn = pBuffer;
switch(fmt)
{
case D3DFMT_A8R8G8B8:
{
for (int y = 0; y < height; y++)
{
u32* pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 4);
pIn += pitch;
}
}
break;
case D3DFMT_DXT1:
memcpy(Lock.pBits,buffer,(width/4)*(height/4)*8);
break;
}
pTexture->UnlockRect(level);
return pTexture;
}
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height,const int pitch, D3DFORMAT fmt)
{
u32* pBuffer = (u32*)buffer;
int level = 0;
D3DLOCKED_RECT Lock;
pTexture->LockRect(level, &Lock, NULL, 0 );
u32* pIn = pBuffer;
switch(fmt)
{
case D3DFMT_A8R8G8B8:
{
for (int y = 0; y < height; y++)
{
u32* pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits,pIn, width*4);
pIn += pitch;
}
}
break;
case D3DFMT_DXT1:
memcpy(Lock.pBits,buffer,(width/4)*(height/4)*8);
break;
}
pTexture->UnlockRect(level);
}
LPDIRECT3DTEXTURE9 CreateRenderTarget(const int width, const int height)
{
LPDIRECT3DTEXTURE9 tex;
HRESULT hr = dev->CreateTexture(width,height,0,D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,&tex,NULL);
if (FAILED(hr))
return 0;
else
return tex;
}
LPDIRECT3DSURFACE9 CreateDepthStencilSurface(const int width, const int height)
{
LPDIRECT3DSURFACE9 surf;
HRESULT hr = dev->CreateDepthStencilSurface(width,height,D3DFMT_D24S8,D3DMULTISAMPLE_NONE,0,0,&surf,0);
if (FAILED(hr))
return 0;
else
return surf;
}
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "D3DBase.h"
#include "D3DTexture.h"
namespace D3D
{
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height,const int pitch, D3DFORMAT fmt)
{
u32* pBuffer = (u32*)buffer;
LPDIRECT3DTEXTURE9 pTexture;
// crazy bitmagic
bool isPow2 = !((width&(width-1)) || (height&(height-1)));
HRESULT hr;
// TODO(ector): allow mipmaps for non-pow textures on newer cards?
if (!isPow2)
hr = dev->CreateTexture(width, height, 1, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
else
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
if(FAILED(hr))
return 0;
int level = 0;
D3DLOCKED_RECT Lock;
pTexture->LockRect(level, &Lock, NULL, 0 );
u32* pIn = pBuffer;
switch(fmt)
{
case D3DFMT_A8R8G8B8:
{
for (int y = 0; y < height; y++)
{
u32* pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 4);
pIn += pitch;
}
}
break;
case D3DFMT_DXT1:
memcpy(Lock.pBits,buffer,(width/4)*(height/4)*8);
break;
}
pTexture->UnlockRect(level);
return pTexture;
}
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height,const int pitch, D3DFORMAT fmt)
{
u32* pBuffer = (u32*)buffer;
int level = 0;
D3DLOCKED_RECT Lock;
pTexture->LockRect(level, &Lock, NULL, 0 );
u32* pIn = pBuffer;
switch(fmt)
{
case D3DFMT_A8R8G8B8:
{
for (int y = 0; y < height; y++)
{
u32* pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits,pIn, width*4);
pIn += pitch;
}
}
break;
case D3DFMT_DXT1:
memcpy(Lock.pBits,buffer,(width/4)*(height/4)*8);
break;
}
pTexture->UnlockRect(level);
}
LPDIRECT3DTEXTURE9 CreateRenderTarget(const int width, const int height)
{
LPDIRECT3DTEXTURE9 tex;
HRESULT hr = dev->CreateTexture(width,height,0,D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,&tex,NULL);
if (FAILED(hr))
return 0;
else
return tex;
}
LPDIRECT3DSURFACE9 CreateDepthStencilSurface(const int width, const int height)
{
LPDIRECT3DSURFACE9 surf;
HRESULT hr = dev->CreateDepthStencilSurface(width,height,D3DFMT_D24S8,D3DMULTISAMPLE_NONE,0,0,&surf,0);
if (FAILED(hr))
return 0;
else
return surf;
}
}

View File

@ -1,397 +1,397 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "D3DBase.h"
#include "D3DUtil.h"
#include "Render.h"
namespace D3D
{
CD3DFont font;
#define MAX_NUM_VERTICES 50*6
struct FONT2DVERTEX {
float x,y,z;
float rhw;
u32 color;
float tu, tv;
};
#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL|D3DFVF_TEX1)
inline FONT2DVERTEX InitFont2DVertex( float x, float y, u32 color, float tu, float tv )
{
FONT2DVERTEX v; v.x=x; v.y=y; v.z=0; v.rhw=1.0f; v.color = color; v.tu = tu; v.tv = tv;
return v;
}
CD3DFont::CD3DFont()
{
m_pTexture = NULL;
m_pVB = NULL;
}
enum {m_dwTexWidth = 512, m_dwTexHeight = 512};
int CD3DFont::Init()
{
int hr;
m_fTextScale = 1.0f; // Draw fonts into texture without scaling
// Create a new texture for the font
hr = dev->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &m_pTexture, NULL );
if( FAILED(hr) )
return hr;
// Prepare to create a bitmap
int *pBitmapBits;
BITMAPINFO bmi;
ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) );
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = (int)m_dwTexWidth;
bmi.bmiHeader.biHeight = -(int)m_dwTexHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biBitCount = 32;
// Create a DC and a bitmap for the font
HDC hDC = CreateCompatibleDC( NULL );
HBITMAP hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS,
(VOID**)&pBitmapBits, NULL, 0 );
SetMapMode( hDC, MM_TEXT );
// Create a font. By specifying ANTIALIASED_QUALITY, we might get an
// antialiased font, but this is not guaranteed.
// We definitely don't want to get it cleartype'd, anyway.
int m_dwFontHeight = 36;
int nHeight = -MulDiv( m_dwFontHeight, int(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 );
int dwBold = FW_NORMAL; ///FW_BOLD
HFONT hFont = CreateFont( nHeight, 0, 0, 0, dwBold, 0,
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
VARIABLE_PITCH, "Tahoma");
if (NULL == hFont)
return E_FAIL;
HGDIOBJ hOldbmBitmap = SelectObject( hDC, hbmBitmap );
HGDIOBJ hOldFont = SelectObject( hDC, hFont );
// Set text properties
SetTextColor( hDC, 0xFFFFFF );
SetBkColor ( hDC, 0 );
SetTextAlign( hDC, TA_TOP );
// Loop through all printable character and output them to the bitmap..
// Meanwhile, keep track of the corresponding tex coords for each character.
int x = 0, y = 0;
char str[2] = "\0";
SIZE size;
for( char c=0; c<127-32; c++ )
{
str[0] = c+32;
GetTextExtentPoint32( hDC, str, 1, &size );
if( (int)(x+size.cx+1) > m_dwTexWidth )
{
x = 0;
y += size.cy+1;
}
ExtTextOut( hDC, x+1, y+0, ETO_OPAQUE | ETO_CLIPPED, NULL, str, 1, NULL );
m_fTexCoords[c][0] = ((float)(x+0))/m_dwTexWidth;
m_fTexCoords[c][1] = ((float)(y+0))/m_dwTexHeight;
m_fTexCoords[c][2] = ((float)(x+0+size.cx))/m_dwTexWidth;
m_fTexCoords[c][3] = ((float)(y+0+size.cy))/m_dwTexHeight;
x += size.cx+3; //3 to avoid annoying ij conflict (part of the j ends up with the i)
}
// Lock the surface and write the alpha values for the set pixels
D3DLOCKED_RECT d3dlr;
m_pTexture->LockRect( 0, &d3dlr, 0, 0 );
unsigned short* pDst16 = (unsigned short*)d3dlr.pBits;
int bAlpha; // 4-bit measure of pixel intensity
for( y=0; y < m_dwTexHeight; y++ )
{
for( x=0; x < m_dwTexWidth; x++ )
{
bAlpha = ((pBitmapBits[m_dwTexWidth*y + x] & 0xff) >> 4);
*pDst16++ = (bAlpha << 12) | 0x0fff;
}
}
// Done updating texture, so clean up used objects
m_pTexture->UnlockRect(0);
SelectObject( hDC, hOldbmBitmap );
DeleteObject( hbmBitmap );
SelectObject( hDC, hOldFont );
DeleteObject( hFont );
// Create vertex buffer for the letters
if( FAILED( hr = dev->CreateVertexBuffer( MAX_NUM_VERTICES*sizeof(FONT2DVERTEX),
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0,
D3DPOOL_DEFAULT, &m_pVB,NULL ) ) )
{
return hr;
}
return S_OK;
}
int CD3DFont::Shutdown()
{
SAFE_RELEASE( m_pVB );
SAFE_RELEASE( m_pTexture );
return S_OK;
}
const int RS[6][2] =
{
{ D3DRS_ALPHABLENDENABLE, TRUE },
{ D3DRS_SRCBLEND, D3DBLEND_SRCALPHA },
{ D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA },
{ D3DRS_CULLMODE, D3DCULL_NONE },
{ D3DRS_ZENABLE, FALSE },
{ D3DRS_FOGENABLE, FALSE },
};
const int TS[6][2] =
{
{D3DTSS_COLOROP, D3DTOP_MODULATE},
{D3DTSS_COLORARG1, D3DTA_TEXTURE},
{D3DTSS_COLORARG2, D3DTA_DIFFUSE },
{D3DTSS_ALPHAOP, D3DTOP_MODULATE },
{D3DTSS_ALPHAARG1, D3DTA_TEXTURE },
{D3DTSS_ALPHAARG2, D3DTA_DIFFUSE },
};
static DWORD RS_old[6];
static DWORD TS_old[6];
static LPDIRECT3DBASETEXTURE9 texture_old;
static DWORD FVF_old;
static LPDIRECT3DVERTEXDECLARATION9 decl_old;
static LPDIRECT3DPIXELSHADER9 ps_old;
static LPDIRECT3DVERTEXSHADER9 vs_old;
void SaveRenderStates()
{
for (int i = 0; i < 6; i++) {
dev->GetRenderState((_D3DRENDERSTATETYPE)RS[i][0], &(RS_old[i]));
dev->GetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), &(TS_old[i]));
}
dev->GetTexture(0, &texture_old);
dev->GetPixelShader(&ps_old);
dev->GetVertexShader(&vs_old);
dev->GetVertexDeclaration(&decl_old);
dev->GetFVF(&FVF_old);
}
void CD3DFont::SetRenderStates()
{
// dev->SetTexture(0, m_pTexture);
Renderer::SetTexture( 0, m_pTexture );
dev->SetPixelShader(0);
dev->SetVertexShader(0);
dev->SetVertexDeclaration(0);
// dev->SetFVF(D3DFVF_FONT2DVERTEX);
Renderer::SetFVF(D3DFVF_FONT2DVERTEX);
for (int i = 0; i < 6; i++) {
// dev->SetRenderState((_D3DRENDERSTATETYPE)RS[i][0],RS[i][1]);
// dev->SetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1]);
Renderer::SetRenderState( (_D3DRENDERSTATETYPE)RS[i][0], RS[i][1] );
Renderer::SetTextureStageState( 0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1] );
}
}
void RestoreRenderStates()
{
// dev->SetTexture(0, texture_old);
Renderer::SetTexture( 0, texture_old );
dev->SetPixelShader(ps_old);
dev->SetVertexShader(vs_old);
dev->SetVertexDeclaration(decl_old);
// dev->SetFVF(FVF_old);
Renderer::SetFVF(FVF_old);
for (int i = 0; i < 6; i++)
{
// dev->SetRenderState((_D3DRENDERSTATETYPE)RS[i][0], RS_old[i]);
// dev->SetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS_old[i]);
Renderer::SetRenderState( (_D3DRENDERSTATETYPE)RS[i][0], RS_old[i] );
Renderer::SetTextureStageState( 0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS_old[i] );
}
}
int CD3DFont::DrawTextScaled( float x, float y, float fXScale, float fYScale, float spacing, u32 dwColor, const char* strText, bool center )
{
SaveRenderStates();
SetRenderStates();
dev->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) );
float vpWidth = 1;
float vpHeight = 1;
float sx = x*vpWidth-0.5f;
float sy = y*vpHeight-0.5f;
float fStartX = sx;
float invLineHeight = 1.0f / (( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight);
// Fill vertex buffer
FONT2DVERTEX* pVertices;
int dwNumTriangles = 0L;
m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
const char *oldstrText=strText;
//First, let's measure the text
float tw=0;
float mx=0;
float maxx=0;
while( *strText )
{
char c = *strText++;
if( c == ('\n') )
mx=0;
if( c < (' ') )
continue;
float tx1 = m_fTexCoords[c-32][0];
float tx2 = m_fTexCoords[c-32][2];
float w = (tx2-tx1)*m_dwTexWidth;
w *= (fXScale*vpHeight)*invLineHeight;
mx += w + spacing*fXScale*vpWidth;
if (mx>maxx) maxx=mx;
}
float offset=-maxx/2;
strText = oldstrText;
//Then let's draw it
if (center)
{
sx+=offset;
fStartX+=offset;
}
float wScale=(fXScale*vpHeight)*invLineHeight;
float hScale=(fYScale*vpHeight)*invLineHeight;
while( *strText )
{
char c = *strText++;
if( c == ('\n') )
{
sx = fStartX;
sy += fYScale*vpHeight;
}
if( c < (' ') )
continue;
c-=32;
float tx1 = m_fTexCoords[c][0];
float ty1 = m_fTexCoords[c][1];
float tx2 = m_fTexCoords[c][2];
float ty2 = m_fTexCoords[c][3];
float w = (tx2-tx1)*m_dwTexWidth;
float h = (ty2-ty1)*m_dwTexHeight;
w *= wScale;
h *= hScale;
FONT2DVERTEX v[6];
v[0]=InitFont2DVertex(sx, sy+h, dwColor, tx1, ty2);
v[1]=InitFont2DVertex(sx, sy, dwColor, tx1, ty1);
v[2]=InitFont2DVertex(sx+w, sy+h, dwColor, tx2, ty2);
v[3]=InitFont2DVertex(sx+w, sy, dwColor, tx2, ty1);
v[4]=v[2];
v[5]=v[1];
memcpy(pVertices,v,6*sizeof(FONT2DVERTEX));
pVertices+=6;
dwNumTriangles += 2;
if( dwNumTriangles * 3 > (MAX_NUM_VERTICES-6) )
{
// Unlock, render, and relock the vertex buffer
m_pVB->Unlock();
// dev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
Renderer::DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
dwNumTriangles = 0;
}
sx += w + spacing*fXScale*vpWidth;
}
// Unlock and render the vertex buffer
m_pVB->Unlock();
if( dwNumTriangles > 0 )
{
// dev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
Renderer::DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
}
RestoreRenderStates();
return S_OK;
}
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1, float v1, float u2, float v2)
{
SaveRenderStates();
struct Q2DVertex { float x,y,z,rhw; u32 color; float u, v; } coords[4] = {
{x1-0.5f, y1-0.5f, 0, 1, color, u1, v1},
{x2-0.5f, y1-0.5f, 0, 1, color, u2, v1},
{x2-0.5f, y2-0.5f, 0, 1, color, u2, v2},
{x1-0.5f, y2-0.5f, 0, 1, color, u1, v2},
};
dev->SetPixelShader(0);
dev->SetVertexShader(0);
dev->SetVertexDeclaration(0);
// dev->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1);
// dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,coords,sizeof(Q2DVertex));
Renderer::SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
Renderer::DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,coords,sizeof(Q2DVertex));
RestoreRenderStates();
}
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "D3DBase.h"
#include "D3DUtil.h"
#include "Render.h"
namespace D3D
{
CD3DFont font;
#define MAX_NUM_VERTICES 50*6
struct FONT2DVERTEX {
float x,y,z;
float rhw;
u32 color;
float tu, tv;
};
#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL|D3DFVF_TEX1)
inline FONT2DVERTEX InitFont2DVertex( float x, float y, u32 color, float tu, float tv )
{
FONT2DVERTEX v; v.x=x; v.y=y; v.z=0; v.rhw=1.0f; v.color = color; v.tu = tu; v.tv = tv;
return v;
}
CD3DFont::CD3DFont()
{
m_pTexture = NULL;
m_pVB = NULL;
}
enum {m_dwTexWidth = 512, m_dwTexHeight = 512};
int CD3DFont::Init()
{
int hr;
m_fTextScale = 1.0f; // Draw fonts into texture without scaling
// Create a new texture for the font
hr = dev->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &m_pTexture, NULL );
if( FAILED(hr) )
return hr;
// Prepare to create a bitmap
int *pBitmapBits;
BITMAPINFO bmi;
ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) );
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = (int)m_dwTexWidth;
bmi.bmiHeader.biHeight = -(int)m_dwTexHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biBitCount = 32;
// Create a DC and a bitmap for the font
HDC hDC = CreateCompatibleDC( NULL );
HBITMAP hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS,
(VOID**)&pBitmapBits, NULL, 0 );
SetMapMode( hDC, MM_TEXT );
// Create a font. By specifying ANTIALIASED_QUALITY, we might get an
// antialiased font, but this is not guaranteed.
// We definitely don't want to get it cleartype'd, anyway.
int m_dwFontHeight = 36;
int nHeight = -MulDiv( m_dwFontHeight, int(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 );
int dwBold = FW_NORMAL; ///FW_BOLD
HFONT hFont = CreateFont( nHeight, 0, 0, 0, dwBold, 0,
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
VARIABLE_PITCH, "Tahoma");
if (NULL == hFont)
return E_FAIL;
HGDIOBJ hOldbmBitmap = SelectObject( hDC, hbmBitmap );
HGDIOBJ hOldFont = SelectObject( hDC, hFont );
// Set text properties
SetTextColor( hDC, 0xFFFFFF );
SetBkColor ( hDC, 0 );
SetTextAlign( hDC, TA_TOP );
// Loop through all printable character and output them to the bitmap..
// Meanwhile, keep track of the corresponding tex coords for each character.
int x = 0, y = 0;
char str[2] = "\0";
SIZE size;
for( char c=0; c<127-32; c++ )
{
str[0] = c+32;
GetTextExtentPoint32( hDC, str, 1, &size );
if( (int)(x+size.cx+1) > m_dwTexWidth )
{
x = 0;
y += size.cy+1;
}
ExtTextOut( hDC, x+1, y+0, ETO_OPAQUE | ETO_CLIPPED, NULL, str, 1, NULL );
m_fTexCoords[c][0] = ((float)(x+0))/m_dwTexWidth;
m_fTexCoords[c][1] = ((float)(y+0))/m_dwTexHeight;
m_fTexCoords[c][2] = ((float)(x+0+size.cx))/m_dwTexWidth;
m_fTexCoords[c][3] = ((float)(y+0+size.cy))/m_dwTexHeight;
x += size.cx+3; //3 to avoid annoying ij conflict (part of the j ends up with the i)
}
// Lock the surface and write the alpha values for the set pixels
D3DLOCKED_RECT d3dlr;
m_pTexture->LockRect( 0, &d3dlr, 0, 0 );
unsigned short* pDst16 = (unsigned short*)d3dlr.pBits;
int bAlpha; // 4-bit measure of pixel intensity
for( y=0; y < m_dwTexHeight; y++ )
{
for( x=0; x < m_dwTexWidth; x++ )
{
bAlpha = ((pBitmapBits[m_dwTexWidth*y + x] & 0xff) >> 4);
*pDst16++ = (bAlpha << 12) | 0x0fff;
}
}
// Done updating texture, so clean up used objects
m_pTexture->UnlockRect(0);
SelectObject( hDC, hOldbmBitmap );
DeleteObject( hbmBitmap );
SelectObject( hDC, hOldFont );
DeleteObject( hFont );
// Create vertex buffer for the letters
if( FAILED( hr = dev->CreateVertexBuffer( MAX_NUM_VERTICES*sizeof(FONT2DVERTEX),
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0,
D3DPOOL_DEFAULT, &m_pVB,NULL ) ) )
{
return hr;
}
return S_OK;
}
int CD3DFont::Shutdown()
{
SAFE_RELEASE( m_pVB );
SAFE_RELEASE( m_pTexture );
return S_OK;
}
const int RS[6][2] =
{
{ D3DRS_ALPHABLENDENABLE, TRUE },
{ D3DRS_SRCBLEND, D3DBLEND_SRCALPHA },
{ D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA },
{ D3DRS_CULLMODE, D3DCULL_NONE },
{ D3DRS_ZENABLE, FALSE },
{ D3DRS_FOGENABLE, FALSE },
};
const int TS[6][2] =
{
{D3DTSS_COLOROP, D3DTOP_MODULATE},
{D3DTSS_COLORARG1, D3DTA_TEXTURE},
{D3DTSS_COLORARG2, D3DTA_DIFFUSE },
{D3DTSS_ALPHAOP, D3DTOP_MODULATE },
{D3DTSS_ALPHAARG1, D3DTA_TEXTURE },
{D3DTSS_ALPHAARG2, D3DTA_DIFFUSE },
};
static DWORD RS_old[6];
static DWORD TS_old[6];
static LPDIRECT3DBASETEXTURE9 texture_old;
static DWORD FVF_old;
static LPDIRECT3DVERTEXDECLARATION9 decl_old;
static LPDIRECT3DPIXELSHADER9 ps_old;
static LPDIRECT3DVERTEXSHADER9 vs_old;
void SaveRenderStates()
{
for (int i = 0; i < 6; i++) {
dev->GetRenderState((_D3DRENDERSTATETYPE)RS[i][0], &(RS_old[i]));
dev->GetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), &(TS_old[i]));
}
dev->GetTexture(0, &texture_old);
dev->GetPixelShader(&ps_old);
dev->GetVertexShader(&vs_old);
dev->GetVertexDeclaration(&decl_old);
dev->GetFVF(&FVF_old);
}
void CD3DFont::SetRenderStates()
{
// dev->SetTexture(0, m_pTexture);
Renderer::SetTexture( 0, m_pTexture );
dev->SetPixelShader(0);
dev->SetVertexShader(0);
dev->SetVertexDeclaration(0);
// dev->SetFVF(D3DFVF_FONT2DVERTEX);
Renderer::SetFVF(D3DFVF_FONT2DVERTEX);
for (int i = 0; i < 6; i++) {
// dev->SetRenderState((_D3DRENDERSTATETYPE)RS[i][0],RS[i][1]);
// dev->SetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1]);
Renderer::SetRenderState( (_D3DRENDERSTATETYPE)RS[i][0], RS[i][1] );
Renderer::SetTextureStageState( 0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1] );
}
}
void RestoreRenderStates()
{
// dev->SetTexture(0, texture_old);
Renderer::SetTexture( 0, texture_old );
dev->SetPixelShader(ps_old);
dev->SetVertexShader(vs_old);
dev->SetVertexDeclaration(decl_old);
// dev->SetFVF(FVF_old);
Renderer::SetFVF(FVF_old);
for (int i = 0; i < 6; i++)
{
// dev->SetRenderState((_D3DRENDERSTATETYPE)RS[i][0], RS_old[i]);
// dev->SetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS_old[i]);
Renderer::SetRenderState( (_D3DRENDERSTATETYPE)RS[i][0], RS_old[i] );
Renderer::SetTextureStageState( 0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS_old[i] );
}
}
int CD3DFont::DrawTextScaled( float x, float y, float fXScale, float fYScale, float spacing, u32 dwColor, const char* strText, bool center )
{
SaveRenderStates();
SetRenderStates();
dev->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) );
float vpWidth = 1;
float vpHeight = 1;
float sx = x*vpWidth-0.5f;
float sy = y*vpHeight-0.5f;
float fStartX = sx;
float invLineHeight = 1.0f / (( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight);
// Fill vertex buffer
FONT2DVERTEX* pVertices;
int dwNumTriangles = 0L;
m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
const char *oldstrText=strText;
//First, let's measure the text
float tw=0;
float mx=0;
float maxx=0;
while( *strText )
{
char c = *strText++;
if( c == ('\n') )
mx=0;
if( c < (' ') )
continue;
float tx1 = m_fTexCoords[c-32][0];
float tx2 = m_fTexCoords[c-32][2];
float w = (tx2-tx1)*m_dwTexWidth;
w *= (fXScale*vpHeight)*invLineHeight;
mx += w + spacing*fXScale*vpWidth;
if (mx>maxx) maxx=mx;
}
float offset=-maxx/2;
strText = oldstrText;
//Then let's draw it
if (center)
{
sx+=offset;
fStartX+=offset;
}
float wScale=(fXScale*vpHeight)*invLineHeight;
float hScale=(fYScale*vpHeight)*invLineHeight;
while( *strText )
{
char c = *strText++;
if( c == ('\n') )
{
sx = fStartX;
sy += fYScale*vpHeight;
}
if( c < (' ') )
continue;
c-=32;
float tx1 = m_fTexCoords[c][0];
float ty1 = m_fTexCoords[c][1];
float tx2 = m_fTexCoords[c][2];
float ty2 = m_fTexCoords[c][3];
float w = (tx2-tx1)*m_dwTexWidth;
float h = (ty2-ty1)*m_dwTexHeight;
w *= wScale;
h *= hScale;
FONT2DVERTEX v[6];
v[0]=InitFont2DVertex(sx, sy+h, dwColor, tx1, ty2);
v[1]=InitFont2DVertex(sx, sy, dwColor, tx1, ty1);
v[2]=InitFont2DVertex(sx+w, sy+h, dwColor, tx2, ty2);
v[3]=InitFont2DVertex(sx+w, sy, dwColor, tx2, ty1);
v[4]=v[2];
v[5]=v[1];
memcpy(pVertices,v,6*sizeof(FONT2DVERTEX));
pVertices+=6;
dwNumTriangles += 2;
if( dwNumTriangles * 3 > (MAX_NUM_VERTICES-6) )
{
// Unlock, render, and relock the vertex buffer
m_pVB->Unlock();
// dev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
Renderer::DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
dwNumTriangles = 0;
}
sx += w + spacing*fXScale*vpWidth;
}
// Unlock and render the vertex buffer
m_pVB->Unlock();
if( dwNumTriangles > 0 )
{
// dev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
Renderer::DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
}
RestoreRenderStates();
return S_OK;
}
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1, float v1, float u2, float v2)
{
SaveRenderStates();
struct Q2DVertex { float x,y,z,rhw; u32 color; float u, v; } coords[4] = {
{x1-0.5f, y1-0.5f, 0, 1, color, u1, v1},
{x2-0.5f, y1-0.5f, 0, 1, color, u2, v1},
{x2-0.5f, y2-0.5f, 0, 1, color, u2, v2},
{x1-0.5f, y2-0.5f, 0, 1, color, u1, v2},
};
dev->SetPixelShader(0);
dev->SetVertexShader(0);
dev->SetVertexDeclaration(0);
// dev->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1);
// dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,coords,sizeof(Q2DVertex));
Renderer::SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
Renderer::DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,coords,sizeof(Q2DVertex));
RestoreRenderStates();
}
}

View File

@ -1,468 +1,468 @@
#include "stdafx.h"
#if 0
#include "OpcodeDecoding.h"
#include "VertexLoader.h"
#include "VertexHandler.h"
#include "DataReader.h"
#include "BPStructs.h"
#include "CPStructs.h"
#include "XFStructs.h"
#include "DLCompiler.h"
#include "x86.h"
#include "main.h"
#include "Utils.h"
CompiledDList::CompiledDList(u32 _addr, u32 _size)
{
dataSize = 0;
data = 0;
code = 0;
addr = _addr;
size = _size;
pass = 0;
numBatches = 0;
batches = 0;
}
CompiledDList::~CompiledDList()
{
if (data)
delete [] data;
if (code)
delete [] code;
if (batches)
delete [] batches;
}
bool CompiledDList::Call()
{
switch(pass) {
case 0: // First compiling pass : find data size
if (Pass1())
{
pass = 1;
return true;
}
else
return false;
case 1: // Second compiling pass : actually compile
//if pass1 succeeded, pass2 will too
Pass2();
pass = 2;
return true;
case 2: // Run pass - we have a compiled dlist, just call it
Run();
return true;
default:
//ERROR
return false;
}
}
bool CompiledDList::Pass1()
{
/* //find the size of code + data, if the dlist is worth recompiling etc
// at the same time, do the ordinary stuff
g_pDataReader = &dlistReader;
OpcodeReaders::SetDListReader(addr, addr+size);
dataSize = 0;
codeSize = 0;
numBatches = 0;
bool lastIsPrim = false;
while (OpcodeReaders::IsDListOKToRead())
{
int Cmd = g_pDataReader->Read8();
switch(Cmd)
{
case GX_LOAD_CP_REG: //0x08
{
u32 SubCmd = g_pDataReader->Read8();
u32 Value = g_pDataReader->Read32();
LoadCPReg(SubCmd,Value);
//COMPILER
codeSize+=13;
}
break;
case GX_LOAD_XF_REG:
{
u32 Cmd2 = g_pDataReader->Read32();
int dwTransferSize = ((Cmd2>>16)&15) + 1;
DWORD dwAddress = Cmd2 & 0xFFFF;
static u32 pData[16];
for (int i=0; i<dwTransferSize; i++)
pData[i] = g_pDataReader->Read32();
LoadXFReg(dwTransferSize,dwAddress,pData);
//COMPILER
dataSize+=dwTransferSize;
codeSize+=17;
}
break;
case GX_LOAD_BP_REG: //0x61
{
u32 cmd=g_pDataReader->Read32();
LoadBPReg(cmd);
codeSize+=9;
}
break;
case GX_LOAD_INDX_A: //used for position matrices
LoadIndexedXF(g_pDataReader->Read32(),0xC);
codeSize+=13;
break;
case GX_LOAD_INDX_B: //used for normal matrices
LoadIndexedXF(g_pDataReader->Read32(),0xD);
codeSize+=13;
break;
case GX_LOAD_INDX_C: //used for postmatrices
LoadIndexedXF(g_pDataReader->Read32(),0xE);
codeSize+=13;
break;
case GX_LOAD_INDX_D: //used for lights
LoadIndexedXF(g_pDataReader->Read32(),0xF);
codeSize+=13;
break;
case GX_CMD_CALL_DL:
MessageBox(0,"Display lists can't recurse!!","error",0);
break;
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
break;
case GX_NOP:
break;
default:
if (Cmd&0x80)
{
int primitive = (Cmd&GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
if (lastIsPrim)
{
//join to last
}
else
{
//finish up last and commit
}
u16 numVertices = g_pDataReader->Read16();
tempvarray.Reset();
VertexLoader::SetVArray(&tempvarray);
VertexLoader *loader = &VertexLoader[Cmd&GX_VAT_MASK];
loader->Setup();
loader->PrepareRun();
int vsize = loader->GetVertexSize();
loader->RunVertices(numVertices);
CVertexHandler::DrawVertices(primitive, numVertices, &tempvarray);
CVertexHandler::Flush();
//COMPILER
codeSize+=21;
numBatches++;
lastIsPrim = true;
}
break;
}
}
if (lastIsPrim)
{
//finish up last and commit
}
codeSize*=2;*/
return true;
}
void CompiledDList::Pass2()
{
/* OpcodeReaders::SetDListReader(addr, addr+size);
data = new u32[dataSize];
code = new u8[codeSize]; //at least
batches = new Batch[numBatches];
int batchCount = 0;
u32 *dataptr = data;
x86Init();
x86SetPtr((s8*)code);
//WC8(0xCC);
//actually do the recompiling, emit code and data, protect the memory
// but again, at the same time do the ordinary stuff
// so the compiled display list won't be run until the third time actually
bool dump = false,lastIsGeom=false;
FILE *f;
#ifndef TEASER
if (dump)
{
f=fopen("D:\\dlistlogs.txt","a");
fprintf(f,"===========================================\n");
}
#endif
while (OpcodeReaders::IsDListOKToRead())
{
int Cmd = g_pDataReader->Read8();
switch(Cmd)
{
case GX_LOAD_CP_REG: //0x08
{
lastIsGeom = false;
u32 SubCmd = g_pDataReader->Read8();
u32 Value = g_pDataReader->Read32();
if (dump)
fprintf(f,"CP | %02x %08x\n",SubCmd,Value);
LoadCPReg(SubCmd,Value);
//COMPILER
PUSH_WordToStack(Value);
PUSH_WordToStack(SubCmd);
CALLFunc((u32)LoadCPReg);
}
break;
case GX_LOAD_XF_REG:
{
lastIsGeom = false;
u32 Cmd2 = g_pDataReader->Read32();
int dwTransferSize = ((Cmd2>>16)&15) + 1;
u32 dwAddress = Cmd2 & 0xFFFF;
static u32 pData[16];
u32 *oldDataPtr = dataptr;
if (dump)
{
fprintf(f,"XF | %01xx %04x\n",dwTransferSize,dwAddress);
for (int i=0; i<dwTransferSize; i++)
fprintf(f, "%08x | %f\n",oldDataPtr[i], *((float*)oldDataPtr+i));
}
for (int i=0; i<dwTransferSize; i++) // a little compiler here too
*dataptr++ = g_pDataReader->Read32();
LoadXFReg(dwTransferSize,dwAddress,oldDataPtr);
//COMPILER
PUSH_WordToStack((u32)oldDataPtr);
PUSH_WordToStack(dwAddress);
PUSH_WordToStack(dwTransferSize);
CALLFunc((u32)LoadXFReg);
}
break;
case GX_LOAD_BP_REG: //0x61
{
lastIsGeom = false;
u32 cmd=g_pDataReader->Read32();
if (dump)
fprintf(f,"BP | %08x\n",cmd);
LoadBPReg(cmd);
//COMPILER
PUSH_WordToStack(cmd);
CALLFunc((u32)LoadBPReg);
}
break;
case GX_LOAD_INDX_A: //usually used for position matrices
{
lastIsGeom = false;
u32 value = g_pDataReader->Read32();
LoadIndexedXF(value,0xC);
//COMPILER
PUSH_WordToStack(0xC);
PUSH_WordToStack(value);
CALLFunc((u32)LoadIndexedXF);
if (dump)
fprintf(f,"LOADINDEXA | pos matrix\n");
}
break;
case GX_LOAD_INDX_B: //usually used for normal matrices
{
lastIsGeom = false;
u32 value = g_pDataReader->Read32();
LoadIndexedXF(value,0xD);
//COMPILER
PUSH_WordToStack(0xD);
PUSH_WordToStack(value);
CALLFunc((u32)LoadIndexedXF);
if (dump)
fprintf(f,"LOADINDEXB | nrm matrix\n");
}
break;
case GX_LOAD_INDX_C: //usually used for postmatrices
{
lastIsGeom = false;
u32 value = g_pDataReader->Read32();
LoadIndexedXF(value,0xE);
//COMPILER
PUSH_WordToStack(0xE);
PUSH_WordToStack(value);
CALLFunc((u32)LoadIndexedXF);
if (dump)
fprintf(f,"LOADINDEXC | post matrix\n");
}
break;
case GX_LOAD_INDX_D: //usually used for lights
{
lastIsGeom = false;
u32 value = g_pDataReader->Read32();
LoadIndexedXF(value,0xF);
//COMPILER
PUSH_WordToStack(0xF);
PUSH_WordToStack(value);
CALLFunc((u32)LoadIndexedXF);
if (dump)
fprintf(f,"LOADINDEXD | light\n");
}
break;
case GX_CMD_CALL_DL:
// ERORRR
break;
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
if (dump)
fprintf(f,"invalidate vc\n");
break;
case GX_NOP:
if (dump)
fprintf(f,"nop\n");
break;
default:
if (Cmd&0x80)
{
int primitive = (Cmd&GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
//if (lastIsGeom) INCSTAT(stats.numJoins);
u16 numVertices = g_pDataReader->Read16();
if (dump)
fprintf(f,"DP: prim=%02x numv=%i\n",primitive,numVertices);
DecodedVArray &va = batches[batchCount].varray;
VertexLoader *loader = &VertexLoader[Cmd&GX_VAT_MASK];
TVtxDesc &vd = loader->GetVtxDesc();
VertexLoader::SetVArray(&va);
loader->Setup();
loader->PrepareRun();
// va.numColors = loader->GetNumColors();
// va.numUVs = loader->GetNumTCs();
// va.numNormals = loader->GetNumNormals();
//va.num
va.Create(numVertices,vd.PosMatIdx,
vd.Tex0MatIdx+vd.Tex1MatIdx+vd.Tex2MatIdx+vd.Tex3MatIdx+
vd.Tex4MatIdx+vd.Tex5MatIdx+vd.Tex6MatIdx+vd.Tex7MatIdx,
va.numNormals, va.numColors, va.numTCs);
int vsize = loader->GetVertexSize();
loader->RunVertices(numVertices);
CVertexHandler::DrawVertices(primitive, numVertices, &va);
CVertexHandler::Flush();
// YES we have now filled our varray
//LETS COMPILE
PUSH_WordToStack(primitive);
PUSH_WordToStack(batchCount);
PUSH_WordToStack((u32)this);
CALLFunc((u32)DrawHelperHelper);
batchCount++;
lastIsGeom = true;
if (dump)
fprintf(f,"DRAW PRIMITIVE: prim=%02x numv=%i\n",primitive,numVertices);
}
break;
}
}
if (dump)
{
fprintf(f,"***************************************\n\n\n");
}
RET();
if (dump)
fclose(f);*/
//we're done, next time just kick the compiled list off, much much faster than interpreting!
}
void CompiledDList::DrawHelperHelper(CompiledDList *dl, int vno, int prim)
{
Batch &b = dl->batches[vno];
CVertexHandler::DrawVertices(prim, b.varray.GetSize(), &b.varray);
}
void CompiledDList::Run()
{
//run the code
((void (*)())(code))();
CVertexHandler::Flush();
}
DListCache::DLCache DListCache::dlists;
void DListCache::Init()
{
}
void DListCache::Shutdown()
{
DLCache::iterator iter = dlists.begin();
for (;iter!=dlists.end();iter++)
iter->second.Destroy();
dlists.clear();
}
void DListCache::Call(u32 _addr, u32 _size)
{
DLCache::iterator iter;
iter = dlists.find(_addr);
if (iter != dlists.end())
{
if (iter->second.size == _size)
{
iter->second.dlist->Call();
return;
}
else // wrong size, need to recompile
{
iter->second.Destroy();
iter=dlists.erase(iter);
}
}
//Make an entry in the table
DLCacheEntry entry;
entry.dlist = new CompiledDList(_addr, _size);
entry.dlist->Call();
entry.frameCount = frameCount;
entry.size = _size;
dlists[_addr] = entry;
INCSTAT(stats.numDListsCreated);
SETSTAT(stats.numDListsAlive,(int)dlists.size());
}
void DListCache::Cleanup()
{
for (DLCache::iterator iter=dlists.begin(); iter!=dlists.end();iter++)
{
DLCacheEntry &entry = iter->second;
if (entry.frameCount<frameCount-80)
{
entry.Destroy();
iter = dlists.erase(iter);
}
}
SETSTAT(stats.numDListsAlive,(int)dlists.size());
}
#include "stdafx.h"
#if 0
#include "OpcodeDecoding.h"
#include "VertexLoader.h"
#include "VertexHandler.h"
#include "DataReader.h"
#include "BPStructs.h"
#include "CPStructs.h"
#include "XFStructs.h"
#include "DLCompiler.h"
#include "x86.h"
#include "main.h"
#include "Utils.h"
CompiledDList::CompiledDList(u32 _addr, u32 _size)
{
dataSize = 0;
data = 0;
code = 0;
addr = _addr;
size = _size;
pass = 0;
numBatches = 0;
batches = 0;
}
CompiledDList::~CompiledDList()
{
if (data)
delete [] data;
if (code)
delete [] code;
if (batches)
delete [] batches;
}
bool CompiledDList::Call()
{
switch(pass) {
case 0: // First compiling pass : find data size
if (Pass1())
{
pass = 1;
return true;
}
else
return false;
case 1: // Second compiling pass : actually compile
//if pass1 succeeded, pass2 will too
Pass2();
pass = 2;
return true;
case 2: // Run pass - we have a compiled dlist, just call it
Run();
return true;
default:
//ERROR
return false;
}
}
bool CompiledDList::Pass1()
{
/* //find the size of code + data, if the dlist is worth recompiling etc
// at the same time, do the ordinary stuff
g_pDataReader = &dlistReader;
OpcodeReaders::SetDListReader(addr, addr+size);
dataSize = 0;
codeSize = 0;
numBatches = 0;
bool lastIsPrim = false;
while (OpcodeReaders::IsDListOKToRead())
{
int Cmd = g_pDataReader->Read8();
switch(Cmd)
{
case GX_LOAD_CP_REG: //0x08
{
u32 SubCmd = g_pDataReader->Read8();
u32 Value = g_pDataReader->Read32();
LoadCPReg(SubCmd,Value);
//COMPILER
codeSize+=13;
}
break;
case GX_LOAD_XF_REG:
{
u32 Cmd2 = g_pDataReader->Read32();
int dwTransferSize = ((Cmd2>>16)&15) + 1;
DWORD dwAddress = Cmd2 & 0xFFFF;
static u32 pData[16];
for (int i=0; i<dwTransferSize; i++)
pData[i] = g_pDataReader->Read32();
LoadXFReg(dwTransferSize,dwAddress,pData);
//COMPILER
dataSize+=dwTransferSize;
codeSize+=17;
}
break;
case GX_LOAD_BP_REG: //0x61
{
u32 cmd=g_pDataReader->Read32();
LoadBPReg(cmd);
codeSize+=9;
}
break;
case GX_LOAD_INDX_A: //used for position matrices
LoadIndexedXF(g_pDataReader->Read32(),0xC);
codeSize+=13;
break;
case GX_LOAD_INDX_B: //used for normal matrices
LoadIndexedXF(g_pDataReader->Read32(),0xD);
codeSize+=13;
break;
case GX_LOAD_INDX_C: //used for postmatrices
LoadIndexedXF(g_pDataReader->Read32(),0xE);
codeSize+=13;
break;
case GX_LOAD_INDX_D: //used for lights
LoadIndexedXF(g_pDataReader->Read32(),0xF);
codeSize+=13;
break;
case GX_CMD_CALL_DL:
MessageBox(0,"Display lists can't recurse!!","error",0);
break;
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
break;
case GX_NOP:
break;
default:
if (Cmd&0x80)
{
int primitive = (Cmd&GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
if (lastIsPrim)
{
//join to last
}
else
{
//finish up last and commit
}
u16 numVertices = g_pDataReader->Read16();
tempvarray.Reset();
VertexLoader::SetVArray(&tempvarray);
VertexLoader *loader = &VertexLoader[Cmd&GX_VAT_MASK];
loader->Setup();
loader->PrepareRun();
int vsize = loader->GetVertexSize();
loader->RunVertices(numVertices);
CVertexHandler::DrawVertices(primitive, numVertices, &tempvarray);
CVertexHandler::Flush();
//COMPILER
codeSize+=21;
numBatches++;
lastIsPrim = true;
}
break;
}
}
if (lastIsPrim)
{
//finish up last and commit
}
codeSize*=2;*/
return true;
}
void CompiledDList::Pass2()
{
/* OpcodeReaders::SetDListReader(addr, addr+size);
data = new u32[dataSize];
code = new u8[codeSize]; //at least
batches = new Batch[numBatches];
int batchCount = 0;
u32 *dataptr = data;
x86Init();
x86SetPtr((s8*)code);
//WC8(0xCC);
//actually do the recompiling, emit code and data, protect the memory
// but again, at the same time do the ordinary stuff
// so the compiled display list won't be run until the third time actually
bool dump = false,lastIsGeom=false;
FILE *f;
#ifndef TEASER
if (dump)
{
f=fopen("D:\\dlistlogs.txt","a");
fprintf(f,"===========================================\n");
}
#endif
while (OpcodeReaders::IsDListOKToRead())
{
int Cmd = g_pDataReader->Read8();
switch(Cmd)
{
case GX_LOAD_CP_REG: //0x08
{
lastIsGeom = false;
u32 SubCmd = g_pDataReader->Read8();
u32 Value = g_pDataReader->Read32();
if (dump)
fprintf(f,"CP | %02x %08x\n",SubCmd,Value);
LoadCPReg(SubCmd,Value);
//COMPILER
PUSH_WordToStack(Value);
PUSH_WordToStack(SubCmd);
CALLFunc((u32)LoadCPReg);
}
break;
case GX_LOAD_XF_REG:
{
lastIsGeom = false;
u32 Cmd2 = g_pDataReader->Read32();
int dwTransferSize = ((Cmd2>>16)&15) + 1;
u32 dwAddress = Cmd2 & 0xFFFF;
static u32 pData[16];
u32 *oldDataPtr = dataptr;
if (dump)
{
fprintf(f,"XF | %01xx %04x\n",dwTransferSize,dwAddress);
for (int i=0; i<dwTransferSize; i++)
fprintf(f, "%08x | %f\n",oldDataPtr[i], *((float*)oldDataPtr+i));
}
for (int i=0; i<dwTransferSize; i++) // a little compiler here too
*dataptr++ = g_pDataReader->Read32();
LoadXFReg(dwTransferSize,dwAddress,oldDataPtr);
//COMPILER
PUSH_WordToStack((u32)oldDataPtr);
PUSH_WordToStack(dwAddress);
PUSH_WordToStack(dwTransferSize);
CALLFunc((u32)LoadXFReg);
}
break;
case GX_LOAD_BP_REG: //0x61
{
lastIsGeom = false;
u32 cmd=g_pDataReader->Read32();
if (dump)
fprintf(f,"BP | %08x\n",cmd);
LoadBPReg(cmd);
//COMPILER
PUSH_WordToStack(cmd);
CALLFunc((u32)LoadBPReg);
}
break;
case GX_LOAD_INDX_A: //usually used for position matrices
{
lastIsGeom = false;
u32 value = g_pDataReader->Read32();
LoadIndexedXF(value,0xC);
//COMPILER
PUSH_WordToStack(0xC);
PUSH_WordToStack(value);
CALLFunc((u32)LoadIndexedXF);
if (dump)
fprintf(f,"LOADINDEXA | pos matrix\n");
}
break;
case GX_LOAD_INDX_B: //usually used for normal matrices
{
lastIsGeom = false;
u32 value = g_pDataReader->Read32();
LoadIndexedXF(value,0xD);
//COMPILER
PUSH_WordToStack(0xD);
PUSH_WordToStack(value);
CALLFunc((u32)LoadIndexedXF);
if (dump)
fprintf(f,"LOADINDEXB | nrm matrix\n");
}
break;
case GX_LOAD_INDX_C: //usually used for postmatrices
{
lastIsGeom = false;
u32 value = g_pDataReader->Read32();
LoadIndexedXF(value,0xE);
//COMPILER
PUSH_WordToStack(0xE);
PUSH_WordToStack(value);
CALLFunc((u32)LoadIndexedXF);
if (dump)
fprintf(f,"LOADINDEXC | post matrix\n");
}
break;
case GX_LOAD_INDX_D: //usually used for lights
{
lastIsGeom = false;
u32 value = g_pDataReader->Read32();
LoadIndexedXF(value,0xF);
//COMPILER
PUSH_WordToStack(0xF);
PUSH_WordToStack(value);
CALLFunc((u32)LoadIndexedXF);
if (dump)
fprintf(f,"LOADINDEXD | light\n");
}
break;
case GX_CMD_CALL_DL:
// ERORRR
break;
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
if (dump)
fprintf(f,"invalidate vc\n");
break;
case GX_NOP:
if (dump)
fprintf(f,"nop\n");
break;
default:
if (Cmd&0x80)
{
int primitive = (Cmd&GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
//if (lastIsGeom) INCSTAT(stats.numJoins);
u16 numVertices = g_pDataReader->Read16();
if (dump)
fprintf(f,"DP: prim=%02x numv=%i\n",primitive,numVertices);
DecodedVArray &va = batches[batchCount].varray;
VertexLoader *loader = &VertexLoader[Cmd&GX_VAT_MASK];
TVtxDesc &vd = loader->GetVtxDesc();
VertexLoader::SetVArray(&va);
loader->Setup();
loader->PrepareRun();
// va.numColors = loader->GetNumColors();
// va.numUVs = loader->GetNumTCs();
// va.numNormals = loader->GetNumNormals();
//va.num
va.Create(numVertices,vd.PosMatIdx,
vd.Tex0MatIdx+vd.Tex1MatIdx+vd.Tex2MatIdx+vd.Tex3MatIdx+
vd.Tex4MatIdx+vd.Tex5MatIdx+vd.Tex6MatIdx+vd.Tex7MatIdx,
va.numNormals, va.numColors, va.numTCs);
int vsize = loader->GetVertexSize();
loader->RunVertices(numVertices);
CVertexHandler::DrawVertices(primitive, numVertices, &va);
CVertexHandler::Flush();
// YES we have now filled our varray
//LETS COMPILE
PUSH_WordToStack(primitive);
PUSH_WordToStack(batchCount);
PUSH_WordToStack((u32)this);
CALLFunc((u32)DrawHelperHelper);
batchCount++;
lastIsGeom = true;
if (dump)
fprintf(f,"DRAW PRIMITIVE: prim=%02x numv=%i\n",primitive,numVertices);
}
break;
}
}
if (dump)
{
fprintf(f,"***************************************\n\n\n");
}
RET();
if (dump)
fclose(f);*/
//we're done, next time just kick the compiled list off, much much faster than interpreting!
}
void CompiledDList::DrawHelperHelper(CompiledDList *dl, int vno, int prim)
{
Batch &b = dl->batches[vno];
CVertexHandler::DrawVertices(prim, b.varray.GetSize(), &b.varray);
}
void CompiledDList::Run()
{
//run the code
((void (*)())(code))();
CVertexHandler::Flush();
}
DListCache::DLCache DListCache::dlists;
void DListCache::Init()
{
}
void DListCache::Shutdown()
{
DLCache::iterator iter = dlists.begin();
for (;iter!=dlists.end();iter++)
iter->second.Destroy();
dlists.clear();
}
void DListCache::Call(u32 _addr, u32 _size)
{
DLCache::iterator iter;
iter = dlists.find(_addr);
if (iter != dlists.end())
{
if (iter->second.size == _size)
{
iter->second.dlist->Call();
return;
}
else // wrong size, need to recompile
{
iter->second.Destroy();
iter=dlists.erase(iter);
}
}
//Make an entry in the table
DLCacheEntry entry;
entry.dlist = new CompiledDList(_addr, _size);
entry.dlist->Call();
entry.frameCount = frameCount;
entry.size = _size;
dlists[_addr] = entry;
INCSTAT(stats.numDListsCreated);
SETSTAT(stats.numDListsAlive,(int)dlists.size());
}
void DListCache::Cleanup()
{
for (DLCache::iterator iter=dlists.begin(); iter!=dlists.end();iter++)
{
DLCacheEntry &entry = iter->second;
if (entry.frameCount<frameCount-80)
{
entry.Destroy();
iter = dlists.erase(iter);
}
}
SETSTAT(stats.numDListsAlive,(int)dlists.size());
}
#endif

View File

@ -1,92 +1,92 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
#include "DecodedVArray.h"
#include "main.h"
DecodedVArray::DecodedVArray()
{
Zero();
}
DecodedVArray::~DecodedVArray()
{
Destroy();
}
void DecodedVArray::Zero()
{
size = 0;
count = 0;
components = 0;
positions = 0;
posMtxInds = 0;
for (int i=0; i<3; i++)
normals[i] = 0;
for (int i=0; i<2; i++)
colors[i] = 0;
for (int i=0; i<8; i++)
{
texMtxInds[i] = 0;
uvs[i] = 0;
}
}
void DecodedVArray::Destroy()
{
//,,
delete [] positions;
delete [] posMtxInds;
for (int i=0; i<3; i++)
delete [] normals[i];
for (int i=0; i<2; i++)
delete [] colors[i];
for (int i=0; i<8; i++)
{
delete [] uvs[i];
delete [] texMtxInds[i];
}
Zero();
}
void DecodedVArray::Create(int _size, int pmcount, int tmcount, int nrmcount, int colcount, int tccount)
{
size = _size;
// position matrix indices
if (pmcount)
posMtxInds = new DecMtxInd[size];
// texture matrix indices
if (tmcount)
for (int i=0; i<tmcount; i++)
texMtxInds[i] = new DecMtxInd[size];
// positions (always)
positions = new DecPos[size];
// normals
if (nrmcount)
for (int i=0; i<nrmcount; i++)
normals[i] = new DecNormal[size];
// colors
if (colcount)
for (int i=0; i<colcount; i++)
colors[i] = new DecColor[size];
if (tccount)
for (int i=0; i<tccount; i++)
uvs[i] = new DecUV[size];
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
#include "DecodedVArray.h"
#include "main.h"
DecodedVArray::DecodedVArray()
{
Zero();
}
DecodedVArray::~DecodedVArray()
{
Destroy();
}
void DecodedVArray::Zero()
{
size = 0;
count = 0;
components = 0;
positions = 0;
posMtxInds = 0;
for (int i=0; i<3; i++)
normals[i] = 0;
for (int i=0; i<2; i++)
colors[i] = 0;
for (int i=0; i<8; i++)
{
texMtxInds[i] = 0;
uvs[i] = 0;
}
}
void DecodedVArray::Destroy()
{
//,,
delete [] positions;
delete [] posMtxInds;
for (int i=0; i<3; i++)
delete [] normals[i];
for (int i=0; i<2; i++)
delete [] colors[i];
for (int i=0; i<8; i++)
{
delete [] uvs[i];
delete [] texMtxInds[i];
}
Zero();
}
void DecodedVArray::Create(int _size, int pmcount, int tmcount, int nrmcount, int colcount, int tccount)
{
size = _size;
// position matrix indices
if (pmcount)
posMtxInds = new DecMtxInd[size];
// texture matrix indices
if (tmcount)
for (int i=0; i<tmcount; i++)
texMtxInds[i] = new DecMtxInd[size];
// positions (always)
positions = new DecPos[size];
// normals
if (nrmcount)
for (int i=0; i<nrmcount; i++)
normals[i] = new DecNormal[size];
// colors
if (colcount)
for (int i=0; i<colcount; i++)
colors[i] = new DecColor[size];
if (tccount)
for (int i=0; i<tccount; i++)
uvs[i] = new DecUV[size];
}

View File

@ -1,246 +1,246 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If 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 <windowsx.h>
#include "resource.h"
#include "W32Util/PropertySheet.h"
#include "W32Util/ShellUtil.h"
#include "D3DBase.h"
#include "D3DPostprocess.h"
#include "Config.h"
#include "TextureCache.h"
#define NUMWNDRES 6
int g_Res[NUMWNDRES][2] =
{
{640,480},
{800,600},
{1024,768},
{1280,960},
{1280,1024},
{1600,1200},
};
struct TabDirect3D : public W32Util::Tab
{
void Init(HWND hDlg)
{
for (int i=0; i<D3D::GetNumAdapters(); i++)
{
const D3D::Adapter &adapter = D3D::GetAdapter(i);
ComboBox_AddString(GetDlgItem(hDlg,IDC_ADAPTER),adapter.ident.Description);
}
const D3D::Adapter &adapter = D3D::GetAdapter(g_Config.iAdapter);
ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_ADAPTER),g_Config.iAdapter);
for (int i = 0; i < (int)adapter.aa_levels.size(); i++)
{
ComboBox_AddString(GetDlgItem(hDlg, IDC_ANTIALIASMODE), adapter.aa_levels[i].name);
}
ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_ANTIALIASMODE), g_Config.iMultisampleMode);
if (adapter.aa_levels.size() == 1)
{
EnableWindow(GetDlgItem(hDlg, IDC_ANTIALIASMODE), FALSE);
}
for (int i = 0; i < (int)adapter.resolutions.size(); i++)
{
const D3D::Resolution &r = adapter.resolutions[i];
ComboBox_AddString(GetDlgItem(hDlg,IDC_RESOLUTION), r.name);
}
ComboBox_SetCurSel(GetDlgItem(hDlg,IDC_RESOLUTION), g_Config.iFSResolution);
for (int i = 0; i < NUMWNDRES; i++)
{
char temp[256];
sprintf(temp,"%ix%i",g_Res[i][0],g_Res[i][1]);
ComboBox_AddString(GetDlgItem(hDlg,IDC_RESOLUTIONWINDOWED),temp);
}
ComboBox_SetCurSel(GetDlgItem(hDlg,IDC_RESOLUTIONWINDOWED),g_Config.iWindowedRes);
CheckDlgButton(hDlg, IDC_FULLSCREENENABLE, g_Config.bFullscreen ? TRUE : FALSE);
CheckDlgButton(hDlg, IDC_VSYNC, g_Config.bVsync ? TRUE : FALSE);
CheckDlgButton(hDlg, IDC_RENDER_TO_MAINWINDOW, g_Config.renderToMainframe ? TRUE : FALSE);
}
void Command(HWND hDlg,WPARAM wParam)
{
/*
switch (LOWORD(wParam))
{
default:
break;
}
*/
}
void Apply(HWND hDlg)
{
g_Config.iAdapter = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_ADAPTER));
g_Config.iWindowedRes = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_RESOLUTIONWINDOWED));
g_Config.iMultisampleMode = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_ANTIALIASMODE));
g_Config.iFSResolution = ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_RESOLUTION));
g_Config.bFullscreen = Button_GetCheck(GetDlgItem(hDlg, IDC_FULLSCREENENABLE)) ? true : false;
g_Config.bVsync = Button_GetCheck(GetDlgItem(hDlg, IDC_VSYNC)) ? true : false;
g_Config.renderToMainframe = Button_GetCheck(GetDlgItem(hDlg, IDC_RENDER_TO_MAINWINDOW)) ? true : false;
g_Config.Save();
}
};
struct TabAdvanced : public W32Util::Tab
{
void Init(HWND hDlg)
{
HWND opt = GetDlgItem(hDlg,IDC_DLOPTLEVEL);
ComboBox_AddString(opt,"0: Interpret (slowest, most compatible)");
ComboBox_AddString(opt,"1: Compile lists and decode vertex lists");
//ComboBox_AddString(opt,"2: Compile+decode to vbufs and use hw xform");
//ComboBox_AddString(opt,"Recompile to vbuffers and shaders");
ComboBox_SetCurSel(opt,g_Config.iCompileDLsLevel);
Button_SetCheck(GetDlgItem(hDlg,IDC_OVERLAYSTATS), g_Config.bOverlayStats);
Button_SetCheck(GetDlgItem(hDlg,IDC_WIREFRAME), g_Config.bWireFrame);
Button_SetCheck(GetDlgItem(hDlg,IDC_TEXDUMP), g_Config.bDumpTextures);
Button_SetCheck(GetDlgItem(hDlg,IDC_SHOWSHADERERRORS), g_Config.bShowShaderErrors);
Button_SetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY), g_Config.bTexFmtOverlayEnable);
Button_SetCheck(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), g_Config.bTexFmtOverlayCenter);
Button_GetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY)) ? Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), true) : Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), false);
SetWindowText(GetDlgItem(hDlg,IDC_TEXDUMPPATH),g_Config.texDumpPath.c_str());
Edit_LimitText(GetDlgItem(hDlg,IDC_TEXDUMPPATH),255);
}
void Command(HWND hDlg,WPARAM wParam)
{
switch (LOWORD(wParam))
{
case IDC_BROWSETEXDUMPPATH:
{
std::string path = W32Util::BrowseForFolder(hDlg,"Choose texture dump path:");
SetWindowText(GetDlgItem(hDlg,IDC_TEXDUMPPATH),path.c_str());
}
break;
case IDC_TEXFMT_OVERLAY:
{
Button_GetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY)) ? Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), true) : Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), false);
}
break;
default:
break;
}
}
void Apply(HWND hDlg)
{
g_Config.bTexFmtOverlayEnable = Button_GetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY)) ? true : false;
g_Config.bTexFmtOverlayCenter = Button_GetCheck(GetDlgItem(hDlg,IDC_TEXFMT_CENTER)) ? true : false;
g_Config.bOverlayStats = Button_GetCheck(GetDlgItem(hDlg,IDC_OVERLAYSTATS)) ? true : false;
g_Config.bWireFrame = Button_GetCheck(GetDlgItem(hDlg,IDC_WIREFRAME)) ? true : false;
g_Config.bDumpTextures = Button_GetCheck(GetDlgItem(hDlg,IDC_TEXDUMP)) ? true : false;
g_Config.iCompileDLsLevel = (int)ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_DLOPTLEVEL));
g_Config.bShowShaderErrors = Button_GetCheck(GetDlgItem(hDlg,IDC_SHOWSHADERERRORS)) ? true : false;
char temp[MAX_PATH];
GetWindowText(GetDlgItem(hDlg,IDC_TEXDUMPPATH), temp, MAX_PATH);
g_Config.texDumpPath = temp;
}
};
struct TabDebug : public W32Util::Tab
{
void Init(HWND hDlg)
{
}
void Command(HWND hDlg,WPARAM wParam)
{
/*
switch (LOWORD(wParam))
{
default:
break;
}
*/
}
void Apply(HWND hDlg)
{
}
};
struct TabEnhancements : public W32Util::Tab
{
void Init(HWND hDlg)
{
Button_SetCheck(GetDlgItem(hDlg,IDC_FORCEFILTERING),g_Config.bForceFiltering);
Button_SetCheck(GetDlgItem(hDlg,IDC_FORCEANISOTROPY),g_Config.bForceMaxAniso);
HWND pp = GetDlgItem(hDlg,IDC_POSTPROCESSEFFECT);
const char **names = Postprocess::GetPostprocessingNames();
int i = 0;
while (true)
{
if (!names[i])
break;
ComboBox_AddString(pp, names[i]);
i++;
}
ComboBox_SetCurSel(pp, g_Config.iPostprocessEffect);
}
void Command(HWND hDlg,WPARAM wParam)
{
/*
switch (LOWORD(wParam))
{
default:
break;
}
*/
}
void Apply(HWND hDlg)
{
g_Config.bForceMaxAniso = Button_GetCheck(GetDlgItem(hDlg, IDC_FORCEANISOTROPY)) ? true : false;
g_Config.bForceFiltering = Button_GetCheck(GetDlgItem(hDlg,IDC_FORCEFILTERING)) ? true : false;
g_Config.iPostprocessEffect = ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_POSTPROCESSEFFECT));
}
};
void DlgSettings_Show(HINSTANCE hInstance, HWND _hParent)
{
bool tfoe = g_Config.bTexFmtOverlayEnable;
bool tfoc = g_Config.bTexFmtOverlayCenter;
g_Config.Load();
W32Util::PropSheet sheet;
sheet.Add(new TabDirect3D,(LPCTSTR)IDD_SETTINGS,"Direct3D");
sheet.Add(new TabEnhancements,(LPCTSTR)IDD_ENHANCEMENTS,"Enhancements");
sheet.Add(new TabAdvanced,(LPCTSTR)IDD_ADVANCED,"Advanced");
//sheet.Add(new TabDebug,(LPCTSTR)IDD_DEBUGGER,"Debugger");
sheet.Show(hInstance,_hParent,"Graphics Plugin");
g_Config.Save();
if(( tfoe != g_Config.bTexFmtOverlayEnable) ||
((g_Config.bTexFmtOverlayEnable) && ( tfoc != g_Config.bTexFmtOverlayCenter)))
{
TextureCache::Invalidate();
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If 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 <windowsx.h>
#include "resource.h"
#include "W32Util/PropertySheet.h"
#include "W32Util/ShellUtil.h"
#include "D3DBase.h"
#include "D3DPostprocess.h"
#include "Config.h"
#include "TextureCache.h"
#define NUMWNDRES 6
int g_Res[NUMWNDRES][2] =
{
{640,480},
{800,600},
{1024,768},
{1280,960},
{1280,1024},
{1600,1200},
};
struct TabDirect3D : public W32Util::Tab
{
void Init(HWND hDlg)
{
for (int i=0; i<D3D::GetNumAdapters(); i++)
{
const D3D::Adapter &adapter = D3D::GetAdapter(i);
ComboBox_AddString(GetDlgItem(hDlg,IDC_ADAPTER),adapter.ident.Description);
}
const D3D::Adapter &adapter = D3D::GetAdapter(g_Config.iAdapter);
ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_ADAPTER),g_Config.iAdapter);
for (int i = 0; i < (int)adapter.aa_levels.size(); i++)
{
ComboBox_AddString(GetDlgItem(hDlg, IDC_ANTIALIASMODE), adapter.aa_levels[i].name);
}
ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_ANTIALIASMODE), g_Config.iMultisampleMode);
if (adapter.aa_levels.size() == 1)
{
EnableWindow(GetDlgItem(hDlg, IDC_ANTIALIASMODE), FALSE);
}
for (int i = 0; i < (int)adapter.resolutions.size(); i++)
{
const D3D::Resolution &r = adapter.resolutions[i];
ComboBox_AddString(GetDlgItem(hDlg,IDC_RESOLUTION), r.name);
}
ComboBox_SetCurSel(GetDlgItem(hDlg,IDC_RESOLUTION), g_Config.iFSResolution);
for (int i = 0; i < NUMWNDRES; i++)
{
char temp[256];
sprintf(temp,"%ix%i",g_Res[i][0],g_Res[i][1]);
ComboBox_AddString(GetDlgItem(hDlg,IDC_RESOLUTIONWINDOWED),temp);
}
ComboBox_SetCurSel(GetDlgItem(hDlg,IDC_RESOLUTIONWINDOWED),g_Config.iWindowedRes);
CheckDlgButton(hDlg, IDC_FULLSCREENENABLE, g_Config.bFullscreen ? TRUE : FALSE);
CheckDlgButton(hDlg, IDC_VSYNC, g_Config.bVsync ? TRUE : FALSE);
CheckDlgButton(hDlg, IDC_RENDER_TO_MAINWINDOW, g_Config.renderToMainframe ? TRUE : FALSE);
}
void Command(HWND hDlg,WPARAM wParam)
{
/*
switch (LOWORD(wParam))
{
default:
break;
}
*/
}
void Apply(HWND hDlg)
{
g_Config.iAdapter = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_ADAPTER));
g_Config.iWindowedRes = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_RESOLUTIONWINDOWED));
g_Config.iMultisampleMode = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_ANTIALIASMODE));
g_Config.iFSResolution = ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_RESOLUTION));
g_Config.bFullscreen = Button_GetCheck(GetDlgItem(hDlg, IDC_FULLSCREENENABLE)) ? true : false;
g_Config.bVsync = Button_GetCheck(GetDlgItem(hDlg, IDC_VSYNC)) ? true : false;
g_Config.renderToMainframe = Button_GetCheck(GetDlgItem(hDlg, IDC_RENDER_TO_MAINWINDOW)) ? true : false;
g_Config.Save();
}
};
struct TabAdvanced : public W32Util::Tab
{
void Init(HWND hDlg)
{
HWND opt = GetDlgItem(hDlg,IDC_DLOPTLEVEL);
ComboBox_AddString(opt,"0: Interpret (slowest, most compatible)");
ComboBox_AddString(opt,"1: Compile lists and decode vertex lists");
//ComboBox_AddString(opt,"2: Compile+decode to vbufs and use hw xform");
//ComboBox_AddString(opt,"Recompile to vbuffers and shaders");
ComboBox_SetCurSel(opt,g_Config.iCompileDLsLevel);
Button_SetCheck(GetDlgItem(hDlg,IDC_OVERLAYSTATS), g_Config.bOverlayStats);
Button_SetCheck(GetDlgItem(hDlg,IDC_WIREFRAME), g_Config.bWireFrame);
Button_SetCheck(GetDlgItem(hDlg,IDC_TEXDUMP), g_Config.bDumpTextures);
Button_SetCheck(GetDlgItem(hDlg,IDC_SHOWSHADERERRORS), g_Config.bShowShaderErrors);
Button_SetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY), g_Config.bTexFmtOverlayEnable);
Button_SetCheck(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), g_Config.bTexFmtOverlayCenter);
Button_GetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY)) ? Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), true) : Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), false);
SetWindowText(GetDlgItem(hDlg,IDC_TEXDUMPPATH),g_Config.texDumpPath.c_str());
Edit_LimitText(GetDlgItem(hDlg,IDC_TEXDUMPPATH),255);
}
void Command(HWND hDlg,WPARAM wParam)
{
switch (LOWORD(wParam))
{
case IDC_BROWSETEXDUMPPATH:
{
std::string path = W32Util::BrowseForFolder(hDlg,"Choose texture dump path:");
SetWindowText(GetDlgItem(hDlg,IDC_TEXDUMPPATH),path.c_str());
}
break;
case IDC_TEXFMT_OVERLAY:
{
Button_GetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY)) ? Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), true) : Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), false);
}
break;
default:
break;
}
}
void Apply(HWND hDlg)
{
g_Config.bTexFmtOverlayEnable = Button_GetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY)) ? true : false;
g_Config.bTexFmtOverlayCenter = Button_GetCheck(GetDlgItem(hDlg,IDC_TEXFMT_CENTER)) ? true : false;
g_Config.bOverlayStats = Button_GetCheck(GetDlgItem(hDlg,IDC_OVERLAYSTATS)) ? true : false;
g_Config.bWireFrame = Button_GetCheck(GetDlgItem(hDlg,IDC_WIREFRAME)) ? true : false;
g_Config.bDumpTextures = Button_GetCheck(GetDlgItem(hDlg,IDC_TEXDUMP)) ? true : false;
g_Config.iCompileDLsLevel = (int)ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_DLOPTLEVEL));
g_Config.bShowShaderErrors = Button_GetCheck(GetDlgItem(hDlg,IDC_SHOWSHADERERRORS)) ? true : false;
char temp[MAX_PATH];
GetWindowText(GetDlgItem(hDlg,IDC_TEXDUMPPATH), temp, MAX_PATH);
g_Config.texDumpPath = temp;
}
};
struct TabDebug : public W32Util::Tab
{
void Init(HWND hDlg)
{
}
void Command(HWND hDlg,WPARAM wParam)
{
/*
switch (LOWORD(wParam))
{
default:
break;
}
*/
}
void Apply(HWND hDlg)
{
}
};
struct TabEnhancements : public W32Util::Tab
{
void Init(HWND hDlg)
{
Button_SetCheck(GetDlgItem(hDlg,IDC_FORCEFILTERING),g_Config.bForceFiltering);
Button_SetCheck(GetDlgItem(hDlg,IDC_FORCEANISOTROPY),g_Config.bForceMaxAniso);
HWND pp = GetDlgItem(hDlg,IDC_POSTPROCESSEFFECT);
const char **names = Postprocess::GetPostprocessingNames();
int i = 0;
while (true)
{
if (!names[i])
break;
ComboBox_AddString(pp, names[i]);
i++;
}
ComboBox_SetCurSel(pp, g_Config.iPostprocessEffect);
}
void Command(HWND hDlg,WPARAM wParam)
{
/*
switch (LOWORD(wParam))
{
default:
break;
}
*/
}
void Apply(HWND hDlg)
{
g_Config.bForceMaxAniso = Button_GetCheck(GetDlgItem(hDlg, IDC_FORCEANISOTROPY)) ? true : false;
g_Config.bForceFiltering = Button_GetCheck(GetDlgItem(hDlg,IDC_FORCEFILTERING)) ? true : false;
g_Config.iPostprocessEffect = ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_POSTPROCESSEFFECT));
}
};
void DlgSettings_Show(HINSTANCE hInstance, HWND _hParent)
{
bool tfoe = g_Config.bTexFmtOverlayEnable;
bool tfoc = g_Config.bTexFmtOverlayCenter;
g_Config.Load();
W32Util::PropSheet sheet;
sheet.Add(new TabDirect3D,(LPCTSTR)IDD_SETTINGS,"Direct3D");
sheet.Add(new TabEnhancements,(LPCTSTR)IDD_ENHANCEMENTS,"Enhancements");
sheet.Add(new TabAdvanced,(LPCTSTR)IDD_ADVANCED,"Advanced");
//sheet.Add(new TabDebug,(LPCTSTR)IDD_DEBUGGER,"Debugger");
sheet.Show(hInstance,_hParent,"Graphics Plugin");
g_Config.Save();
if(( tfoe != g_Config.bTexFmtOverlayEnable) ||
((g_Config.bTexFmtOverlayEnable) && ( tfoc != g_Config.bTexFmtOverlayCenter)))
{
TextureCache::Invalidate();
}
}

View File

@ -1,173 +1,173 @@
#include <windows.h>
#include "../../Core/Src/Core.h"
#include "Config.h"
#include "main.h"
#include "EmuWindow.h"
namespace EmuWindow
{
HWND m_hWnd = NULL;
HWND m_hParent = NULL;
HINSTANCE m_hInstance = NULL;
WNDCLASSEX wndClass;
const TCHAR m_szClassName[] = "DolphinEmuWnd";
int g_winstyle;
HWND GetWnd()
{
return m_hWnd;
}
HWND GetParentWnd()
{
return m_hParent;
}
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
{
HDC hdc;
PAINTSTRUCT ps;
switch( iMsg )
{
case WM_PAINT:
hdc = BeginPaint( hWnd, &ps );
EndPaint( hWnd, &ps );
return 0;
case WM_KEYDOWN:
switch( LOWORD( wParam ))
{
case VK_ESCAPE: /* Pressing esc quits */
//DestroyWindow(hWnd);
//PostQuitMessage(0);
break;
/*
case MY_KEYS:
hypotheticalScene->sendMessage(KEYDOWN...);
*/
}
g_VideoInitialize.pKeyPress(LOWORD(wParam), GetAsyncKeyState(VK_SHIFT) != 0, GetAsyncKeyState(VK_CONTROL) != 0);
break;
case WM_CLOSE:
//Core::SetState(Core::CORE_UNINITIALIZED);
return 0;
case WM_DESTROY:
//Shutdown();
//PostQuitMessage( 0 );
break;
case WM_SIZE:
// Reset the D3D Device here
// Also make damn sure that this is not called from inside rendering a frame :P
break;
case WM_SYSCOMMAND:
switch (wParam)
{
case SC_SCREENSAVE:
case SC_MONITORPOWER:
return 0;
}
break;
}
return DefWindowProc(hWnd, iMsg, wParam, lParam);
}
HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title)
{
wndClass.cbSize = sizeof( wndClass );
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = m_szClassName;
wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
m_hInstance = hInstance;
RegisterClassEx( &wndClass );
if (parent)
{
m_hWnd = CreateWindow(m_szClassName, title,
WS_CHILD,
CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,
parent, NULL, hInstance, NULL );
m_hParent = parent;
ShowWindow(m_hWnd, SW_SHOWMAXIMIZED);
}
else
{
DWORD style = g_Config.bFullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW;
RECT rc = {0, 0, width, height};
AdjustWindowRect(&rc, style, false);
int w = rc.right - rc.left;
int h = rc.bottom - rc.top;
rc.left = (1280 - w)/2;
rc.right = rc.left + w;
rc.top = (1024 - h)/2;
rc.bottom = rc.top + h;
m_hWnd = CreateWindow(m_szClassName, title,
style,
rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
parent, NULL, hInstance, NULL );
g_winstyle = GetWindowLong( m_hWnd, GWL_STYLE );
g_winstyle &= ~WS_MAXIMIZE & ~WS_MINIMIZE; // remove minimize/maximize style
}
return m_hWnd;
}
void Show()
{
ShowWindow(m_hWnd, SW_SHOW);
BringWindowToTop(m_hWnd);
UpdateWindow(m_hWnd);
}
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title)
{
return OpenWindow(hParent, hInstance, 640, 480, title);
}
void Close()
{
DestroyWindow(m_hWnd);
UnregisterClass(m_szClassName, m_hInstance);
}
void SetSize(int width, int height)
{
RECT rc = {0, 0, width, height};
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false);
int w = rc.right - rc.left;
int h = rc.bottom - rc.top;
rc.left = (1280 - w)/2;
rc.right = rc.left + w;
rc.top = (1024 - h)/2;
rc.bottom = rc.top + h;
::MoveWindow(m_hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE);
}
}
#include <windows.h>
#include "../../Core/Src/Core.h"
#include "Config.h"
#include "main.h"
#include "EmuWindow.h"
namespace EmuWindow
{
HWND m_hWnd = NULL;
HWND m_hParent = NULL;
HINSTANCE m_hInstance = NULL;
WNDCLASSEX wndClass;
const TCHAR m_szClassName[] = "DolphinEmuWnd";
int g_winstyle;
HWND GetWnd()
{
return m_hWnd;
}
HWND GetParentWnd()
{
return m_hParent;
}
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
{
HDC hdc;
PAINTSTRUCT ps;
switch( iMsg )
{
case WM_PAINT:
hdc = BeginPaint( hWnd, &ps );
EndPaint( hWnd, &ps );
return 0;
case WM_KEYDOWN:
switch( LOWORD( wParam ))
{
case VK_ESCAPE: /* Pressing esc quits */
//DestroyWindow(hWnd);
//PostQuitMessage(0);
break;
/*
case MY_KEYS:
hypotheticalScene->sendMessage(KEYDOWN...);
*/
}
g_VideoInitialize.pKeyPress(LOWORD(wParam), GetAsyncKeyState(VK_SHIFT) != 0, GetAsyncKeyState(VK_CONTROL) != 0);
break;
case WM_CLOSE:
//Core::SetState(Core::CORE_UNINITIALIZED);
return 0;
case WM_DESTROY:
//Shutdown();
//PostQuitMessage( 0 );
break;
case WM_SIZE:
// Reset the D3D Device here
// Also make damn sure that this is not called from inside rendering a frame :P
break;
case WM_SYSCOMMAND:
switch (wParam)
{
case SC_SCREENSAVE:
case SC_MONITORPOWER:
return 0;
}
break;
}
return DefWindowProc(hWnd, iMsg, wParam, lParam);
}
HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title)
{
wndClass.cbSize = sizeof( wndClass );
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = m_szClassName;
wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
m_hInstance = hInstance;
RegisterClassEx( &wndClass );
if (parent)
{
m_hWnd = CreateWindow(m_szClassName, title,
WS_CHILD,
CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,
parent, NULL, hInstance, NULL );
m_hParent = parent;
ShowWindow(m_hWnd, SW_SHOWMAXIMIZED);
}
else
{
DWORD style = g_Config.bFullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW;
RECT rc = {0, 0, width, height};
AdjustWindowRect(&rc, style, false);
int w = rc.right - rc.left;
int h = rc.bottom - rc.top;
rc.left = (1280 - w)/2;
rc.right = rc.left + w;
rc.top = (1024 - h)/2;
rc.bottom = rc.top + h;
m_hWnd = CreateWindow(m_szClassName, title,
style,
rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
parent, NULL, hInstance, NULL );
g_winstyle = GetWindowLong( m_hWnd, GWL_STYLE );
g_winstyle &= ~WS_MAXIMIZE & ~WS_MINIMIZE; // remove minimize/maximize style
}
return m_hWnd;
}
void Show()
{
ShowWindow(m_hWnd, SW_SHOW);
BringWindowToTop(m_hWnd);
UpdateWindow(m_hWnd);
}
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title)
{
return OpenWindow(hParent, hInstance, 640, 480, title);
}
void Close()
{
DestroyWindow(m_hWnd);
UnregisterClass(m_szClassName, m_hInstance);
}
void SetSize(int width, int height)
{
RECT rc = {0, 0, width, height};
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false);
int w = rc.right - rc.left;
int h = rc.bottom - rc.top;
rc.left = (1280 - w)/2;
rc.right = rc.left + w;
rc.top = (1024 - h)/2;
rc.bottom = rc.top + h;
::MoveWindow(m_hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE);
}
}

View File

@ -1,130 +1,130 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
#include "IndexGenerator.h"
/*
*
QUAD simulator
0 2 4 6
1 3 5 7
021231 243453
*/
void IndexGenerator::Start(unsigned short *startptr)
{
ptr=startptr;
index=0;
numPrims=0;
}
void IndexGenerator::AddList(int numVerts)
{
int numTris = numVerts/3;
if (numTris<=0) return;
for (int i=0; i<numTris; i++)
{
*ptr++ = index+i*3;
*ptr++ = index+i*3+1;
*ptr++ = index+i*3+2;
}
index += numVerts;
numPrims += numTris;
}
void IndexGenerator::AddStrip(int numVerts)
{
int numTris = numVerts-2;
if (numTris<=0) return;
bool wind = false;
for (int i=0; i<numTris; i++)
{
*ptr++ = index+i;
*ptr++ = index+i+(wind?2:1);
*ptr++ = index+i+(wind?1:2);
wind = !wind;
}
index += numVerts;
numPrims += numTris;
}
void IndexGenerator::AddLineList(int numVerts)
{
int numLines= numVerts/2;
if (numLines<=0) return;
for (int i=0; i<numLines; i++)
{
*ptr++ = index+i*2;
*ptr++ = index+i*2+1;
}
index += numVerts;
numPrims += numLines;
}
void IndexGenerator::AddLineStrip(int numVerts)
{
int numLines = numVerts-1;
if (numLines<=0) return;
for (int i=0; i<numLines; i++)
{
*ptr++ = index+i;
*ptr++ = index+i+1;
}
index += numVerts;
numPrims += numLines;
}
void IndexGenerator::AddFan(int numVerts)
{
int numTris = numVerts-2;
if (numTris<=0) return;
for (int i=0; i<numTris; i++)
{
*ptr++ = index;
*ptr++ = index+i+1;
*ptr++ = index+i+2;
}
index += numVerts;
numPrims += numTris;
}
void IndexGenerator::AddQuads(int numVerts)
{
int numTris = (numVerts/4)*2;
if (numTris<=0) return;
for (int i=0; i<numTris/2; i++)
{
*ptr++=index+i*4;
*ptr++=index+i*4+1;
*ptr++=index+i*4+3;
*ptr++=index+i*4+1;
*ptr++=index+i*4+2;
*ptr++=index+i*4+3;
}
index += numVerts;
numPrims += numTris;
}
void IndexGenerator::AddPointList(int numVerts)
{
index += numVerts;
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
#include "IndexGenerator.h"
/*
*
QUAD simulator
0 2 4 6
1 3 5 7
021231 243453
*/
void IndexGenerator::Start(unsigned short *startptr)
{
ptr=startptr;
index=0;
numPrims=0;
}
void IndexGenerator::AddList(int numVerts)
{
int numTris = numVerts/3;
if (numTris<=0) return;
for (int i=0; i<numTris; i++)
{
*ptr++ = index+i*3;
*ptr++ = index+i*3+1;
*ptr++ = index+i*3+2;
}
index += numVerts;
numPrims += numTris;
}
void IndexGenerator::AddStrip(int numVerts)
{
int numTris = numVerts-2;
if (numTris<=0) return;
bool wind = false;
for (int i=0; i<numTris; i++)
{
*ptr++ = index+i;
*ptr++ = index+i+(wind?2:1);
*ptr++ = index+i+(wind?1:2);
wind = !wind;
}
index += numVerts;
numPrims += numTris;
}
void IndexGenerator::AddLineList(int numVerts)
{
int numLines= numVerts/2;
if (numLines<=0) return;
for (int i=0; i<numLines; i++)
{
*ptr++ = index+i*2;
*ptr++ = index+i*2+1;
}
index += numVerts;
numPrims += numLines;
}
void IndexGenerator::AddLineStrip(int numVerts)
{
int numLines = numVerts-1;
if (numLines<=0) return;
for (int i=0; i<numLines; i++)
{
*ptr++ = index+i;
*ptr++ = index+i+1;
}
index += numVerts;
numPrims += numLines;
}
void IndexGenerator::AddFan(int numVerts)
{
int numTris = numVerts-2;
if (numTris<=0) return;
for (int i=0; i<numTris; i++)
{
*ptr++ = index;
*ptr++ = index+i+1;
*ptr++ = index+i+2;
}
index += numVerts;
numPrims += numTris;
}
void IndexGenerator::AddQuads(int numVerts)
{
int numTris = (numVerts/4)*2;
if (numTris<=0) return;
for (int i=0; i<numTris/2; i++)
{
*ptr++=index+i*4;
*ptr++=index+i*4+1;
*ptr++=index+i*4+3;
*ptr++=index+i*4+1;
*ptr++=index+i*4+2;
*ptr++=index+i*4+3;
}
index += numVerts;
numPrims += numTris;
}
void IndexGenerator::AddPointList(int numVerts)
{
index += numVerts;
}

View File

@ -1,354 +1,354 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//DL facts:
// Ikaruga uses (nearly) NO display lists!
// Zelda WW uses TONS of display lists
// Zelda TP uses almost 100% display lists except menus (we like this!)
// Note that it IS NOT GENERALLY POSSIBLE to precompile display lists! You can compile them as they are
// and hope that the vertex format doesn't change, though, if you do it just when they are
// called. The reason is that the vertex format affects the sizes of the vertices.
#include "D3DBase.h"
#include "Common.h"
#include "Statistics.h"
#include "Profiler.h"
#include "VertexManager.h"
#include "TransformEngine.h"
#include "OpcodeDecoding.h"
#include "TextureCache.h"
#include "ShaderManager.h"
#include "BPStructs.h"
#include "XFStructs.h"
#include "Utils.h"
#include "Fifo.h"
#include "DataReader.h"
DecodedVArray tempvarray;
u8 *g_pVideoData = 0;
extern u8* FAKE_GetFifoStartPtr();
extern u8* FAKE_GetFifoEndPtr();
static void Decode();
static void ExecuteDisplayList(u32 address, u32 size)
{
u8* old_pVideoData = g_pVideoData;
u8* startAddress = Memory_GetPtr(address);
//Avoid the crash if Memory_GetPtr failed ..
if (startAddress!=0)
{
g_pVideoData = startAddress;
// temporarily swap dl and non-dl(small "hack" for the stats)
Statistics::SwapDL();
while((u32)(g_pVideoData - startAddress) < size)
{
Decode();
}
INCSTAT(stats.numDListsCalled);
INCSTAT(stats.thisFrame.numDListsCalled);
// un-swap
Statistics::SwapDL();
// reset to the old pointer
g_pVideoData = old_pVideoData;
}
}
bool FifoCommandRunnable()
{
u32 iBufferSize = (u32)(FAKE_GetFifoEndPtr()-g_pVideoData);
if (iBufferSize == 0)
return false; // can't peek
u8 Cmd = DataPeek8(0);
u32 iCommandSize = 0;
switch(Cmd)
{
case GX_NOP:
// Hm, this means that we scan over nop streams pretty slowly...
iCommandSize = 1;
break;
case GX_LOAD_CP_REG:
iCommandSize = 6;
break;
case GX_LOAD_INDX_A:
case GX_LOAD_INDX_B:
case GX_LOAD_INDX_C:
case GX_LOAD_INDX_D:
iCommandSize = 5;
break;
case GX_CMD_CALL_DL:
iCommandSize = 9;
break;
case 0x44:
iCommandSize = 1;
// zelda 4 swords calls it and checks the metrics registers after that
break;
case GX_CMD_INVL_VC: // invalid vertex cache - no parameter?
iCommandSize = 1;
break;
case GX_LOAD_BP_REG:
iCommandSize = 5;
break;
case GX_LOAD_XF_REG:
{
// check if we can read the header
if (iBufferSize >= 5)
{
iCommandSize = 1 + 4;
u32 Cmd2 = DataPeek32(1);
int dwTransferSize = ((Cmd2 >> 16) & 15) + 1;
iCommandSize += dwTransferSize * 4;
}
else
{
return false;
}
}
break;
default:
if (Cmd&0x80)
{
// check if we can read the header
if (iBufferSize >= 3)
{
iCommandSize = 1 + 2;
u16 numVertices = DataPeek16(1);
VertexLoader& vtxLoader = g_VertexLoaders[Cmd & GX_VAT_MASK];
vtxLoader.Setup();
int vsize = vtxLoader.GetVertexSize();
iCommandSize += numVertices * vsize;
}
else
{
return false;
}
}
else
{
char szTemp[1024];
sprintf(szTemp, "GFX: Unknown Opcode (0x%x).\n"
"This means one of the following:\n"
"* The emulated GPU got desynced, disabling dual core can help\n"
"* Command stream corrupted by some spurious memory bug\n"
"* This really is an unknown opcode (unlikely)\n\n"
"* Some other sort of bug\n\n"
"Dolphin will now likely crash or hang. Enjoy.", Cmd);
MessageBox(NULL, szTemp, "Video-Plugin", MB_OK);
g_VideoInitialize.pLog(szTemp, TRUE);
{
SCPFifoStruct &fifo = *g_VideoInitialize.pCPFifo;
char szTmp[256];
// sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr());
sprintf(szTmp, "Illegal command %02x\n"
"CPBase: 0x%08x\n"
"CPEnd: 0x%08x\n"
"CPHiWatermark: 0x%08x\n"
"CPLoWatermark: 0x%08x\n"
"CPReadWriteDistance: 0x%08x\n"
"CPWritePointer: 0x%08x\n"
"CPReadPointer: 0x%08x\n"
"CPBreakpoint: 0x%08x\n"
"bFF_GPReadEnable: %s\n"
"bFF_BPEnable: %s\n"
"bFF_GPLinkEnable: %s\n"
"bFF_Breakpoint: %s\n"
,Cmd, fifo.CPBase, fifo.CPEnd, fifo.CPHiWatermark, fifo.CPLoWatermark, fifo.CPReadWriteDistance
,fifo.CPWritePointer, fifo.CPReadPointer, fifo.CPBreakpoint, fifo.bFF_GPReadEnable ? "true" : "false"
,fifo.bFF_BPEnable ? "true" : "false" ,fifo.bFF_GPLinkEnable ? "true" : "false"
,fifo.bFF_Breakpoint ? "true" : "false");
g_VideoInitialize.pLog(szTmp, TRUE);
MessageBox(0,szTmp,"GFX ERROR",0);
// _assert_msg_(0,szTmp,"");
}
}
break;
}
if (iCommandSize > iBufferSize)
return false;
#ifdef _DEBUG
char temp[256];
sprintf(temp, "OP detected: Cmd 0x%x size %i buffer %i",Cmd, iCommandSize, iBufferSize);
g_VideoInitialize.pLog(temp, FALSE);
#endif
return true;
}
static void Decode(void)
{
int Cmd = DataReadU8();
switch (Cmd)
{
case GX_NOP:
break;
case GX_LOAD_CP_REG:
{
u32 SubCmd = DataReadU8();
u32 Value = DataReadU32();
LoadCPReg(SubCmd,Value);
}
break;
case GX_LOAD_XF_REG:
{
u32 Cmd2 = DataReadU32();
int dwTransferSize = ((Cmd2>>16)&15) + 1;
u32 dwAddress = Cmd2 & 0xFFFF;
static u32 pData[16];
for (int i=0; i<dwTransferSize; i++)
pData[i] = DataReadU32();
LoadXFReg(dwTransferSize,dwAddress,pData);
}
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);
}
break;
// draw primitives
default:
if (Cmd&0x80)
{
// load vertices
u16 numVertices = DataReadU16();
tempvarray.Reset();
VertexLoader::SetVArray(&tempvarray);
VertexLoader& vtxLoader = g_VertexLoaders[Cmd & GX_VAT_MASK];
vtxLoader.Setup();
vtxLoader.PrepareRun();
int vsize = vtxLoader.GetVertexSize();
vtxLoader.RunVertices(numVertices);
// add vertices
int primitive = (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
VertexManager::AddVertices(primitive, numVertices, &tempvarray);
}
else
{
SCPFifoStruct &fifo = *g_VideoInitialize.pCPFifo;
char szTmp[256];
// sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr());
sprintf(szTmp, "Illegal command %02x\n"
"CPBase: 0x%08x\n"
"CPEnd: 0x%08x\n"
"CPHiWatermark: 0x%08x\n"
"CPLoWatermark: 0x%08x\n"
"CPReadWriteDistance: 0x%08x\n"
"CPWritePointer: 0x%08x\n"
"CPReadPointer: 0x%08x\n"
"CPBreakpoint: 0x%08x\n"
"bFF_GPReadEnable: %s\n"
"bFF_BPEnable: %s\n"
"bFF_GPLinkEnable: %s\n"
"bFF_Breakpoint: %s\n"
,Cmd, fifo.CPBase, fifo.CPEnd, fifo.CPHiWatermark, fifo.CPLoWatermark, fifo.CPReadWriteDistance
,fifo.CPWritePointer, fifo.CPReadPointer, fifo.CPBreakpoint, fifo.bFF_GPReadEnable ? "true" : "false"
,fifo.bFF_BPEnable ? "true" : "false" ,fifo.bFF_GPLinkEnable ? "true" : "false"
,fifo.bFF_Breakpoint ? "true" : "false");
g_VideoInitialize.pLog(szTmp, TRUE);
MessageBox(0,szTmp,"GFX ERROR",0);
// _assert_msg_(0,szTmp,"");
break;
}
break;
}
}
void OpcodeDecoder_Init()
{
g_pVideoData = FAKE_GetFifoStartPtr();
tempvarray.Create(65536*3, 1, 8, 3, 2, 8);
}
void OpcodeDecoder_Shutdown()
{
//VirtualFree((LPVOID)buffer,0,MEM_RELEASE);
tempvarray.Destroy();
}
void OpcodeDecoder_Run()
{
DVSTARTPROFILE();
while (FifoCommandRunnable())
{
Decode();
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//DL facts:
// Ikaruga uses (nearly) NO display lists!
// Zelda WW uses TONS of display lists
// Zelda TP uses almost 100% display lists except menus (we like this!)
// Note that it IS NOT GENERALLY POSSIBLE to precompile display lists! You can compile them as they are
// and hope that the vertex format doesn't change, though, if you do it just when they are
// called. The reason is that the vertex format affects the sizes of the vertices.
#include "D3DBase.h"
#include "Common.h"
#include "Statistics.h"
#include "Profiler.h"
#include "VertexManager.h"
#include "TransformEngine.h"
#include "OpcodeDecoding.h"
#include "TextureCache.h"
#include "ShaderManager.h"
#include "BPStructs.h"
#include "XFStructs.h"
#include "Utils.h"
#include "Fifo.h"
#include "DataReader.h"
DecodedVArray tempvarray;
u8 *g_pVideoData = 0;
extern u8* FAKE_GetFifoStartPtr();
extern u8* FAKE_GetFifoEndPtr();
static void Decode();
static void ExecuteDisplayList(u32 address, u32 size)
{
u8* old_pVideoData = g_pVideoData;
u8* startAddress = Memory_GetPtr(address);
//Avoid the crash if Memory_GetPtr failed ..
if (startAddress!=0)
{
g_pVideoData = startAddress;
// temporarily swap dl and non-dl(small "hack" for the stats)
Statistics::SwapDL();
while((u32)(g_pVideoData - startAddress) < size)
{
Decode();
}
INCSTAT(stats.numDListsCalled);
INCSTAT(stats.thisFrame.numDListsCalled);
// un-swap
Statistics::SwapDL();
// reset to the old pointer
g_pVideoData = old_pVideoData;
}
}
bool FifoCommandRunnable()
{
u32 iBufferSize = (u32)(FAKE_GetFifoEndPtr()-g_pVideoData);
if (iBufferSize == 0)
return false; // can't peek
u8 Cmd = DataPeek8(0);
u32 iCommandSize = 0;
switch(Cmd)
{
case GX_NOP:
// Hm, this means that we scan over nop streams pretty slowly...
iCommandSize = 1;
break;
case GX_LOAD_CP_REG:
iCommandSize = 6;
break;
case GX_LOAD_INDX_A:
case GX_LOAD_INDX_B:
case GX_LOAD_INDX_C:
case GX_LOAD_INDX_D:
iCommandSize = 5;
break;
case GX_CMD_CALL_DL:
iCommandSize = 9;
break;
case 0x44:
iCommandSize = 1;
// zelda 4 swords calls it and checks the metrics registers after that
break;
case GX_CMD_INVL_VC: // invalid vertex cache - no parameter?
iCommandSize = 1;
break;
case GX_LOAD_BP_REG:
iCommandSize = 5;
break;
case GX_LOAD_XF_REG:
{
// check if we can read the header
if (iBufferSize >= 5)
{
iCommandSize = 1 + 4;
u32 Cmd2 = DataPeek32(1);
int dwTransferSize = ((Cmd2 >> 16) & 15) + 1;
iCommandSize += dwTransferSize * 4;
}
else
{
return false;
}
}
break;
default:
if (Cmd&0x80)
{
// check if we can read the header
if (iBufferSize >= 3)
{
iCommandSize = 1 + 2;
u16 numVertices = DataPeek16(1);
VertexLoader& vtxLoader = g_VertexLoaders[Cmd & GX_VAT_MASK];
vtxLoader.Setup();
int vsize = vtxLoader.GetVertexSize();
iCommandSize += numVertices * vsize;
}
else
{
return false;
}
}
else
{
char szTemp[1024];
sprintf(szTemp, "GFX: Unknown Opcode (0x%x).\n"
"This means one of the following:\n"
"* The emulated GPU got desynced, disabling dual core can help\n"
"* Command stream corrupted by some spurious memory bug\n"
"* This really is an unknown opcode (unlikely)\n\n"
"* Some other sort of bug\n\n"
"Dolphin will now likely crash or hang. Enjoy.", Cmd);
MessageBox(NULL, szTemp, "Video-Plugin", MB_OK);
g_VideoInitialize.pLog(szTemp, TRUE);
{
SCPFifoStruct &fifo = *g_VideoInitialize.pCPFifo;
char szTmp[256];
// sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr());
sprintf(szTmp, "Illegal command %02x\n"
"CPBase: 0x%08x\n"
"CPEnd: 0x%08x\n"
"CPHiWatermark: 0x%08x\n"
"CPLoWatermark: 0x%08x\n"
"CPReadWriteDistance: 0x%08x\n"
"CPWritePointer: 0x%08x\n"
"CPReadPointer: 0x%08x\n"
"CPBreakpoint: 0x%08x\n"
"bFF_GPReadEnable: %s\n"
"bFF_BPEnable: %s\n"
"bFF_GPLinkEnable: %s\n"
"bFF_Breakpoint: %s\n"
,Cmd, fifo.CPBase, fifo.CPEnd, fifo.CPHiWatermark, fifo.CPLoWatermark, fifo.CPReadWriteDistance
,fifo.CPWritePointer, fifo.CPReadPointer, fifo.CPBreakpoint, fifo.bFF_GPReadEnable ? "true" : "false"
,fifo.bFF_BPEnable ? "true" : "false" ,fifo.bFF_GPLinkEnable ? "true" : "false"
,fifo.bFF_Breakpoint ? "true" : "false");
g_VideoInitialize.pLog(szTmp, TRUE);
MessageBox(0,szTmp,"GFX ERROR",0);
// _assert_msg_(0,szTmp,"");
}
}
break;
}
if (iCommandSize > iBufferSize)
return false;
#ifdef _DEBUG
char temp[256];
sprintf(temp, "OP detected: Cmd 0x%x size %i buffer %i",Cmd, iCommandSize, iBufferSize);
g_VideoInitialize.pLog(temp, FALSE);
#endif
return true;
}
static void Decode(void)
{
int Cmd = DataReadU8();
switch (Cmd)
{
case GX_NOP:
break;
case GX_LOAD_CP_REG:
{
u32 SubCmd = DataReadU8();
u32 Value = DataReadU32();
LoadCPReg(SubCmd,Value);
}
break;
case GX_LOAD_XF_REG:
{
u32 Cmd2 = DataReadU32();
int dwTransferSize = ((Cmd2>>16)&15) + 1;
u32 dwAddress = Cmd2 & 0xFFFF;
static u32 pData[16];
for (int i=0; i<dwTransferSize; i++)
pData[i] = DataReadU32();
LoadXFReg(dwTransferSize,dwAddress,pData);
}
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);
}
break;
// draw primitives
default:
if (Cmd&0x80)
{
// load vertices
u16 numVertices = DataReadU16();
tempvarray.Reset();
VertexLoader::SetVArray(&tempvarray);
VertexLoader& vtxLoader = g_VertexLoaders[Cmd & GX_VAT_MASK];
vtxLoader.Setup();
vtxLoader.PrepareRun();
int vsize = vtxLoader.GetVertexSize();
vtxLoader.RunVertices(numVertices);
// add vertices
int primitive = (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
VertexManager::AddVertices(primitive, numVertices, &tempvarray);
}
else
{
SCPFifoStruct &fifo = *g_VideoInitialize.pCPFifo;
char szTmp[256];
// sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr());
sprintf(szTmp, "Illegal command %02x\n"
"CPBase: 0x%08x\n"
"CPEnd: 0x%08x\n"
"CPHiWatermark: 0x%08x\n"
"CPLoWatermark: 0x%08x\n"
"CPReadWriteDistance: 0x%08x\n"
"CPWritePointer: 0x%08x\n"
"CPReadPointer: 0x%08x\n"
"CPBreakpoint: 0x%08x\n"
"bFF_GPReadEnable: %s\n"
"bFF_BPEnable: %s\n"
"bFF_GPLinkEnable: %s\n"
"bFF_Breakpoint: %s\n"
,Cmd, fifo.CPBase, fifo.CPEnd, fifo.CPHiWatermark, fifo.CPLoWatermark, fifo.CPReadWriteDistance
,fifo.CPWritePointer, fifo.CPReadPointer, fifo.CPBreakpoint, fifo.bFF_GPReadEnable ? "true" : "false"
,fifo.bFF_BPEnable ? "true" : "false" ,fifo.bFF_GPLinkEnable ? "true" : "false"
,fifo.bFF_Breakpoint ? "true" : "false");
g_VideoInitialize.pLog(szTmp, TRUE);
MessageBox(0,szTmp,"GFX ERROR",0);
// _assert_msg_(0,szTmp,"");
break;
}
break;
}
}
void OpcodeDecoder_Init()
{
g_pVideoData = FAKE_GetFifoStartPtr();
tempvarray.Create(65536*3, 1, 8, 3, 2, 8);
}
void OpcodeDecoder_Shutdown()
{
//VirtualFree((LPVOID)buffer,0,MEM_RELEASE);
tempvarray.Destroy();
}
void OpcodeDecoder_Run()
{
DVSTARTPROFILE();
while (FifoCommandRunnable())
{
Decode();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,451 +1,451 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <d3dx9.h>
#include "Common.h"
#include "Statistics.h"
#include "Config.h"
#include "main.h"
#include "VertexManager.h"
#include "Render.h"
#include "OpcodeDecoding.h"
#include "BPStructs.h"
#include "XFStructs.h"
#include "D3DPostprocess.h"
#include "D3DUtil.h"
#include "ShaderManager.h"
#include "TextureCache.h"
#include "Utils.h"
#include "EmuWindow.h"
#include <list>
float Renderer::m_x,Renderer::m_y,Renderer::m_width, Renderer::m_height, Renderer::xScale,Renderer::yScale;
std::vector<LPDIRECT3DBASETEXTURE9> Renderer::m_Textures;
DWORD Renderer::m_RenderStates[MaxRenderStates];
DWORD Renderer::m_TextureStageStates[MaxTextureStages][MaxTextureTypes];
DWORD Renderer::m_SamplerStates[MaxSamplerSize][MaxSamplerTypes];
DWORD Renderer::m_FVF;
#define NUMWNDRES 6
extern int g_Res[NUMWNDRES][2];
struct Message
{
Message(const std::string &msg, u32 dw) : message( msg ), dwTimeStamp( dw )
{
}
std::string message;
u32 dwTimeStamp;
};
static std::list<Message> s_listMsgs;
void Renderer::Init(SVideoInitialize &_VideoInitialize)
{
EmuWindow::SetSize(g_Res[g_Config.iWindowedRes][0], g_Res[g_Config.iWindowedRes][1]);
D3D::Create(g_Config.iAdapter, EmuWindow::GetWnd(), g_Config.bFullscreen, g_Config.iFSResolution, g_Config.iMultisampleMode);
D3DVIEWPORT9 vp;
D3D::dev->GetViewport(&vp);
m_x = 0;
m_y = 0;
m_width = (float)vp.Width;
m_height = (float)vp.Height;
xScale = 640.0f / (float)vp.Width;
yScale = 480.0f / (float)vp.Height;
D3D::font.Init();
Initialize();
}
void Renderer::Shutdown(void)
{
D3D::font.Shutdown();
D3D::EndFrame();
D3D::Close();
}
void Renderer::Initialize(void)
{
m_FVF = 0;
m_Textures.reserve( MaxTextureStages );
for ( int i = 0; i < MaxTextureStages; i++ )
{
m_Textures.push_back( NULL );
}
for (int i=0; i<8; i++)
{
D3D::dev->SetSamplerState(i, D3DSAMP_MAXANISOTROPY, 16);
}
ReinitView();
Postprocess::Initialize();
Postprocess::BeginFrame();
D3D::BeginFrame(true, 0);
VertexManager::BeginFrame();
}
void Renderer::AddMessage(const std::string &message, u32 ms)
{
s_listMsgs.push_back(Message(message, timeGetTime()+ms));
}
void Renderer::ProcessMessages()
{
if (s_listMsgs.size() > 0) {
int left = 25, top = 15;
std::list<Message>::iterator it = s_listMsgs.begin();
while( it != s_listMsgs.end() )
{
int time_left = (int)(it->dwTimeStamp - timeGetTime());
int alpha = 255;
if(time_left<1024)
{
alpha=time_left>>2;
if(time_left<0) alpha=0;
}
alpha <<= 24;
RenderText(it->message, left+1, top+1, 0x000000|alpha);
RenderText(it->message, left, top, 0xffff30|alpha);
top += 15;
if (time_left <= 0)
it = s_listMsgs.erase(it);
else ++it;
}
}
}
void Renderer::RenderText(const std::string &text, int left, int top, u32 color)
{
D3D::font.DrawTextScaled((float)left, (float)top, 20, 20, 0.0f, color, text.c_str(), false);
}
void dumpMatrix(D3DXMATRIX &mtx)
{
for (int y=0; y<4; y++)
{
char temp[256];
sprintf(temp,"%4.4f %4.4f %4.4f %4.4f",mtx.m[y][0],mtx.m[y][1],mtx.m[y][2],mtx.m[y][3]);
g_VideoInitialize.pLog(temp, FALSE);
}
}
void Renderer::ReinitView()
{
D3DXMATRIX mtx;
D3DXMatrixIdentity(&mtx);
D3D::dev->SetTransform(D3DTS_VIEW,&mtx);
D3D::dev->SetTransform(D3DTS_WORLD,&mtx);
float width = (float)D3D::GetDisplayWidth();
float height = (float)D3D::GetDisplayHeight();
xScale = width/640.0f;
yScale = height/480.0f;
RECT rc = {
(LONG)(m_x*xScale), (LONG)(m_y*yScale), (LONG)(m_width*xScale), (LONG)(m_height*yScale)
};
}
void Renderer::SwapBuffers(void)
{
// center window again
if (EmuWindow::GetParentWnd())
{
RECT rcWindow;
GetWindowRect(EmuWindow::GetParentWnd(), &rcWindow);
int width = rcWindow.right - rcWindow.left;
int height = rcWindow.bottom - rcWindow.top;
::MoveWindow(EmuWindow::GetWnd(), 0,0,width,height, FALSE);
// nBackbufferWidth = width;
// nBackbufferHeight = height;
}
//Finish up the current frame, print some stats
Postprocess::FinalizeFrame();
if (g_Config.bOverlayStats)
{
char st[2048];
char *p = st;
p+=sprintf(p,"Num textures created: %i\n",stats.numTexturesCreated);
p+=sprintf(p,"Num textures alive: %i\n",stats.numTexturesAlive);
p+=sprintf(p,"Num pshaders created: %i\n",stats.numPixelShadersCreated);
p+=sprintf(p,"Num pshaders alive: %i\n",stats.numPixelShadersAlive);
p+=sprintf(p,"Num vshaders created: %i\n",stats.numVertexShadersCreated);
p+=sprintf(p,"Num vshaders alive: %i\n",stats.numVertexShadersAlive);
p+=sprintf(p,"Num dlists called: %i\n",stats.numDListsCalled);
p+=sprintf(p,"Num dlists created: %i\n",stats.numDListsCreated);
p+=sprintf(p,"Num dlists alive: %i\n",stats.numDListsAlive);
p+=sprintf(p,"Num primitives: %i\n",stats.thisFrame.numPrims);
p+=sprintf(p,"Num primitive joins: %i\n",stats.thisFrame.numPrimitiveJoins);
p+=sprintf(p,"Num primitives (DL): %i\n",stats.thisFrame.numDLPrims);
p+=sprintf(p,"Num XF loads: %i\n",stats.thisFrame.numXFLoads);
p+=sprintf(p,"Num XF loads (DL): %i\n",stats.thisFrame.numXFLoadsInDL);
p+=sprintf(p,"Num CP loads: %i\n",stats.thisFrame.numCPLoads);
p+=sprintf(p,"Num CP loads (DL): %i\n",stats.thisFrame.numCPLoadsInDL);
p+=sprintf(p,"Num BP loads: %i\n",stats.thisFrame.numBPLoads);
p+=sprintf(p,"Num BP loads (DL): %i\n",stats.thisFrame.numBPLoadsInDL);
D3D::font.DrawTextScaled(0,30,20,20,0.0f,0xFF00FFFF,st,false);
//end frame
}
ProcessMessages();
#if defined(DVPROFILE)
if( g_bWriteProfile ) {
//g_bWriteProfile = 0;
static int framenum = 0;
const int UPDATE_FRAMES = 8;
if( ++framenum >= UPDATE_FRAMES ) {
DVProfWrite("prof.txt", UPDATE_FRAMES);
DVProfClear();
framenum = 0;
}
}
#endif
D3D::EndFrame();
//D3D frame is now over
//////////////////////////////////////////////////////////////////////////
//clean out old stuff from caches
frameCount++;
PShaderCache::Cleanup();
VShaderCache::Cleanup();
TextureCache::Cleanup();
//DListCache::Cleanup();
//////////////////////////////////////////////////////////////////////////
//Begin new frame
//Set default viewport and scissor, for the clear to work correctly
stats.ResetFrame();
D3DVIEWPORT9 vp;
vp.X = 0;
vp.Y = 0;
vp.Width = (DWORD)m_width;
vp.Height = (DWORD)m_height;
vp.MinZ = 0;
vp.MaxZ = 0;
D3D::dev->SetViewport(&vp);
RECT rc;
rc.left = 0;
rc.top = 0;
rc.right = (LONG)m_width;
rc.bottom = (LONG)m_height;
D3D::dev->SetScissorRect(&rc);
u32 clearColor = (bpmem.clearcolorAR<<16)|bpmem.clearcolorGB;
// clearColor |= 0x003F003F;
// D3D::BeginFrame(true,clearColor,1.0f);
D3D::BeginFrame(false,clearColor,1.0f);
// D3D::EnableAlphaToCoverage();
Postprocess::BeginFrame();
VertexManager::BeginFrame();
if (g_Config.bOldCard)
D3D::font.SetRenderStates(); //compatibility with low end cards
}
void Renderer::Flush(void)
{
// render the rest of the vertex buffer
//only to be used for debugging purposes
//D3D::EndFrame();
//D3D::BeginFrame(false,0);
}
void Renderer::SetViewport(float* _Viewport)
{
Viewport* pViewport = (Viewport*)_Viewport;
D3DVIEWPORT9 vp;
float x=(pViewport->xOrig-662)*2;
float y=(pViewport->yOrig-582)*2; //something is wrong, but what??
y-=16;
float w=pViewport->wd*2; //multiply up to real size
float h=pViewport->ht*-2; //why is this negative? oh well..
if (x < 0.0f) x = 0.0f;
if (y < 0.0f) y = 0.0f;
if (x > 640.0f) x = 639.0f;
if (y > 480.0f) y = 479.0f;
if (w < 0) w=1;
if (h < 0) h=1;
if (x+w > 640.0f) w=640-x;
if (y+h > 480.0f) h=480-y;
//x=y=0;
//if(w>0.0f) w=0.0f;
//if(h<0.0f) h=0.0f;
vp.X = (DWORD)(x*xScale);
vp.Y = (DWORD)(y*yScale);
vp.Width = (DWORD)(w*xScale);
vp.Height = (DWORD)(h*yScale);
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
// char temp[256];
// sprintf(temp,"Viewport: %i %i %i %i %f %f",vp.X,vp.Y,vp.Width,vp.Height,vp.MinZ,vp.MaxZ);
// g_VideoInitialize.pLog(temp, FALSE);
D3D::dev->SetViewport(&vp);
}
void Renderer::SetScissorBox(RECT &rc)
{
rc.left = (int)(rc.left * xScale);
rc.top = (int)(rc.top * yScale);
rc.right = (int)(rc.right * xScale);
rc.bottom = (int)(rc.bottom * yScale);
if (rc.right >= rc.left && rc.bottom >= rc.top)
D3D::dev->SetScissorRect(&rc);
else
g_VideoInitialize.pLog("SCISSOR ERROR", FALSE);
}
void Renderer::SetProjection(float* pMatrix, int constantIndex)
{
D3DXMATRIX mtx;
if (pMatrix[6] == 0)
{
mtx.m[0][0] = pMatrix[0];
mtx.m[1][0] = 0.0f;
mtx.m[2][0] = pMatrix[1];
mtx.m[3][0] = -0.5f/m_width;
mtx.m[0][1] = 0.0f;
mtx.m[1][1] = pMatrix[2];
mtx.m[2][1] = pMatrix[3];
mtx.m[3][1] = +0.5f/m_height;
mtx.m[0][2] = 0.0f;
mtx.m[1][2] = 0.0f;
mtx.m[2][2] = -(1-pMatrix[4]);
mtx.m[3][2] = pMatrix[5];
mtx.m[0][3] = 0.0f;
mtx.m[1][3] = 0.0f;
mtx.m[2][3] = -1.0f;
mtx.m[3][3] = 0.0f;
}
else
{
mtx.m[0][0] = pMatrix[0];
mtx.m[1][0] = 0.0f;
mtx.m[2][0] = 0.0f;
mtx.m[3][0] = pMatrix[1]-0.5f/m_width; // fix d3d pixel center
mtx.m[0][1] = 0.0f;
mtx.m[1][1] = pMatrix[2];
mtx.m[2][1] = 0.0f;
mtx.m[3][1] = pMatrix[3]+0.5f/m_height; // fix d3d pixel center
mtx.m[0][2] = 0.0f;
mtx.m[1][2] = 0.0f;
mtx.m[2][2] = pMatrix[4];
mtx.m[3][2] = -(-1 - pMatrix[5]);
mtx.m[0][3] = 0;
mtx.m[1][3] = 0;
mtx.m[2][3] = 0.0f;
mtx.m[3][3] = 1.0f;
}
D3D::dev->SetVertexShaderConstantF(constantIndex, mtx, 4);
}
void Renderer::SetTexture( DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture )
{
if ( m_Textures[Stage] != pTexture )
{
m_Textures[Stage] = pTexture;
D3D::dev->SetTexture( Stage, pTexture );
}
}
void Renderer::SetFVF( DWORD FVF )
{
if ( m_FVF != FVF )
{
m_FVF = FVF;
D3D::dev->SetFVF( FVF );
}
}
void Renderer::SetRenderState( D3DRENDERSTATETYPE State, DWORD Value )
{
if ( m_RenderStates[State] != Value )
{
m_RenderStates[State] = Value;
D3D::dev->SetRenderState( State, Value );
}
}
void Renderer::SetTextureStageState( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value )
{
if ( m_TextureStageStates[Stage][Type] != Value )
{
m_TextureStageStates[Stage][Type] = Value;
D3D::dev->SetTextureStageState( Stage, Type, Value );
}
}
void Renderer::SetSamplerState( DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value )
{
if ( m_SamplerStates[Sampler][Type] != Value )
{
m_SamplerStates[Sampler][Type] = Value;
D3D::dev->SetSamplerState( Sampler, Type, Value );
}
}
void Renderer::DrawPrimitiveUP( D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, const void* pVertexStreamZeroData, UINT VertexStreamZeroStride )
{
D3D::dev->DrawPrimitiveUP( PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride );
}
void Renderer::DrawPrimitive( D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount )
{
D3D::dev->DrawPrimitive( PrimitiveType, StartVertex, PrimitiveCount );
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <d3dx9.h>
#include "Common.h"
#include "Statistics.h"
#include "Config.h"
#include "main.h"
#include "VertexManager.h"
#include "Render.h"
#include "OpcodeDecoding.h"
#include "BPStructs.h"
#include "XFStructs.h"
#include "D3DPostprocess.h"
#include "D3DUtil.h"
#include "ShaderManager.h"
#include "TextureCache.h"
#include "Utils.h"
#include "EmuWindow.h"
#include <list>
float Renderer::m_x,Renderer::m_y,Renderer::m_width, Renderer::m_height, Renderer::xScale,Renderer::yScale;
std::vector<LPDIRECT3DBASETEXTURE9> Renderer::m_Textures;
DWORD Renderer::m_RenderStates[MaxRenderStates];
DWORD Renderer::m_TextureStageStates[MaxTextureStages][MaxTextureTypes];
DWORD Renderer::m_SamplerStates[MaxSamplerSize][MaxSamplerTypes];
DWORD Renderer::m_FVF;
#define NUMWNDRES 6
extern int g_Res[NUMWNDRES][2];
struct Message
{
Message(const std::string &msg, u32 dw) : message( msg ), dwTimeStamp( dw )
{
}
std::string message;
u32 dwTimeStamp;
};
static std::list<Message> s_listMsgs;
void Renderer::Init(SVideoInitialize &_VideoInitialize)
{
EmuWindow::SetSize(g_Res[g_Config.iWindowedRes][0], g_Res[g_Config.iWindowedRes][1]);
D3D::Create(g_Config.iAdapter, EmuWindow::GetWnd(), g_Config.bFullscreen, g_Config.iFSResolution, g_Config.iMultisampleMode);
D3DVIEWPORT9 vp;
D3D::dev->GetViewport(&vp);
m_x = 0;
m_y = 0;
m_width = (float)vp.Width;
m_height = (float)vp.Height;
xScale = 640.0f / (float)vp.Width;
yScale = 480.0f / (float)vp.Height;
D3D::font.Init();
Initialize();
}
void Renderer::Shutdown(void)
{
D3D::font.Shutdown();
D3D::EndFrame();
D3D::Close();
}
void Renderer::Initialize(void)
{
m_FVF = 0;
m_Textures.reserve( MaxTextureStages );
for ( int i = 0; i < MaxTextureStages; i++ )
{
m_Textures.push_back( NULL );
}
for (int i=0; i<8; i++)
{
D3D::dev->SetSamplerState(i, D3DSAMP_MAXANISOTROPY, 16);
}
ReinitView();
Postprocess::Initialize();
Postprocess::BeginFrame();
D3D::BeginFrame(true, 0);
VertexManager::BeginFrame();
}
void Renderer::AddMessage(const std::string &message, u32 ms)
{
s_listMsgs.push_back(Message(message, timeGetTime()+ms));
}
void Renderer::ProcessMessages()
{
if (s_listMsgs.size() > 0) {
int left = 25, top = 15;
std::list<Message>::iterator it = s_listMsgs.begin();
while( it != s_listMsgs.end() )
{
int time_left = (int)(it->dwTimeStamp - timeGetTime());
int alpha = 255;
if(time_left<1024)
{
alpha=time_left>>2;
if(time_left<0) alpha=0;
}
alpha <<= 24;
RenderText(it->message, left+1, top+1, 0x000000|alpha);
RenderText(it->message, left, top, 0xffff30|alpha);
top += 15;
if (time_left <= 0)
it = s_listMsgs.erase(it);
else ++it;
}
}
}
void Renderer::RenderText(const std::string &text, int left, int top, u32 color)
{
D3D::font.DrawTextScaled((float)left, (float)top, 20, 20, 0.0f, color, text.c_str(), false);
}
void dumpMatrix(D3DXMATRIX &mtx)
{
for (int y=0; y<4; y++)
{
char temp[256];
sprintf(temp,"%4.4f %4.4f %4.4f %4.4f",mtx.m[y][0],mtx.m[y][1],mtx.m[y][2],mtx.m[y][3]);
g_VideoInitialize.pLog(temp, FALSE);
}
}
void Renderer::ReinitView()
{
D3DXMATRIX mtx;
D3DXMatrixIdentity(&mtx);
D3D::dev->SetTransform(D3DTS_VIEW,&mtx);
D3D::dev->SetTransform(D3DTS_WORLD,&mtx);
float width = (float)D3D::GetDisplayWidth();
float height = (float)D3D::GetDisplayHeight();
xScale = width/640.0f;
yScale = height/480.0f;
RECT rc = {
(LONG)(m_x*xScale), (LONG)(m_y*yScale), (LONG)(m_width*xScale), (LONG)(m_height*yScale)
};
}
void Renderer::SwapBuffers(void)
{
// center window again
if (EmuWindow::GetParentWnd())
{
RECT rcWindow;
GetWindowRect(EmuWindow::GetParentWnd(), &rcWindow);
int width = rcWindow.right - rcWindow.left;
int height = rcWindow.bottom - rcWindow.top;
::MoveWindow(EmuWindow::GetWnd(), 0,0,width,height, FALSE);
// nBackbufferWidth = width;
// nBackbufferHeight = height;
}
//Finish up the current frame, print some stats
Postprocess::FinalizeFrame();
if (g_Config.bOverlayStats)
{
char st[2048];
char *p = st;
p+=sprintf(p,"Num textures created: %i\n",stats.numTexturesCreated);
p+=sprintf(p,"Num textures alive: %i\n",stats.numTexturesAlive);
p+=sprintf(p,"Num pshaders created: %i\n",stats.numPixelShadersCreated);
p+=sprintf(p,"Num pshaders alive: %i\n",stats.numPixelShadersAlive);
p+=sprintf(p,"Num vshaders created: %i\n",stats.numVertexShadersCreated);
p+=sprintf(p,"Num vshaders alive: %i\n",stats.numVertexShadersAlive);
p+=sprintf(p,"Num dlists called: %i\n",stats.numDListsCalled);
p+=sprintf(p,"Num dlists created: %i\n",stats.numDListsCreated);
p+=sprintf(p,"Num dlists alive: %i\n",stats.numDListsAlive);
p+=sprintf(p,"Num primitives: %i\n",stats.thisFrame.numPrims);
p+=sprintf(p,"Num primitive joins: %i\n",stats.thisFrame.numPrimitiveJoins);
p+=sprintf(p,"Num primitives (DL): %i\n",stats.thisFrame.numDLPrims);
p+=sprintf(p,"Num XF loads: %i\n",stats.thisFrame.numXFLoads);
p+=sprintf(p,"Num XF loads (DL): %i\n",stats.thisFrame.numXFLoadsInDL);
p+=sprintf(p,"Num CP loads: %i\n",stats.thisFrame.numCPLoads);
p+=sprintf(p,"Num CP loads (DL): %i\n",stats.thisFrame.numCPLoadsInDL);
p+=sprintf(p,"Num BP loads: %i\n",stats.thisFrame.numBPLoads);
p+=sprintf(p,"Num BP loads (DL): %i\n",stats.thisFrame.numBPLoadsInDL);
D3D::font.DrawTextScaled(0,30,20,20,0.0f,0xFF00FFFF,st,false);
//end frame
}
ProcessMessages();
#if defined(DVPROFILE)
if( g_bWriteProfile ) {
//g_bWriteProfile = 0;
static int framenum = 0;
const int UPDATE_FRAMES = 8;
if( ++framenum >= UPDATE_FRAMES ) {
DVProfWrite("prof.txt", UPDATE_FRAMES);
DVProfClear();
framenum = 0;
}
}
#endif
D3D::EndFrame();
//D3D frame is now over
//////////////////////////////////////////////////////////////////////////
//clean out old stuff from caches
frameCount++;
PShaderCache::Cleanup();
VShaderCache::Cleanup();
TextureCache::Cleanup();
//DListCache::Cleanup();
//////////////////////////////////////////////////////////////////////////
//Begin new frame
//Set default viewport and scissor, for the clear to work correctly
stats.ResetFrame();
D3DVIEWPORT9 vp;
vp.X = 0;
vp.Y = 0;
vp.Width = (DWORD)m_width;
vp.Height = (DWORD)m_height;
vp.MinZ = 0;
vp.MaxZ = 0;
D3D::dev->SetViewport(&vp);
RECT rc;
rc.left = 0;
rc.top = 0;
rc.right = (LONG)m_width;
rc.bottom = (LONG)m_height;
D3D::dev->SetScissorRect(&rc);
u32 clearColor = (bpmem.clearcolorAR<<16)|bpmem.clearcolorGB;
// clearColor |= 0x003F003F;
// D3D::BeginFrame(true,clearColor,1.0f);
D3D::BeginFrame(false,clearColor,1.0f);
// D3D::EnableAlphaToCoverage();
Postprocess::BeginFrame();
VertexManager::BeginFrame();
if (g_Config.bOldCard)
D3D::font.SetRenderStates(); //compatibility with low end cards
}
void Renderer::Flush(void)
{
// render the rest of the vertex buffer
//only to be used for debugging purposes
//D3D::EndFrame();
//D3D::BeginFrame(false,0);
}
void Renderer::SetViewport(float* _Viewport)
{
Viewport* pViewport = (Viewport*)_Viewport;
D3DVIEWPORT9 vp;
float x=(pViewport->xOrig-662)*2;
float y=(pViewport->yOrig-582)*2; //something is wrong, but what??
y-=16;
float w=pViewport->wd*2; //multiply up to real size
float h=pViewport->ht*-2; //why is this negative? oh well..
if (x < 0.0f) x = 0.0f;
if (y < 0.0f) y = 0.0f;
if (x > 640.0f) x = 639.0f;
if (y > 480.0f) y = 479.0f;
if (w < 0) w=1;
if (h < 0) h=1;
if (x+w > 640.0f) w=640-x;
if (y+h > 480.0f) h=480-y;
//x=y=0;
//if(w>0.0f) w=0.0f;
//if(h<0.0f) h=0.0f;
vp.X = (DWORD)(x*xScale);
vp.Y = (DWORD)(y*yScale);
vp.Width = (DWORD)(w*xScale);
vp.Height = (DWORD)(h*yScale);
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
// char temp[256];
// sprintf(temp,"Viewport: %i %i %i %i %f %f",vp.X,vp.Y,vp.Width,vp.Height,vp.MinZ,vp.MaxZ);
// g_VideoInitialize.pLog(temp, FALSE);
D3D::dev->SetViewport(&vp);
}
void Renderer::SetScissorBox(RECT &rc)
{
rc.left = (int)(rc.left * xScale);
rc.top = (int)(rc.top * yScale);
rc.right = (int)(rc.right * xScale);
rc.bottom = (int)(rc.bottom * yScale);
if (rc.right >= rc.left && rc.bottom >= rc.top)
D3D::dev->SetScissorRect(&rc);
else
g_VideoInitialize.pLog("SCISSOR ERROR", FALSE);
}
void Renderer::SetProjection(float* pMatrix, int constantIndex)
{
D3DXMATRIX mtx;
if (pMatrix[6] == 0)
{
mtx.m[0][0] = pMatrix[0];
mtx.m[1][0] = 0.0f;
mtx.m[2][0] = pMatrix[1];
mtx.m[3][0] = -0.5f/m_width;
mtx.m[0][1] = 0.0f;
mtx.m[1][1] = pMatrix[2];
mtx.m[2][1] = pMatrix[3];
mtx.m[3][1] = +0.5f/m_height;
mtx.m[0][2] = 0.0f;
mtx.m[1][2] = 0.0f;
mtx.m[2][2] = -(1-pMatrix[4]);
mtx.m[3][2] = pMatrix[5];
mtx.m[0][3] = 0.0f;
mtx.m[1][3] = 0.0f;
mtx.m[2][3] = -1.0f;
mtx.m[3][3] = 0.0f;
}
else
{
mtx.m[0][0] = pMatrix[0];
mtx.m[1][0] = 0.0f;
mtx.m[2][0] = 0.0f;
mtx.m[3][0] = pMatrix[1]-0.5f/m_width; // fix d3d pixel center
mtx.m[0][1] = 0.0f;
mtx.m[1][1] = pMatrix[2];
mtx.m[2][1] = 0.0f;
mtx.m[3][1] = pMatrix[3]+0.5f/m_height; // fix d3d pixel center
mtx.m[0][2] = 0.0f;
mtx.m[1][2] = 0.0f;
mtx.m[2][2] = pMatrix[4];
mtx.m[3][2] = -(-1 - pMatrix[5]);
mtx.m[0][3] = 0;
mtx.m[1][3] = 0;
mtx.m[2][3] = 0.0f;
mtx.m[3][3] = 1.0f;
}
D3D::dev->SetVertexShaderConstantF(constantIndex, mtx, 4);
}
void Renderer::SetTexture( DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture )
{
if ( m_Textures[Stage] != pTexture )
{
m_Textures[Stage] = pTexture;
D3D::dev->SetTexture( Stage, pTexture );
}
}
void Renderer::SetFVF( DWORD FVF )
{
if ( m_FVF != FVF )
{
m_FVF = FVF;
D3D::dev->SetFVF( FVF );
}
}
void Renderer::SetRenderState( D3DRENDERSTATETYPE State, DWORD Value )
{
if ( m_RenderStates[State] != Value )
{
m_RenderStates[State] = Value;
D3D::dev->SetRenderState( State, Value );
}
}
void Renderer::SetTextureStageState( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value )
{
if ( m_TextureStageStates[Stage][Type] != Value )
{
m_TextureStageStates[Stage][Type] = Value;
D3D::dev->SetTextureStageState( Stage, Type, Value );
}
}
void Renderer::SetSamplerState( DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value )
{
if ( m_SamplerStates[Sampler][Type] != Value )
{
m_SamplerStates[Sampler][Type] = Value;
D3D::dev->SetSamplerState( Sampler, Type, Value );
}
}
void Renderer::DrawPrimitiveUP( D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, const void* pVertexStreamZeroData, UINT VertexStreamZeroStride )
{
D3D::dev->DrawPrimitiveUP( PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride );
}
void Renderer::DrawPrimitive( D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount )
{
D3D::dev->DrawPrimitive( PrimitiveType, StartVertex, PrimitiveCount );
}

View File

@ -1,218 +1,218 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "D3DBase.h"
#include "Statistics.h"
#include "Utils.h"
#include "Profiler.h"
#include "ShaderManager.h"
#include "VertexLoader.h"
#include "BPMemory.h"
#include "XFMemory.h"
//I hope we don't get too many hash collisions :p
//all these magic numbers are primes, it should help a bit
tevhash GetCurrentTEV()
{
u32 hash = bpmem.genMode.numindstages + bpmem.genMode.numtevstages*11 + bpmem.genMode.numtexgens*8*17;
for (int i = 0; i < (int)bpmem.genMode.numtevstages+1; i++)
{
hash = _rotl(hash,3) ^ (bpmem.combiners[i].colorC.hex*13);
hash = _rotl(hash,7) ^ ((bpmem.combiners[i].alphaC.hex&0xFFFFFFFC)*3);
hash = _rotl(hash,9) ^ xfregs.texcoords[i].texmtxinfo.projection*451;
}
for (int i = 0; i < (int)bpmem.genMode.numtevstages/2+1; i++)
{
hash = _rotl(hash,13) ^ (bpmem.tevorders[i].hex*7);
}
for (int i = 0; i < 8; i++)
{
hash = _rotl(hash,3) ^ bpmem.tevksel[i].swap1;
hash = _rotl(hash,3) ^ bpmem.tevksel[i].swap2;
}
hash ^= bpmem.dstalpha.enable ^ 0xc0debabe;
hash = _rotl(hash,4) ^ bpmem.alphaFunc.comp0*7;
hash = _rotl(hash,4) ^ bpmem.alphaFunc.comp1*13;
hash = _rotl(hash,4) ^ bpmem.alphaFunc.logic*11;
return hash;
}
PShaderCache::PSCache PShaderCache::pshaders;
VShaderCache::VSCache VShaderCache::vshaders;
void PShaderCache::Init()
{
}
void PShaderCache::Shutdown()
{
PSCache::iterator iter = pshaders.begin();
for (;iter!=pshaders.end();iter++)
iter->second.Destroy();
pshaders.clear();
}
void PShaderCache::SetShader()
{
if (D3D::GetShaderVersion() < 2)
return; // we are screwed
static LPDIRECT3DPIXELSHADER9 lastShader = 0;
DVSTARTPROFILE();
tevhash currentHash = GetCurrentTEV();
PSCache::iterator iter;
iter = pshaders.find(currentHash);
if (iter != pshaders.end())
{
iter->second.frameCount = frameCount;
PSCacheEntry &entry = iter->second;
if (!lastShader || entry.shader != lastShader)
{
D3D::dev->SetPixelShader(entry.shader);
lastShader = entry.shader;
}
return;
}
const char *code = GeneratePixelShader();
LPDIRECT3DPIXELSHADER9 shader = D3D::CompilePShader(code, int(strlen(code)));
if (shader)
{
//Make an entry in the table
PSCacheEntry newentry;
newentry.shader = shader;
newentry.frameCount = frameCount;
pshaders[currentHash] = newentry;
}
D3D::dev->SetPixelShader(shader);
INCSTAT(stats.numPixelShadersCreated);
SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size());
}
void PShaderCache::Cleanup()
{
PSCache::iterator iter;
iter = pshaders.begin();
while (iter != pshaders.end())
{
PSCacheEntry &entry = iter->second;
if (entry.frameCount < frameCount-30)
{
entry.Destroy();
iter = pshaders.erase(iter);
}
else
{
iter++;
}
}
SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size());
}
void VShaderCache::Init()
{
}
void VShaderCache::Shutdown()
{
VSCache::iterator iter = vshaders.begin();
for (; iter != vshaders.end(); iter++)
iter->second.Destroy();
vshaders.clear();
}
void VShaderCache::SetShader()
{
static LPDIRECT3DVERTEXSHADER9 shader = NULL;
if (D3D::GetShaderVersion() < 2)
return; // we are screwed
if (shader) {
//D3D::dev->SetVertexShader(shader);
return;
}
static LPDIRECT3DVERTEXSHADER9 lastShader = 0;
DVSTARTPROFILE();
tevhash currentHash = GetCurrentTEV();
VSCache::iterator iter;
iter = vshaders.find(currentHash);
if (iter != vshaders.end())
{
iter->second.frameCount=frameCount;
VSCacheEntry &entry = iter->second;
if (!lastShader || entry.shader != lastShader)
{
D3D::dev->SetVertexShader(entry.shader);
lastShader = entry.shader;
}
return;
}
const char *code = GenerateVertexShader();
shader = D3D::CompileVShader(code, int(strlen(code)));
if (shader)
{
//Make an entry in the table
VSCacheEntry entry;
entry.shader = shader;
entry.frameCount=frameCount;
vshaders[currentHash] = entry;
}
D3D::dev->SetVertexShader(shader);
INCSTAT(stats.numVertexShadersCreated);
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
}
void VShaderCache::Cleanup()
{
for (VSCache::iterator iter=vshaders.begin(); iter!=vshaders.end();)
{
VSCacheEntry &entry = iter->second;
if (entry.frameCount < frameCount - 30)
{
entry.Destroy();
iter = vshaders.erase(iter);
}
else
{
++iter;
}
}
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "D3DBase.h"
#include "Statistics.h"
#include "Utils.h"
#include "Profiler.h"
#include "ShaderManager.h"
#include "VertexLoader.h"
#include "BPMemory.h"
#include "XFMemory.h"
//I hope we don't get too many hash collisions :p
//all these magic numbers are primes, it should help a bit
tevhash GetCurrentTEV()
{
u32 hash = bpmem.genMode.numindstages + bpmem.genMode.numtevstages*11 + bpmem.genMode.numtexgens*8*17;
for (int i = 0; i < (int)bpmem.genMode.numtevstages+1; i++)
{
hash = _rotl(hash,3) ^ (bpmem.combiners[i].colorC.hex*13);
hash = _rotl(hash,7) ^ ((bpmem.combiners[i].alphaC.hex&0xFFFFFFFC)*3);
hash = _rotl(hash,9) ^ xfregs.texcoords[i].texmtxinfo.projection*451;
}
for (int i = 0; i < (int)bpmem.genMode.numtevstages/2+1; i++)
{
hash = _rotl(hash,13) ^ (bpmem.tevorders[i].hex*7);
}
for (int i = 0; i < 8; i++)
{
hash = _rotl(hash,3) ^ bpmem.tevksel[i].swap1;
hash = _rotl(hash,3) ^ bpmem.tevksel[i].swap2;
}
hash ^= bpmem.dstalpha.enable ^ 0xc0debabe;
hash = _rotl(hash,4) ^ bpmem.alphaFunc.comp0*7;
hash = _rotl(hash,4) ^ bpmem.alphaFunc.comp1*13;
hash = _rotl(hash,4) ^ bpmem.alphaFunc.logic*11;
return hash;
}
PShaderCache::PSCache PShaderCache::pshaders;
VShaderCache::VSCache VShaderCache::vshaders;
void PShaderCache::Init()
{
}
void PShaderCache::Shutdown()
{
PSCache::iterator iter = pshaders.begin();
for (;iter!=pshaders.end();iter++)
iter->second.Destroy();
pshaders.clear();
}
void PShaderCache::SetShader()
{
if (D3D::GetShaderVersion() < 2)
return; // we are screwed
static LPDIRECT3DPIXELSHADER9 lastShader = 0;
DVSTARTPROFILE();
tevhash currentHash = GetCurrentTEV();
PSCache::iterator iter;
iter = pshaders.find(currentHash);
if (iter != pshaders.end())
{
iter->second.frameCount = frameCount;
PSCacheEntry &entry = iter->second;
if (!lastShader || entry.shader != lastShader)
{
D3D::dev->SetPixelShader(entry.shader);
lastShader = entry.shader;
}
return;
}
const char *code = GeneratePixelShader();
LPDIRECT3DPIXELSHADER9 shader = D3D::CompilePShader(code, int(strlen(code)));
if (shader)
{
//Make an entry in the table
PSCacheEntry newentry;
newentry.shader = shader;
newentry.frameCount = frameCount;
pshaders[currentHash] = newentry;
}
D3D::dev->SetPixelShader(shader);
INCSTAT(stats.numPixelShadersCreated);
SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size());
}
void PShaderCache::Cleanup()
{
PSCache::iterator iter;
iter = pshaders.begin();
while (iter != pshaders.end())
{
PSCacheEntry &entry = iter->second;
if (entry.frameCount < frameCount-30)
{
entry.Destroy();
iter = pshaders.erase(iter);
}
else
{
iter++;
}
}
SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size());
}
void VShaderCache::Init()
{
}
void VShaderCache::Shutdown()
{
VSCache::iterator iter = vshaders.begin();
for (; iter != vshaders.end(); iter++)
iter->second.Destroy();
vshaders.clear();
}
void VShaderCache::SetShader()
{
static LPDIRECT3DVERTEXSHADER9 shader = NULL;
if (D3D::GetShaderVersion() < 2)
return; // we are screwed
if (shader) {
//D3D::dev->SetVertexShader(shader);
return;
}
static LPDIRECT3DVERTEXSHADER9 lastShader = 0;
DVSTARTPROFILE();
tevhash currentHash = GetCurrentTEV();
VSCache::iterator iter;
iter = vshaders.find(currentHash);
if (iter != vshaders.end())
{
iter->second.frameCount=frameCount;
VSCacheEntry &entry = iter->second;
if (!lastShader || entry.shader != lastShader)
{
D3D::dev->SetVertexShader(entry.shader);
lastShader = entry.shader;
}
return;
}
const char *code = GenerateVertexShader();
shader = D3D::CompileVShader(code, int(strlen(code)));
if (shader)
{
//Make an entry in the table
VSCacheEntry entry;
entry.shader = shader;
entry.frameCount=frameCount;
vshaders[currentHash] = entry;
}
D3D::dev->SetVertexShader(shader);
INCSTAT(stats.numVertexShadersCreated);
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
}
void VShaderCache::Cleanup()
{
for (VSCache::iterator iter=vshaders.begin(); iter!=vshaders.end();)
{
VSCacheEntry &entry = iter->second;
if (entry.frameCount < frameCount - 30)
{
entry.Destroy();
iter = vshaders.erase(iter);
}
else
{
++iter;
}
}
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
}

View File

@ -1,251 +1,251 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <d3dx9.h>
#include "Common.h"
#include "Statistics.h"
#include "D3DBase.h"
#include "D3DTexture.h"
#include "Render.h"
#include "TextureDecoder.h"
#include "TextureCache.h"
#include "Config.h"
#include "main.h"
u8 *TextureCache::temp = NULL;
TextureCache::TexCache TextureCache::textures;
extern int frameCount;
#define TEMP_SIZE (1024*1024*4)
void TextureCache::TCacheEntry::Destroy()
{
if (texture)
texture->Release();
texture = 0;
if (!isRenderTarget) {
u32 *ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(addr + hashoffset*4);
if (*ptr == hash)
*ptr = oldpixel;
}
}
void TextureCache::Init()
{
temp = (u8*)VirtualAlloc(0,TEMP_SIZE,MEM_COMMIT,PAGE_READWRITE);
TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter);
}
void TextureCache::Invalidate()
{
TexCache::iterator iter = textures.begin();
for (; iter != textures.end(); iter++)
iter->second.Destroy();
textures.clear();
TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter);
}
void TextureCache::Shutdown()
{
Invalidate();
if (temp != NULL)
{
VirtualFree(temp, 0, MEM_RELEASE);
temp = NULL;
}
}
void TextureCache::Cleanup()
{
TexCache::iterator iter=textures.begin();
while(iter != textures.end())
{
if (frameCount>20+iter->second.frameCount)
{
if (!iter->second.isRenderTarget)
{
iter->second.Destroy();
iter = textures.erase(iter);
}
else
{
iter++;
}
}
else
{
iter++;
}
}
}
void TextureCache::Load(int stage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt)
{
if (address == 0)
return;
TexCache::iterator iter = textures.find(address);
u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address);
int palSize = TexDecoder_GetPaletteSize(format);
u32 palhash = 0xc0debabe;
if (palSize)
{
if (palSize>16)
palSize = 16; //let's not do excessive amount of checking
u8 *pal = g_VideoInitialize.pGetMemoryPointer(tlutaddr);
if (pal != 0)
{
for (int i=0; i<palSize; i++)
{
palhash = _rotl(palhash,13);
palhash ^= pal[i];
palhash += 31;
}
}
}
static LPDIRECT3DTEXTURE9 lastTexture[8] = {0,0,0,0,0,0,0,0};
if (iter != textures.end())
{
TCacheEntry &entry = iter->second;
if (entry.isRenderTarget || (((u32 *)ptr)[entry.hashoffset] == entry.hash && palhash == entry.paletteHash)) //stupid, improve
{
iter->second.frameCount = frameCount;
if (lastTexture[stage] == iter->second.texture)
{
return;
}
lastTexture[stage] = iter->second.texture;
// D3D::dev->SetTexture(stage,iter->second.texture);
Renderer::SetTexture( stage, iter->second.texture );
return;
}
else
{
TCacheEntry &entry = iter->second;
/* if (width == iter->second.w && height==entry.h && format==entry.fmt)
{
LPDIRECT3DTEXTURE9 tex = entry.texture;
int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16;
int expandedWidth = (width+bs) & (~bs);
D3DFORMAT dfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt);
D3D::ReplaceTexture2D(tex,temp,width,height,expandedWidth,dfmt);
D3D::dev->SetTexture(stage,tex);
return;
}
else
{*/
iter->second.Destroy();
textures.erase(iter);
//}
}
}
int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16;
int expandedWidth = (width+bs) & (~bs);
PC_TexFormat pcfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt);
D3DFORMAT d3d_fmt;
switch (pcfmt) {
case PC_TEX_FMT_BGRA32:
d3d_fmt = D3DFMT_A8R8G8B8;
break;
}
//Make an entry in the table
TCacheEntry entry;
entry.hashoffset = 0;
entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF);
entry.paletteHash = palhash;
entry.oldpixel = ((u32 *)ptr)[entry.hashoffset];
((u32 *)ptr)[entry.hashoffset] = entry.hash;
entry.addr = address;
entry.isRenderTarget=false;
entry.isNonPow2 = ((width&(width-1)) || (height&(height-1)));
entry.texture = D3D::CreateTexture2D((BYTE*)temp, width, height, expandedWidth, d3d_fmt);
entry.frameCount = frameCount;
entry.w=width;
entry.h=height;
entry.fmt=format;
textures[address] = entry;
if (g_Config.bDumpTextures)
{ // dump texture to file
static int counter = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%s\\txt_%04i_%i.png", g_Config.texDumpPath.c_str(), counter++, format);
D3DXSaveTextureToFile(szTemp,D3DXIFF_BMP,entry.texture,0);
}
INCSTAT(stats.numTexturesCreated);
SETSTAT(stats.numTexturesAlive, (int)textures.size());
//Set the texture!
// D3D::dev->SetTexture(stage,entry.texture);
Renderer::SetTexture( stage, entry.texture );
lastTexture[stage] = entry.texture;
}
void TextureCache::CopyEFBToRenderTarget(u32 address, RECT *source)
{
TexCache::iterator iter;
LPDIRECT3DTEXTURE9 tex;
iter = textures.find(address);
if (iter != textures.end())
{
if (!iter->second.isRenderTarget)
{
g_VideoInitialize.pLog("Using non-rendertarget texture as render target!!! WTF?", FALSE);
//TODO: remove it and recreate it as a render target
}
tex = iter->second.texture;
iter->second.frameCount=frameCount;
}
else
{
TCacheEntry entry;
entry.isRenderTarget=true;
entry.hash = 0;
entry.hashoffset = 0;
entry.frameCount = frameCount;
// TODO(ector): infer this size in some sensible way
D3D::dev->CreateTexture(512,512,1,D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &entry.texture, 0);
textures[address] = entry;
tex = entry.texture;
}
LPDIRECT3DSURFACE9 srcSurface,destSurface;
tex->GetSurfaceLevel(0,&destSurface);
srcSurface = D3D::GetBackBufferSurface();
D3D::dev->StretchRect(srcSurface,source,destSurface,0,D3DTEXF_NONE);
destSurface->Release();
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <d3dx9.h>
#include "Common.h"
#include "Statistics.h"
#include "D3DBase.h"
#include "D3DTexture.h"
#include "Render.h"
#include "TextureDecoder.h"
#include "TextureCache.h"
#include "Config.h"
#include "main.h"
u8 *TextureCache::temp = NULL;
TextureCache::TexCache TextureCache::textures;
extern int frameCount;
#define TEMP_SIZE (1024*1024*4)
void TextureCache::TCacheEntry::Destroy()
{
if (texture)
texture->Release();
texture = 0;
if (!isRenderTarget) {
u32 *ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(addr + hashoffset*4);
if (*ptr == hash)
*ptr = oldpixel;
}
}
void TextureCache::Init()
{
temp = (u8*)VirtualAlloc(0,TEMP_SIZE,MEM_COMMIT,PAGE_READWRITE);
TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter);
}
void TextureCache::Invalidate()
{
TexCache::iterator iter = textures.begin();
for (; iter != textures.end(); iter++)
iter->second.Destroy();
textures.clear();
TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter);
}
void TextureCache::Shutdown()
{
Invalidate();
if (temp != NULL)
{
VirtualFree(temp, 0, MEM_RELEASE);
temp = NULL;
}
}
void TextureCache::Cleanup()
{
TexCache::iterator iter=textures.begin();
while(iter != textures.end())
{
if (frameCount>20+iter->second.frameCount)
{
if (!iter->second.isRenderTarget)
{
iter->second.Destroy();
iter = textures.erase(iter);
}
else
{
iter++;
}
}
else
{
iter++;
}
}
}
void TextureCache::Load(int stage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt)
{
if (address == 0)
return;
TexCache::iterator iter = textures.find(address);
u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address);
int palSize = TexDecoder_GetPaletteSize(format);
u32 palhash = 0xc0debabe;
if (palSize)
{
if (palSize>16)
palSize = 16; //let's not do excessive amount of checking
u8 *pal = g_VideoInitialize.pGetMemoryPointer(tlutaddr);
if (pal != 0)
{
for (int i=0; i<palSize; i++)
{
palhash = _rotl(palhash,13);
palhash ^= pal[i];
palhash += 31;
}
}
}
static LPDIRECT3DTEXTURE9 lastTexture[8] = {0,0,0,0,0,0,0,0};
if (iter != textures.end())
{
TCacheEntry &entry = iter->second;
if (entry.isRenderTarget || (((u32 *)ptr)[entry.hashoffset] == entry.hash && palhash == entry.paletteHash)) //stupid, improve
{
iter->second.frameCount = frameCount;
if (lastTexture[stage] == iter->second.texture)
{
return;
}
lastTexture[stage] = iter->second.texture;
// D3D::dev->SetTexture(stage,iter->second.texture);
Renderer::SetTexture( stage, iter->second.texture );
return;
}
else
{
TCacheEntry &entry = iter->second;
/* if (width == iter->second.w && height==entry.h && format==entry.fmt)
{
LPDIRECT3DTEXTURE9 tex = entry.texture;
int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16;
int expandedWidth = (width+bs) & (~bs);
D3DFORMAT dfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt);
D3D::ReplaceTexture2D(tex,temp,width,height,expandedWidth,dfmt);
D3D::dev->SetTexture(stage,tex);
return;
}
else
{*/
iter->second.Destroy();
textures.erase(iter);
//}
}
}
int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16;
int expandedWidth = (width+bs) & (~bs);
PC_TexFormat pcfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt);
D3DFORMAT d3d_fmt;
switch (pcfmt) {
case PC_TEX_FMT_BGRA32:
d3d_fmt = D3DFMT_A8R8G8B8;
break;
}
//Make an entry in the table
TCacheEntry entry;
entry.hashoffset = 0;
entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF);
entry.paletteHash = palhash;
entry.oldpixel = ((u32 *)ptr)[entry.hashoffset];
((u32 *)ptr)[entry.hashoffset] = entry.hash;
entry.addr = address;
entry.isRenderTarget=false;
entry.isNonPow2 = ((width&(width-1)) || (height&(height-1)));
entry.texture = D3D::CreateTexture2D((BYTE*)temp, width, height, expandedWidth, d3d_fmt);
entry.frameCount = frameCount;
entry.w=width;
entry.h=height;
entry.fmt=format;
textures[address] = entry;
if (g_Config.bDumpTextures)
{ // dump texture to file
static int counter = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%s\\txt_%04i_%i.png", g_Config.texDumpPath.c_str(), counter++, format);
D3DXSaveTextureToFile(szTemp,D3DXIFF_BMP,entry.texture,0);
}
INCSTAT(stats.numTexturesCreated);
SETSTAT(stats.numTexturesAlive, (int)textures.size());
//Set the texture!
// D3D::dev->SetTexture(stage,entry.texture);
Renderer::SetTexture( stage, entry.texture );
lastTexture[stage] = entry.texture;
}
void TextureCache::CopyEFBToRenderTarget(u32 address, RECT *source)
{
TexCache::iterator iter;
LPDIRECT3DTEXTURE9 tex;
iter = textures.find(address);
if (iter != textures.end())
{
if (!iter->second.isRenderTarget)
{
g_VideoInitialize.pLog("Using non-rendertarget texture as render target!!! WTF?", FALSE);
//TODO: remove it and recreate it as a render target
}
tex = iter->second.texture;
iter->second.frameCount=frameCount;
}
else
{
TCacheEntry entry;
entry.isRenderTarget=true;
entry.hash = 0;
entry.hashoffset = 0;
entry.frameCount = frameCount;
// TODO(ector): infer this size in some sensible way
D3D::dev->CreateTexture(512,512,1,D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &entry.texture, 0);
textures[address] = entry;
tex = entry.texture;
}
LPDIRECT3DSURFACE9 srcSurface,destSurface;
tex->GetSurfaceLevel(0,&destSurface);
srcSurface = D3D::GetBackBufferSurface();
D3D::dev->StretchRect(srcSurface,source,destSurface,0,D3DTEXF_NONE);
destSurface->Release();
}

View File

@ -1,372 +1,372 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <fvec.h>
#include "Common.h"
#include "Profiler.h"
// #include "Globals.h"
#include "Vec3.h"
#include "TransformEngine.h"
#include "VertexManager.h"
#include "VertexLoader.h"
#include "BPStructs.h"
#include "XFStructs.h"
#include "Utils.h"
#include "RGBAFloat.h"
float *CTransformEngine::m_pPosMatrix;
float *CTransformEngine::m_pNormalMatrix;
float *CTransformEngine::m_pTexMatrix[8];
float *CTransformEngine::m_pTexPostMatrix[8];
const Light *GetLight(int i)
{
return (const Light *)(xfmem + XFMEM_LIGHTS) + i;
}
float DoLighting(const Light *light, const LitChannel &chan, const Vec3 &pos, const Vec3 &normal)
{
float val;
if (chan.attnfunc == 0 || chan.attnfunc == 2) //no attn
{
Vec3 ldir = (Vec3(light->dpos) - pos);
val = ldir.normalized() * normal;
}
else
{
float aattn = 0;
float d;
float mul = 1.0f;
if (chan.attnfunc == 3)
{
Vec3 ldir = (Vec3(light->dpos) - pos);
d = ldir.length();
Vec3 ldirNorm = ldir / d; //normalize
float l = ldirNorm * normal;
aattn = Vec3(light->ddir) * ldirNorm;
mul = l;
}
else if (chan.attnfunc == 1)
{
d = aattn = Vec3(light->shalfangle) * normal;
mul = (Vec3(light->sdir) * normal > 0) ? (normal * Vec3(light->shalfangle)) : 0;
if (mul < 0)
mul = 0;
}
float spot = (light->a2*aattn*aattn + light->a1*aattn + light->a0);
float dist = 1.0f/(light->k2*d*d + light->k1*d + light->k0);
if (spot<0)
spot=0;
val = mul * spot * dist;
}
if (val < 0 && chan.diffusefunc == 2) // clamp
val = 0;
return val;
}
void VtxMulMtx43T(Vec3 &out, const Vec3 &in, const float pMatrix[12])
{
out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2] + 1 * pMatrix[3];
out.y = in.x * pMatrix[4] + in.y * pMatrix[5] + in.z * pMatrix[6] + 1 * pMatrix[7];
out.z = in.x * pMatrix[8] + in.y * pMatrix[9] + in.z * pMatrix[10] + 1 * pMatrix[11];
}
void VtxMulMtx43(Vec3 &out, const Vec3 &in, const float pMatrix[12])
{
VtxMulMtx43T(out,in,pMatrix);
//TODO(XK): Turns out that SSE2 computations are slower... Can anyone do
// anything about it?
/*
F32vec4 a(in.x, in.y, in.z, 1), b(pMatrix[0], pMatrix[1], pMatrix[2], pMatrix[3]);
out.x = add_horizontal(a * b);
b[0] = pMatrix[4]; b[1] = pMatrix[5]; b[2] = pMatrix[6]; b[3] = pMatrix[7];
out.y = add_horizontal(a * b);
b[0] = pMatrix[8]; b[1] = pMatrix[9]; b[2] = pMatrix[10]; b[3] = pMatrix[11];
out.z = add_horizontal(a * b);
*/
}
void VtxMulMtx42(Vec3 &out, const Vec3 &in, const float pMatrix[8])
{
out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2] + 1 * pMatrix[3];
out.y = in.x * pMatrix[4] + in.y * pMatrix[5] + in.z * pMatrix[6] + 1 * pMatrix[7];
}
void VtxMulMtx33(Vec3 &out, const Vec3 &in, const float pMatrix[9])
{
out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2];
out.y = in.x * pMatrix[3] + in.y * pMatrix[4] + in.z * pMatrix[5];
out.z = in.x * pMatrix[6] + in.y * pMatrix[7] + in.z * pMatrix[8];
}
void CTransformEngine::TransformVertices(int _numVertices, const DecodedVArray *varray, D3DVertex *vbuffer)
{
if (vbuffer == 0)
{
MessageBox(0,"TransformVertices : vbuffer == 0","WTF",0);
}
DVSTARTPROFILE();
RGBAFloat lightColors[8];
RGBAFloat lightVals[8];
RGBAFloat chans[2];
u32 components = varray->GetComponents();
// TODO: only for active lights
for (int i=0; i<8; i++)
lightColors[i].convert_GC(GetLight(i)->color);
for (int i=0; i<_numVertices; i++)
{
//////////////////////////////////////////////////////////////////////////
//Step 1: xform position and normal
//////////////////////////////////////////////////////////////////////////
Vec3 OrigPos = varray->GetPos(i);
if (varray->hasPosMatIdx)
{
int index = varray->GetPosMtxInd(i);
SetPosNormalMatrix(
(float*)xfmem + (index & 63) * 4, //CHECK
(float*)xfmem + 0x400 + 3 * (index & 31)); //CHECK
}
for (int j = 0; j < 8; j++)
{
if (varray->hasTexMatIdx[j])
{
float *flipmem = (float *)xfmem;
int index = varray->GetTexMtxInd(j, i);
SetTexMatrix(j, flipmem + index * 4);
}
}
Vec3 TempPos;
// m_pPosMatrix can be switched out, through matrixindex vertex components
VtxMulMtx43(TempPos, OrigPos, m_pPosMatrix);
Vec3 TempNormal;
Vec3 OrigNormal;
if (varray->hasNrm)
{
OrigNormal = varray->GetNormal(0, i);
VtxMulMtx33(TempNormal, OrigNormal, m_pNormalMatrix);
TempNormal.normalize();
}
else
{
OrigNormal.setZero();
TempNormal.setZero();
}
//////////////////////////////////////////////////////////////////////////
//Step 2: Light!
//////////////////////////////////////////////////////////////////////////
//find all used lights
u32 lightMask =
xfregs.colChans[0].color.GetFullLightMask() | xfregs.colChans[0].alpha.GetFullLightMask() |
xfregs.colChans[1].color.GetFullLightMask() | xfregs.colChans[1].alpha.GetFullLightMask();
float r0=0,g0=0,b0=0,a0=0;
//go through them and compute the lit colors
//Sum lighting for both two color channels if they're active
for (int j = 0; j < (int)bpmem.genMode.numcolchans; j++)
{
RGBAFloat material;
RGBAFloat lightSum(0,0,0,0);
bool hasColorJ = (components & (VertexLoader::VB_HAS_COL0 << j)) != 0;
//get basic material color from appropriate sources (this would compile nicely!:)
if (xfregs.colChans[j].color.matsource == GX_SRC_REG)
material.convertRGB_GC(xfregs.colChans[j].matColor);
else
{
if (hasColorJ)
material.convertRGB(varray->GetColor(j, i));
else
material.r=material.g=material.b=1.0f;
}
if (xfregs.colChans[j].alpha.matsource == GX_SRC_REG)
material.convertA_GC(xfregs.colChans[j].matColor);
else
{
if (hasColorJ)
material.convertA(varray->GetColor(j, i));
else
material.a=1.0f;
}
//combine together the light values from the lights that affect the color
if (xfregs.colChans[j].color.enablelighting)
{
//choose ambient source and start our lightsum accumulator with its value..
if (xfregs.colChans[j].color.ambsource == GX_SRC_REG)
lightSum.convertRGB_GC(xfregs.colChans[j].ambColor); //ambient
else
{
if (hasColorJ)
lightSum.convertRGB(varray->GetColor(j, i));
else
{
lightSum.r=0.0f;lightSum.g=0.0f;lightSum.b=0.0f;
}
}
//accumulate light colors
int cmask = xfregs.colChans[j].color.GetFullLightMask();
for (int l=0; l<8; l++)
{
if (cmask&1)
{
float val = DoLighting(GetLight(l), xfregs.colChans[j].color, TempPos, TempNormal);
float r = lightColors[l].r * val;
float g = lightColors[l].g * val;
float b = lightColors[l].b * val;
lightSum.r += r;
lightSum.g += g;
lightSum.b += b;
}
cmask >>= 1;
}
}
else
{
lightSum.r = lightSum.g = lightSum.b = 1.0f;
}
//combine together the light values from the lights that affect alpha (should be rare)
if (xfregs.colChans[j].alpha.enablelighting)
{
//choose ambient source..
if (xfregs.colChans[j].alpha.ambsource==GX_SRC_REG)
lightSum.convertA_GC(xfregs.colChans[j].ambColor);
else
{
if (hasColorJ)
lightSum.convertA(varray->GetColor(j, i));
else
lightSum.a=0.0f;
}
//accumulate light alphas
int amask = xfregs.colChans[j].alpha.GetFullLightMask();
for (int l = 0; l < 8; l++)
{
if (amask&1)
{
float val = DoLighting(GetLight(l), xfregs.colChans[j].alpha, TempPos, TempNormal);
float a = lightColors[l].a * val;
lightSum.a += a;
}
amask >>= 1;
}
}
else
{
lightSum.a=1.0f;
}
chans[j] = lightSum * material;
chans[j].clamp();
}
//////////////////////////////////////////////////////////////////////////
//Step 3: Generate texture coordinates!
//////////////////////////////////////////////////////////////////////////
Vec3 TempUVs[8];
for (int j = 0; j < xfregs.numTexGens; j++)
{
Vec3 t;
switch (xfregs.texcoords[j].texmtxinfo.sourcerow) {
case XF_SRCGEOM_INROW: t = OrigPos; break; //HACK WTFF???
case XF_SRCNORMAL_INROW: t = OrigNormal; break;
case XF_SRCCOLORS_INROW: break; //set uvs to something?
case XF_SRCBINORMAL_T_INROW: t=Vec3(0,0,0);break;
case XF_SRCBINORMAL_B_INROW: t=Vec3(0,0,0);break;
default:
{
int c = xfregs.texcoords[j].texmtxinfo.sourcerow - XF_SRCTEX0_INROW;
bool hasTCC = (components & (VertexLoader::VB_HAS_UV0 << c)) != 0;
if (c >= 0 && c <= 7 && hasTCC)
{
const DecUV &uv = varray->GetUV(c, i);
t = Vec3(uv.u, uv.v, 1);
}
}
}
Vec3 out,out2;
switch (xfregs.texcoords[j].texmtxinfo.texgentype)
{
case XF_TEXGEN_COLOR_STRGBC0:
out = Vec3(chans[0].r*255, chans[0].g*255, 1)/255.0f;
break;
case XF_TEXGEN_COLOR_STRGBC1:
out = Vec3(chans[1].r*255, chans[1].g*255, 1)/255.0f; //FIX: take color1 instead
break;
case XF_TEXGEN_REGULAR:
if (xfregs.texcoords[j].texmtxinfo.projection)
VtxMulMtx43(out, t, m_pTexMatrix[j]);
else
VtxMulMtx42(out, t, m_pTexMatrix[j]);
break;
}
if (xfregs.texcoords[j].postmtxinfo.normalize)
out.normalize();
int postMatrix = xfregs.texcoords[j].postmtxinfo.index;
float *pmtx = ((float*)xfmem) + 0x500 + postMatrix * 4; //CHECK
//multiply with postmatrix
VtxMulMtx43(TempUVs[j], out, pmtx);
}
//////////////////////////////////////////////////////////////////////////
//Step 4: Output the vertex!
//////////////////////////////////////////////////////////////////////////
for (int j = 0; j < 2; j++)
chans[j].convertToD3DColor(vbuffer[i].colors[j]);
vbuffer[i].pos = TempPos;
vbuffer[i].normal = TempNormal;
for (int j = 0; j < (int)bpmem.genMode.numtexgens; j++)
{
vbuffer[i].uv[j].u = TempUVs[j].x;
vbuffer[i].uv[j].v = TempUVs[j].y;
vbuffer[i].uv[j].w = TempUVs[j].z;
}
}
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <fvec.h>
#include "Common.h"
#include "Profiler.h"
// #include "Globals.h"
#include "Vec3.h"
#include "TransformEngine.h"
#include "VertexManager.h"
#include "VertexLoader.h"
#include "BPStructs.h"
#include "XFStructs.h"
#include "Utils.h"
#include "RGBAFloat.h"
float *CTransformEngine::m_pPosMatrix;
float *CTransformEngine::m_pNormalMatrix;
float *CTransformEngine::m_pTexMatrix[8];
float *CTransformEngine::m_pTexPostMatrix[8];
const Light *GetLight(int i)
{
return (const Light *)(xfmem + XFMEM_LIGHTS) + i;
}
float DoLighting(const Light *light, const LitChannel &chan, const Vec3 &pos, const Vec3 &normal)
{
float val;
if (chan.attnfunc == 0 || chan.attnfunc == 2) //no attn
{
Vec3 ldir = (Vec3(light->dpos) - pos);
val = ldir.normalized() * normal;
}
else
{
float aattn = 0;
float d;
float mul = 1.0f;
if (chan.attnfunc == 3)
{
Vec3 ldir = (Vec3(light->dpos) - pos);
d = ldir.length();
Vec3 ldirNorm = ldir / d; //normalize
float l = ldirNorm * normal;
aattn = Vec3(light->ddir) * ldirNorm;
mul = l;
}
else if (chan.attnfunc == 1)
{
d = aattn = Vec3(light->shalfangle) * normal;
mul = (Vec3(light->sdir) * normal > 0) ? (normal * Vec3(light->shalfangle)) : 0;
if (mul < 0)
mul = 0;
}
float spot = (light->a2*aattn*aattn + light->a1*aattn + light->a0);
float dist = 1.0f/(light->k2*d*d + light->k1*d + light->k0);
if (spot<0)
spot=0;
val = mul * spot * dist;
}
if (val < 0 && chan.diffusefunc == 2) // clamp
val = 0;
return val;
}
void VtxMulMtx43T(Vec3 &out, const Vec3 &in, const float pMatrix[12])
{
out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2] + 1 * pMatrix[3];
out.y = in.x * pMatrix[4] + in.y * pMatrix[5] + in.z * pMatrix[6] + 1 * pMatrix[7];
out.z = in.x * pMatrix[8] + in.y * pMatrix[9] + in.z * pMatrix[10] + 1 * pMatrix[11];
}
void VtxMulMtx43(Vec3 &out, const Vec3 &in, const float pMatrix[12])
{
VtxMulMtx43T(out,in,pMatrix);
//TODO(XK): Turns out that SSE2 computations are slower... Can anyone do
// anything about it?
/*
F32vec4 a(in.x, in.y, in.z, 1), b(pMatrix[0], pMatrix[1], pMatrix[2], pMatrix[3]);
out.x = add_horizontal(a * b);
b[0] = pMatrix[4]; b[1] = pMatrix[5]; b[2] = pMatrix[6]; b[3] = pMatrix[7];
out.y = add_horizontal(a * b);
b[0] = pMatrix[8]; b[1] = pMatrix[9]; b[2] = pMatrix[10]; b[3] = pMatrix[11];
out.z = add_horizontal(a * b);
*/
}
void VtxMulMtx42(Vec3 &out, const Vec3 &in, const float pMatrix[8])
{
out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2] + 1 * pMatrix[3];
out.y = in.x * pMatrix[4] + in.y * pMatrix[5] + in.z * pMatrix[6] + 1 * pMatrix[7];
}
void VtxMulMtx33(Vec3 &out, const Vec3 &in, const float pMatrix[9])
{
out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2];
out.y = in.x * pMatrix[3] + in.y * pMatrix[4] + in.z * pMatrix[5];
out.z = in.x * pMatrix[6] + in.y * pMatrix[7] + in.z * pMatrix[8];
}
void CTransformEngine::TransformVertices(int _numVertices, const DecodedVArray *varray, D3DVertex *vbuffer)
{
if (vbuffer == 0)
{
MessageBox(0,"TransformVertices : vbuffer == 0","WTF",0);
}
DVSTARTPROFILE();
RGBAFloat lightColors[8];
RGBAFloat lightVals[8];
RGBAFloat chans[2];
u32 components = varray->GetComponents();
// TODO: only for active lights
for (int i=0; i<8; i++)
lightColors[i].convert_GC(GetLight(i)->color);
for (int i=0; i<_numVertices; i++)
{
//////////////////////////////////////////////////////////////////////////
//Step 1: xform position and normal
//////////////////////////////////////////////////////////////////////////
Vec3 OrigPos = varray->GetPos(i);
if (varray->hasPosMatIdx)
{
int index = varray->GetPosMtxInd(i);
SetPosNormalMatrix(
(float*)xfmem + (index & 63) * 4, //CHECK
(float*)xfmem + 0x400 + 3 * (index & 31)); //CHECK
}
for (int j = 0; j < 8; j++)
{
if (varray->hasTexMatIdx[j])
{
float *flipmem = (float *)xfmem;
int index = varray->GetTexMtxInd(j, i);
SetTexMatrix(j, flipmem + index * 4);
}
}
Vec3 TempPos;
// m_pPosMatrix can be switched out, through matrixindex vertex components
VtxMulMtx43(TempPos, OrigPos, m_pPosMatrix);
Vec3 TempNormal;
Vec3 OrigNormal;
if (varray->hasNrm)
{
OrigNormal = varray->GetNormal(0, i);
VtxMulMtx33(TempNormal, OrigNormal, m_pNormalMatrix);
TempNormal.normalize();
}
else
{
OrigNormal.setZero();
TempNormal.setZero();
}
//////////////////////////////////////////////////////////////////////////
//Step 2: Light!
//////////////////////////////////////////////////////////////////////////
//find all used lights
u32 lightMask =
xfregs.colChans[0].color.GetFullLightMask() | xfregs.colChans[0].alpha.GetFullLightMask() |
xfregs.colChans[1].color.GetFullLightMask() | xfregs.colChans[1].alpha.GetFullLightMask();
float r0=0,g0=0,b0=0,a0=0;
//go through them and compute the lit colors
//Sum lighting for both two color channels if they're active
for (int j = 0; j < (int)bpmem.genMode.numcolchans; j++)
{
RGBAFloat material;
RGBAFloat lightSum(0,0,0,0);
bool hasColorJ = (components & (VertexLoader::VB_HAS_COL0 << j)) != 0;
//get basic material color from appropriate sources (this would compile nicely!:)
if (xfregs.colChans[j].color.matsource == GX_SRC_REG)
material.convertRGB_GC(xfregs.colChans[j].matColor);
else
{
if (hasColorJ)
material.convertRGB(varray->GetColor(j, i));
else
material.r=material.g=material.b=1.0f;
}
if (xfregs.colChans[j].alpha.matsource == GX_SRC_REG)
material.convertA_GC(xfregs.colChans[j].matColor);
else
{
if (hasColorJ)
material.convertA(varray->GetColor(j, i));
else
material.a=1.0f;
}
//combine together the light values from the lights that affect the color
if (xfregs.colChans[j].color.enablelighting)
{
//choose ambient source and start our lightsum accumulator with its value..
if (xfregs.colChans[j].color.ambsource == GX_SRC_REG)
lightSum.convertRGB_GC(xfregs.colChans[j].ambColor); //ambient
else
{
if (hasColorJ)
lightSum.convertRGB(varray->GetColor(j, i));
else
{
lightSum.r=0.0f;lightSum.g=0.0f;lightSum.b=0.0f;
}
}
//accumulate light colors
int cmask = xfregs.colChans[j].color.GetFullLightMask();
for (int l=0; l<8; l++)
{
if (cmask&1)
{
float val = DoLighting(GetLight(l), xfregs.colChans[j].color, TempPos, TempNormal);
float r = lightColors[l].r * val;
float g = lightColors[l].g * val;
float b = lightColors[l].b * val;
lightSum.r += r;
lightSum.g += g;
lightSum.b += b;
}
cmask >>= 1;
}
}
else
{
lightSum.r = lightSum.g = lightSum.b = 1.0f;
}
//combine together the light values from the lights that affect alpha (should be rare)
if (xfregs.colChans[j].alpha.enablelighting)
{
//choose ambient source..
if (xfregs.colChans[j].alpha.ambsource==GX_SRC_REG)
lightSum.convertA_GC(xfregs.colChans[j].ambColor);
else
{
if (hasColorJ)
lightSum.convertA(varray->GetColor(j, i));
else
lightSum.a=0.0f;
}
//accumulate light alphas
int amask = xfregs.colChans[j].alpha.GetFullLightMask();
for (int l = 0; l < 8; l++)
{
if (amask&1)
{
float val = DoLighting(GetLight(l), xfregs.colChans[j].alpha, TempPos, TempNormal);
float a = lightColors[l].a * val;
lightSum.a += a;
}
amask >>= 1;
}
}
else
{
lightSum.a=1.0f;
}
chans[j] = lightSum * material;
chans[j].clamp();
}
//////////////////////////////////////////////////////////////////////////
//Step 3: Generate texture coordinates!
//////////////////////////////////////////////////////////////////////////
Vec3 TempUVs[8];
for (int j = 0; j < xfregs.numTexGens; j++)
{
Vec3 t;
switch (xfregs.texcoords[j].texmtxinfo.sourcerow) {
case XF_SRCGEOM_INROW: t = OrigPos; break; //HACK WTFF???
case XF_SRCNORMAL_INROW: t = OrigNormal; break;
case XF_SRCCOLORS_INROW: break; //set uvs to something?
case XF_SRCBINORMAL_T_INROW: t=Vec3(0,0,0);break;
case XF_SRCBINORMAL_B_INROW: t=Vec3(0,0,0);break;
default:
{
int c = xfregs.texcoords[j].texmtxinfo.sourcerow - XF_SRCTEX0_INROW;
bool hasTCC = (components & (VertexLoader::VB_HAS_UV0 << c)) != 0;
if (c >= 0 && c <= 7 && hasTCC)
{
const DecUV &uv = varray->GetUV(c, i);
t = Vec3(uv.u, uv.v, 1);
}
}
}
Vec3 out,out2;
switch (xfregs.texcoords[j].texmtxinfo.texgentype)
{
case XF_TEXGEN_COLOR_STRGBC0:
out = Vec3(chans[0].r*255, chans[0].g*255, 1)/255.0f;
break;
case XF_TEXGEN_COLOR_STRGBC1:
out = Vec3(chans[1].r*255, chans[1].g*255, 1)/255.0f; //FIX: take color1 instead
break;
case XF_TEXGEN_REGULAR:
if (xfregs.texcoords[j].texmtxinfo.projection)
VtxMulMtx43(out, t, m_pTexMatrix[j]);
else
VtxMulMtx42(out, t, m_pTexMatrix[j]);
break;
}
if (xfregs.texcoords[j].postmtxinfo.normalize)
out.normalize();
int postMatrix = xfregs.texcoords[j].postmtxinfo.index;
float *pmtx = ((float*)xfmem) + 0x500 + postMatrix * 4; //CHECK
//multiply with postmatrix
VtxMulMtx43(TempUVs[j], out, pmtx);
}
//////////////////////////////////////////////////////////////////////////
//Step 4: Output the vertex!
//////////////////////////////////////////////////////////////////////////
for (int j = 0; j < 2; j++)
chans[j].convertToD3DColor(vbuffer[i].colors[j]);
vbuffer[i].pos = TempPos;
vbuffer[i].normal = TempNormal;
for (int j = 0; j < (int)bpmem.genMode.numtexgens; j++)
{
vbuffer[i].uv[j].u = TempUVs[j].x;
vbuffer[i].uv[j].v = TempUVs[j].y;
vbuffer[i].uv[j].w = TempUVs[j].z;
}
}
}

View File

@ -1,45 +1,45 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifdef _WIN32
#include "W32Util/Misc.h"
#endif
#include "Common.h"
#include <assert.h>
int frameCount;
// Message handler for about box.
LRESULT CALLBACK AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM /*lParam*/)
{
switch (message)
{
case WM_INITDIALOG:
W32Util::CenterWindow(hDlg);
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifdef _WIN32
#include "W32Util/Misc.h"
#endif
#include "Common.h"
#include <assert.h>
int frameCount;
// Message handler for about box.
LRESULT CALLBACK AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM /*lParam*/)
{
switch (message)
{
case WM_INITDIALOG:
W32Util::CenterWindow(hDlg);
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}

View File

@ -1,363 +1,363 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <stdio.h>
#include "x64Emitter.h"
#include "Common.h"
#include "LookUpTables.h"
#include "Profiler.h"
#include "VertexManager.h"
#include "VertexLoader.h"
#include "XFStructs.h"
#include "BPStructs.h"
#include "DataReader.h"
#include "DecodedVArray.h"
//these don't need to be saved
float posScale;
float tcScale[8];
int tcElements[8];
int tcFormat[8];
int colElements[2];
float tcScaleU[8];
float tcScaleV[8];
int tcIndex;
int colIndex;
u32 addr;
DecodedVArray *varray;
int ComputeVertexSize(u32 comp)
{
int size = 0;
if (comp & VertexLoader::VB_HAS_POSMTXIDX)
size += 4;
if (comp & (VertexLoader::VB_HAS_TEXMTXIDX0 | VertexLoader::VB_HAS_TEXMTXIDX1 | VertexLoader::VB_HAS_TEXMTXIDX2 | VertexLoader::VB_HAS_TEXMTXIDX3))
size += 4;
if (comp & (VertexLoader::VB_HAS_TEXMTXIDX4 | VertexLoader::VB_HAS_TEXMTXIDX5 | VertexLoader::VB_HAS_TEXMTXIDX6 | VertexLoader::VB_HAS_TEXMTXIDX7))
size += 4;
if (comp & VertexLoader::VB_HAS_NRM0)
size += 4;
if (comp & (VertexLoader::VB_HAS_NRM1 | VertexLoader::VB_HAS_NRM2)) //combine into single check for speed
size += 8;
if (comp & VertexLoader::VB_HAS_COL0)
size += 4;
if (comp & VertexLoader::VB_HAS_COL1)
size += 4;
for (int i = 0; i < 8; i++)
if (comp & (VertexLoader::VB_HAS_UV0 << i))
size += 8;
return size;
}
void VertexLoader::SetVArray(DecodedVArray *_varray)
{
varray = _varray;
}
#include "VertexLoader_MtxIndex.h"
#include "VertexLoader_Position.h"
#include "VertexLoader_Normal.h"
#include "VertexLoader_Color.h"
#include "VertexLoader_TextCoord.h"
VertexLoader g_VertexLoaders[8];
TVtxDesc VertexLoader::m_VtxDesc;
bool VertexLoader::m_DescDirty = true;
VertexLoader::VertexLoader()
{
m_numPipelineStates = 0;
m_VertexSize = 0;
m_AttrDirty = true;
VertexLoader_Normal::Init();
}
VertexLoader::~VertexLoader()
{
}
void VertexLoader::Setup()
{
if (!m_AttrDirty && !m_DescDirty)
return;
DVSTARTPROFILE();
// Reset pipeline
m_VertexSize = 0;
m_numPipelineStates = 0;
m_components = 0;
// Position Matrix Index
if (m_VtxDesc.PosMatIdx)
{
m_PipelineStates[m_numPipelineStates++] = PosMtx_ReadDirect_UByte;
m_VertexSize += 1;
m_components |= VB_HAS_POSMTXIDX;
}
// Texture matrix indices
if (m_VtxDesc.Tex0MatIdx) {m_components|=VB_HAS_TEXMTXIDX0; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
if (m_VtxDesc.Tex1MatIdx) {m_components|=VB_HAS_TEXMTXIDX1; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
if (m_VtxDesc.Tex2MatIdx) {m_components|=VB_HAS_TEXMTXIDX2; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
if (m_VtxDesc.Tex3MatIdx) {m_components|=VB_HAS_TEXMTXIDX3; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
if (m_VtxDesc.Tex4MatIdx) {m_components|=VB_HAS_TEXMTXIDX4; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
if (m_VtxDesc.Tex5MatIdx) {m_components|=VB_HAS_TEXMTXIDX5; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
if (m_VtxDesc.Tex6MatIdx) {m_components|=VB_HAS_TEXMTXIDX6; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
if (m_VtxDesc.Tex7MatIdx) {m_components|=VB_HAS_TEXMTXIDX7; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
// Position
switch (m_VtxDesc.Position)
{
case NOT_PRESENT: {_assert_msg_(0,"Vertex descriptor without position!","WTF?");} break;
case DIRECT:
{
int SizePro = 0;
switch (m_VtxAttr.PosFormat)
{
case FORMAT_UBYTE: SizePro=1; WriteCall(Pos_ReadDirect_UByte); break;
case FORMAT_BYTE: SizePro=1; WriteCall(Pos_ReadDirect_Byte); break;
case FORMAT_USHORT: SizePro=2; WriteCall(Pos_ReadDirect_UShort); break;
case FORMAT_SHORT: SizePro=2; WriteCall(Pos_ReadDirect_Short); break;
case FORMAT_FLOAT: SizePro=4; WriteCall(Pos_ReadDirect_Float); break;
default: _assert_(0); break;
}
if (m_VtxAttr.PosElements == 1)
m_VertexSize += SizePro * 3;
else
m_VertexSize += SizePro * 2;
}
break;
case INDEX8:
m_VertexSize+=1;
switch (m_VtxAttr.PosFormat)
{
case FORMAT_UBYTE: WriteCall(Pos_ReadIndex8_UByte); break; //WTF?
case FORMAT_BYTE: WriteCall(Pos_ReadIndex8_Byte); break;
case FORMAT_USHORT: WriteCall(Pos_ReadIndex8_UShort); break;
case FORMAT_SHORT: WriteCall(Pos_ReadIndex8_Short); break;
case FORMAT_FLOAT: WriteCall(Pos_ReadIndex8_Float); break;
default: _assert_(0); break;
}
break;
case INDEX16:
m_VertexSize+=2;
switch (m_VtxAttr.PosFormat)
{
case FORMAT_UBYTE: WriteCall(Pos_ReadIndex16_UByte); break;
case FORMAT_BYTE: WriteCall(Pos_ReadIndex16_Byte); break;
case FORMAT_USHORT: WriteCall(Pos_ReadIndex16_UShort); break;
case FORMAT_SHORT: WriteCall(Pos_ReadIndex16_Short); break;
case FORMAT_FLOAT: WriteCall(Pos_ReadIndex16_Float); break;
default: _assert_(0); break;
}
break;
}
// Normals
if (m_VtxDesc.Normal != NOT_PRESENT)
{
VertexLoader_Normal::index3 = m_VtxAttr.NormalIndex3 ? true : false;
unsigned int uSize = VertexLoader_Normal::GetSize(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements);
TPipelineFunction pFunc = VertexLoader_Normal::GetFunction(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements);
if (pFunc == 0)
{
char temp[256];
sprintf(temp,"%i %i %i", m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements);
MessageBox(0,"VertexLoader_Normal::GetFunction returned zero!",temp,0);
}
WriteCall(pFunc);
m_VertexSize += uSize;
int m_numNormals = (m_VtxAttr.NormalElements == 1) ? NRM_THREE : NRM_ONE;
m_components |= VB_HAS_NRM0;
if (m_numNormals == NRM_THREE)
m_components |= VB_HAS_NRM1 | VB_HAS_NRM2;
}
// Colors
int col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1};
for (int i = 0; i < 2; i++)
SetupColor(i,col[i], m_VtxAttr.color[i].Comp, m_VtxAttr.color[i].Elements);
// TextureCoord
// Since m_VtxDesc.Text7Coord is broken across a 32 bit word boundary, retrieve its value manually.
// If we didn't do this, the vertex format would be read as one bit offset from where it should be, making
// 01 become 00, and 10/11 become 01
int tc[8] = {
m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord,
m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, (m_VtxDesc.Hex >> 31) & 3
};
for (int i = 0; i < 8; i++)
SetupTexCoord(i, tc[i],
m_VtxAttr.texCoord[i].Format,
m_VtxAttr.texCoord[i].Elements,
m_VtxAttr.texCoord[i].Frac);
}
void VertexLoader::SetupColor(int num, int mode, int format, int elements)
{
m_components |= VB_HAS_COL0 << num;
switch (mode)
{
case NOT_PRESENT:
m_components &= ~(VB_HAS_COL0 << num);
break;
case DIRECT:
switch (format)
{
case FORMAT_16B_565: m_VertexSize+=2; WriteCall(Color_ReadDirect_16b_565); break;
case FORMAT_24B_888: m_VertexSize+=3; WriteCall(Color_ReadDirect_24b_888); break;
case FORMAT_32B_888x: m_VertexSize+=4; WriteCall(Color_ReadDirect_32b_888x); break;
case FORMAT_16B_4444: m_VertexSize+=2; WriteCall(Color_ReadDirect_16b_4444); break;
case FORMAT_24B_6666: m_VertexSize+=3; WriteCall(Color_ReadDirect_24b_6666); break;
case FORMAT_32B_8888: m_VertexSize+=4; WriteCall(Color_ReadDirect_32b_8888); break;
default: _assert_(0); break;
}
break;
case INDEX8:
switch (format)
{
case FORMAT_16B_565: WriteCall(Color_ReadIndex8_16b_565); break;
case FORMAT_24B_888: WriteCall(Color_ReadIndex8_24b_888); break;
case FORMAT_32B_888x: WriteCall(Color_ReadIndex8_32b_888x); break;
case FORMAT_16B_4444: WriteCall(Color_ReadIndex8_16b_4444); break;
case FORMAT_24B_6666: WriteCall(Color_ReadIndex8_24b_6666); break;
case FORMAT_32B_8888: WriteCall(Color_ReadIndex8_32b_8888); break;
default: _assert_(0); break;
}
m_VertexSize+=1;
break;
case INDEX16:
switch (format)
{
case FORMAT_16B_565: WriteCall(Color_ReadIndex16_16b_565); break;
case FORMAT_24B_888: WriteCall(Color_ReadIndex16_24b_888); break;
case FORMAT_32B_888x: WriteCall(Color_ReadIndex16_32b_888x); break;
case FORMAT_16B_4444: WriteCall(Color_ReadIndex16_16b_4444); break;
case FORMAT_24B_6666: WriteCall(Color_ReadIndex16_24b_6666); break;
case FORMAT_32B_8888: WriteCall(Color_ReadIndex16_32b_8888); break;
default: _assert_(0); break;
}
m_VertexSize+=2;
break;
}
}
void VertexLoader::SetupTexCoord(int num, int mode, int format, int elements, int _iFrac)
{
m_components |= VB_HAS_UV0 << num;
switch (mode)
{
case NOT_PRESENT:
m_components &= ~(VB_HAS_UV0 << num);
break;
case DIRECT:
{
int sizePro=0;
switch (format)
{
case FORMAT_UBYTE: sizePro = 1; WriteCall(TexCoord_ReadDirect_UByte); break;
case FORMAT_BYTE: sizePro = 1; WriteCall(TexCoord_ReadDirect_Byte); break;
case FORMAT_USHORT: sizePro = 2; WriteCall(TexCoord_ReadDirect_UShort); break;
case FORMAT_SHORT: sizePro = 2; WriteCall(TexCoord_ReadDirect_Short); break;
case FORMAT_FLOAT: sizePro = 4; WriteCall(TexCoord_ReadDirect_Float); break;
default: _assert_(0); break;
}
m_VertexSize += sizePro * (elements ? 2 : 1);
}
break;
case INDEX8:
switch (format)
{
case FORMAT_UBYTE: WriteCall(TexCoord_ReadIndex8_UByte); break;
case FORMAT_BYTE: WriteCall(TexCoord_ReadIndex8_Byte); break;
case FORMAT_USHORT: WriteCall(TexCoord_ReadIndex8_UShort); break;
case FORMAT_SHORT: WriteCall(TexCoord_ReadIndex8_Short); break;
case FORMAT_FLOAT: WriteCall(TexCoord_ReadIndex8_Float); break;
default: _assert_(0); break;
}
m_VertexSize+=1;
break;
case INDEX16:
switch (format)
{
case FORMAT_UBYTE: WriteCall(TexCoord_ReadIndex16_UByte); break;
case FORMAT_BYTE: WriteCall(TexCoord_ReadIndex16_Byte); break;
case FORMAT_USHORT: WriteCall(TexCoord_ReadIndex16_UShort); break;
case FORMAT_SHORT: WriteCall(TexCoord_ReadIndex16_Short); break;
case FORMAT_FLOAT: WriteCall(TexCoord_ReadIndex16_Float); break;
default: _assert_(0);
}
m_VertexSize+=2;
break;
}
}
void VertexLoader::WriteCall(TPipelineFunction func)
{
m_PipelineStates[m_numPipelineStates++] = func;
}
using namespace Gen;
void VertexLoader::PrepareRun()
{
posScale = shiftLookup[m_VtxAttr.PosFrac];
for (int i = 0; i < 8; i++)
{
tcScaleU[i] = shiftLookup[m_VtxAttr.texCoord[i].Frac];
tcScaleV[i] = shiftLookup[m_VtxAttr.texCoord[i].Frac];
tcElements[i] = m_VtxAttr.texCoord[i].Elements;
tcFormat[i] = m_VtxAttr.texCoord[i].Format;
}
for (int i = 0; i < 2; i++)
colElements[i] = m_VtxAttr.color[i].Elements;
varray->SetComponents(m_components);
}
void VertexLoader::RunVertices(int count)
{
DVSTARTPROFILE();
for (int v = 0; v < count; v++)
{
tcIndex = 0;
colIndex = 0;
s_texmtxread = 0;
for (int i = 0; i < m_numPipelineStates; i++)
{
m_PipelineStates[i](&m_VtxAttr);
}
varray->Next();
}
/*
This is not the bottleneck ATM, so compiling etc doesn't really help.
At least not when all we do is compile it to a list of function calls.
Should help more when we inline, but this requires the new vertex format.
Maybe later, and with smarter caching.
if (count)
{
this->m_counter = count;
((void (*)())((void*)&m_compiledCode[0]))();
}*/
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <stdio.h>
#include "x64Emitter.h"
#include "Common.h"
#include "LookUpTables.h"
#include "Profiler.h"
#include "VertexManager.h"
#include "VertexLoader.h"
#include "XFStructs.h"
#include "BPStructs.h"
#include "DataReader.h"
#include "DecodedVArray.h"
//these don't need to be saved
float posScale;
float tcScale[8];
int tcElements[8];
int tcFormat[8];
int colElements[2];
float tcScaleU[8];
float tcScaleV[8];
int tcIndex;
int colIndex;
u32 addr;
DecodedVArray *varray;
int ComputeVertexSize(u32 comp)
{
int size = 0;
if (comp & VertexLoader::VB_HAS_POSMTXIDX)
size += 4;
if (comp & (VertexLoader::VB_HAS_TEXMTXIDX0 | VertexLoader::VB_HAS_TEXMTXIDX1 | VertexLoader::VB_HAS_TEXMTXIDX2 | VertexLoader::VB_HAS_TEXMTXIDX3))
size += 4;
if (comp & (VertexLoader::VB_HAS_TEXMTXIDX4 | VertexLoader::VB_HAS_TEXMTXIDX5 | VertexLoader::VB_HAS_TEXMTXIDX6 | VertexLoader::VB_HAS_TEXMTXIDX7))
size += 4;
if (comp & VertexLoader::VB_HAS_NRM0)
size += 4;
if (comp & (VertexLoader::VB_HAS_NRM1 | VertexLoader::VB_HAS_NRM2)) //combine into single check for speed
size += 8;
if (comp & VertexLoader::VB_HAS_COL0)
size += 4;
if (comp & VertexLoader::VB_HAS_COL1)
size += 4;
for (int i = 0; i < 8; i++)
if (comp & (VertexLoader::VB_HAS_UV0 << i))
size += 8;
return size;
}
void VertexLoader::SetVArray(DecodedVArray *_varray)
{
varray = _varray;
}
#include "VertexLoader_MtxIndex.h"
#include "VertexLoader_Position.h"
#include "VertexLoader_Normal.h"
#include "VertexLoader_Color.h"
#include "VertexLoader_TextCoord.h"
VertexLoader g_VertexLoaders[8];
TVtxDesc VertexLoader::m_VtxDesc;
bool VertexLoader::m_DescDirty = true;
VertexLoader::VertexLoader()
{
m_numPipelineStates = 0;
m_VertexSize = 0;
m_AttrDirty = true;
VertexLoader_Normal::Init();
}
VertexLoader::~VertexLoader()
{
}
void VertexLoader::Setup()
{
if (!m_AttrDirty && !m_DescDirty)
return;
DVSTARTPROFILE();
// Reset pipeline
m_VertexSize = 0;
m_numPipelineStates = 0;
m_components = 0;
// Position Matrix Index
if (m_VtxDesc.PosMatIdx)
{
m_PipelineStates[m_numPipelineStates++] = PosMtx_ReadDirect_UByte;
m_VertexSize += 1;
m_components |= VB_HAS_POSMTXIDX;
}
// Texture matrix indices
if (m_VtxDesc.Tex0MatIdx) {m_components|=VB_HAS_TEXMTXIDX0; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
if (m_VtxDesc.Tex1MatIdx) {m_components|=VB_HAS_TEXMTXIDX1; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
if (m_VtxDesc.Tex2MatIdx) {m_components|=VB_HAS_TEXMTXIDX2; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
if (m_VtxDesc.Tex3MatIdx) {m_components|=VB_HAS_TEXMTXIDX3; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
if (m_VtxDesc.Tex4MatIdx) {m_components|=VB_HAS_TEXMTXIDX4; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
if (m_VtxDesc.Tex5MatIdx) {m_components|=VB_HAS_TEXMTXIDX5; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
if (m_VtxDesc.Tex6MatIdx) {m_components|=VB_HAS_TEXMTXIDX6; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
if (m_VtxDesc.Tex7MatIdx) {m_components|=VB_HAS_TEXMTXIDX7; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
// Position
switch (m_VtxDesc.Position)
{
case NOT_PRESENT: {_assert_msg_(0,"Vertex descriptor without position!","WTF?");} break;
case DIRECT:
{
int SizePro = 0;
switch (m_VtxAttr.PosFormat)
{
case FORMAT_UBYTE: SizePro=1; WriteCall(Pos_ReadDirect_UByte); break;
case FORMAT_BYTE: SizePro=1; WriteCall(Pos_ReadDirect_Byte); break;
case FORMAT_USHORT: SizePro=2; WriteCall(Pos_ReadDirect_UShort); break;
case FORMAT_SHORT: SizePro=2; WriteCall(Pos_ReadDirect_Short); break;
case FORMAT_FLOAT: SizePro=4; WriteCall(Pos_ReadDirect_Float); break;
default: _assert_(0); break;
}
if (m_VtxAttr.PosElements == 1)
m_VertexSize += SizePro * 3;
else
m_VertexSize += SizePro * 2;
}
break;
case INDEX8:
m_VertexSize+=1;
switch (m_VtxAttr.PosFormat)
{
case FORMAT_UBYTE: WriteCall(Pos_ReadIndex8_UByte); break; //WTF?
case FORMAT_BYTE: WriteCall(Pos_ReadIndex8_Byte); break;
case FORMAT_USHORT: WriteCall(Pos_ReadIndex8_UShort); break;
case FORMAT_SHORT: WriteCall(Pos_ReadIndex8_Short); break;
case FORMAT_FLOAT: WriteCall(Pos_ReadIndex8_Float); break;
default: _assert_(0); break;
}
break;
case INDEX16:
m_VertexSize+=2;
switch (m_VtxAttr.PosFormat)
{
case FORMAT_UBYTE: WriteCall(Pos_ReadIndex16_UByte); break;
case FORMAT_BYTE: WriteCall(Pos_ReadIndex16_Byte); break;
case FORMAT_USHORT: WriteCall(Pos_ReadIndex16_UShort); break;
case FORMAT_SHORT: WriteCall(Pos_ReadIndex16_Short); break;
case FORMAT_FLOAT: WriteCall(Pos_ReadIndex16_Float); break;
default: _assert_(0); break;
}
break;
}
// Normals
if (m_VtxDesc.Normal != NOT_PRESENT)
{
VertexLoader_Normal::index3 = m_VtxAttr.NormalIndex3 ? true : false;
unsigned int uSize = VertexLoader_Normal::GetSize(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements);
TPipelineFunction pFunc = VertexLoader_Normal::GetFunction(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements);
if (pFunc == 0)
{
char temp[256];
sprintf(temp,"%i %i %i", m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements);
MessageBox(0,"VertexLoader_Normal::GetFunction returned zero!",temp,0);
}
WriteCall(pFunc);
m_VertexSize += uSize;
int m_numNormals = (m_VtxAttr.NormalElements == 1) ? NRM_THREE : NRM_ONE;
m_components |= VB_HAS_NRM0;
if (m_numNormals == NRM_THREE)
m_components |= VB_HAS_NRM1 | VB_HAS_NRM2;
}
// Colors
int col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1};
for (int i = 0; i < 2; i++)
SetupColor(i,col[i], m_VtxAttr.color[i].Comp, m_VtxAttr.color[i].Elements);
// TextureCoord
// Since m_VtxDesc.Text7Coord is broken across a 32 bit word boundary, retrieve its value manually.
// If we didn't do this, the vertex format would be read as one bit offset from where it should be, making
// 01 become 00, and 10/11 become 01
int tc[8] = {
m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord,
m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, (m_VtxDesc.Hex >> 31) & 3
};
for (int i = 0; i < 8; i++)
SetupTexCoord(i, tc[i],
m_VtxAttr.texCoord[i].Format,
m_VtxAttr.texCoord[i].Elements,
m_VtxAttr.texCoord[i].Frac);
}
void VertexLoader::SetupColor(int num, int mode, int format, int elements)
{
m_components |= VB_HAS_COL0 << num;
switch (mode)
{
case NOT_PRESENT:
m_components &= ~(VB_HAS_COL0 << num);
break;
case DIRECT:
switch (format)
{
case FORMAT_16B_565: m_VertexSize+=2; WriteCall(Color_ReadDirect_16b_565); break;
case FORMAT_24B_888: m_VertexSize+=3; WriteCall(Color_ReadDirect_24b_888); break;
case FORMAT_32B_888x: m_VertexSize+=4; WriteCall(Color_ReadDirect_32b_888x); break;
case FORMAT_16B_4444: m_VertexSize+=2; WriteCall(Color_ReadDirect_16b_4444); break;
case FORMAT_24B_6666: m_VertexSize+=3; WriteCall(Color_ReadDirect_24b_6666); break;
case FORMAT_32B_8888: m_VertexSize+=4; WriteCall(Color_ReadDirect_32b_8888); break;
default: _assert_(0); break;
}
break;
case INDEX8:
switch (format)
{
case FORMAT_16B_565: WriteCall(Color_ReadIndex8_16b_565); break;
case FORMAT_24B_888: WriteCall(Color_ReadIndex8_24b_888); break;
case FORMAT_32B_888x: WriteCall(Color_ReadIndex8_32b_888x); break;
case FORMAT_16B_4444: WriteCall(Color_ReadIndex8_16b_4444); break;
case FORMAT_24B_6666: WriteCall(Color_ReadIndex8_24b_6666); break;
case FORMAT_32B_8888: WriteCall(Color_ReadIndex8_32b_8888); break;
default: _assert_(0); break;
}
m_VertexSize+=1;
break;
case INDEX16:
switch (format)
{
case FORMAT_16B_565: WriteCall(Color_ReadIndex16_16b_565); break;
case FORMAT_24B_888: WriteCall(Color_ReadIndex16_24b_888); break;
case FORMAT_32B_888x: WriteCall(Color_ReadIndex16_32b_888x); break;
case FORMAT_16B_4444: WriteCall(Color_ReadIndex16_16b_4444); break;
case FORMAT_24B_6666: WriteCall(Color_ReadIndex16_24b_6666); break;
case FORMAT_32B_8888: WriteCall(Color_ReadIndex16_32b_8888); break;
default: _assert_(0); break;
}
m_VertexSize+=2;
break;
}
}
void VertexLoader::SetupTexCoord(int num, int mode, int format, int elements, int _iFrac)
{
m_components |= VB_HAS_UV0 << num;
switch (mode)
{
case NOT_PRESENT:
m_components &= ~(VB_HAS_UV0 << num);
break;
case DIRECT:
{
int sizePro=0;
switch (format)
{
case FORMAT_UBYTE: sizePro = 1; WriteCall(TexCoord_ReadDirect_UByte); break;
case FORMAT_BYTE: sizePro = 1; WriteCall(TexCoord_ReadDirect_Byte); break;
case FORMAT_USHORT: sizePro = 2; WriteCall(TexCoord_ReadDirect_UShort); break;
case FORMAT_SHORT: sizePro = 2; WriteCall(TexCoord_ReadDirect_Short); break;
case FORMAT_FLOAT: sizePro = 4; WriteCall(TexCoord_ReadDirect_Float); break;
default: _assert_(0); break;
}
m_VertexSize += sizePro * (elements ? 2 : 1);
}
break;
case INDEX8:
switch (format)
{
case FORMAT_UBYTE: WriteCall(TexCoord_ReadIndex8_UByte); break;
case FORMAT_BYTE: WriteCall(TexCoord_ReadIndex8_Byte); break;
case FORMAT_USHORT: WriteCall(TexCoord_ReadIndex8_UShort); break;
case FORMAT_SHORT: WriteCall(TexCoord_ReadIndex8_Short); break;
case FORMAT_FLOAT: WriteCall(TexCoord_ReadIndex8_Float); break;
default: _assert_(0); break;
}
m_VertexSize+=1;
break;
case INDEX16:
switch (format)
{
case FORMAT_UBYTE: WriteCall(TexCoord_ReadIndex16_UByte); break;
case FORMAT_BYTE: WriteCall(TexCoord_ReadIndex16_Byte); break;
case FORMAT_USHORT: WriteCall(TexCoord_ReadIndex16_UShort); break;
case FORMAT_SHORT: WriteCall(TexCoord_ReadIndex16_Short); break;
case FORMAT_FLOAT: WriteCall(TexCoord_ReadIndex16_Float); break;
default: _assert_(0);
}
m_VertexSize+=2;
break;
}
}
void VertexLoader::WriteCall(TPipelineFunction func)
{
m_PipelineStates[m_numPipelineStates++] = func;
}
using namespace Gen;
void VertexLoader::PrepareRun()
{
posScale = shiftLookup[m_VtxAttr.PosFrac];
for (int i = 0; i < 8; i++)
{
tcScaleU[i] = shiftLookup[m_VtxAttr.texCoord[i].Frac];
tcScaleV[i] = shiftLookup[m_VtxAttr.texCoord[i].Frac];
tcElements[i] = m_VtxAttr.texCoord[i].Elements;
tcFormat[i] = m_VtxAttr.texCoord[i].Format;
}
for (int i = 0; i < 2; i++)
colElements[i] = m_VtxAttr.color[i].Elements;
varray->SetComponents(m_components);
}
void VertexLoader::RunVertices(int count)
{
DVSTARTPROFILE();
for (int v = 0; v < count; v++)
{
tcIndex = 0;
colIndex = 0;
s_texmtxread = 0;
for (int i = 0; i < m_numPipelineStates; i++)
{
m_PipelineStates[i](&m_VtxAttr);
}
varray->Next();
}
/*
This is not the bottleneck ATM, so compiling etc doesn't really help.
At least not when all we do is compile it to a list of function calls.
Should help more when we inline, but this requires the new vertex format.
Maybe later, and with smarter caching.
if (count)
{
this->m_counter = count;
((void (*)())((void*)&m_compiledCode[0]))();
}*/
}

View File

@ -1,488 +1,488 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "main.h"
#include "Utils.h"
#include "DecodedVArray.h"
#include "VertexLoader.h"
#include "VertexLoader_Normal.h"
u8 VertexLoader_Normal::m_sizeTable[NUM_NRM_TYPE][NUM_NRM_FORMAT][NUM_NRM_ELEMENTS];
TPipelineFunction VertexLoader_Normal::m_funcTable[NUM_NRM_TYPE][NUM_NRM_FORMAT][NUM_NRM_ELEMENTS];
bool VertexLoader_Normal::index3;
// __________________________________________________________________________________________________
// Init
//
void VertexLoader_Normal::Init(void)
{
// size table
m_sizeTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT] = 3;
m_sizeTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT] = 3;
m_sizeTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT] = 6;
m_sizeTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT] = 6;
m_sizeTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT] = 12;
m_sizeTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT3] = 9;
m_sizeTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT3] = 9;
m_sizeTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT3] = 18;
m_sizeTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT3] = 18;
m_sizeTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT3] = 36;
m_sizeTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT] = 1;
m_sizeTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT] = 1;
m_sizeTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT] = 1;
m_sizeTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT] = 1;
m_sizeTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT] = 1;
m_sizeTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT3] = 3;
m_sizeTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT3] = 3;
m_sizeTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT3] = 3;
m_sizeTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT3] = 3;
m_sizeTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT3] = 3;
m_sizeTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT] = 2;
m_sizeTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT] = 2;
m_sizeTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT] = 2;
m_sizeTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT] = 2;
m_sizeTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT] = 2;
m_sizeTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT3] = 6;
m_sizeTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT3] = 6;
m_sizeTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT3] = 6;
m_sizeTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT3] = 6;
m_sizeTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT3] = 6;
// function table
m_funcTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT] = Normal_DirectByte; //HACK
m_funcTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT] = Normal_DirectByte;
m_funcTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT] = Normal_DirectShort; //HACK
m_funcTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT] = Normal_DirectShort;
m_funcTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT] = Normal_DirectFloat;
m_funcTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT3] = Normal_DirectByte3; //HACK
m_funcTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT3] = Normal_DirectByte3;
m_funcTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT3] = Normal_DirectShort3; //HACK
m_funcTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT3] = Normal_DirectShort3;
m_funcTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT3] = Normal_DirectFloat3;
m_funcTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT] = Normal_Index8_Byte; //HACK
m_funcTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT] = Normal_Index8_Byte;
m_funcTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT] = Normal_Index8_Short; //HACK
m_funcTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT] = Normal_Index8_Short;
m_funcTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT] = Normal_Index8_Float;
m_funcTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT3] = Normal_Index8_Byte3; //HACK
m_funcTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT3] = Normal_Index8_Byte3;
m_funcTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT3] = Normal_Index8_Short3; //HACK
m_funcTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT3] = Normal_Index8_Short3;
m_funcTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT3] = Normal_Index8_Float3;
m_funcTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT] = Normal_Index16_Byte; //HACK
m_funcTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT] = Normal_Index16_Byte;
m_funcTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT] = Normal_Index16_Short; //HACK
m_funcTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT] = Normal_Index16_Short;
m_funcTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT] = Normal_Index16_Float;
m_funcTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT3] = Normal_Index16_Byte3; //HACK
m_funcTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT3] = Normal_Index16_Byte3;
m_funcTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT3] = Normal_Index16_Short3; //HACK
m_funcTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT3] = Normal_Index16_Short3;
m_funcTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT3] = Normal_Index16_Float3;
}
// __________________________________________________________________________________________________
// GetSize
//
unsigned int
VertexLoader_Normal::GetSize(unsigned int _type, unsigned int _format, unsigned int _elements)
{
return m_sizeTable[_type][_format][_elements];
}
// __________________________________________________________________________________________________
// GetFunction
//
TPipelineFunction
VertexLoader_Normal::GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements)
{
TPipelineFunction pFunc = m_funcTable[_type][_format][_elements];
return pFunc;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// --- Direct ---
//
/////////////////////////////////////////////////////////////////////////////////////////////////////
// __________________________________________________________________________________________________
// Normal_DirectByte
//
void LOADERDECL
VertexLoader_Normal::Normal_DirectByte(const void* _p)
{
varray->SetNormalX(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
varray->SetNormalY(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
varray->SetNormalZ(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
}
// __________________________________________________________________________________________________
// Normal_DirectShort
//
void LOADERDECL
VertexLoader_Normal::Normal_DirectShort(const void* _p)
{
varray->SetNormalX(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
varray->SetNormalY(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
varray->SetNormalZ(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
}
// __________________________________________________________________________________________________
// Normal_DirectFloat
//
void LOADERDECL
VertexLoader_Normal::Normal_DirectFloat(const void* _p)
{
varray->SetNormalX(0, DataReadF32());
varray->SetNormalY(0, DataReadF32());
varray->SetNormalZ(0, DataReadF32());
}
// __________________________________________________________________________________________________
// Normal_DirectByte3
//
void LOADERDECL
VertexLoader_Normal::Normal_DirectByte3(const void* _p)
{
for (int i=0; i<3; i++)
{
varray->SetNormalX(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
varray->SetNormalY(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
varray->SetNormalZ(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
}
}
// __________________________________________________________________________________________________
// Normal_DirectShort3
//
void LOADERDECL
VertexLoader_Normal::Normal_DirectShort3(const void* _p)
{
for (int i=0; i<3; i++)
{
varray->SetNormalX(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
varray->SetNormalY(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
varray->SetNormalZ(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
}
}
// __________________________________________________________________________________________________
// Normal_DirectFloat3
//
void LOADERDECL
VertexLoader_Normal::Normal_DirectFloat3(const void* _p)
{
for (int i=0; i<3; i++)
{
varray->SetNormalX(i, DataReadF32());
varray->SetNormalY(i, DataReadF32());
varray->SetNormalZ(i, DataReadF32());
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// --- Index8 ---
//
/////////////////////////////////////////////////////////////////////////////////////////////////////
// __________________________________________________________________________________________________
// Normal_Index8_Byte
//
void LOADERDECL
VertexLoader_Normal::Normal_Index8_Byte(const void* _p)
{
u8 Index = DataReadU8();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
varray->SetNormalX(0, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
varray->SetNormalY(0, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
varray->SetNormalZ(0, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
}
// __________________________________________________________________________________________________
// Normal_Index8_Short
//
void LOADERDECL
VertexLoader_Normal::Normal_Index8_Short(const void* _p)
{
u8 Index = DataReadU8();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
varray->SetNormalX(0, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
varray->SetNormalY(0, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
varray->SetNormalZ(0, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
}
// __________________________________________________________________________________________________
// Normal_Index8_Float
//
void LOADERDECL
VertexLoader_Normal::Normal_Index8_Float(const void* _p)
{
u8 Index = DataReadU8();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
varray->SetNormalX(0, Memory_Read_Float(iAddress));
varray->SetNormalY(0, Memory_Read_Float(iAddress+4));
varray->SetNormalZ(0, Memory_Read_Float(iAddress+8));
}
// __________________________________________________________________________________________________
// Normal_Index8_Byte3
//
void LOADERDECL
VertexLoader_Normal::Normal_Index8_Byte3(const void* _p)
{
if (index3)
{
for (int i=0; i<3; i++)
{
u8 Index = DataReadU8();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
}
}
else
{
u8 Index = DataReadU8();
for (int i=0; i<3; i++)
{
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
}
}
}
// __________________________________________________________________________________________________
// Normal_Index8_Short3
//
void LOADERDECL
VertexLoader_Normal::Normal_Index8_Short3(const void* _p)
{
if (index3)
{
for (int i=0; i<3; i++)
{
u8 Index = DataReadU8();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
}
}
else
{
u8 Index = DataReadU8();
for (int i=0; i<3; i++)
{
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
}
}
}
// __________________________________________________________________________________________________
// Normal_Index8_Float3
//
void LOADERDECL
VertexLoader_Normal::Normal_Index8_Float3(const void* _p)
{
if (index3)
{
for (int i=0; i<3; i++)
{
u8 Index = DataReadU8();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
varray->SetNormalX(i, Memory_Read_Float(iAddress));
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
}
}
else
{
u8 Index = DataReadU8();
for (int i=0; i<3; i++)
{
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
varray->SetNormalX(i, Memory_Read_Float(iAddress));
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// --- Index16 ---
//
/////////////////////////////////////////////////////////////////////////////////////////////////////
// __________________________________________________________________________________________________
// Normal_Index16_Byte
//
void LOADERDECL
VertexLoader_Normal::Normal_Index16_Byte(const void* _p)
{
u16 Index = DataReadU16();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
varray->SetNormalX(0, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
varray->SetNormalY(0, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
varray->SetNormalZ(0, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
}
// __________________________________________________________________________________________________
// Normal_Index16_Short
//
void LOADERDECL
VertexLoader_Normal::Normal_Index16_Short(const void* _p)
{
u16 Index = DataReadU16();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
varray->SetNormalX(0, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
varray->SetNormalY(0, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
varray->SetNormalZ(0, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
}
// __________________________________________________________________________________________________
// Normal_Index8_Float
//
void LOADERDECL
VertexLoader_Normal::Normal_Index16_Float(const void* _p)
{
u16 Index = DataReadU16();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
varray->SetNormalX(0, Memory_Read_Float(iAddress));
varray->SetNormalY(0, Memory_Read_Float(iAddress+4));
varray->SetNormalZ(0, Memory_Read_Float(iAddress+8));
}
// __________________________________________________________________________________________________
// Normal_Index16_Byte3
//
void LOADERDECL
VertexLoader_Normal::Normal_Index16_Byte3(const void* _p)
{
if (index3)
{
for (int i=0; i<3; i++)
{
u16 Index = DataReadU16();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
}
}
else
{
u16 Index = DataReadU16();
for (int i=0; i<3; i++)
{
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
}
}
}
// __________________________________________________________________________________________________
// Normal_Index16_Short3
//
void LOADERDECL
VertexLoader_Normal::Normal_Index16_Short3(const void* _p)
{
if (index3)
{
for (int i=0; i<3; i++)
{
u16 Index = DataReadU16();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
}
}
else
{
u16 Index = DataReadU16();
for (int i=0; i<3; i++)
{
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
}
}
}
// __________________________________________________________________________________________________
// Normal_Index16_Float3
//
void LOADERDECL
VertexLoader_Normal::Normal_Index16_Float3(const void* _p)
{
if (index3)
{
for (int i=0; i<3; i++)
{
u16 Index = DataReadU16();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
varray->SetNormalX(i, Memory_Read_Float(iAddress ));
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
}
}
else
{
u16 Index = DataReadU16();
for (int i=0; i<3; i++)
{
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
varray->SetNormalX(i, Memory_Read_Float(iAddress ));
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
}
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "main.h"
#include "Utils.h"
#include "DecodedVArray.h"
#include "VertexLoader.h"
#include "VertexLoader_Normal.h"
u8 VertexLoader_Normal::m_sizeTable[NUM_NRM_TYPE][NUM_NRM_FORMAT][NUM_NRM_ELEMENTS];
TPipelineFunction VertexLoader_Normal::m_funcTable[NUM_NRM_TYPE][NUM_NRM_FORMAT][NUM_NRM_ELEMENTS];
bool VertexLoader_Normal::index3;
// __________________________________________________________________________________________________
// Init
//
void VertexLoader_Normal::Init(void)
{
// size table
m_sizeTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT] = 3;
m_sizeTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT] = 3;
m_sizeTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT] = 6;
m_sizeTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT] = 6;
m_sizeTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT] = 12;
m_sizeTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT3] = 9;
m_sizeTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT3] = 9;
m_sizeTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT3] = 18;
m_sizeTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT3] = 18;
m_sizeTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT3] = 36;
m_sizeTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT] = 1;
m_sizeTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT] = 1;
m_sizeTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT] = 1;
m_sizeTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT] = 1;
m_sizeTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT] = 1;
m_sizeTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT3] = 3;
m_sizeTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT3] = 3;
m_sizeTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT3] = 3;
m_sizeTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT3] = 3;
m_sizeTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT3] = 3;
m_sizeTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT] = 2;
m_sizeTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT] = 2;
m_sizeTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT] = 2;
m_sizeTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT] = 2;
m_sizeTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT] = 2;
m_sizeTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT3] = 6;
m_sizeTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT3] = 6;
m_sizeTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT3] = 6;
m_sizeTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT3] = 6;
m_sizeTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT3] = 6;
// function table
m_funcTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT] = Normal_DirectByte; //HACK
m_funcTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT] = Normal_DirectByte;
m_funcTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT] = Normal_DirectShort; //HACK
m_funcTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT] = Normal_DirectShort;
m_funcTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT] = Normal_DirectFloat;
m_funcTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT3] = Normal_DirectByte3; //HACK
m_funcTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT3] = Normal_DirectByte3;
m_funcTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT3] = Normal_DirectShort3; //HACK
m_funcTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT3] = Normal_DirectShort3;
m_funcTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT3] = Normal_DirectFloat3;
m_funcTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT] = Normal_Index8_Byte; //HACK
m_funcTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT] = Normal_Index8_Byte;
m_funcTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT] = Normal_Index8_Short; //HACK
m_funcTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT] = Normal_Index8_Short;
m_funcTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT] = Normal_Index8_Float;
m_funcTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT3] = Normal_Index8_Byte3; //HACK
m_funcTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT3] = Normal_Index8_Byte3;
m_funcTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT3] = Normal_Index8_Short3; //HACK
m_funcTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT3] = Normal_Index8_Short3;
m_funcTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT3] = Normal_Index8_Float3;
m_funcTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT] = Normal_Index16_Byte; //HACK
m_funcTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT] = Normal_Index16_Byte;
m_funcTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT] = Normal_Index16_Short; //HACK
m_funcTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT] = Normal_Index16_Short;
m_funcTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT] = Normal_Index16_Float;
m_funcTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT3] = Normal_Index16_Byte3; //HACK
m_funcTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT3] = Normal_Index16_Byte3;
m_funcTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT3] = Normal_Index16_Short3; //HACK
m_funcTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT3] = Normal_Index16_Short3;
m_funcTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT3] = Normal_Index16_Float3;
}
// __________________________________________________________________________________________________
// GetSize
//
unsigned int
VertexLoader_Normal::GetSize(unsigned int _type, unsigned int _format, unsigned int _elements)
{
return m_sizeTable[_type][_format][_elements];
}
// __________________________________________________________________________________________________
// GetFunction
//
TPipelineFunction
VertexLoader_Normal::GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements)
{
TPipelineFunction pFunc = m_funcTable[_type][_format][_elements];
return pFunc;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// --- Direct ---
//
/////////////////////////////////////////////////////////////////////////////////////////////////////
// __________________________________________________________________________________________________
// Normal_DirectByte
//
void LOADERDECL
VertexLoader_Normal::Normal_DirectByte(const void* _p)
{
varray->SetNormalX(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
varray->SetNormalY(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
varray->SetNormalZ(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
}
// __________________________________________________________________________________________________
// Normal_DirectShort
//
void LOADERDECL
VertexLoader_Normal::Normal_DirectShort(const void* _p)
{
varray->SetNormalX(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
varray->SetNormalY(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
varray->SetNormalZ(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
}
// __________________________________________________________________________________________________
// Normal_DirectFloat
//
void LOADERDECL
VertexLoader_Normal::Normal_DirectFloat(const void* _p)
{
varray->SetNormalX(0, DataReadF32());
varray->SetNormalY(0, DataReadF32());
varray->SetNormalZ(0, DataReadF32());
}
// __________________________________________________________________________________________________
// Normal_DirectByte3
//
void LOADERDECL
VertexLoader_Normal::Normal_DirectByte3(const void* _p)
{
for (int i=0; i<3; i++)
{
varray->SetNormalX(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
varray->SetNormalY(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
varray->SetNormalZ(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
}
}
// __________________________________________________________________________________________________
// Normal_DirectShort3
//
void LOADERDECL
VertexLoader_Normal::Normal_DirectShort3(const void* _p)
{
for (int i=0; i<3; i++)
{
varray->SetNormalX(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
varray->SetNormalY(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
varray->SetNormalZ(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
}
}
// __________________________________________________________________________________________________
// Normal_DirectFloat3
//
void LOADERDECL
VertexLoader_Normal::Normal_DirectFloat3(const void* _p)
{
for (int i=0; i<3; i++)
{
varray->SetNormalX(i, DataReadF32());
varray->SetNormalY(i, DataReadF32());
varray->SetNormalZ(i, DataReadF32());
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// --- Index8 ---
//
/////////////////////////////////////////////////////////////////////////////////////////////////////
// __________________________________________________________________________________________________
// Normal_Index8_Byte
//
void LOADERDECL
VertexLoader_Normal::Normal_Index8_Byte(const void* _p)
{
u8 Index = DataReadU8();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
varray->SetNormalX(0, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
varray->SetNormalY(0, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
varray->SetNormalZ(0, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
}
// __________________________________________________________________________________________________
// Normal_Index8_Short
//
void LOADERDECL
VertexLoader_Normal::Normal_Index8_Short(const void* _p)
{
u8 Index = DataReadU8();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
varray->SetNormalX(0, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
varray->SetNormalY(0, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
varray->SetNormalZ(0, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
}
// __________________________________________________________________________________________________
// Normal_Index8_Float
//
void LOADERDECL
VertexLoader_Normal::Normal_Index8_Float(const void* _p)
{
u8 Index = DataReadU8();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
varray->SetNormalX(0, Memory_Read_Float(iAddress));
varray->SetNormalY(0, Memory_Read_Float(iAddress+4));
varray->SetNormalZ(0, Memory_Read_Float(iAddress+8));
}
// __________________________________________________________________________________________________
// Normal_Index8_Byte3
//
void LOADERDECL
VertexLoader_Normal::Normal_Index8_Byte3(const void* _p)
{
if (index3)
{
for (int i=0; i<3; i++)
{
u8 Index = DataReadU8();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
}
}
else
{
u8 Index = DataReadU8();
for (int i=0; i<3; i++)
{
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
}
}
}
// __________________________________________________________________________________________________
// Normal_Index8_Short3
//
void LOADERDECL
VertexLoader_Normal::Normal_Index8_Short3(const void* _p)
{
if (index3)
{
for (int i=0; i<3; i++)
{
u8 Index = DataReadU8();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
}
}
else
{
u8 Index = DataReadU8();
for (int i=0; i<3; i++)
{
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
}
}
}
// __________________________________________________________________________________________________
// Normal_Index8_Float3
//
void LOADERDECL
VertexLoader_Normal::Normal_Index8_Float3(const void* _p)
{
if (index3)
{
for (int i=0; i<3; i++)
{
u8 Index = DataReadU8();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
varray->SetNormalX(i, Memory_Read_Float(iAddress));
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
}
}
else
{
u8 Index = DataReadU8();
for (int i=0; i<3; i++)
{
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
varray->SetNormalX(i, Memory_Read_Float(iAddress));
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// --- Index16 ---
//
/////////////////////////////////////////////////////////////////////////////////////////////////////
// __________________________________________________________________________________________________
// Normal_Index16_Byte
//
void LOADERDECL
VertexLoader_Normal::Normal_Index16_Byte(const void* _p)
{
u16 Index = DataReadU16();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
varray->SetNormalX(0, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
varray->SetNormalY(0, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
varray->SetNormalZ(0, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
}
// __________________________________________________________________________________________________
// Normal_Index16_Short
//
void LOADERDECL
VertexLoader_Normal::Normal_Index16_Short(const void* _p)
{
u16 Index = DataReadU16();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
varray->SetNormalX(0, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
varray->SetNormalY(0, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
varray->SetNormalZ(0, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
}
// __________________________________________________________________________________________________
// Normal_Index8_Float
//
void LOADERDECL
VertexLoader_Normal::Normal_Index16_Float(const void* _p)
{
u16 Index = DataReadU16();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
varray->SetNormalX(0, Memory_Read_Float(iAddress));
varray->SetNormalY(0, Memory_Read_Float(iAddress+4));
varray->SetNormalZ(0, Memory_Read_Float(iAddress+8));
}
// __________________________________________________________________________________________________
// Normal_Index16_Byte3
//
void LOADERDECL
VertexLoader_Normal::Normal_Index16_Byte3(const void* _p)
{
if (index3)
{
for (int i=0; i<3; i++)
{
u16 Index = DataReadU16();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
}
}
else
{
u16 Index = DataReadU16();
for (int i=0; i<3; i++)
{
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
}
}
}
// __________________________________________________________________________________________________
// Normal_Index16_Short3
//
void LOADERDECL
VertexLoader_Normal::Normal_Index16_Short3(const void* _p)
{
if (index3)
{
for (int i=0; i<3; i++)
{
u16 Index = DataReadU16();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
}
}
else
{
u16 Index = DataReadU16();
for (int i=0; i<3; i++)
{
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
}
}
}
// __________________________________________________________________________________________________
// Normal_Index16_Float3
//
void LOADERDECL
VertexLoader_Normal::Normal_Index16_Float3(const void* _p)
{
if (index3)
{
for (int i=0; i<3; i++)
{
u16 Index = DataReadU16();
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
varray->SetNormalX(i, Memory_Read_Float(iAddress ));
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
}
}
else
{
u16 Index = DataReadU16();
for (int i=0; i<3; i++)
{
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
varray->SetNormalX(i, Memory_Read_Float(iAddress ));
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
}
}
}

View File

@ -1,234 +1,234 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "D3DBase.h"
#include "Statistics.h"
#include "Profiler.h"
#include "VertexManager.h"
#include "OpcodeDecoding.h"
#include "TransformEngine.h"
#include "IndexGenerator.h"
#include "BPStructs.h"
#include "XFStructs.h"
#include "ShaderManager.h"
#include "Utils.h"
using namespace D3D;
namespace VertexManager
{
static IndexGenerator indexGen;
static Collection collection;
static LPDIRECT3DVERTEXDECLARATION9 vDecl;
static D3DVertex *fakeVBuffer;
static u16 *fakeIBuffer;
#define MAXVBUFFERSIZE 65536*3
#define MAXIBUFFERSIZE 65536*3
const D3DVERTEXELEMENT9 decl[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
{ 0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
{ 0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1 },
{ 0, 32+12*0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
{ 0, 32+12*1, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
{ 0, 32+12*2, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2 },
{ 0, 32+12*3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3 },
{ 0, 32+12*4, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4 },
{ 0, 32+12*5, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 5 },
{ 0, 32+12*6, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 6 },
{ 0, 32+12*7, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 7 },
D3DDECL_END()
};
bool Init()
{
collection = C_NOTHING;
fakeVBuffer = new D3DVertex[65536];
fakeIBuffer = new u16[65536];
CreateDeviceObjects();
return true;
}
void Shutdown()
{
DestroyDeviceObjects();
delete [] fakeVBuffer;
delete [] fakeIBuffer;
}
void CreateDeviceObjects()
{
HRESULT hr;
if (FAILED(hr = D3D::dev->CreateVertexDeclaration(decl, &vDecl)))
{
MessageBox(0,"Failed to create vertex declaration","sdfsd",0);
return;
}
}
void BeginFrame()
{
D3D::dev->SetVertexDeclaration(vDecl);
//D3D::dev->SetStreamSource(0,vBuffer,0,sizeof(D3DVertex));
}
void DestroyDeviceObjects()
{
if (vDecl)
vDecl->Release();
vDecl = 0;
}
void AddIndices(int _primitive, int _numVertices)
{
switch(_primitive) {
case GX_DRAW_QUADS: indexGen.AddQuads(_numVertices); return;
case GX_DRAW_TRIANGLES: indexGen.AddList(_numVertices); return;
case GX_DRAW_TRIANGLE_STRIP: indexGen.AddStrip(_numVertices); return;
case GX_DRAW_TRIANGLE_FAN: indexGen.AddFan(_numVertices); return;
case GX_DRAW_LINE_STRIP: indexGen.AddLineStrip(_numVertices); return;
case GX_DRAW_LINES: indexGen.AddLineList(_numVertices); return;
case GX_DRAW_POINTS: indexGen.AddPointList(_numVertices); return;
}
}
const Collection collectionTypeLUT[8] =
{
C_TRIANGLES,//quads
C_NOTHING, //nothing
C_TRIANGLES,//triangles
C_TRIANGLES,//strip
C_TRIANGLES,//fan
C_LINES, //lines
C_LINES, //linestrip
C_POINTS //guess :P
};
D3DVertex *vbufferwrite;
void AddVertices(int _primitive, int _numVertices, const DecodedVArray *varray)
{
if (_numVertices <= 0) //This check is pretty stupid...
return;
Collection type = collectionTypeLUT[_primitive];
if (type == C_NOTHING)
return;
DVSTARTPROFILE();
_assert_msg_(type != C_NOTHING, "type == C_NOTHING!!", "WTF");
if (indexGen.GetNumVerts() > 1000) // TODO(ector): Raise?
Flush();
ADDSTAT(stats.thisFrame.numPrims, _numVertices);
if (collection != type)
{
//We are NOT collecting the right type.
Flush();
collection = type;
u16 *ptr = 0;
if (type != C_POINTS)
{
ptr = fakeIBuffer;
indexGen.Start((unsigned short*)ptr);
AddIndices(_primitive,_numVertices);
}
vbufferwrite = fakeVBuffer;
if (_numVertices >= MAXVBUFFERSIZE)
MessageBox(NULL, "To much vertices for the buffer", "Video.DLL", MB_OK);
CTransformEngine::TransformVertices(_numVertices, varray, vbufferwrite);
}
else //We are collecting the right type, keep going
{
_assert_msg_(vbufferwrite!=0, "collecting: vbufferwrite == 0!","WTF");
INCSTAT(stats.thisFrame.numPrimitiveJoins);
//Success, keep adding to unlocked buffer
int last = indexGen.GetNumVerts();
AddIndices(_primitive, _numVertices);
if (_numVertices >= MAXVBUFFERSIZE)
MessageBox(NULL, "Too many vertices for the buffer", "Video.DLL", MB_OK);
CTransformEngine::TransformVertices(_numVertices, varray, vbufferwrite + last);
}
}
const D3DPRIMITIVETYPE pts[3] =
{
D3DPT_POINTLIST, //DUMMY
D3DPT_TRIANGLELIST,
D3DPT_LINELIST,
};
void Flush()
{
DVSTARTPROFILE();
if (collection != C_NOTHING)
{
ActivateTextures();
int numVertices = indexGen.GetNumVerts();
if (numVertices != 0)
{
PShaderCache::SetShader(); // TODO(ector): only do this if shader has changed
VShaderCache::SetShader(); // TODO(ector): only do this if shader has changed
if (collection != C_POINTS)
{
int numPrimitives = indexGen.GetNumPrims();
D3D::dev->DrawIndexedPrimitiveUP(pts[(int)collection],
0,
numVertices,
numPrimitives,
fakeIBuffer,
D3DFMT_INDEX16,
fakeVBuffer,
sizeof(D3DVertex));
}
else
{
D3D::dev->SetIndices(0);
// D3D::dev->DrawPrimitiveUP(D3DPT_POINTLIST,
// numVertices,
// fakeVBuffer,
// sizeof(D3DVertex));
Renderer::DrawPrimitiveUP( D3DPT_POINTLIST, numVertices, fakeVBuffer, sizeof(D3DVertex) );
}
}
collection = C_NOTHING;
}
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "D3DBase.h"
#include "Statistics.h"
#include "Profiler.h"
#include "VertexManager.h"
#include "OpcodeDecoding.h"
#include "TransformEngine.h"
#include "IndexGenerator.h"
#include "BPStructs.h"
#include "XFStructs.h"
#include "ShaderManager.h"
#include "Utils.h"
using namespace D3D;
namespace VertexManager
{
static IndexGenerator indexGen;
static Collection collection;
static LPDIRECT3DVERTEXDECLARATION9 vDecl;
static D3DVertex *fakeVBuffer;
static u16 *fakeIBuffer;
#define MAXVBUFFERSIZE 65536*3
#define MAXIBUFFERSIZE 65536*3
const D3DVERTEXELEMENT9 decl[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
{ 0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
{ 0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1 },
{ 0, 32+12*0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
{ 0, 32+12*1, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
{ 0, 32+12*2, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2 },
{ 0, 32+12*3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3 },
{ 0, 32+12*4, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4 },
{ 0, 32+12*5, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 5 },
{ 0, 32+12*6, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 6 },
{ 0, 32+12*7, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 7 },
D3DDECL_END()
};
bool Init()
{
collection = C_NOTHING;
fakeVBuffer = new D3DVertex[65536];
fakeIBuffer = new u16[65536];
CreateDeviceObjects();
return true;
}
void Shutdown()
{
DestroyDeviceObjects();
delete [] fakeVBuffer;
delete [] fakeIBuffer;
}
void CreateDeviceObjects()
{
HRESULT hr;
if (FAILED(hr = D3D::dev->CreateVertexDeclaration(decl, &vDecl)))
{
MessageBox(0,"Failed to create vertex declaration","sdfsd",0);
return;
}
}
void BeginFrame()
{
D3D::dev->SetVertexDeclaration(vDecl);
//D3D::dev->SetStreamSource(0,vBuffer,0,sizeof(D3DVertex));
}
void DestroyDeviceObjects()
{
if (vDecl)
vDecl->Release();
vDecl = 0;
}
void AddIndices(int _primitive, int _numVertices)
{
switch(_primitive) {
case GX_DRAW_QUADS: indexGen.AddQuads(_numVertices); return;
case GX_DRAW_TRIANGLES: indexGen.AddList(_numVertices); return;
case GX_DRAW_TRIANGLE_STRIP: indexGen.AddStrip(_numVertices); return;
case GX_DRAW_TRIANGLE_FAN: indexGen.AddFan(_numVertices); return;
case GX_DRAW_LINE_STRIP: indexGen.AddLineStrip(_numVertices); return;
case GX_DRAW_LINES: indexGen.AddLineList(_numVertices); return;
case GX_DRAW_POINTS: indexGen.AddPointList(_numVertices); return;
}
}
const Collection collectionTypeLUT[8] =
{
C_TRIANGLES,//quads
C_NOTHING, //nothing
C_TRIANGLES,//triangles
C_TRIANGLES,//strip
C_TRIANGLES,//fan
C_LINES, //lines
C_LINES, //linestrip
C_POINTS //guess :P
};
D3DVertex *vbufferwrite;
void AddVertices(int _primitive, int _numVertices, const DecodedVArray *varray)
{
if (_numVertices <= 0) //This check is pretty stupid...
return;
Collection type = collectionTypeLUT[_primitive];
if (type == C_NOTHING)
return;
DVSTARTPROFILE();
_assert_msg_(type != C_NOTHING, "type == C_NOTHING!!", "WTF");
if (indexGen.GetNumVerts() > 1000) // TODO(ector): Raise?
Flush();
ADDSTAT(stats.thisFrame.numPrims, _numVertices);
if (collection != type)
{
//We are NOT collecting the right type.
Flush();
collection = type;
u16 *ptr = 0;
if (type != C_POINTS)
{
ptr = fakeIBuffer;
indexGen.Start((unsigned short*)ptr);
AddIndices(_primitive,_numVertices);
}
vbufferwrite = fakeVBuffer;
if (_numVertices >= MAXVBUFFERSIZE)
MessageBox(NULL, "To much vertices for the buffer", "Video.DLL", MB_OK);
CTransformEngine::TransformVertices(_numVertices, varray, vbufferwrite);
}
else //We are collecting the right type, keep going
{
_assert_msg_(vbufferwrite!=0, "collecting: vbufferwrite == 0!","WTF");
INCSTAT(stats.thisFrame.numPrimitiveJoins);
//Success, keep adding to unlocked buffer
int last = indexGen.GetNumVerts();
AddIndices(_primitive, _numVertices);
if (_numVertices >= MAXVBUFFERSIZE)
MessageBox(NULL, "Too many vertices for the buffer", "Video.DLL", MB_OK);
CTransformEngine::TransformVertices(_numVertices, varray, vbufferwrite + last);
}
}
const D3DPRIMITIVETYPE pts[3] =
{
D3DPT_POINTLIST, //DUMMY
D3DPT_TRIANGLELIST,
D3DPT_LINELIST,
};
void Flush()
{
DVSTARTPROFILE();
if (collection != C_NOTHING)
{
ActivateTextures();
int numVertices = indexGen.GetNumVerts();
if (numVertices != 0)
{
PShaderCache::SetShader(); // TODO(ector): only do this if shader has changed
VShaderCache::SetShader(); // TODO(ector): only do this if shader has changed
if (collection != C_POINTS)
{
int numPrimitives = indexGen.GetNumPrims();
D3D::dev->DrawIndexedPrimitiveUP(pts[(int)collection],
0,
numVertices,
numPrimitives,
fakeIBuffer,
D3DFMT_INDEX16,
fakeVBuffer,
sizeof(D3DVertex));
}
else
{
D3D::dev->SetIndices(0);
// D3D::dev->DrawPrimitiveUP(D3DPT_POINTLIST,
// numVertices,
// fakeVBuffer,
// sizeof(D3DVertex));
Renderer::DrawPrimitiveUP( D3DPT_POINTLIST, numVertices, fakeVBuffer, sizeof(D3DVertex) );
}
}
collection = C_NOTHING;
}
}
} // namespace

View File

@ -1,142 +1,142 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
#include "D3DShader.h"
#include "VertexShader.h"
#include "BPStructs.h"
static const char *genericVS = "// Generic Vertex Shader\
\n\
struct VS_INPUT {\n\
float4 pos : POSITION;\n\
float3 normal : NORMAL;\n\
float4 colors[2] : COLOR0;\n\
float3 uv[8] : TEXCOORD0;\n\
};\n\
\n\
struct VS_OUTPUT {\n\
float4 pos : POSITION;\n\
float4 colors[2] : COLOR0;\n\
//numtexgen\n\
float4 uv[5] : TEXCOORD0;\n\
};\n\
\n\
uniform matrix matWorldViewProj : register(c0);\n\
\n\
VS_OUTPUT main(const VS_INPUT input)\n\
{\n\
VS_OUTPUT output;\n\
\n\
output.pos = mul(matWorldViewProj, input.pos);\n\
// texgen\n\
for (int i=0; i<5; i++)\n\
output.uv[i] = float4(input.uv[i].xyz,1);\n\
\n\
for (int i=0; i<2; i++)\n output.colors[i] = input.colors[i];\n\
return output;\n\
}\0";
const char *GenerateVertexShader() {
return genericVS;
}
/*
char text2[65536];
#define WRITE p+=sprintf
void WriteTexgen(char *&p, int n);
const char *GenerateVertexShader()
{
int numColors = 2;
int numUV = 8;
int numTexgen = bpmem.genMode.numtexgens;
int numNormals = 3;
bool fogEnable = false;
bool hasNormal = true;
char *p = text2;
WRITE(p,"//Vertex Shader\n");
WRITE(p,"//%i uv->%i texgens, %i colors\n",numUV,numTexgen,numColors);
WRITE(p,"\n");
WRITE(p,"struct VS_INPUT {\n");
WRITE(p," float4 pos : POSITION;\n");
WRITE(p," float3 normal : NORMAL;\n");
if (numColors)
WRITE(p," float4 colors[%i] : COLOR0;\n",numColors);
if (numUV)
WRITE(p," float3 uv[%i] : TEXCOORD0;\n",numUV);
WRITE(p,"};\n");
WRITE(p,"\n");
WRITE(p,"struct VS_OUTPUT {\n");
WRITE(p," float4 pos : POSITION;\n");
WRITE(p," float4 colors[%i] : COLOR0;\n",numColors);
if (numTexgen)
WRITE(p," float4 uv[%i] : TEXCOORD0;\n",numTexgen);
if (fogEnable)
WRITE(p," float fog : FOG;\n",numTexgen);
WRITE(p,"};\n");
WRITE(p,"\n");
WRITE(p,"uniform matrix matWorldViewProj : register(c0);\n");
WRITE(p,"\n");
WRITE(p,"VS_OUTPUT main(const VS_INPUT input)\n");
WRITE(p,"{\n");
WRITE(p," VS_OUTPUT output;");
WRITE(p,"\n");
WRITE(p," output.pos = mul(matWorldViewProj, input.pos);\n");
for (int i = 0; i < (int)bpmem.genMode.numtexgens; i++)
{
//build the equation for this stage
WriteTexgen(p,i);
}
WRITE(p," for (int i=0; i<2; i++)\n output.colors[i] = input.colors[i];\n");
//WRITE(p," output.fog = 0.0f;");
WRITE(p,"return output;\n");
WRITE(p,"}\n");
WRITE(p,"\0");
// MessageBox(0,text2,0,0);
return text2;
}
/*
* xform->vertexshader ideas
*//*
void WriteTexgen(char *&p, int n)
{
WRITE(p," output.uv[%i] = float4(input.uv[%i].xy,0,input.uv[%i].z);\n",n,n,n);
}
void WriteLight(int color, int component)
{
} */
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
#include "D3DShader.h"
#include "VertexShader.h"
#include "BPStructs.h"
static const char *genericVS = "// Generic Vertex Shader\
\n\
struct VS_INPUT {\n\
float4 pos : POSITION;\n\
float3 normal : NORMAL;\n\
float4 colors[2] : COLOR0;\n\
float3 uv[8] : TEXCOORD0;\n\
};\n\
\n\
struct VS_OUTPUT {\n\
float4 pos : POSITION;\n\
float4 colors[2] : COLOR0;\n\
//numtexgen\n\
float4 uv[5] : TEXCOORD0;\n\
};\n\
\n\
uniform matrix matWorldViewProj : register(c0);\n\
\n\
VS_OUTPUT main(const VS_INPUT input)\n\
{\n\
VS_OUTPUT output;\n\
\n\
output.pos = mul(matWorldViewProj, input.pos);\n\
// texgen\n\
for (int i=0; i<5; i++)\n\
output.uv[i] = float4(input.uv[i].xyz,1);\n\
\n\
for (int i=0; i<2; i++)\n output.colors[i] = input.colors[i];\n\
return output;\n\
}\0";
const char *GenerateVertexShader() {
return genericVS;
}
/*
char text2[65536];
#define WRITE p+=sprintf
void WriteTexgen(char *&p, int n);
const char *GenerateVertexShader()
{
int numColors = 2;
int numUV = 8;
int numTexgen = bpmem.genMode.numtexgens;
int numNormals = 3;
bool fogEnable = false;
bool hasNormal = true;
char *p = text2;
WRITE(p,"//Vertex Shader\n");
WRITE(p,"//%i uv->%i texgens, %i colors\n",numUV,numTexgen,numColors);
WRITE(p,"\n");
WRITE(p,"struct VS_INPUT {\n");
WRITE(p," float4 pos : POSITION;\n");
WRITE(p," float3 normal : NORMAL;\n");
if (numColors)
WRITE(p," float4 colors[%i] : COLOR0;\n",numColors);
if (numUV)
WRITE(p," float3 uv[%i] : TEXCOORD0;\n",numUV);
WRITE(p,"};\n");
WRITE(p,"\n");
WRITE(p,"struct VS_OUTPUT {\n");
WRITE(p," float4 pos : POSITION;\n");
WRITE(p," float4 colors[%i] : COLOR0;\n",numColors);
if (numTexgen)
WRITE(p," float4 uv[%i] : TEXCOORD0;\n",numTexgen);
if (fogEnable)
WRITE(p," float fog : FOG;\n",numTexgen);
WRITE(p,"};\n");
WRITE(p,"\n");
WRITE(p,"uniform matrix matWorldViewProj : register(c0);\n");
WRITE(p,"\n");
WRITE(p,"VS_OUTPUT main(const VS_INPUT input)\n");
WRITE(p,"{\n");
WRITE(p," VS_OUTPUT output;");
WRITE(p,"\n");
WRITE(p," output.pos = mul(matWorldViewProj, input.pos);\n");
for (int i = 0; i < (int)bpmem.genMode.numtexgens; i++)
{
//build the equation for this stage
WriteTexgen(p,i);
}
WRITE(p," for (int i=0; i<2; i++)\n output.colors[i] = input.colors[i];\n");
//WRITE(p," output.fog = 0.0f;");
WRITE(p,"return output;\n");
WRITE(p,"}\n");
WRITE(p,"\0");
// MessageBox(0,text2,0,0);
return text2;
}
/*
* xform->vertexshader ideas
*//*
void WriteTexgen(char *&p, int n)
{
WRITE(p," output.uv[%i] = float4(input.uv[%i].xy,0,input.uv[%i].z);\n",n,n,n);
}
void WriteLight(int color, int component)
{
} */

View File

@ -1,29 +1,29 @@
#include <windows.h>
#include <vector>
#include "DialogManager.h"
typedef std::vector <HWND> WindowList;
WindowList dialogs;
void DialogManager::AddDlg(HWND hDialog)
{
dialogs.push_back(hDialog);
}
bool DialogManager::IsDialogMessage(LPMSG message)
{
WindowList::iterator iter;
for (iter=dialogs.begin(); iter!=dialogs.end(); iter++)
{
if (::IsDialogMessage(*iter,message))
return true;
}
return false;
}
void DialogManager::EnableAll(BOOL enable)
{
WindowList::iterator iter;
for (iter=dialogs.begin(); iter!=dialogs.end(); iter++)
EnableWindow(*iter,enable);
}
#include <windows.h>
#include <vector>
#include "DialogManager.h"
typedef std::vector <HWND> WindowList;
WindowList dialogs;
void DialogManager::AddDlg(HWND hDialog)
{
dialogs.push_back(hDialog);
}
bool DialogManager::IsDialogMessage(LPMSG message)
{
WindowList::iterator iter;
for (iter=dialogs.begin(); iter!=dialogs.end(); iter++)
{
if (::IsDialogMessage(*iter,message))
return true;
}
return false;
}
void DialogManager::EnableAll(BOOL enable)
{
WindowList::iterator iter;
for (iter=dialogs.begin(); iter!=dialogs.end(); iter++)
EnableWindow(*iter,enable);
}

View File

@ -1,148 +1,148 @@
#include <stdio.h>
#include <stdlib.h>
#include "File.h"
namespace W32Util
{
File::File()
{
fileHandle = INVALID_HANDLE_VALUE;
isOpen=false;
}
File::~File()
{
}
bool File::Open(const TCHAR *filename, eFileMode _mode)
{
mode = _mode;
//it's time to open the file
fileHandle = CreateFile(filename,
mode==FILE_READ ? GENERIC_READ : GENERIC_WRITE, //open mode
mode == FILE_READ ? FILE_SHARE_READ : NULL, //sharemode
NULL, //security
mode==FILE_READ ? OPEN_EXISTING : CREATE_ALWAYS, //create mode
FILE_ATTRIBUTE_NORMAL, //atrributes
NULL); //template
if (fileHandle == INVALID_HANDLE_VALUE)
isOpen=false;
else
isOpen=true;
return isOpen;
}
void File::Close()
{
if (isOpen)
{
//close the file and reset variables
CloseHandle(fileHandle);
fileHandle=INVALID_HANDLE_VALUE;
isOpen=false;
}
}
int File::GetSize()
{
if (!isOpen) //of course
return 0;
else
return GetFileSize(fileHandle,0);
}
int File::Write(void *data, int size) //let's do some writing
{
if (isOpen)
{
DWORD written;
WriteFile(fileHandle, data, size, &written,0);
return written; //we return the number of bytes that actually got written
}
else
{
return 0;
}
}
int File::Read(void *data, int size)
{
if (isOpen)
{
DWORD wasRead;
ReadFile(fileHandle, data, size, &wasRead,0);
return wasRead; //we return the number of bytes that actually was read
}
else
{
return 0;
}
}
int File::WR(void *data, int size)
{
if (mode==FILE_READ)
return Read(data,size);
else
return Write(data,size);
}
bool File::MagicCookie(int cookie)
{
if (mode==FILE_READ)
{
if (ReadInt()!=cookie)
{
char mojs[5],temp[256];
mojs[4]=0;
*(int*)mojs=cookie;
sprintf(temp,"W32Util::File: Magic Cookie %s is bad!",mojs);
MessageBox(0,temp,"Error reading file",MB_ICONERROR);
return false;
}
else
return true;
}
else if (mode==FILE_WRITE)
{
WriteInt(cookie);
return true;
}
return false;
}
int File::ReadInt()
{
int temp;
if (Read(&temp, sizeof(int)))
return temp;
else
return 0;
}
void File::WriteInt(int i)
{
Write(&i,sizeof(int));
}
char File::ReadChar()
{
char temp;
if (Read(&temp, sizeof(char)))
return temp;
else
return 0;
}
void File::WriteChar(char i)
{
Write(&i,sizeof(char));
}
#include <stdio.h>
#include <stdlib.h>
#include "File.h"
namespace W32Util
{
File::File()
{
fileHandle = INVALID_HANDLE_VALUE;
isOpen=false;
}
File::~File()
{
}
bool File::Open(const TCHAR *filename, eFileMode _mode)
{
mode = _mode;
//it's time to open the file
fileHandle = CreateFile(filename,
mode==FILE_READ ? GENERIC_READ : GENERIC_WRITE, //open mode
mode == FILE_READ ? FILE_SHARE_READ : NULL, //sharemode
NULL, //security
mode==FILE_READ ? OPEN_EXISTING : CREATE_ALWAYS, //create mode
FILE_ATTRIBUTE_NORMAL, //atrributes
NULL); //template
if (fileHandle == INVALID_HANDLE_VALUE)
isOpen=false;
else
isOpen=true;
return isOpen;
}
void File::Close()
{
if (isOpen)
{
//close the file and reset variables
CloseHandle(fileHandle);
fileHandle=INVALID_HANDLE_VALUE;
isOpen=false;
}
}
int File::GetSize()
{
if (!isOpen) //of course
return 0;
else
return GetFileSize(fileHandle,0);
}
int File::Write(void *data, int size) //let's do some writing
{
if (isOpen)
{
DWORD written;
WriteFile(fileHandle, data, size, &written,0);
return written; //we return the number of bytes that actually got written
}
else
{
return 0;
}
}
int File::Read(void *data, int size)
{
if (isOpen)
{
DWORD wasRead;
ReadFile(fileHandle, data, size, &wasRead,0);
return wasRead; //we return the number of bytes that actually was read
}
else
{
return 0;
}
}
int File::WR(void *data, int size)
{
if (mode==FILE_READ)
return Read(data,size);
else
return Write(data,size);
}
bool File::MagicCookie(int cookie)
{
if (mode==FILE_READ)
{
if (ReadInt()!=cookie)
{
char mojs[5],temp[256];
mojs[4]=0;
*(int*)mojs=cookie;
sprintf(temp,"W32Util::File: Magic Cookie %s is bad!",mojs);
MessageBox(0,temp,"Error reading file",MB_ICONERROR);
return false;
}
else
return true;
}
else if (mode==FILE_WRITE)
{
WriteInt(cookie);
return true;
}
return false;
}
int File::ReadInt()
{
int temp;
if (Read(&temp, sizeof(int)))
return temp;
else
return 0;
}
void File::WriteInt(int i)
{
Write(&i,sizeof(int));
}
char File::ReadChar()
{
char temp;
if (Read(&temp, sizeof(char)))
return temp;
else
return 0;
}
void File::WriteChar(char i)
{
Write(&i,sizeof(char));
}
}

View File

@ -1,102 +1,102 @@
#include <stdio.h>
#include <stdlib.h>
#include "Misc.h"
namespace W32Util
{
//shamelessly taken from http://www.catch22.org.uk/tuts/tips.asp
void CenterWindow(HWND hwnd)
{
HWND hwndParent;
RECT rect, rectP;
int width, height;
int screenwidth, screenheight;
int x, y;
//make the window relative to its parent
hwndParent = GetParent(hwnd);
if (!hwndParent)
return;
GetWindowRect(hwnd, &rect);
GetWindowRect(hwndParent, &rectP);
width = rect.right - rect.left;
height = rect.bottom - rect.top;
x = ((rectP.right-rectP.left) - width) / 2 + rectP.left;
y = ((rectP.bottom-rectP.top) - height) / 2 + rectP.top;
screenwidth = GetSystemMetrics(SM_CXSCREEN);
screenheight = GetSystemMetrics(SM_CYSCREEN);
//make sure that the dialog box never moves outside of
//the screen
if(x < 0) x = 0;
if(y < 0) y = 0;
if(x + width > screenwidth) x = screenwidth - width;
if(y + height > screenheight) y = screenheight - height;
MoveWindow(hwnd, x, y, width, height, FALSE);
}
HBITMAP CreateBitmapFromARGB(HWND someHwnd, DWORD *image, int w, int h)
{
BITMAPINFO *bitmap_header;
static char bitmapbuffer[sizeof(BITMAPINFO)+16];
memset(bitmapbuffer,0,sizeof(BITMAPINFO)+16);
bitmap_header=(BITMAPINFO *)bitmapbuffer;
bitmap_header->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmap_header->bmiHeader.biPlanes = 1;
bitmap_header->bmiHeader.biBitCount = 32;
bitmap_header->bmiHeader.biCompression = BI_RGB;
bitmap_header->bmiHeader.biWidth = w;
bitmap_header->bmiHeader.biHeight = -h;
((unsigned long *)bitmap_header->bmiColors)[0] = 0x00FF0000;
((unsigned long *)bitmap_header->bmiColors)[1] = 0x0000FF00;
((unsigned long *)bitmap_header->bmiColors)[2] = 0x000000FF;
HDC dc = GetDC(someHwnd);
HBITMAP bitmap = CreateDIBitmap(dc,&bitmap_header->bmiHeader,CBM_INIT,image,bitmap_header,DIB_RGB_COLORS);
ReleaseDC(someHwnd,dc);
return bitmap;
}
void NiceSizeFormat(size_t size, char *out)
{
char *sizes[] = {"b","KB","MB","GB","TB","PB","EB"};
int s = 0;
int frac = 0;
while (size>1024)
{
s++;
frac = (int)size & 1023;
size /= 1024;
}
float f = (float)size + ((float)frac / 1024.0f);
sprintf(out,"%3.1f %s",f,sizes[s]);
}
BOOL CopyTextToClipboard(HWND hwnd, TCHAR *text)
{
OpenClipboard(hwnd);
EmptyClipboard();
HANDLE hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (strlen(text) + 1) * sizeof(TCHAR));
if (hglbCopy == NULL)
{
CloseClipboard();
return FALSE;
}
// Lock the handle and copy the text to the buffer.
TCHAR *lptstrCopy = (TCHAR *)GlobalLock(hglbCopy);
strcpy(lptstrCopy, text);
lptstrCopy[strlen(text)] = (TCHAR) 0; // null character
GlobalUnlock(hglbCopy);
SetClipboardData(CF_TEXT,hglbCopy);
CloseClipboard();
return TRUE;
}
#include <stdio.h>
#include <stdlib.h>
#include "Misc.h"
namespace W32Util
{
//shamelessly taken from http://www.catch22.org.uk/tuts/tips.asp
void CenterWindow(HWND hwnd)
{
HWND hwndParent;
RECT rect, rectP;
int width, height;
int screenwidth, screenheight;
int x, y;
//make the window relative to its parent
hwndParent = GetParent(hwnd);
if (!hwndParent)
return;
GetWindowRect(hwnd, &rect);
GetWindowRect(hwndParent, &rectP);
width = rect.right - rect.left;
height = rect.bottom - rect.top;
x = ((rectP.right-rectP.left) - width) / 2 + rectP.left;
y = ((rectP.bottom-rectP.top) - height) / 2 + rectP.top;
screenwidth = GetSystemMetrics(SM_CXSCREEN);
screenheight = GetSystemMetrics(SM_CYSCREEN);
//make sure that the dialog box never moves outside of
//the screen
if(x < 0) x = 0;
if(y < 0) y = 0;
if(x + width > screenwidth) x = screenwidth - width;
if(y + height > screenheight) y = screenheight - height;
MoveWindow(hwnd, x, y, width, height, FALSE);
}
HBITMAP CreateBitmapFromARGB(HWND someHwnd, DWORD *image, int w, int h)
{
BITMAPINFO *bitmap_header;
static char bitmapbuffer[sizeof(BITMAPINFO)+16];
memset(bitmapbuffer,0,sizeof(BITMAPINFO)+16);
bitmap_header=(BITMAPINFO *)bitmapbuffer;
bitmap_header->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmap_header->bmiHeader.biPlanes = 1;
bitmap_header->bmiHeader.biBitCount = 32;
bitmap_header->bmiHeader.biCompression = BI_RGB;
bitmap_header->bmiHeader.biWidth = w;
bitmap_header->bmiHeader.biHeight = -h;
((unsigned long *)bitmap_header->bmiColors)[0] = 0x00FF0000;
((unsigned long *)bitmap_header->bmiColors)[1] = 0x0000FF00;
((unsigned long *)bitmap_header->bmiColors)[2] = 0x000000FF;
HDC dc = GetDC(someHwnd);
HBITMAP bitmap = CreateDIBitmap(dc,&bitmap_header->bmiHeader,CBM_INIT,image,bitmap_header,DIB_RGB_COLORS);
ReleaseDC(someHwnd,dc);
return bitmap;
}
void NiceSizeFormat(size_t size, char *out)
{
char *sizes[] = {"b","KB","MB","GB","TB","PB","EB"};
int s = 0;
int frac = 0;
while (size>1024)
{
s++;
frac = (int)size & 1023;
size /= 1024;
}
float f = (float)size + ((float)frac / 1024.0f);
sprintf(out,"%3.1f %s",f,sizes[s]);
}
BOOL CopyTextToClipboard(HWND hwnd, TCHAR *text)
{
OpenClipboard(hwnd);
EmptyClipboard();
HANDLE hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (strlen(text) + 1) * sizeof(TCHAR));
if (hglbCopy == NULL)
{
CloseClipboard();
return FALSE;
}
// Lock the handle and copy the text to the buffer.
TCHAR *lptstrCopy = (TCHAR *)GlobalLock(hglbCopy);
strcpy(lptstrCopy, text);
lptstrCopy[strlen(text)] = (TCHAR) 0; // null character
GlobalUnlock(hglbCopy);
SetClipboardData(CF_TEXT,hglbCopy);
CloseClipboard();
return TRUE;
}
}

View File

@ -1,225 +1,225 @@
#include "Misc.h"
#include "PropertySheet.h"
namespace W32Util
{
bool centered;
PropSheet::PropSheet()
{
watermark = 0;
header = 0;
icon = 0;
}
int CALLBACK PropSheet::Callback(HWND hwndDlg, UINT uMsg, LPARAM lParam)
{
switch (uMsg) {
case PSCB_PRECREATE:
{
if (uMsg == PSCB_PRECREATE)
{
/*
if (lParam)
{
DLGTEMPLATE *pDlgTemplate;
DLGTEMPLATEEX *pDlgTemplateEx;
pDlgTemplateEx = (DLGTEMPLATEEX *)lParam;
if (pDlgTemplateEx->signature == 0xFFFF)
{
// pDlgTemplateEx points to an extended
// dialog template structure.
//pDlgTemplate->style |= DS_SETFONT;
u8 *tmp1 = (u8*)&pDlgTemplateEx + sizeof(DLGTEMPLATEEX);
u16 *tmp = (u16*)tmp1;
tmp++; //skip menu
tmp++; //skip dlg class
//Crash();
//Here we should bash in Segoe UI
//It turns out to be way complicated though
//Not worth it
}
else
{
// This is a standard dialog template
// structure.
pDlgTemplate = (DLGTEMPLATE *)lParam;
}
} */
}
}
break;
case PSCB_INITIALIZED:
{
}
return 0;
}
return 0;
}
void PropSheet::Show(HINSTANCE hInstance, HWND hParent, std::string title, int startpage, bool floating, bool wizard)
{
HPROPSHEETPAGE *pages = new HPROPSHEETPAGE[list.size()];
PROPSHEETPAGE page;
//common settings
memset((void*)&page,0,sizeof(PROPSHEETPAGE));
page.dwSize = sizeof(PROPSHEETPAGE);
page.hInstance = hInstance;
int i=0;
for (DlgList::iterator iter = list.begin(); iter != list.end(); iter++, i++)
{
if (wizard)
{
if (i == 0 || i == list.size()-1)
page.dwFlags = PSP_HIDEHEADER;
else
page.dwFlags = PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
}
else
{
page.dwFlags = PSP_USETITLE;
}
page.pszTemplate = iter->resource;
page.pfnDlgProc = Tab::TabDlgProc;
page.pszTitle = iter->title;
page.pszHeaderTitle = wizard?iter->title:0;
page.pszHeaderSubTitle = wizard?iter->hdrSubTitle:0;
page.lParam = (LPARAM)iter->tab;
pages[i] = CreatePropertySheetPage(&page);
}
PROPSHEETHEADER sheet;
memset(&sheet,0,sizeof(sheet));
sheet.dwSize = sizeof(PROPSHEETHEADER);
sheet.hInstance = hInstance;
sheet.hwndParent = hParent;
sheet.pszbmWatermark = watermark;
sheet.pszbmHeader = header;
if (icon)
sheet.hIcon = icon;
if (wizard)
sheet.dwFlags = PSH_USECALLBACK | PSH_WIZARD97 | (watermark?PSH_WATERMARK:0) | (header?PSH_HEADER:0);
else
sheet.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
sheet.dwFlags |= PSH_NOCONTEXTHELP;
if (floating)
sheet.dwFlags |= PSH_MODELESS;
//else
// sheet.dwFlags |= PSH_NOAPPLYNOW;
if (icon)
sheet.dwFlags |= PSH_USEHICON;
sheet.pszCaption = title.c_str();
sheet.nPages = (UINT)list.size();
sheet.phpage = pages;
sheet.nStartPage = startpage;
sheet.pfnCallback = (PFNPROPSHEETCALLBACK)Callback;
NONCLIENTMETRICS ncm = {0};
ncm.cbSize = sizeof(ncm);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
hDialogFont = CreateFontIndirect(&ncm.lfMessageFont);
if (wizard)
{
//Create the intro/end title font
LOGFONT TitleLogFont = ncm.lfMessageFont;
TitleLogFont.lfWeight = FW_BOLD;
lstrcpy(TitleLogFont.lfFaceName, TEXT("Verdana Bold"));
//StringCchCopy(TitleLogFont.lfFaceName, 32, TEXT("Verdana Bold"));
HDC hdc = GetDC(NULL); //gets the screen DC
int FontSize = 12;
TitleLogFont.lfHeight = 0 - GetDeviceCaps(hdc, LOGPIXELSY) * FontSize / 72;
hTitleFont = CreateFontIndirect(&TitleLogFont);
ReleaseDC(NULL, hdc);
}
else
hTitleFont = 0;
centered=false;
PropertySheet(&sheet);
if (!floating)
{
for (DlgList::iterator iter = list.begin(); iter != list.end(); iter++)
{
delete iter->tab;
}
DeleteObject(hTitleFont);
}
DeleteObject(hDialogFont);
delete [] pages;
}
void PropSheet::Add(Tab *tab, LPCTSTR resource, LPCTSTR title, LPCTSTR subtitle)
{
tab->sheet = this;
list.push_back(Page(tab,resource,title,subtitle));
}
void WizExteriorPage::Init(HWND hDlg)
{
HWND hwndControl = GetDlgItem(hDlg, captionID);
//SetWindowFont(hwndControl, sheet->GetTitleFont(), TRUE);
SendMessage(hwndControl,WM_SETFONT,(WPARAM)sheet->GetTitleFont(),0);
}
INT_PTR Tab::TabDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
Tab *tab = (Tab *)GetWindowLongPtr(hDlg, GWLP_USERDATA);
switch(message)
{
case WM_INITDIALOG:
{
if (!centered) //HACK
{
CenterWindow(GetParent(hDlg));
centered=true;
}
LPARAM l = ((LPPROPSHEETPAGE)lParam)->lParam;
tab = (Tab *)l;
SetWindowLongPtr(hDlg, GWLP_USERDATA, (DWORD_PTR)l);
tab->Init(hDlg);
}
break;
case WM_COMMAND:
tab->Command(hDlg,wParam);
break;
case WM_NOTIFY:
{
LPPSHNOTIFY lppsn = (LPPSHNOTIFY) lParam;
HWND sheet = lppsn->hdr.hwndFrom;
switch(lppsn->hdr.code) {
case PSN_APPLY:
tab->Apply(hDlg);
break;
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg),
(tab->HasPrev()?PSWIZB_BACK:0) |
(tab->HasNext()?PSWIZB_NEXT:0) |
(tab->HasFinish()?PSWIZB_FINISH:0));
break;
case PSN_WIZNEXT:
tab->Apply(hDlg); //maybe not always good
break;
case PSN_WIZBACK:
case PSN_RESET: //cancel
break;
}
}
break;
}
return 0;
}
#include "Misc.h"
#include "PropertySheet.h"
namespace W32Util
{
bool centered;
PropSheet::PropSheet()
{
watermark = 0;
header = 0;
icon = 0;
}
int CALLBACK PropSheet::Callback(HWND hwndDlg, UINT uMsg, LPARAM lParam)
{
switch (uMsg) {
case PSCB_PRECREATE:
{
if (uMsg == PSCB_PRECREATE)
{
/*
if (lParam)
{
DLGTEMPLATE *pDlgTemplate;
DLGTEMPLATEEX *pDlgTemplateEx;
pDlgTemplateEx = (DLGTEMPLATEEX *)lParam;
if (pDlgTemplateEx->signature == 0xFFFF)
{
// pDlgTemplateEx points to an extended
// dialog template structure.
//pDlgTemplate->style |= DS_SETFONT;
u8 *tmp1 = (u8*)&pDlgTemplateEx + sizeof(DLGTEMPLATEEX);
u16 *tmp = (u16*)tmp1;
tmp++; //skip menu
tmp++; //skip dlg class
//Crash();
//Here we should bash in Segoe UI
//It turns out to be way complicated though
//Not worth it
}
else
{
// This is a standard dialog template
// structure.
pDlgTemplate = (DLGTEMPLATE *)lParam;
}
} */
}
}
break;
case PSCB_INITIALIZED:
{
}
return 0;
}
return 0;
}
void PropSheet::Show(HINSTANCE hInstance, HWND hParent, std::string title, int startpage, bool floating, bool wizard)
{
HPROPSHEETPAGE *pages = new HPROPSHEETPAGE[list.size()];
PROPSHEETPAGE page;
//common settings
memset((void*)&page,0,sizeof(PROPSHEETPAGE));
page.dwSize = sizeof(PROPSHEETPAGE);
page.hInstance = hInstance;
int i=0;
for (DlgList::iterator iter = list.begin(); iter != list.end(); iter++, i++)
{
if (wizard)
{
if (i == 0 || i == list.size()-1)
page.dwFlags = PSP_HIDEHEADER;
else
page.dwFlags = PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
}
else
{
page.dwFlags = PSP_USETITLE;
}
page.pszTemplate = iter->resource;
page.pfnDlgProc = Tab::TabDlgProc;
page.pszTitle = iter->title;
page.pszHeaderTitle = wizard?iter->title:0;
page.pszHeaderSubTitle = wizard?iter->hdrSubTitle:0;
page.lParam = (LPARAM)iter->tab;
pages[i] = CreatePropertySheetPage(&page);
}
PROPSHEETHEADER sheet;
memset(&sheet,0,sizeof(sheet));
sheet.dwSize = sizeof(PROPSHEETHEADER);
sheet.hInstance = hInstance;
sheet.hwndParent = hParent;
sheet.pszbmWatermark = watermark;
sheet.pszbmHeader = header;
if (icon)
sheet.hIcon = icon;
if (wizard)
sheet.dwFlags = PSH_USECALLBACK | PSH_WIZARD97 | (watermark?PSH_WATERMARK:0) | (header?PSH_HEADER:0);
else
sheet.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
sheet.dwFlags |= PSH_NOCONTEXTHELP;
if (floating)
sheet.dwFlags |= PSH_MODELESS;
//else
// sheet.dwFlags |= PSH_NOAPPLYNOW;
if (icon)
sheet.dwFlags |= PSH_USEHICON;
sheet.pszCaption = title.c_str();
sheet.nPages = (UINT)list.size();
sheet.phpage = pages;
sheet.nStartPage = startpage;
sheet.pfnCallback = (PFNPROPSHEETCALLBACK)Callback;
NONCLIENTMETRICS ncm = {0};
ncm.cbSize = sizeof(ncm);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
hDialogFont = CreateFontIndirect(&ncm.lfMessageFont);
if (wizard)
{
//Create the intro/end title font
LOGFONT TitleLogFont = ncm.lfMessageFont;
TitleLogFont.lfWeight = FW_BOLD;
lstrcpy(TitleLogFont.lfFaceName, TEXT("Verdana Bold"));
//StringCchCopy(TitleLogFont.lfFaceName, 32, TEXT("Verdana Bold"));
HDC hdc = GetDC(NULL); //gets the screen DC
int FontSize = 12;
TitleLogFont.lfHeight = 0 - GetDeviceCaps(hdc, LOGPIXELSY) * FontSize / 72;
hTitleFont = CreateFontIndirect(&TitleLogFont);
ReleaseDC(NULL, hdc);
}
else
hTitleFont = 0;
centered=false;
PropertySheet(&sheet);
if (!floating)
{
for (DlgList::iterator iter = list.begin(); iter != list.end(); iter++)
{
delete iter->tab;
}
DeleteObject(hTitleFont);
}
DeleteObject(hDialogFont);
delete [] pages;
}
void PropSheet::Add(Tab *tab, LPCTSTR resource, LPCTSTR title, LPCTSTR subtitle)
{
tab->sheet = this;
list.push_back(Page(tab,resource,title,subtitle));
}
void WizExteriorPage::Init(HWND hDlg)
{
HWND hwndControl = GetDlgItem(hDlg, captionID);
//SetWindowFont(hwndControl, sheet->GetTitleFont(), TRUE);
SendMessage(hwndControl,WM_SETFONT,(WPARAM)sheet->GetTitleFont(),0);
}
INT_PTR Tab::TabDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
Tab *tab = (Tab *)GetWindowLongPtr(hDlg, GWLP_USERDATA);
switch(message)
{
case WM_INITDIALOG:
{
if (!centered) //HACK
{
CenterWindow(GetParent(hDlg));
centered=true;
}
LPARAM l = ((LPPROPSHEETPAGE)lParam)->lParam;
tab = (Tab *)l;
SetWindowLongPtr(hDlg, GWLP_USERDATA, (DWORD_PTR)l);
tab->Init(hDlg);
}
break;
case WM_COMMAND:
tab->Command(hDlg,wParam);
break;
case WM_NOTIFY:
{
LPPSHNOTIFY lppsn = (LPPSHNOTIFY) lParam;
HWND sheet = lppsn->hdr.hwndFrom;
switch(lppsn->hdr.code) {
case PSN_APPLY:
tab->Apply(hDlg);
break;
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg),
(tab->HasPrev()?PSWIZB_BACK:0) |
(tab->HasNext()?PSWIZB_NEXT:0) |
(tab->HasFinish()?PSWIZB_FINISH:0));
break;
case PSN_WIZNEXT:
tab->Apply(hDlg); //maybe not always good
break;
case PSN_WIZBACK:
case PSN_RESET: //cancel
break;
}
}
break;
}
return 0;
}
}

View File

@ -1,124 +1,124 @@
#include <shlobj.h>
#include <xstring>
#include <string>
#include "ShellUtil.h"
namespace W32Util
{
std::string BrowseForFolder(HWND parent, char *title)
{
BROWSEINFO info;
memset(&info,0,sizeof(info));
info.hwndOwner = parent;
info.lpszTitle = title;
info.ulFlags = BIF_EDITBOX | BIF_RETURNONLYFSDIRS;
//info.pszDisplayName
LPCITEMIDLIST idList = SHBrowseForFolder(&info);
char temp[MAX_PATH];
SHGetPathFromIDList(idList, temp);
if (strlen(temp))
{
return temp;
}
else
return "";
}
//---------------------------------------------------------------------------------------------------
// function WinBrowseForFileName
//---------------------------------------------------------------------------------------------------
bool BrowseForFileName (bool _bLoad, HWND _hParent, const char *_pTitle,
const char *_pInitialFolder,const char *_pFilter,const char *_pExtension,
std::string& _strFileName)
{
char szFile [MAX_PATH+1];
char szFileTitle [MAX_PATH+1];
strcpy (szFile,"");
strcpy (szFileTitle,"");
OPENFILENAME ofn;
ZeroMemory (&ofn,sizeof (ofn));
ofn.lStructSize = sizeof (OPENFILENAME);
ofn.lpstrInitialDir = _pInitialFolder;
ofn.lpstrFilter = _pFilter;
ofn.nMaxFile = sizeof (szFile);
ofn.lpstrFile = szFile;
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = sizeof (szFileTitle);
ofn.lpstrDefExt = _pExtension;
ofn.hwndOwner = _hParent;
ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_HIDEREADONLY;
if (_strFileName.size () != 0)
ofn.lpstrFile = (char *)_strFileName.c_str();
if (((_bLoad)?GetOpenFileName (&ofn):GetSaveFileName (&ofn)))
{
_strFileName = ofn.lpstrFile;
return true;
}
else
return false;
}
std::vector<std::string> BrowseForFileNameMultiSelect(bool _bLoad, HWND _hParent, const char *_pTitle,
const char *_pInitialFolder,const char *_pFilter,const char *_pExtension)
{
char szFile [MAX_PATH+1+2048*2];
char szFileTitle [MAX_PATH+1];
strcpy (szFile,"");
strcpy (szFileTitle,"");
OPENFILENAME ofn;
ZeroMemory (&ofn,sizeof (ofn));
ofn.lStructSize = sizeof (OPENFILENAME);
ofn.lpstrInitialDir = _pInitialFolder;
ofn.lpstrFilter = _pFilter;
ofn.nMaxFile = sizeof (szFile);
ofn.lpstrFile = szFile;
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = sizeof (szFileTitle);
ofn.lpstrDefExt = _pExtension;
ofn.hwndOwner = _hParent;
ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT ;
std::vector<std::string> files;
if (((_bLoad)?GetOpenFileName (&ofn):GetSaveFileName (&ofn)))
{
std::string directory = ofn.lpstrFile;
char *temp = ofn.lpstrFile;
char *oldtemp = temp;
temp+=strlen(temp)+1;
if (*temp==0)
{
//we only got one file
files.push_back(std::string(oldtemp));
}
else
{
while (*temp)
{
files.push_back(directory+"\\"+std::string(temp));
temp+=strlen(temp)+1;
}
}
return files;
}
else
return std::vector<std::string>(); // empty vector;
}
#include <shlobj.h>
#include <xstring>
#include <string>
#include "ShellUtil.h"
namespace W32Util
{
std::string BrowseForFolder(HWND parent, char *title)
{
BROWSEINFO info;
memset(&info,0,sizeof(info));
info.hwndOwner = parent;
info.lpszTitle = title;
info.ulFlags = BIF_EDITBOX | BIF_RETURNONLYFSDIRS;
//info.pszDisplayName
LPCITEMIDLIST idList = SHBrowseForFolder(&info);
char temp[MAX_PATH];
SHGetPathFromIDList(idList, temp);
if (strlen(temp))
{
return temp;
}
else
return "";
}
//---------------------------------------------------------------------------------------------------
// function WinBrowseForFileName
//---------------------------------------------------------------------------------------------------
bool BrowseForFileName (bool _bLoad, HWND _hParent, const char *_pTitle,
const char *_pInitialFolder,const char *_pFilter,const char *_pExtension,
std::string& _strFileName)
{
char szFile [MAX_PATH+1];
char szFileTitle [MAX_PATH+1];
strcpy (szFile,"");
strcpy (szFileTitle,"");
OPENFILENAME ofn;
ZeroMemory (&ofn,sizeof (ofn));
ofn.lStructSize = sizeof (OPENFILENAME);
ofn.lpstrInitialDir = _pInitialFolder;
ofn.lpstrFilter = _pFilter;
ofn.nMaxFile = sizeof (szFile);
ofn.lpstrFile = szFile;
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = sizeof (szFileTitle);
ofn.lpstrDefExt = _pExtension;
ofn.hwndOwner = _hParent;
ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_HIDEREADONLY;
if (_strFileName.size () != 0)
ofn.lpstrFile = (char *)_strFileName.c_str();
if (((_bLoad)?GetOpenFileName (&ofn):GetSaveFileName (&ofn)))
{
_strFileName = ofn.lpstrFile;
return true;
}
else
return false;
}
std::vector<std::string> BrowseForFileNameMultiSelect(bool _bLoad, HWND _hParent, const char *_pTitle,
const char *_pInitialFolder,const char *_pFilter,const char *_pExtension)
{
char szFile [MAX_PATH+1+2048*2];
char szFileTitle [MAX_PATH+1];
strcpy (szFile,"");
strcpy (szFileTitle,"");
OPENFILENAME ofn;
ZeroMemory (&ofn,sizeof (ofn));
ofn.lStructSize = sizeof (OPENFILENAME);
ofn.lpstrInitialDir = _pInitialFolder;
ofn.lpstrFilter = _pFilter;
ofn.nMaxFile = sizeof (szFile);
ofn.lpstrFile = szFile;
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = sizeof (szFileTitle);
ofn.lpstrDefExt = _pExtension;
ofn.hwndOwner = _hParent;
ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT ;
std::vector<std::string> files;
if (((_bLoad)?GetOpenFileName (&ofn):GetSaveFileName (&ofn)))
{
std::string directory = ofn.lpstrFile;
char *temp = ofn.lpstrFile;
char *oldtemp = temp;
temp+=strlen(temp)+1;
if (*temp==0)
{
//we only got one file
files.push_back(std::string(oldtemp));
}
else
{
while (*temp)
{
files.push_back(directory+"\\"+std::string(temp));
temp+=strlen(temp)+1;
}
}
return files;
}
else
return std::vector<std::string>(); // empty vector;
}
}

View File

@ -1,94 +1,94 @@
#include <commctrl.h>
#include "TabControl.h"
namespace W32Util
{
// __________________________________________________________________________________________________
// constructor
//
TabControl::TabControl(HINSTANCE _hInstance, HWND _hTabCtrl,DLGPROC _lpDialogFunc) :
m_hInstance(_hInstance),
m_hTabCtrl(_hTabCtrl),
m_numDialogs(0)
{
for (int i=0; i<MAX_WIN_DIALOGS; i++)
m_WinDialogs[i] = NULL;
}
// __________________________________________________________________________________________________
// destructor
//
TabControl::~TabControl(void)
{}
// __________________________________________________________________________________________________
// AddItem
//
HWND TabControl::AddItem (char* _szText,int _iResource,DLGPROC _lpDialogFunc)
{
TCITEM tcItem;
ZeroMemory (&tcItem,sizeof (tcItem));
tcItem.mask = TCIF_TEXT | TCIF_IMAGE;
tcItem.dwState = 0;
tcItem.pszText = _szText;
tcItem.cchTextMax = sizeof (_szText);
tcItem.iImage = -1;
int nResult = TabCtrl_InsertItem (m_hTabCtrl,TabCtrl_GetItemCount (m_hTabCtrl),&tcItem);
HWND hDialog = CreateDialog(m_hInstance,(LPCSTR)_iResource,m_hTabCtrl,_lpDialogFunc);
RECT rectInnerWindow = {0,0,0,0};
GetWindowRect (m_hTabCtrl,&rectInnerWindow);
TabCtrl_AdjustRect (m_hTabCtrl,FALSE,&rectInnerWindow);
POINT pntPosition = {rectInnerWindow.left,rectInnerWindow.top};
ScreenToClient(m_hTabCtrl, &pntPosition);
SetWindowPos(hDialog, 0,
pntPosition.x, pntPosition.y,
rectInnerWindow.right - rectInnerWindow.left,rectInnerWindow.bottom - rectInnerWindow.top,0);
ShowWindow(hDialog,SW_NORMAL);
m_WinDialogs[m_numDialogs] = hDialog;
m_numDialogs++;
SelectDialog (0);
return hDialog;
}
// __________________________________________________________________________________________________
// SelectDialog
//
void TabControl::SelectDialog (int _nDialogId)
{
for (int i = 0 ; i < m_numDialogs ; i ++)
if (m_WinDialogs[i] != NULL)
ShowWindow(m_WinDialogs[i],i == _nDialogId ? SW_NORMAL : SW_HIDE);
}
// __________________________________________________________________________________________________
// MessageHandler
//
void TabControl::MessageHandler(UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_NOTIFY)
{
NMHDR* pNotifyMessage = NULL;
pNotifyMessage = (LPNMHDR)lParam;
if (pNotifyMessage->hwndFrom == m_hTabCtrl)
{
int iPage = TabCtrl_GetCurSel (m_hTabCtrl);
SelectDialog (iPage);
}
}
}
}
#include <commctrl.h>
#include "TabControl.h"
namespace W32Util
{
// __________________________________________________________________________________________________
// constructor
//
TabControl::TabControl(HINSTANCE _hInstance, HWND _hTabCtrl,DLGPROC _lpDialogFunc) :
m_hInstance(_hInstance),
m_hTabCtrl(_hTabCtrl),
m_numDialogs(0)
{
for (int i=0; i<MAX_WIN_DIALOGS; i++)
m_WinDialogs[i] = NULL;
}
// __________________________________________________________________________________________________
// destructor
//
TabControl::~TabControl(void)
{}
// __________________________________________________________________________________________________
// AddItem
//
HWND TabControl::AddItem (char* _szText,int _iResource,DLGPROC _lpDialogFunc)
{
TCITEM tcItem;
ZeroMemory (&tcItem,sizeof (tcItem));
tcItem.mask = TCIF_TEXT | TCIF_IMAGE;
tcItem.dwState = 0;
tcItem.pszText = _szText;
tcItem.cchTextMax = sizeof (_szText);
tcItem.iImage = -1;
int nResult = TabCtrl_InsertItem (m_hTabCtrl,TabCtrl_GetItemCount (m_hTabCtrl),&tcItem);
HWND hDialog = CreateDialog(m_hInstance,(LPCSTR)_iResource,m_hTabCtrl,_lpDialogFunc);
RECT rectInnerWindow = {0,0,0,0};
GetWindowRect (m_hTabCtrl,&rectInnerWindow);
TabCtrl_AdjustRect (m_hTabCtrl,FALSE,&rectInnerWindow);
POINT pntPosition = {rectInnerWindow.left,rectInnerWindow.top};
ScreenToClient(m_hTabCtrl, &pntPosition);
SetWindowPos(hDialog, 0,
pntPosition.x, pntPosition.y,
rectInnerWindow.right - rectInnerWindow.left,rectInnerWindow.bottom - rectInnerWindow.top,0);
ShowWindow(hDialog,SW_NORMAL);
m_WinDialogs[m_numDialogs] = hDialog;
m_numDialogs++;
SelectDialog (0);
return hDialog;
}
// __________________________________________________________________________________________________
// SelectDialog
//
void TabControl::SelectDialog (int _nDialogId)
{
for (int i = 0 ; i < m_numDialogs ; i ++)
if (m_WinDialogs[i] != NULL)
ShowWindow(m_WinDialogs[i],i == _nDialogId ? SW_NORMAL : SW_HIDE);
}
// __________________________________________________________________________________________________
// MessageHandler
//
void TabControl::MessageHandler(UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_NOTIFY)
{
NMHDR* pNotifyMessage = NULL;
pNotifyMessage = (LPNMHDR)lParam;
if (pNotifyMessage->hwndFrom == m_hTabCtrl)
{
int iPage = TabCtrl_GetCurSel (m_hTabCtrl);
SelectDialog (iPage);
}
}
}
}

View File

@ -1,82 +1,82 @@
#include "Thread.h"
namespace W32Util
{
// __________________________________________________________________________________________________
// Constructor
//
Thread::Thread ( DWORD (WINAPI * pFun) (void* arg), void* pArg)
{
_handle = CreateThread (
0, // Security attributes
0, // Stack size
pFun,
pArg,
CREATE_SUSPENDED,
&_tid);
}
// __________________________________________________________________________________________________
// Destructor
//
Thread::~Thread (void)
{
if (_handle != NULL)
{
if (CloseHandle (_handle) == FALSE)
{
Terminate();
}
}
}
// __________________________________________________________________________________________________
// Resume
//
void
Thread::Resume (void)
{
if (_handle != NULL)
ResumeThread (_handle);
}
// __________________________________________________________________________________________________
// WaitForDeath
//
void
Thread::WaitForDeath (void)
{
if (_handle != NULL)
WaitForSingleObject (_handle, 100);
}
// __________________________________________________________________________________________________
// Terminate
//
void
Thread::Terminate (void)
{
if (_handle != NULL)
TerminateThread (_handle, 0);
_handle = NULL;
}
// __________________________________________________________________________________________________
// SetPriority
//
void
Thread::SetPriority (int _nPriority)
{
if (_handle != NULL)
SetThreadPriority(_handle, _nPriority);
}
// __________________________________________________________________________________________________
// Suspend
//
void
Thread::Suspend (void)
{
if (_handle != NULL)
SuspendThread(_handle);
}
#include "Thread.h"
namespace W32Util
{
// __________________________________________________________________________________________________
// Constructor
//
Thread::Thread ( DWORD (WINAPI * pFun) (void* arg), void* pArg)
{
_handle = CreateThread (
0, // Security attributes
0, // Stack size
pFun,
pArg,
CREATE_SUSPENDED,
&_tid);
}
// __________________________________________________________________________________________________
// Destructor
//
Thread::~Thread (void)
{
if (_handle != NULL)
{
if (CloseHandle (_handle) == FALSE)
{
Terminate();
}
}
}
// __________________________________________________________________________________________________
// Resume
//
void
Thread::Resume (void)
{
if (_handle != NULL)
ResumeThread (_handle);
}
// __________________________________________________________________________________________________
// WaitForDeath
//
void
Thread::WaitForDeath (void)
{
if (_handle != NULL)
WaitForSingleObject (_handle, 100);
}
// __________________________________________________________________________________________________
// Terminate
//
void
Thread::Terminate (void)
{
if (_handle != NULL)
TerminateThread (_handle, 0);
_handle = NULL;
}
// __________________________________________________________________________________________________
// SetPriority
//
void
Thread::SetPriority (int _nPriority)
{
if (_handle != NULL)
SetThreadPriority(_handle, _nPriority);
}
// __________________________________________________________________________________________________
// Suspend
//
void
Thread::Suspend (void)
{
if (_handle != NULL)
SuspendThread(_handle);
}
}

View File

@ -1,136 +1,136 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
#include "Profiler.h"
#include "XFStructs.h"
#include "Render.h"
#include "main.h"
#include "VertexManager.h"
#include "Utils.h"
// LoadXFReg 0x10
void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
{
DVSTARTPROFILE();
u32 address = baseAddress;
for (int i = 0; i < (int)transferSize; i++)
{
address = baseAddress + i;
// Setup a Matrix
if (address < 0x1000)
{
u32* p1 = &xfmem[address];
memcpy(p1, &pData[i], transferSize*4);
i += transferSize;
}
else if (address < 0x2000)
{
u32 data = pData[i];
switch (address)
{
case 0x1006:
//SetGPMetric
break;
case 0x1008: //__GXXfVtxSpecs, wrote 0004
break;
case 0x1009: //GXSetNumChans (no)
break;
case 0x100a: xfregs.colChans[0].ambColor = data; break; //GXSetChanAmbientcolor
case 0x100b: xfregs.colChans[1].ambColor = data; break; //GXSetChanAmbientcolor
case 0x100c: xfregs.colChans[0].matColor = data; break; //GXSetChanMatcolor (rgba)
case 0x100d: xfregs.colChans[1].matColor = data; break; //GXSetChanMatcolor (rgba)
case 0x100e: xfregs.colChans[0].color.hex = data; break; //color0
case 0x100f: xfregs.colChans[1].color.hex = data; break; //color1
case 0x1010: xfregs.colChans[0].alpha.hex = data; break; //alpha0
case 0x1011: xfregs.colChans[1].alpha.hex = data; break; //alpha1
case 0x1018:
break;
case 0x101a:
VertexManager::Flush();
memcpy(xfregs.rawViewport, &pData[i], sizeof(xfregs.rawViewport));
XFUpdateVP();
i += 6;
break;
case 0x1020:
VertexManager::Flush();
memcpy(xfregs.rawProjection, &pData[i], sizeof(xfregs.rawProjection));
XFUpdatePJ();
i += 7;
return;
case 0x103f:
xfregs.numTexGens = data;
break;
case 0x1040: xfregs.texcoords[0].texmtxinfo.hex = data; break;
case 0x1041: xfregs.texcoords[1].texmtxinfo.hex = data; break;
case 0x1042: xfregs.texcoords[2].texmtxinfo.hex = data; break;
case 0x1043: xfregs.texcoords[3].texmtxinfo.hex = data; break;
case 0x1044: xfregs.texcoords[4].texmtxinfo.hex = data; break;
case 0x1045: xfregs.texcoords[5].texmtxinfo.hex = data; break;
case 0x1046: xfregs.texcoords[6].texmtxinfo.hex = data; break;
case 0x1047: xfregs.texcoords[7].texmtxinfo.hex = data; break;
case 0x1050: xfregs.texcoords[0].postmtxinfo.hex = data; break;
case 0x1051: xfregs.texcoords[1].postmtxinfo.hex = data; break;
case 0x1052: xfregs.texcoords[2].postmtxinfo.hex = data; break;
case 0x1053: xfregs.texcoords[3].postmtxinfo.hex = data; break;
case 0x1054: xfregs.texcoords[4].postmtxinfo.hex = data; break;
case 0x1055: xfregs.texcoords[5].postmtxinfo.hex = data; break;
case 0x1056: xfregs.texcoords[6].postmtxinfo.hex = data; break;
case 0x1057: xfregs.texcoords[7].postmtxinfo.hex = data; break;
default:
break;
}
}
else if (address>=0x4000)
{
// MessageBox(NULL, "1", "1", MB_OK);
//4010 __GXSetGenMode
}
}
}
// Check docs for this sucker...
void LoadIndexedXF(u32 val, int array)
{
DVSTARTPROFILE();
int index = val >> 16;
int address = val & 0xFFF; //check mask
int size = ((val >> 12) & 0xF)+1;
//load stuff from array to address in xf mem
for (int i = 0; i < size; i++)
xfmem[address + i] = Memory_Read_U32(arraybases[array] + arraystrides[array]*index + i*4);
}
void XFUpdateVP()
{
Renderer::SetViewport(xfregs.rawViewport);
}
void XFUpdatePJ()
{
Renderer::SetProjection(xfregs.rawProjection, 0);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
#include "Profiler.h"
#include "XFStructs.h"
#include "Render.h"
#include "main.h"
#include "VertexManager.h"
#include "Utils.h"
// LoadXFReg 0x10
void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
{
DVSTARTPROFILE();
u32 address = baseAddress;
for (int i = 0; i < (int)transferSize; i++)
{
address = baseAddress + i;
// Setup a Matrix
if (address < 0x1000)
{
u32* p1 = &xfmem[address];
memcpy(p1, &pData[i], transferSize*4);
i += transferSize;
}
else if (address < 0x2000)
{
u32 data = pData[i];
switch (address)
{
case 0x1006:
//SetGPMetric
break;
case 0x1008: //__GXXfVtxSpecs, wrote 0004
break;
case 0x1009: //GXSetNumChans (no)
break;
case 0x100a: xfregs.colChans[0].ambColor = data; break; //GXSetChanAmbientcolor
case 0x100b: xfregs.colChans[1].ambColor = data; break; //GXSetChanAmbientcolor
case 0x100c: xfregs.colChans[0].matColor = data; break; //GXSetChanMatcolor (rgba)
case 0x100d: xfregs.colChans[1].matColor = data; break; //GXSetChanMatcolor (rgba)
case 0x100e: xfregs.colChans[0].color.hex = data; break; //color0
case 0x100f: xfregs.colChans[1].color.hex = data; break; //color1
case 0x1010: xfregs.colChans[0].alpha.hex = data; break; //alpha0
case 0x1011: xfregs.colChans[1].alpha.hex = data; break; //alpha1
case 0x1018:
break;
case 0x101a:
VertexManager::Flush();
memcpy(xfregs.rawViewport, &pData[i], sizeof(xfregs.rawViewport));
XFUpdateVP();
i += 6;
break;
case 0x1020:
VertexManager::Flush();
memcpy(xfregs.rawProjection, &pData[i], sizeof(xfregs.rawProjection));
XFUpdatePJ();
i += 7;
return;
case 0x103f:
xfregs.numTexGens = data;
break;
case 0x1040: xfregs.texcoords[0].texmtxinfo.hex = data; break;
case 0x1041: xfregs.texcoords[1].texmtxinfo.hex = data; break;
case 0x1042: xfregs.texcoords[2].texmtxinfo.hex = data; break;
case 0x1043: xfregs.texcoords[3].texmtxinfo.hex = data; break;
case 0x1044: xfregs.texcoords[4].texmtxinfo.hex = data; break;
case 0x1045: xfregs.texcoords[5].texmtxinfo.hex = data; break;
case 0x1046: xfregs.texcoords[6].texmtxinfo.hex = data; break;
case 0x1047: xfregs.texcoords[7].texmtxinfo.hex = data; break;
case 0x1050: xfregs.texcoords[0].postmtxinfo.hex = data; break;
case 0x1051: xfregs.texcoords[1].postmtxinfo.hex = data; break;
case 0x1052: xfregs.texcoords[2].postmtxinfo.hex = data; break;
case 0x1053: xfregs.texcoords[3].postmtxinfo.hex = data; break;
case 0x1054: xfregs.texcoords[4].postmtxinfo.hex = data; break;
case 0x1055: xfregs.texcoords[5].postmtxinfo.hex = data; break;
case 0x1056: xfregs.texcoords[6].postmtxinfo.hex = data; break;
case 0x1057: xfregs.texcoords[7].postmtxinfo.hex = data; break;
default:
break;
}
}
else if (address>=0x4000)
{
// MessageBox(NULL, "1", "1", MB_OK);
//4010 __GXSetGenMode
}
}
}
// Check docs for this sucker...
void LoadIndexedXF(u32 val, int array)
{
DVSTARTPROFILE();
int index = val >> 16;
int address = val & 0xFFF; //check mask
int size = ((val >> 12) & 0xF)+1;
//load stuff from array to address in xf mem
for (int i = 0; i < size; i++)
xfmem[address + i] = Memory_Read_U32(arraybases[array] + arraystrides[array]*index + i*4);
}
void XFUpdateVP()
{
Renderer::SetViewport(xfregs.rawViewport);
}
void XFUpdatePJ()
{
Renderer::SetProjection(xfregs.rawProjection, 0);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,322 +1,322 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <tchar.h>
#include <windows.h>
#include <d3dx9.h>
#include "Common.h"
#include "svnrev.h"
#include "resource.h"
#include "main.h"
#include "Config.h"
#include "Fifo.h"
#include "OpcodeDecoding.h"
#include "TextureCache.h"
#include "BPStructs.h"
#include "VertexManager.h"
#include "TransformEngine.h"
#include "DlgSettings.h"
#include "D3DPostprocess.h"
#include "D3DTexture.h"
#include "D3DUtil.h"
#include "W32Util/Misc.h"
#include "EmuWindow.h"
#include "VideoState.h"
#include "XFBConvert.h"
#include "Utils.h"
HINSTANCE g_hInstance = NULL;
SVideoInitialize g_VideoInitialize;
int initCount = 0;
void DllDebugger(HWND _hParent, bool Show)
{
// TODO: implement
}
BOOL APIENTRY DllMain( HINSTANCE hinstDLL, // DLL module handle
DWORD dwReason, // reason called
LPVOID lpvReserved) // reserved
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
default:
break;
}
g_hInstance = hinstDLL;
return TRUE;
}
BOOL Callback_PeekMessages()
{
//TODO: peek message
MSG msg;
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
return FALSE;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return TRUE;
}
void UpdateFPSDisplay(const char *text)
{
char temp[512];
sprintf_s(temp, 512, "SVN R%i: DX9: %s", SVN_REV, text);
SetWindowText( EmuWindow::GetWnd(), temp);
}
bool Init()
{
g_Config.Load();
if (initCount == 0)
{
// create the window
if ( !g_Config.renderToMainframe || g_VideoInitialize.pWindowHandle == NULL ) // ignore parent for this plugin
{
g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create(NULL, g_hInstance, "Loading - Please wait.");
}
else
{
g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create((HWND)g_VideoInitialize.pWindowHandle, g_hInstance, "Loading - Please wait.");
}
if ( g_VideoInitialize.pWindowHandle == NULL )
{
MessageBox(GetActiveWindow(), "An error has occurred while trying to create the window.", "Fatal Error", MB_OK);
return false;
}
EmuWindow::Show();
g_VideoInitialize.pPeekMessages = Callback_PeekMessages;
g_VideoInitialize.pUpdateFPSDisplay = UpdateFPSDisplay;
if (FAILED(D3D::Init()))
{
MessageBox(GetActiveWindow(), "Unable to initialize Direct3D. Please make sure that you have DirectX 9.0c correctly installed.", "Fatal Error", MB_OK);
return false;
}
InitLUTs();
InitXFBConvTables();
}
initCount++;
return true;
}
void DeInit()
{
initCount--;
if (initCount==0)
{
D3D::Shutdown();
EmuWindow::Close();
}
}
// ====================================================================================
void GetDllInfo (PLUGIN_INFO* _PluginInfo)
{
_PluginInfo->Version = 0x0100;
_PluginInfo->Type = PLUGIN_TYPE_VIDEO;
#ifdef DEBUGFAST
sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin DebugFast (DX9)");
#else
#ifndef _DEBUG
sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin (DX9)");
#else
sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin Debug (DX9)");
#endif
#endif
}
void DllAbout(HWND _hParent)
{
DialogBox(g_hInstance,(LPCSTR)IDD_ABOUT,_hParent,(DLGPROC)AboutProc);
}
void DllConfig(HWND _hParent)
{
if (Init())
{
DlgSettings_Show(g_hInstance,_hParent);
DeInit();
}
}
void Video_Initialize(SVideoInitialize* _pVideoInitialize)
{
if (_pVideoInitialize == NULL)
return;
frameCount = 0;
g_VideoInitialize = *_pVideoInitialize;
Init();
_pVideoInitialize->pPeekMessages = g_VideoInitialize.pPeekMessages;
_pVideoInitialize->pUpdateFPSDisplay = g_VideoInitialize.pUpdateFPSDisplay;
_pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle;
Renderer::AddMessage("Dolphin Direct3D9 Video Plugin.",5000);
}
void Video_DoState(unsigned char **ptr, int mode) {
// Clear all caches
TextureCache::Invalidate();
PointerWrap p(ptr, mode);
VideoCommon_DoState(p);
//PanicAlert("Saving/Loading state from DirectX9");
}
void Video_EnterLoop()
{
Fifo_EnterLoop(g_VideoInitialize);
}
void Video_Prepare(void)
{
Renderer::Init(g_VideoInitialize);
TextureCache::Init();
BPInit();
VertexManager::Init();
Fifo_Init();
OpcodeDecoder_Init();
}
void Video_Shutdown(void)
{
Fifo_Shutdown();
VertexManager::Shutdown();
TextureCache::Shutdown();
Renderer::Shutdown();
OpcodeDecoder_Shutdown();
DeInit();
}
void Video_Stop(void)
{
}
void Video_UpdateXFB(u8* /*_pXFB*/, u32 /*_dwWidth*/, u32 /*_dwHeight*/, s32 /*_dwYOffset*/)
{
/*
ConvertXFB(tempBuffer, _pXFB, _dwWidth, _dwHeight);
// blubb
static LPDIRECT3DTEXTURE9 pTexture = D3D::CreateTexture2D((BYTE*)tempBuffer, _dwWidth, _dwHeight, _dwWidth, D3DFMT_A8R8G8B8);
D3D::ReplaceTexture2D(pTexture, (BYTE*)tempBuffer, _dwWidth, _dwHeight, _dwWidth, D3DFMT_A8R8G8B8);
D3D::dev->SetTexture(0, pTexture);
D3D::quad2d(0,0,(float)Postprocess::GetWidth(),(float)Postprocess::GetHeight(), 0xFFFFFFFF);
D3D::EndFrame();
D3D::BeginFrame();*/
}
void DebugLog(const char* _fmt, ...)
{
#ifdef _DEBUG
char Msg[512];
va_list ap;
va_start( ap, _fmt );
vsprintf( Msg, _fmt, ap );
va_end( ap );
g_VideoInitialize.pLog(Msg, FALSE);
#endif
}
void __Log(int log, const char *format, ...)
{
// char temp[512];
//va_list args;
//va_start(args, format);
//CharArrayFromFormatV(temp, 512, format, args);
//va_end(args);
DebugLog(format); //"%s", temp);
}
HRESULT ScreenShot(TCHAR *File)
{
if (D3D::dev == NULL)
return S_FALSE;
D3DDISPLAYMODE DisplayMode;
if (FAILED(D3D::dev->GetDisplayMode(0, &DisplayMode)))
return S_FALSE;
LPDIRECT3DSURFACE9 surf;
if (FAILED(D3D::dev->CreateOffscreenPlainSurface(DisplayMode.Width, DisplayMode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL)))
return S_FALSE;
if (FAILED(D3D::dev->GetFrontBufferData(0, surf)))
{
surf->Release();
return S_FALSE;
}
RECT rect;
::GetWindowRect(EmuWindow::GetWnd(), &rect);
if (FAILED(D3DXSaveSurfaceToFile(File, D3DXIFF_JPG, surf, NULL, &rect)))
{
surf->Release();
return S_FALSE;
}
surf->Release();
return S_OK;
}
BOOL Video_Screenshot(TCHAR* _szFilename)
{
if (ScreenShot(_szFilename) == S_OK)
return TRUE;
return FALSE;
}
void Video_AddMessage(const char* pstr, u32 milliseconds)
{
Renderer::AddMessage(pstr,milliseconds);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <tchar.h>
#include <windows.h>
#include <d3dx9.h>
#include "Common.h"
#include "svnrev.h"
#include "resource.h"
#include "main.h"
#include "Config.h"
#include "Fifo.h"
#include "OpcodeDecoding.h"
#include "TextureCache.h"
#include "BPStructs.h"
#include "VertexManager.h"
#include "TransformEngine.h"
#include "DlgSettings.h"
#include "D3DPostprocess.h"
#include "D3DTexture.h"
#include "D3DUtil.h"
#include "W32Util/Misc.h"
#include "EmuWindow.h"
#include "VideoState.h"
#include "XFBConvert.h"
#include "Utils.h"
HINSTANCE g_hInstance = NULL;
SVideoInitialize g_VideoInitialize;
int initCount = 0;
void DllDebugger(HWND _hParent, bool Show)
{
// TODO: implement
}
BOOL APIENTRY DllMain( HINSTANCE hinstDLL, // DLL module handle
DWORD dwReason, // reason called
LPVOID lpvReserved) // reserved
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
default:
break;
}
g_hInstance = hinstDLL;
return TRUE;
}
BOOL Callback_PeekMessages()
{
//TODO: peek message
MSG msg;
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
return FALSE;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return TRUE;
}
void UpdateFPSDisplay(const char *text)
{
char temp[512];
sprintf_s(temp, 512, "SVN R%i: DX9: %s", SVN_REV, text);
SetWindowText( EmuWindow::GetWnd(), temp);
}
bool Init()
{
g_Config.Load();
if (initCount == 0)
{
// create the window
if ( !g_Config.renderToMainframe || g_VideoInitialize.pWindowHandle == NULL ) // ignore parent for this plugin
{
g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create(NULL, g_hInstance, "Loading - Please wait.");
}
else
{
g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create((HWND)g_VideoInitialize.pWindowHandle, g_hInstance, "Loading - Please wait.");
}
if ( g_VideoInitialize.pWindowHandle == NULL )
{
MessageBox(GetActiveWindow(), "An error has occurred while trying to create the window.", "Fatal Error", MB_OK);
return false;
}
EmuWindow::Show();
g_VideoInitialize.pPeekMessages = Callback_PeekMessages;
g_VideoInitialize.pUpdateFPSDisplay = UpdateFPSDisplay;
if (FAILED(D3D::Init()))
{
MessageBox(GetActiveWindow(), "Unable to initialize Direct3D. Please make sure that you have DirectX 9.0c correctly installed.", "Fatal Error", MB_OK);
return false;
}
InitLUTs();
InitXFBConvTables();
}
initCount++;
return true;
}
void DeInit()
{
initCount--;
if (initCount==0)
{
D3D::Shutdown();
EmuWindow::Close();
}
}
// ====================================================================================
void GetDllInfo (PLUGIN_INFO* _PluginInfo)
{
_PluginInfo->Version = 0x0100;
_PluginInfo->Type = PLUGIN_TYPE_VIDEO;
#ifdef DEBUGFAST
sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin DebugFast (DX9)");
#else
#ifndef _DEBUG
sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin (DX9)");
#else
sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin Debug (DX9)");
#endif
#endif
}
void DllAbout(HWND _hParent)
{
DialogBox(g_hInstance,(LPCSTR)IDD_ABOUT,_hParent,(DLGPROC)AboutProc);
}
void DllConfig(HWND _hParent)
{
if (Init())
{
DlgSettings_Show(g_hInstance,_hParent);
DeInit();
}
}
void Video_Initialize(SVideoInitialize* _pVideoInitialize)
{
if (_pVideoInitialize == NULL)
return;
frameCount = 0;
g_VideoInitialize = *_pVideoInitialize;
Init();
_pVideoInitialize->pPeekMessages = g_VideoInitialize.pPeekMessages;
_pVideoInitialize->pUpdateFPSDisplay = g_VideoInitialize.pUpdateFPSDisplay;
_pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle;
Renderer::AddMessage("Dolphin Direct3D9 Video Plugin.",5000);
}
void Video_DoState(unsigned char **ptr, int mode) {
// Clear all caches
TextureCache::Invalidate();
PointerWrap p(ptr, mode);
VideoCommon_DoState(p);
//PanicAlert("Saving/Loading state from DirectX9");
}
void Video_EnterLoop()
{
Fifo_EnterLoop(g_VideoInitialize);
}
void Video_Prepare(void)
{
Renderer::Init(g_VideoInitialize);
TextureCache::Init();
BPInit();
VertexManager::Init();
Fifo_Init();
OpcodeDecoder_Init();
}
void Video_Shutdown(void)
{
Fifo_Shutdown();
VertexManager::Shutdown();
TextureCache::Shutdown();
Renderer::Shutdown();
OpcodeDecoder_Shutdown();
DeInit();
}
void Video_Stop(void)
{
}
void Video_UpdateXFB(u8* /*_pXFB*/, u32 /*_dwWidth*/, u32 /*_dwHeight*/, s32 /*_dwYOffset*/)
{
/*
ConvertXFB(tempBuffer, _pXFB, _dwWidth, _dwHeight);
// blubb
static LPDIRECT3DTEXTURE9 pTexture = D3D::CreateTexture2D((BYTE*)tempBuffer, _dwWidth, _dwHeight, _dwWidth, D3DFMT_A8R8G8B8);
D3D::ReplaceTexture2D(pTexture, (BYTE*)tempBuffer, _dwWidth, _dwHeight, _dwWidth, D3DFMT_A8R8G8B8);
D3D::dev->SetTexture(0, pTexture);
D3D::quad2d(0,0,(float)Postprocess::GetWidth(),(float)Postprocess::GetHeight(), 0xFFFFFFFF);
D3D::EndFrame();
D3D::BeginFrame();*/
}
void DebugLog(const char* _fmt, ...)
{
#ifdef _DEBUG
char Msg[512];
va_list ap;
va_start( ap, _fmt );
vsprintf( Msg, _fmt, ap );
va_end( ap );
g_VideoInitialize.pLog(Msg, FALSE);
#endif
}
void __Log(int log, const char *format, ...)
{
// char temp[512];
//va_list args;
//va_start(args, format);
//CharArrayFromFormatV(temp, 512, format, args);
//va_end(args);
DebugLog(format); //"%s", temp);
}
HRESULT ScreenShot(TCHAR *File)
{
if (D3D::dev == NULL)
return S_FALSE;
D3DDISPLAYMODE DisplayMode;
if (FAILED(D3D::dev->GetDisplayMode(0, &DisplayMode)))
return S_FALSE;
LPDIRECT3DSURFACE9 surf;
if (FAILED(D3D::dev->CreateOffscreenPlainSurface(DisplayMode.Width, DisplayMode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL)))
return S_FALSE;
if (FAILED(D3D::dev->GetFrontBufferData(0, surf)))
{
surf->Release();
return S_FALSE;
}
RECT rect;
::GetWindowRect(EmuWindow::GetWnd(), &rect);
if (FAILED(D3DXSaveSurfaceToFile(File, D3DXIFF_JPG, surf, NULL, &rect)))
{
surf->Release();
return S_FALSE;
}
surf->Release();
return S_OK;
}
BOOL Video_Screenshot(TCHAR* _szFilename)
{
if (ScreenShot(_szFilename) == S_OK)
return TRUE;
return FALSE;
}
void Video_AddMessage(const char* pstr, u32 milliseconds)
{
Renderer::AddMessage(pstr,milliseconds);
}

View File

@ -1,18 +1,18 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"

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

Some files were not shown because too many files have changed in this diff Show More