mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-05-05 12:14:23 +02:00
set svn:eol-style=native for Plugins/**.cpp
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1441 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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*)¤tPos, 0);
|
||||
int numBytesToRender = FIX128(ModBufferSize(currentPos - lastPos));
|
||||
|
||||
if (numBytesToRender >= 256)
|
||||
{
|
||||
if (numBytesToRender > sizeof(realtimeBuffer))
|
||||
MessageBox(0,"soundThread: too big render call",0,0);
|
||||
(*callback)(realtimeBuffer, numBytesToRender >> 2, 16, sampleRate, 2);
|
||||
|
||||
WriteDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender);
|
||||
currentPos = ModBufferSize(lastPos + numBytesToRender);
|
||||
totalRenderedBytes += numBytesToRender;
|
||||
|
||||
lastPos = currentPos;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&soundCriticalSection);
|
||||
WaitForSingleObject(soundSyncEvent, MAXWAIT);
|
||||
}
|
||||
|
||||
dsBuffer->Stop();
|
||||
return(0); //hurra!
|
||||
}
|
||||
|
||||
bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback)
|
||||
{
|
||||
callback = _callback;
|
||||
threadData = 0;
|
||||
sampleRate = _sampleRate;
|
||||
|
||||
//no security attributes, automatic resetting, init state nonset, untitled
|
||||
soundSyncEvent = CreateEvent(0, false, false, 0);
|
||||
|
||||
//vi initierar den...........
|
||||
InitializeCriticalSection(&soundCriticalSection);
|
||||
|
||||
//vi vill ha access till DSOUND så...
|
||||
if (FAILED(DirectSoundCreate8(0, &ds, 0)))
|
||||
return false;
|
||||
|
||||
ds->SetCooperativeLevel(window, DSSCL_NORMAL);
|
||||
|
||||
if (!CreateBuffer())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD num1;
|
||||
short* p1;
|
||||
dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0);
|
||||
memset(p1, 0, num1);
|
||||
dsBuffer->Unlock(p1, num1, 0, 0);
|
||||
totalRenderedBytes = -bufferSize;
|
||||
DWORD h;
|
||||
hThread = CreateThread(0, 0, soundThread, 0, 0, &h);
|
||||
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DSound_UpdateSound()
|
||||
{
|
||||
SetEvent(soundSyncEvent);
|
||||
}
|
||||
|
||||
void DSound_StopSound()
|
||||
{
|
||||
EnterCriticalSection(&soundCriticalSection);
|
||||
threadData = 1;
|
||||
// kick the thread if it's waiting
|
||||
SetEvent(soundSyncEvent);
|
||||
LeaveCriticalSection(&soundCriticalSection);
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
CloseHandle(hThread);
|
||||
|
||||
dsBuffer->Release();
|
||||
ds->Release();
|
||||
|
||||
CloseHandle(soundSyncEvent);
|
||||
soundSyncEvent = INVALID_HANDLE_VALUE;
|
||||
hThread = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
int DSound_GetCurSample()
|
||||
{
|
||||
EnterCriticalSection(&soundCriticalSection);
|
||||
int playCursor;
|
||||
dsBuffer->GetCurrentPosition((DWORD*)&playCursor, 0);
|
||||
playCursor = ModBufferSize(playCursor - lastPos) + totalRenderedBytes;
|
||||
LeaveCriticalSection(&soundCriticalSection);
|
||||
return(playCursor);
|
||||
}
|
||||
|
||||
float DSound_GetTimer()
|
||||
{
|
||||
return((float)DSound_GetCurSample() * (1.0f / (4.0f * sampleRate)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <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*)¤tPos, 0);
|
||||
int numBytesToRender = FIX128(ModBufferSize(currentPos - lastPos));
|
||||
|
||||
if (numBytesToRender >= 256)
|
||||
{
|
||||
if (numBytesToRender > sizeof(realtimeBuffer))
|
||||
MessageBox(0,"soundThread: too big render call",0,0);
|
||||
(*callback)(realtimeBuffer, numBytesToRender >> 2, 16, sampleRate, 2);
|
||||
|
||||
WriteDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender);
|
||||
currentPos = ModBufferSize(lastPos + numBytesToRender);
|
||||
totalRenderedBytes += numBytesToRender;
|
||||
|
||||
lastPos = currentPos;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&soundCriticalSection);
|
||||
WaitForSingleObject(soundSyncEvent, MAXWAIT);
|
||||
}
|
||||
|
||||
dsBuffer->Stop();
|
||||
return(0); //hurra!
|
||||
}
|
||||
|
||||
bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback)
|
||||
{
|
||||
callback = _callback;
|
||||
threadData = 0;
|
||||
sampleRate = _sampleRate;
|
||||
|
||||
//no security attributes, automatic resetting, init state nonset, untitled
|
||||
soundSyncEvent = CreateEvent(0, false, false, 0);
|
||||
|
||||
//vi initierar den...........
|
||||
InitializeCriticalSection(&soundCriticalSection);
|
||||
|
||||
//vi vill ha access till DSOUND så...
|
||||
if (FAILED(DirectSoundCreate8(0, &ds, 0)))
|
||||
return false;
|
||||
|
||||
ds->SetCooperativeLevel(window, DSSCL_NORMAL);
|
||||
|
||||
if (!CreateBuffer())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD num1;
|
||||
short* p1;
|
||||
dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0);
|
||||
memset(p1, 0, num1);
|
||||
dsBuffer->Unlock(p1, num1, 0, 0);
|
||||
totalRenderedBytes = -bufferSize;
|
||||
DWORD h;
|
||||
hThread = CreateThread(0, 0, soundThread, 0, 0, &h);
|
||||
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DSound_UpdateSound()
|
||||
{
|
||||
SetEvent(soundSyncEvent);
|
||||
}
|
||||
|
||||
void DSound_StopSound()
|
||||
{
|
||||
EnterCriticalSection(&soundCriticalSection);
|
||||
threadData = 1;
|
||||
// kick the thread if it's waiting
|
||||
SetEvent(soundSyncEvent);
|
||||
LeaveCriticalSection(&soundCriticalSection);
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
CloseHandle(hThread);
|
||||
|
||||
dsBuffer->Release();
|
||||
ds->Release();
|
||||
|
||||
CloseHandle(soundSyncEvent);
|
||||
soundSyncEvent = INVALID_HANDLE_VALUE;
|
||||
hThread = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
int DSound_GetCurSample()
|
||||
{
|
||||
EnterCriticalSection(&soundCriticalSection);
|
||||
int playCursor;
|
||||
dsBuffer->GetCurrentPosition((DWORD*)&playCursor, 0);
|
||||
playCursor = ModBufferSize(playCursor - lastPos) + totalRenderedBytes;
|
||||
LeaveCriticalSection(&soundCriticalSection);
|
||||
return(playCursor);
|
||||
}
|
||||
|
||||
float DSound_GetTimer()
|
||||
{
|
||||
return((float)DSound_GetCurSample() * (1.0f / (4.0f * sampleRate)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
{}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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*)¤tPos, 0);
|
||||
int numBytesToRender = FIX32(ModBufferSize(currentPos - lastPos));
|
||||
|
||||
//renderStuff(numBytesToRender/2);
|
||||
//if (numBytesToRender>bufferSize/2) numBytesToRender=0;
|
||||
|
||||
if (numBytesToRender >= 256)
|
||||
{
|
||||
(*callback)(realtimeBuffer, numBytesToRender >> 2, 16, 44100, 2);
|
||||
|
||||
writeDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender);
|
||||
|
||||
currentPos = ModBufferSize(lastPos + numBytesToRender);
|
||||
totalRenderedBytes += numBytesToRender;
|
||||
|
||||
lastPos = currentPos;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&soundCriticalSection);
|
||||
WaitForSingleObject(soundSyncEvent, MAXWAIT);
|
||||
}
|
||||
|
||||
dsBuffer->Stop();
|
||||
|
||||
threadData = 2;
|
||||
return(0); //hurra!
|
||||
}
|
||||
|
||||
|
||||
bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback)
|
||||
{
|
||||
callback = _callback;
|
||||
threadData = 0;
|
||||
sampleRate = _sampleRate;
|
||||
|
||||
//no security attributes, automatic resetting, init state nonset, untitled
|
||||
soundSyncEvent = CreateEvent(0, false, false, 0);
|
||||
|
||||
//vi initierar den...........
|
||||
InitializeCriticalSection(&soundCriticalSection);
|
||||
|
||||
//vi vill ha access till DSOUND så...
|
||||
if (FAILED(DirectSoundCreate8(0, &ds, 0)))
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
//samarbetsvillig? nää :)
|
||||
ds->SetCooperativeLevel(window, DSSCL_NORMAL); //DSSCL_PRIORITY?
|
||||
|
||||
//så.. skapa buffern
|
||||
if (!createBuffer())
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
//rensa den.. ?
|
||||
DWORD num1;
|
||||
short* p1;
|
||||
|
||||
dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0);
|
||||
|
||||
memset(p1, 0, num1);
|
||||
dsBuffer->Unlock(p1, num1, 0, 0);
|
||||
totalRenderedBytes = -bufferSize;
|
||||
DWORD h;
|
||||
hThread = CreateThread(0, 0, soundThread, 0, 0, &h);
|
||||
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
void DSound_UpdateSound()
|
||||
{
|
||||
SetEvent(soundSyncEvent);
|
||||
}
|
||||
|
||||
|
||||
void DSound_StopSound()
|
||||
{
|
||||
EnterCriticalSection(&soundCriticalSection);
|
||||
threadData = 1;
|
||||
//kick the thread if it's waiting
|
||||
SetEvent(soundSyncEvent);
|
||||
LeaveCriticalSection(&soundCriticalSection);
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
CloseHandle(hThread);
|
||||
|
||||
dsBuffer->Release();
|
||||
ds->Release();
|
||||
|
||||
CloseHandle(soundSyncEvent);
|
||||
}
|
||||
|
||||
|
||||
int DSound_GetCurSample()
|
||||
{
|
||||
EnterCriticalSection(&soundCriticalSection);
|
||||
int playCursor;
|
||||
dsBuffer->GetCurrentPosition((DWORD*)&playCursor, 0);
|
||||
playCursor = ModBufferSize(playCursor - lastPos) + totalRenderedBytes;
|
||||
LeaveCriticalSection(&soundCriticalSection);
|
||||
return(playCursor);
|
||||
}
|
||||
|
||||
|
||||
float DSound_GetTimer()
|
||||
{
|
||||
return((float)DSound_GetCurSample() * (1.0f / (4.0f * 44100.0f)));
|
||||
}
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <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*)¤tPos, 0);
|
||||
int numBytesToRender = FIX32(ModBufferSize(currentPos - lastPos));
|
||||
|
||||
//renderStuff(numBytesToRender/2);
|
||||
//if (numBytesToRender>bufferSize/2) numBytesToRender=0;
|
||||
|
||||
if (numBytesToRender >= 256)
|
||||
{
|
||||
(*callback)(realtimeBuffer, numBytesToRender >> 2, 16, 44100, 2);
|
||||
|
||||
writeDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender);
|
||||
|
||||
currentPos = ModBufferSize(lastPos + numBytesToRender);
|
||||
totalRenderedBytes += numBytesToRender;
|
||||
|
||||
lastPos = currentPos;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&soundCriticalSection);
|
||||
WaitForSingleObject(soundSyncEvent, MAXWAIT);
|
||||
}
|
||||
|
||||
dsBuffer->Stop();
|
||||
|
||||
threadData = 2;
|
||||
return(0); //hurra!
|
||||
}
|
||||
|
||||
|
||||
bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback)
|
||||
{
|
||||
callback = _callback;
|
||||
threadData = 0;
|
||||
sampleRate = _sampleRate;
|
||||
|
||||
//no security attributes, automatic resetting, init state nonset, untitled
|
||||
soundSyncEvent = CreateEvent(0, false, false, 0);
|
||||
|
||||
//vi initierar den...........
|
||||
InitializeCriticalSection(&soundCriticalSection);
|
||||
|
||||
//vi vill ha access till DSOUND så...
|
||||
if (FAILED(DirectSoundCreate8(0, &ds, 0)))
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
//samarbetsvillig? nää :)
|
||||
ds->SetCooperativeLevel(window, DSSCL_NORMAL); //DSSCL_PRIORITY?
|
||||
|
||||
//så.. skapa buffern
|
||||
if (!createBuffer())
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
//rensa den.. ?
|
||||
DWORD num1;
|
||||
short* p1;
|
||||
|
||||
dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0);
|
||||
|
||||
memset(p1, 0, num1);
|
||||
dsBuffer->Unlock(p1, num1, 0, 0);
|
||||
totalRenderedBytes = -bufferSize;
|
||||
DWORD h;
|
||||
hThread = CreateThread(0, 0, soundThread, 0, 0, &h);
|
||||
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
void DSound_UpdateSound()
|
||||
{
|
||||
SetEvent(soundSyncEvent);
|
||||
}
|
||||
|
||||
|
||||
void DSound_StopSound()
|
||||
{
|
||||
EnterCriticalSection(&soundCriticalSection);
|
||||
threadData = 1;
|
||||
//kick the thread if it's waiting
|
||||
SetEvent(soundSyncEvent);
|
||||
LeaveCriticalSection(&soundCriticalSection);
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
CloseHandle(hThread);
|
||||
|
||||
dsBuffer->Release();
|
||||
ds->Release();
|
||||
|
||||
CloseHandle(soundSyncEvent);
|
||||
}
|
||||
|
||||
|
||||
int DSound_GetCurSample()
|
||||
{
|
||||
EnterCriticalSection(&soundCriticalSection);
|
||||
int playCursor;
|
||||
dsBuffer->GetCurrentPosition((DWORD*)&playCursor, 0);
|
||||
playCursor = ModBufferSize(playCursor - lastPos) + totalRenderedBytes;
|
||||
LeaveCriticalSection(&soundCriticalSection);
|
||||
return(playCursor);
|
||||
}
|
||||
|
||||
|
||||
float DSound_GetTimer()
|
||||
{
|
||||
return((float)DSound_GetCurSample() * (1.0f / (4.0f * 44100.0f)));
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
// =======================================================================================
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
{}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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]))();
|
||||
}*/
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
} */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -1,122 +1,122 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Globals.h"
|
||||
#include "Common.h"
|
||||
#include "IniFile.h"
|
||||
#include "Config.h"
|
||||
|
||||
Config g_Config;
|
||||
|
||||
Config::Config()
|
||||
{
|
||||
memset(this, 0, sizeof(Config));
|
||||
}
|
||||
|
||||
void Config::Load()
|
||||
{
|
||||
std::string temp;
|
||||
IniFile iniFile;
|
||||
iniFile.Load(FULL_CONFIG_DIR "gfx_opengl.ini");
|
||||
|
||||
// get resolution
|
||||
iniFile.Get("Hardware", "WindowedRes", &temp, 0);
|
||||
if(temp.empty())
|
||||
temp = "640x480";
|
||||
strcpy(iWindowedRes, temp.c_str());
|
||||
iniFile.Get("Hardware", "FullscreenRes", &temp, 0);
|
||||
if(temp.empty())
|
||||
temp = "640x480";
|
||||
strcpy(iFSResolution, temp.c_str());
|
||||
|
||||
iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); // Hardware
|
||||
iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, 0);
|
||||
iniFile.Get("Settings", "StretchToFit", &bStretchToFit, false);
|
||||
iniFile.Get("Settings", "KeepAR", &bKeepAR, false);
|
||||
iniFile.Get("Settings", "HideCursor", &bHideCursor, false);
|
||||
|
||||
iniFile.Get("Settings", "SafeTextureCache", &bSafeTextureCache, false); // Settings
|
||||
iniFile.Get("Settings", "ShowFPS", &bShowFPS, false); // Settings
|
||||
iniFile.Get("Settings", "OverlayStats", &bOverlayStats, false);
|
||||
iniFile.Get("Settings", "DLOptimize", &iCompileDLsLevel, 0);
|
||||
iniFile.Get("Settings", "DumpTextures", &bDumpTextures, 0);
|
||||
iniFile.Get("Settings", "ShowShaderErrors", &bShowShaderErrors, 0);
|
||||
iniFile.Get("Settings", "Multisample", &iMultisampleMode, 0);
|
||||
if (iMultisampleMode == 0)
|
||||
iMultisampleMode = 1;
|
||||
std::string s;
|
||||
iniFile.Get("Settings", "TexDumpPath", &s, 0);
|
||||
if (s.size() < sizeof(texDumpPath) )
|
||||
strcpy(texDumpPath, s.c_str());
|
||||
else {
|
||||
strncpy(texDumpPath, s.c_str(), sizeof(texDumpPath)-1);
|
||||
texDumpPath[sizeof(texDumpPath)-1] = 0;
|
||||
}
|
||||
|
||||
iniFile.Get("Settings", "TexFmtOverlayEnable", &bTexFmtOverlayEnable, 0);
|
||||
iniFile.Get("Settings", "TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0);
|
||||
iniFile.Get("Settings", "UseXFB", &bUseXFB, 0);
|
||||
iniFile.Get("Settings", "WireFrame", &bWireFrame, 0);
|
||||
iniFile.Get("Settings", "DisableLighting", &bDisableLighting, 0);
|
||||
iniFile.Get("Settings", "DisableTexturing", &bDisableTexturing, 0);
|
||||
|
||||
iniFile.Get("Enhancements", "ForceFiltering", &bForceFiltering, 0);
|
||||
iniFile.Get("Enhancements", "MaxAnisotropy", &iMaxAnisotropy, 3); // NOTE - this is x in (1 << x)
|
||||
|
||||
iniFile.Get("Hacks", "EFBToTextureDisable", &bEFBToTextureDisable, 0);
|
||||
iniFile.Get("Hacks", "EFBToTextureDisableHotKey", &bEFBToTextureDisableHotKey, 0);
|
||||
iniFile.Get("Hacks", "ProjectionHax1", &bProjectionHax1, 0);
|
||||
iniFile.Get("Hacks", "ProjectionHax2", &bProjectionHax2, 0);
|
||||
}
|
||||
|
||||
void Config::Save()
|
||||
{
|
||||
IniFile iniFile;
|
||||
iniFile.Load(FULL_CONFIG_DIR "gfx_opengl.ini");
|
||||
iniFile.Set("Hardware", "WindowedRes", iWindowedRes);
|
||||
iniFile.Set("Hardware", "FullscreenRes", iFSResolution);
|
||||
iniFile.Set("Hardware", "Fullscreen", bFullscreen);
|
||||
iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe);
|
||||
iniFile.Set("Settings", "StretchToFit", bStretchToFit);
|
||||
iniFile.Set("Settings", "KeepAR", bKeepAR);
|
||||
iniFile.Set("Settings", "HideCursor", bHideCursor);
|
||||
|
||||
iniFile.Set("Settings", "SafeTextureCache", bSafeTextureCache);
|
||||
iniFile.Set("Settings", "ShowFPS", bShowFPS);
|
||||
iniFile.Set("Settings", "OverlayStats", bOverlayStats);
|
||||
iniFile.Set("Settings", "DLOptimize", iCompileDLsLevel);
|
||||
iniFile.Set("Settings", "DumpTextures", bDumpTextures);
|
||||
iniFile.Set("Settings", "ShowShaderErrors", bShowShaderErrors);
|
||||
iniFile.Set("Settings", "Multisample", iMultisampleMode);
|
||||
iniFile.Set("Settings", "TexDumpPath", texDumpPath);
|
||||
iniFile.Set("Settings", "TexFmtOverlayEnable", bTexFmtOverlayEnable);
|
||||
iniFile.Set("Settings", "TexFmtOverlayCenter", bTexFmtOverlayCenter);
|
||||
iniFile.Set("Settings", "UseXFB", bUseXFB);
|
||||
iniFile.Set("Settings", "Wireframe", bWireFrame);
|
||||
iniFile.Set("Settings", "DisableLighting", bDisableLighting);
|
||||
iniFile.Set("Settings", "DisableTexturing", bDisableTexturing);
|
||||
|
||||
iniFile.Set("Enhancements", "ForceFiltering", bForceFiltering);
|
||||
iniFile.Set("Enhancements", "MaxAnisotropy", iMaxAnisotropy);
|
||||
|
||||
iniFile.Set("Hacks", "EFBToTextureDisable", bEFBToTextureDisable);
|
||||
iniFile.Set("Hacks", "EFBToTextureDisableHotKey", bEFBToTextureDisableHotKey);
|
||||
iniFile.Set("Hacks", "ProjectionHax1", bProjectionHax1);
|
||||
iniFile.Set("Hacks", "ProjectionHax2", bProjectionHax2);
|
||||
|
||||
iniFile.Save(FULL_CONFIG_DIR "gfx_opengl.ini");
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Globals.h"
|
||||
#include "Common.h"
|
||||
#include "IniFile.h"
|
||||
#include "Config.h"
|
||||
|
||||
Config g_Config;
|
||||
|
||||
Config::Config()
|
||||
{
|
||||
memset(this, 0, sizeof(Config));
|
||||
}
|
||||
|
||||
void Config::Load()
|
||||
{
|
||||
std::string temp;
|
||||
IniFile iniFile;
|
||||
iniFile.Load(FULL_CONFIG_DIR "gfx_opengl.ini");
|
||||
|
||||
// get resolution
|
||||
iniFile.Get("Hardware", "WindowedRes", &temp, 0);
|
||||
if(temp.empty())
|
||||
temp = "640x480";
|
||||
strcpy(iWindowedRes, temp.c_str());
|
||||
iniFile.Get("Hardware", "FullscreenRes", &temp, 0);
|
||||
if(temp.empty())
|
||||
temp = "640x480";
|
||||
strcpy(iFSResolution, temp.c_str());
|
||||
|
||||
iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); // Hardware
|
||||
iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, 0);
|
||||
iniFile.Get("Settings", "StretchToFit", &bStretchToFit, false);
|
||||
iniFile.Get("Settings", "KeepAR", &bKeepAR, false);
|
||||
iniFile.Get("Settings", "HideCursor", &bHideCursor, false);
|
||||
|
||||
iniFile.Get("Settings", "SafeTextureCache", &bSafeTextureCache, false); // Settings
|
||||
iniFile.Get("Settings", "ShowFPS", &bShowFPS, false); // Settings
|
||||
iniFile.Get("Settings", "OverlayStats", &bOverlayStats, false);
|
||||
iniFile.Get("Settings", "DLOptimize", &iCompileDLsLevel, 0);
|
||||
iniFile.Get("Settings", "DumpTextures", &bDumpTextures, 0);
|
||||
iniFile.Get("Settings", "ShowShaderErrors", &bShowShaderErrors, 0);
|
||||
iniFile.Get("Settings", "Multisample", &iMultisampleMode, 0);
|
||||
if (iMultisampleMode == 0)
|
||||
iMultisampleMode = 1;
|
||||
std::string s;
|
||||
iniFile.Get("Settings", "TexDumpPath", &s, 0);
|
||||
if (s.size() < sizeof(texDumpPath) )
|
||||
strcpy(texDumpPath, s.c_str());
|
||||
else {
|
||||
strncpy(texDumpPath, s.c_str(), sizeof(texDumpPath)-1);
|
||||
texDumpPath[sizeof(texDumpPath)-1] = 0;
|
||||
}
|
||||
|
||||
iniFile.Get("Settings", "TexFmtOverlayEnable", &bTexFmtOverlayEnable, 0);
|
||||
iniFile.Get("Settings", "TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0);
|
||||
iniFile.Get("Settings", "UseXFB", &bUseXFB, 0);
|
||||
iniFile.Get("Settings", "WireFrame", &bWireFrame, 0);
|
||||
iniFile.Get("Settings", "DisableLighting", &bDisableLighting, 0);
|
||||
iniFile.Get("Settings", "DisableTexturing", &bDisableTexturing, 0);
|
||||
|
||||
iniFile.Get("Enhancements", "ForceFiltering", &bForceFiltering, 0);
|
||||
iniFile.Get("Enhancements", "MaxAnisotropy", &iMaxAnisotropy, 3); // NOTE - this is x in (1 << x)
|
||||
|
||||
iniFile.Get("Hacks", "EFBToTextureDisable", &bEFBToTextureDisable, 0);
|
||||
iniFile.Get("Hacks", "EFBToTextureDisableHotKey", &bEFBToTextureDisableHotKey, 0);
|
||||
iniFile.Get("Hacks", "ProjectionHax1", &bProjectionHax1, 0);
|
||||
iniFile.Get("Hacks", "ProjectionHax2", &bProjectionHax2, 0);
|
||||
}
|
||||
|
||||
void Config::Save()
|
||||
{
|
||||
IniFile iniFile;
|
||||
iniFile.Load(FULL_CONFIG_DIR "gfx_opengl.ini");
|
||||
iniFile.Set("Hardware", "WindowedRes", iWindowedRes);
|
||||
iniFile.Set("Hardware", "FullscreenRes", iFSResolution);
|
||||
iniFile.Set("Hardware", "Fullscreen", bFullscreen);
|
||||
iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe);
|
||||
iniFile.Set("Settings", "StretchToFit", bStretchToFit);
|
||||
iniFile.Set("Settings", "KeepAR", bKeepAR);
|
||||
iniFile.Set("Settings", "HideCursor", bHideCursor);
|
||||
|
||||
iniFile.Set("Settings", "SafeTextureCache", bSafeTextureCache);
|
||||
iniFile.Set("Settings", "ShowFPS", bShowFPS);
|
||||
iniFile.Set("Settings", "OverlayStats", bOverlayStats);
|
||||
iniFile.Set("Settings", "DLOptimize", iCompileDLsLevel);
|
||||
iniFile.Set("Settings", "DumpTextures", bDumpTextures);
|
||||
iniFile.Set("Settings", "ShowShaderErrors", bShowShaderErrors);
|
||||
iniFile.Set("Settings", "Multisample", iMultisampleMode);
|
||||
iniFile.Set("Settings", "TexDumpPath", texDumpPath);
|
||||
iniFile.Set("Settings", "TexFmtOverlayEnable", bTexFmtOverlayEnable);
|
||||
iniFile.Set("Settings", "TexFmtOverlayCenter", bTexFmtOverlayCenter);
|
||||
iniFile.Set("Settings", "UseXFB", bUseXFB);
|
||||
iniFile.Set("Settings", "Wireframe", bWireFrame);
|
||||
iniFile.Set("Settings", "DisableLighting", bDisableLighting);
|
||||
iniFile.Set("Settings", "DisableTexturing", bDisableTexturing);
|
||||
|
||||
iniFile.Set("Enhancements", "ForceFiltering", bForceFiltering);
|
||||
iniFile.Set("Enhancements", "MaxAnisotropy", iMaxAnisotropy);
|
||||
|
||||
iniFile.Set("Hacks", "EFBToTextureDisable", bEFBToTextureDisable);
|
||||
iniFile.Set("Hacks", "EFBToTextureDisableHotKey", bEFBToTextureDisableHotKey);
|
||||
iniFile.Set("Hacks", "ProjectionHax1", bProjectionHax1);
|
||||
iniFile.Set("Hacks", "ProjectionHax2", bProjectionHax2);
|
||||
|
||||
iniFile.Save(FULL_CONFIG_DIR "gfx_opengl.ini");
|
||||
}
|
||||
|
||||
@@ -1,482 +1,482 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "../Globals.h"
|
||||
|
||||
#include "IniFile.h" // Common files
|
||||
|
||||
#include "../Config.h" // Config settings
|
||||
|
||||
#include "PBView.h" // Debugger files
|
||||
#include "Debugger.h"
|
||||
#include "../Logging/Console.h" // open and close console
|
||||
|
||||
// externals
|
||||
extern int gSaveFile; // make this an int to allow multiple save file options
|
||||
extern int gPreset;
|
||||
int A, B;
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// Declare events
|
||||
BEGIN_EVENT_TABLE(CDebugger,wxDialog)
|
||||
EVT_SHOW(CDebugger::OnShow)
|
||||
EVT_CLOSE(CDebugger::OnClose)
|
||||
EVT_BUTTON(ID_UPD,CDebugger::OnUpdate)
|
||||
|
||||
EVT_CHECKBOX(ID_SAVETOFILE,CDebugger::GeneralSettings) // General settings
|
||||
EVT_CHECKBOX(ID_SHOWCONSOLE,CDebugger::GeneralSettings)
|
||||
EVT_CHECKLISTBOX(ID_CHECKLIST1, CDebugger::LogSettings) // Check list box
|
||||
EVT_RADIOBOX(IDC_RADIO1, CDebugger::ChangeFrequency) // Update freq.
|
||||
|
||||
EVT_BUTTON(ID_AP,CDebugger::Ap)
|
||||
EVT_BUTTON(ID_AM,CDebugger::Am)
|
||||
EVT_BUTTON(ID_BP,CDebugger::Bp)
|
||||
EVT_BUTTON(ID_BM,CDebugger::Bm)
|
||||
END_EVENT_TABLE()
|
||||
// =======================================================================================
|
||||
|
||||
|
||||
CDebugger::CDebugger(wxWindow *parent, wxWindowID id, const wxString &title,
|
||||
const wxPoint &position, const wxSize& size, long style)
|
||||
: wxDialog(parent, id, title, position, size, style)
|
||||
, m_GPRListView(NULL)
|
||||
{
|
||||
CreateGUIControls();
|
||||
|
||||
// load ini...
|
||||
IniFile file;
|
||||
file.Load(DEBUGGER_CONFIG_FILE);
|
||||
this->Load(file);
|
||||
}
|
||||
|
||||
CDebugger::~CDebugger()
|
||||
{
|
||||
// empty
|
||||
IniFile file;
|
||||
file.Load(DEBUGGER_CONFIG_FILE);
|
||||
this->Save(file);
|
||||
file.Save(DEBUGGER_CONFIG_FILE);
|
||||
}
|
||||
|
||||
void CDebugger::Save(IniFile& _IniFile) const
|
||||
{
|
||||
// TODO1: make this work when we close the entire program to, currently on total close we get
|
||||
// weird values, perhaps because of some conflict with the rendering window
|
||||
// TODO2: get the screen resolution and make limits from that
|
||||
if(GetPosition().x < 1000 && GetPosition().y < 1000
|
||||
&& GetSize().GetWidth() < 1000 && GetSize().GetHeight() < 1000
|
||||
)
|
||||
{
|
||||
_IniFile.Set("VideoWindow", "x", GetPosition().x);
|
||||
_IniFile.Set("VideoWindow", "y", GetPosition().y);
|
||||
_IniFile.Set("VideoWindow", "w", GetSize().GetWidth());
|
||||
_IniFile.Set("VideoWindow", "h", GetSize().GetHeight());
|
||||
}
|
||||
_IniFile.Set("VideoWindow", "Console", m_Check[2]->IsChecked()); // save settings
|
||||
_IniFile.Set("VideoWindow", "UpdateFrequency", m_RadioBox[1]->GetSelection());
|
||||
_IniFile.Set("VideoWindow", "LogLevel", g_Config.iLog);
|
||||
}
|
||||
|
||||
|
||||
void CDebugger::Load(IniFile& _IniFile)
|
||||
{
|
||||
int x,y,w,h;
|
||||
_IniFile.Get("VideoWindow", "x", &x, GetPosition().x);
|
||||
_IniFile.Get("VideoWindow", "y", &y, GetPosition().y);
|
||||
_IniFile.Get("VideoWindow", "w", &w, GetSize().GetWidth());
|
||||
_IniFile.Get("VideoWindow", "h", &h, GetSize().GetHeight());
|
||||
SetSize(x, y, w, h);
|
||||
|
||||
// saved settings
|
||||
bool Console;
|
||||
_IniFile.Get("VideoWindow", "Console", &Console, m_Check[2]->IsChecked());
|
||||
m_Check[2]->SetValue(Console);
|
||||
DoShowHideConsole();
|
||||
|
||||
_IniFile.Get("VideoWindow", "UpdateFrequency", &gUpdFreq, m_RadioBox[1]->GetSelection());
|
||||
m_RadioBox[1]->SetSelection(gUpdFreq);
|
||||
DoChangeFrequency();
|
||||
|
||||
_IniFile.Get("VideoWindow", "LogLevel", &g_Config.iLog, 0);
|
||||
m_settings->Check(g_Config.iLog - 1, true);
|
||||
}
|
||||
|
||||
void CDebugger::CreateGUIControls()
|
||||
{
|
||||
// Basic settings
|
||||
SetTitle(wxT("OpenGL Debugging"));
|
||||
SetIcon(wxNullIcon);
|
||||
SetSize(8, 8, 200, 100); // these will become the minimin sizes allowed by resizing
|
||||
Center();
|
||||
|
||||
// Declarations
|
||||
wxBoxSizer *sMain, *sGeneral;
|
||||
wxButton* m_Upd;
|
||||
wxButton* m_Ap; wxButton* m_Am;
|
||||
wxButton* m_Bp; wxButton* m_Bm;
|
||||
|
||||
wxStaticBoxSizer* sLeft;
|
||||
|
||||
|
||||
// Notebook -----------------------------------------------------
|
||||
m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize);
|
||||
m_PageMain = new wxPanel(m_Notebook, ID_PAGEMAIN, wxDefaultPosition, wxDefaultSize);
|
||||
m_Notebook->AddPage(m_PageMain, wxT("Main"));
|
||||
|
||||
|
||||
|
||||
// ===================================================================
|
||||
// Main Page
|
||||
|
||||
|
||||
// Buttons -----------------------------------------------------
|
||||
wxStaticBoxSizer * m_updSizer = new wxStaticBoxSizer (wxVERTICAL, m_PageMain, wxT("Update"));
|
||||
m_Upd = new wxButton(m_PageMain, ID_UPD, wxT("Update"),
|
||||
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
m_updSizer->Add(m_Upd, 0, 0, 5);
|
||||
// ------------------------
|
||||
|
||||
|
||||
// Variables -----------------------------------------------------
|
||||
wxStaticBoxSizer * m_buttonSizer = new wxStaticBoxSizer (wxVERTICAL, m_PageMain, wxT("Variables"));
|
||||
m_Ap = new wxButton(m_PageMain, ID_AP, wxT("A +"),
|
||||
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
//m_SelC->Enable(false);
|
||||
m_Am = new wxButton(m_PageMain, ID_AM, wxT("A -"),
|
||||
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
//m_Presets->Enable(false);
|
||||
m_Bp = new wxButton(m_PageMain, ID_BP, wxT("B +"),
|
||||
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
m_Bm = new wxButton(m_PageMain, ID_BM, wxT("B -"),
|
||||
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
|
||||
m_buttonSizer->Add(m_Ap, 0, 0, 5);
|
||||
m_buttonSizer->Add(m_Am, 0, 0, 5);
|
||||
m_buttonSizer->Add(m_Bp, 0, 0, 5);
|
||||
m_buttonSizer->Add(m_Bm, 0, 0, 5);
|
||||
// ------------------------
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// m_PageMain: Options
|
||||
// -------------------------
|
||||
wxStaticBoxSizer * m_optionsSizer = new wxStaticBoxSizer(wxVERTICAL, m_PageMain, wxT("Options"));
|
||||
//m_Label[0] = new wxStaticBox(m_PageMain, IDG_LABEL1, wxT("Options"),
|
||||
// wxDefaultPosition, wxDefaultSize, 0);
|
||||
//wxStaticBoxSizer * m_checkSizer3 = new wxStaticBoxSizer (m_Label[0], wxVERTICAL);
|
||||
|
||||
// checkboxes
|
||||
m_Check[0] = new wxCheckBox(m_PageMain, ID_SAVETOFILE, wxT("Save to file"),
|
||||
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
m_Check[2] = new wxCheckBox(m_PageMain, ID_SHOWCONSOLE, wxT("Show console"),
|
||||
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
|
||||
m_optionsSizer->Add(m_Check[0], 0, 0, 5);
|
||||
m_optionsSizer->Add(m_Check[2], 0, 0, 5);
|
||||
// ------------------------
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// m_PageMain: Log settings checkboxes
|
||||
// -------------------------
|
||||
wxStaticBoxSizer * m_logSizer = new wxStaticBoxSizer(wxVERTICAL, m_PageMain, wxT("Log setting"));
|
||||
m_settings = new wxCheckListBox(m_PageMain, ID_CHECKLIST1, wxDefaultPosition, wxDefaultSize,
|
||||
0, NULL, wxNO_BORDER);
|
||||
|
||||
m_settings->Append(wxT("Info log"));
|
||||
m_settings->Append(wxT("Primary log"));
|
||||
|
||||
m_settings->Check(0, bInfoLog);
|
||||
m_settings->Check(1, bPrimLog);
|
||||
|
||||
// because the wxCheckListBox is a little underdeveloped we have to help it with this
|
||||
// to bad there's no windows xp styles for the checkboxes
|
||||
m_settings->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
|
||||
m_settings->SetMinSize(wxSize(m_settings->GetSize().GetWidth() - 40,
|
||||
m_settings->GetCount() * 15));
|
||||
|
||||
m_logSizer->Add(m_settings, 0, 0, 0);
|
||||
// ------------------------
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// m_PageMain: Radio boxes
|
||||
// -------------------------
|
||||
int m_radioBoxNChoices[3];
|
||||
|
||||
wxString m_radioBoxChoices0[] = { wxT("Show base 10"), wxT("Show base 16") };
|
||||
m_radioBoxNChoices[0] = sizeof( m_radioBoxChoices0 ) / sizeof( wxString );
|
||||
m_RadioBox[0] = new wxRadioBox( m_PageMain, IDC_RADIO0, wxT("Show base"),
|
||||
wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[0], m_radioBoxChoices0, 1, wxRA_SPECIFY_COLS);
|
||||
m_RadioBox[0]->Enable(false);
|
||||
|
||||
wxString m_radioBoxChoices1[] = { wxT("Never"), wxT("5 times/s"), wxT("15 times/s"), wxT("30 times/s") };
|
||||
m_radioBoxNChoices[1] = sizeof( m_radioBoxChoices1 ) / sizeof( wxString );
|
||||
m_RadioBox[1] = new wxRadioBox( m_PageMain, IDC_RADIO1, wxT("Update freq."),
|
||||
wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[1], m_radioBoxChoices1, 1, wxRA_SPECIFY_COLS);
|
||||
|
||||
wxString m_radioBoxChoices2[] = { wxT("Win stretch") };
|
||||
m_radioBoxNChoices[2] = sizeof( m_radioBoxChoices2 ) / sizeof( wxString );
|
||||
m_RadioBox[2] = new wxRadioBox( m_PageMain, IDC_RADIO2, wxT("Presets"),
|
||||
wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[2], m_radioBoxChoices2, 1, wxRA_SPECIFY_COLS);
|
||||
// ------------------------
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Main: Left buttons and checkboxes
|
||||
// ------------------------
|
||||
wxBoxSizer* sButtons = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
//sButtons->AddStretchSpacer(1);
|
||||
|
||||
sButtons->Add(m_updSizer, 0, 0, 5); // update button
|
||||
sButtons->Add(m_buttonSizer, 0, 0, 5); // variables buttons
|
||||
sButtons->Add(m_logSizer, 0, 0, 5); // log settings
|
||||
|
||||
sButtons->Add(m_optionsSizer, 0, 2, 5); // Log options, show console etc.
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Main: Right buttons and checkboxes
|
||||
// ------------------------
|
||||
wxBoxSizer* sButtons2 = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
sButtons2->Add(m_RadioBox[0], 0, 0, 5); // Show base
|
||||
sButtons2->Add(m_RadioBox[1], 0, 0, 5); // Update frequency
|
||||
sButtons2->Add(m_RadioBox[2], 0, 0, 5); // Preset views
|
||||
//sButtons2->AddStretchSpacer(1);
|
||||
//sButtons2->Add(m_checkSizer2, 0, 2, 5);
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Main: Parameter tables view, the big window
|
||||
sLeft = new wxStaticBoxSizer(wxVERTICAL, m_PageMain, wxT("Current Status"));
|
||||
|
||||
m_GPRListView = new CPBView(m_PageMain, ID_GPR, wxDefaultPosition, GetSize(),
|
||||
wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT | wxLC_SINGLE_SEL | wxLC_SORT_ASCENDING);
|
||||
|
||||
sLeft->Add(m_GPRListView, 1, wxEXPAND|wxALL, 5);
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// General container
|
||||
// -----------------------------
|
||||
sGeneral = new wxBoxSizer(wxHORIZONTAL);
|
||||
sGeneral->Add(sLeft, 1, wxEXPAND | wxALL, 5);
|
||||
sGeneral->Add(sButtons, 0, wxEXPAND | (wxUP | wxDOWN), 5);
|
||||
sGeneral->Add(sButtons2, 0, wxEXPAND | (wxUP | wxDOWN | wxRIGHT | wxLEFT), 5);
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Main container
|
||||
// -----------------------------
|
||||
sMain = new wxBoxSizer(wxVERTICAL);
|
||||
sMain->Add(m_Notebook, 1, wxEXPAND | wxALL, 5);
|
||||
|
||||
m_PageMain->SetSizer(sGeneral);
|
||||
this->SetSizer(sMain);
|
||||
//sGeneral->SetSizeHints(this);
|
||||
|
||||
//NotifyUpdate();
|
||||
//Freeze(); // unfreeze this if you want to use it
|
||||
}
|
||||
|
||||
|
||||
// ==========================================================================
|
||||
// System functions
|
||||
// --------------
|
||||
void CDebugger::OnShow(wxShowEvent& /*event*/)
|
||||
{
|
||||
// bring the console back to
|
||||
if(m_Check[2]->IsChecked())
|
||||
{
|
||||
OpenConsole();
|
||||
#ifdef _WIN32
|
||||
MoveWindow(GetConsoleHwnd(), 0,400, 1280,500, true); // Move window TODO: make this
|
||||
// adjustable from the debugging window
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void CDebugger::OnClose(wxCloseEvent& /*event*/)
|
||||
{
|
||||
// save the window position when we hide the window to
|
||||
IniFile file;
|
||||
file.Load(DEBUGGER_CONFIG_FILE);
|
||||
this->Save(file);
|
||||
file.Save(DEBUGGER_CONFIG_FILE);
|
||||
|
||||
EndModal(0); // it seems like this works for Show() to, not just ShowModal();
|
||||
CloseConsole(); // The console goes with the wx window
|
||||
}
|
||||
|
||||
|
||||
void CDebugger::DoHide()
|
||||
{
|
||||
Hide();
|
||||
CloseConsole(); // The console goes with the wx window
|
||||
}
|
||||
|
||||
void CDebugger::DoShow()
|
||||
{
|
||||
Show();
|
||||
DoShowHideConsole(); // The console goes with the wx window
|
||||
}
|
||||
|
||||
|
||||
void CDebugger::OnUpdate(wxCommandEvent& /*event*/)
|
||||
{
|
||||
this->NotifyUpdate();
|
||||
}
|
||||
// ===============
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// Change preset
|
||||
// --------------
|
||||
void CDebugger::ChangePreset(wxCommandEvent& event)
|
||||
{
|
||||
DoChangePreset();
|
||||
}
|
||||
|
||||
void CDebugger::DoChangePreset()
|
||||
{
|
||||
if(m_RadioBox[2]->GetSelection() == 0)
|
||||
gPreset = 0;
|
||||
else if(m_RadioBox[2]->GetSelection() == 1)
|
||||
gPreset = 1;
|
||||
else if(m_RadioBox[2]->GetSelection() == 2)
|
||||
gPreset = 2;
|
||||
else if(m_RadioBox[2]->GetSelection() == 3)
|
||||
gPreset = 3;
|
||||
}
|
||||
// ==============
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// Control variables
|
||||
// --------------
|
||||
void CDebugger::Ap(wxCommandEvent& event)
|
||||
{
|
||||
A += 50;
|
||||
//MessageBox(0, "", "", 0);
|
||||
__Log("%i", A);
|
||||
}
|
||||
void CDebugger::Am(wxCommandEvent& event)
|
||||
{
|
||||
A -= 50;
|
||||
}
|
||||
void CDebugger::Bp(wxCommandEvent& event)
|
||||
{
|
||||
B += 50;
|
||||
}
|
||||
void CDebugger::Bm(wxCommandEvent& event)
|
||||
{
|
||||
B -= 50;
|
||||
}
|
||||
// ==============
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// Change update frequency
|
||||
// --------------
|
||||
void CDebugger::ChangeFrequency(wxCommandEvent& event)
|
||||
{
|
||||
DoChangeFrequency();
|
||||
}
|
||||
|
||||
void CDebugger::DoChangeFrequency()
|
||||
{
|
||||
if(m_RadioBox[1]->GetSelection() == 0)
|
||||
gUpdFreq = 0;
|
||||
else if(m_RadioBox[1]->GetSelection() == 1)
|
||||
gUpdFreq = 5;
|
||||
else if(m_RadioBox[1]->GetSelection() == 2)
|
||||
gUpdFreq = 15;
|
||||
else
|
||||
gUpdFreq = 30;
|
||||
}
|
||||
// ==============
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// General settings
|
||||
// --------------
|
||||
void CDebugger::GeneralSettings(wxCommandEvent& event)
|
||||
{
|
||||
switch (event.GetId())
|
||||
{
|
||||
case ID_SAVETOFILE: // Save to file
|
||||
gSaveFile = m_Check[0]->IsChecked();
|
||||
break;
|
||||
case ID_SHOWCONSOLE:
|
||||
DoShowHideConsole();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// ==============
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// Show or hide console window
|
||||
// --------------
|
||||
void CDebugger::DoShowHideConsole()
|
||||
{
|
||||
if(m_Check[2]->IsChecked())
|
||||
{
|
||||
OpenConsole();
|
||||
#ifdef _WIN32
|
||||
MoveWindow(GetConsoleHwnd(), 0,400, 1280,500, true); // move window, TODO: make this
|
||||
// adjustable from the debugging window
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseConsole();
|
||||
}
|
||||
}
|
||||
// ==============
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// Enable or disable logs
|
||||
// --------------
|
||||
void CDebugger::LogSettings(wxCommandEvent& event)
|
||||
{
|
||||
// Only allow one selected log at a time
|
||||
for (u32 i = 0; i < m_settings->GetCount(); ++i)
|
||||
if(i != (u32)event.GetInt()) m_settings->Check(i, false);
|
||||
|
||||
if(m_settings->IsChecked(0)) g_Config.iLog = CONF_LOG;
|
||||
else if(m_settings->IsChecked(1)) g_Config.iLog = CONF_PRIMLOG;
|
||||
else g_Config.iLog = 0;
|
||||
}
|
||||
// ==============
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// Update the wxListCtrl
|
||||
// --------------
|
||||
void CDebugger::NotifyUpdate()
|
||||
{
|
||||
if (m_GPRListView != NULL)
|
||||
{
|
||||
m_GPRListView->Update();
|
||||
}
|
||||
}
|
||||
// ==============
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "../Globals.h"
|
||||
|
||||
#include "IniFile.h" // Common files
|
||||
|
||||
#include "../Config.h" // Config settings
|
||||
|
||||
#include "PBView.h" // Debugger files
|
||||
#include "Debugger.h"
|
||||
#include "../Logging/Console.h" // open and close console
|
||||
|
||||
// externals
|
||||
extern int gSaveFile; // make this an int to allow multiple save file options
|
||||
extern int gPreset;
|
||||
int A, B;
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// Declare events
|
||||
BEGIN_EVENT_TABLE(CDebugger,wxDialog)
|
||||
EVT_SHOW(CDebugger::OnShow)
|
||||
EVT_CLOSE(CDebugger::OnClose)
|
||||
EVT_BUTTON(ID_UPD,CDebugger::OnUpdate)
|
||||
|
||||
EVT_CHECKBOX(ID_SAVETOFILE,CDebugger::GeneralSettings) // General settings
|
||||
EVT_CHECKBOX(ID_SHOWCONSOLE,CDebugger::GeneralSettings)
|
||||
EVT_CHECKLISTBOX(ID_CHECKLIST1, CDebugger::LogSettings) // Check list box
|
||||
EVT_RADIOBOX(IDC_RADIO1, CDebugger::ChangeFrequency) // Update freq.
|
||||
|
||||
EVT_BUTTON(ID_AP,CDebugger::Ap)
|
||||
EVT_BUTTON(ID_AM,CDebugger::Am)
|
||||
EVT_BUTTON(ID_BP,CDebugger::Bp)
|
||||
EVT_BUTTON(ID_BM,CDebugger::Bm)
|
||||
END_EVENT_TABLE()
|
||||
// =======================================================================================
|
||||
|
||||
|
||||
CDebugger::CDebugger(wxWindow *parent, wxWindowID id, const wxString &title,
|
||||
const wxPoint &position, const wxSize& size, long style)
|
||||
: wxDialog(parent, id, title, position, size, style)
|
||||
, m_GPRListView(NULL)
|
||||
{
|
||||
CreateGUIControls();
|
||||
|
||||
// load ini...
|
||||
IniFile file;
|
||||
file.Load(DEBUGGER_CONFIG_FILE);
|
||||
this->Load(file);
|
||||
}
|
||||
|
||||
CDebugger::~CDebugger()
|
||||
{
|
||||
// empty
|
||||
IniFile file;
|
||||
file.Load(DEBUGGER_CONFIG_FILE);
|
||||
this->Save(file);
|
||||
file.Save(DEBUGGER_CONFIG_FILE);
|
||||
}
|
||||
|
||||
void CDebugger::Save(IniFile& _IniFile) const
|
||||
{
|
||||
// TODO1: make this work when we close the entire program to, currently on total close we get
|
||||
// weird values, perhaps because of some conflict with the rendering window
|
||||
// TODO2: get the screen resolution and make limits from that
|
||||
if(GetPosition().x < 1000 && GetPosition().y < 1000
|
||||
&& GetSize().GetWidth() < 1000 && GetSize().GetHeight() < 1000
|
||||
)
|
||||
{
|
||||
_IniFile.Set("VideoWindow", "x", GetPosition().x);
|
||||
_IniFile.Set("VideoWindow", "y", GetPosition().y);
|
||||
_IniFile.Set("VideoWindow", "w", GetSize().GetWidth());
|
||||
_IniFile.Set("VideoWindow", "h", GetSize().GetHeight());
|
||||
}
|
||||
_IniFile.Set("VideoWindow", "Console", m_Check[2]->IsChecked()); // save settings
|
||||
_IniFile.Set("VideoWindow", "UpdateFrequency", m_RadioBox[1]->GetSelection());
|
||||
_IniFile.Set("VideoWindow", "LogLevel", g_Config.iLog);
|
||||
}
|
||||
|
||||
|
||||
void CDebugger::Load(IniFile& _IniFile)
|
||||
{
|
||||
int x,y,w,h;
|
||||
_IniFile.Get("VideoWindow", "x", &x, GetPosition().x);
|
||||
_IniFile.Get("VideoWindow", "y", &y, GetPosition().y);
|
||||
_IniFile.Get("VideoWindow", "w", &w, GetSize().GetWidth());
|
||||
_IniFile.Get("VideoWindow", "h", &h, GetSize().GetHeight());
|
||||
SetSize(x, y, w, h);
|
||||
|
||||
// saved settings
|
||||
bool Console;
|
||||
_IniFile.Get("VideoWindow", "Console", &Console, m_Check[2]->IsChecked());
|
||||
m_Check[2]->SetValue(Console);
|
||||
DoShowHideConsole();
|
||||
|
||||
_IniFile.Get("VideoWindow", "UpdateFrequency", &gUpdFreq, m_RadioBox[1]->GetSelection());
|
||||
m_RadioBox[1]->SetSelection(gUpdFreq);
|
||||
DoChangeFrequency();
|
||||
|
||||
_IniFile.Get("VideoWindow", "LogLevel", &g_Config.iLog, 0);
|
||||
m_settings->Check(g_Config.iLog - 1, true);
|
||||
}
|
||||
|
||||
void CDebugger::CreateGUIControls()
|
||||
{
|
||||
// Basic settings
|
||||
SetTitle(wxT("OpenGL Debugging"));
|
||||
SetIcon(wxNullIcon);
|
||||
SetSize(8, 8, 200, 100); // these will become the minimin sizes allowed by resizing
|
||||
Center();
|
||||
|
||||
// Declarations
|
||||
wxBoxSizer *sMain, *sGeneral;
|
||||
wxButton* m_Upd;
|
||||
wxButton* m_Ap; wxButton* m_Am;
|
||||
wxButton* m_Bp; wxButton* m_Bm;
|
||||
|
||||
wxStaticBoxSizer* sLeft;
|
||||
|
||||
|
||||
// Notebook -----------------------------------------------------
|
||||
m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize);
|
||||
m_PageMain = new wxPanel(m_Notebook, ID_PAGEMAIN, wxDefaultPosition, wxDefaultSize);
|
||||
m_Notebook->AddPage(m_PageMain, wxT("Main"));
|
||||
|
||||
|
||||
|
||||
// ===================================================================
|
||||
// Main Page
|
||||
|
||||
|
||||
// Buttons -----------------------------------------------------
|
||||
wxStaticBoxSizer * m_updSizer = new wxStaticBoxSizer (wxVERTICAL, m_PageMain, wxT("Update"));
|
||||
m_Upd = new wxButton(m_PageMain, ID_UPD, wxT("Update"),
|
||||
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
m_updSizer->Add(m_Upd, 0, 0, 5);
|
||||
// ------------------------
|
||||
|
||||
|
||||
// Variables -----------------------------------------------------
|
||||
wxStaticBoxSizer * m_buttonSizer = new wxStaticBoxSizer (wxVERTICAL, m_PageMain, wxT("Variables"));
|
||||
m_Ap = new wxButton(m_PageMain, ID_AP, wxT("A +"),
|
||||
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
//m_SelC->Enable(false);
|
||||
m_Am = new wxButton(m_PageMain, ID_AM, wxT("A -"),
|
||||
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
//m_Presets->Enable(false);
|
||||
m_Bp = new wxButton(m_PageMain, ID_BP, wxT("B +"),
|
||||
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
m_Bm = new wxButton(m_PageMain, ID_BM, wxT("B -"),
|
||||
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
|
||||
m_buttonSizer->Add(m_Ap, 0, 0, 5);
|
||||
m_buttonSizer->Add(m_Am, 0, 0, 5);
|
||||
m_buttonSizer->Add(m_Bp, 0, 0, 5);
|
||||
m_buttonSizer->Add(m_Bm, 0, 0, 5);
|
||||
// ------------------------
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// m_PageMain: Options
|
||||
// -------------------------
|
||||
wxStaticBoxSizer * m_optionsSizer = new wxStaticBoxSizer(wxVERTICAL, m_PageMain, wxT("Options"));
|
||||
//m_Label[0] = new wxStaticBox(m_PageMain, IDG_LABEL1, wxT("Options"),
|
||||
// wxDefaultPosition, wxDefaultSize, 0);
|
||||
//wxStaticBoxSizer * m_checkSizer3 = new wxStaticBoxSizer (m_Label[0], wxVERTICAL);
|
||||
|
||||
// checkboxes
|
||||
m_Check[0] = new wxCheckBox(m_PageMain, ID_SAVETOFILE, wxT("Save to file"),
|
||||
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
m_Check[2] = new wxCheckBox(m_PageMain, ID_SHOWCONSOLE, wxT("Show console"),
|
||||
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
|
||||
m_optionsSizer->Add(m_Check[0], 0, 0, 5);
|
||||
m_optionsSizer->Add(m_Check[2], 0, 0, 5);
|
||||
// ------------------------
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// m_PageMain: Log settings checkboxes
|
||||
// -------------------------
|
||||
wxStaticBoxSizer * m_logSizer = new wxStaticBoxSizer(wxVERTICAL, m_PageMain, wxT("Log setting"));
|
||||
m_settings = new wxCheckListBox(m_PageMain, ID_CHECKLIST1, wxDefaultPosition, wxDefaultSize,
|
||||
0, NULL, wxNO_BORDER);
|
||||
|
||||
m_settings->Append(wxT("Info log"));
|
||||
m_settings->Append(wxT("Primary log"));
|
||||
|
||||
m_settings->Check(0, bInfoLog);
|
||||
m_settings->Check(1, bPrimLog);
|
||||
|
||||
// because the wxCheckListBox is a little underdeveloped we have to help it with this
|
||||
// to bad there's no windows xp styles for the checkboxes
|
||||
m_settings->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
|
||||
m_settings->SetMinSize(wxSize(m_settings->GetSize().GetWidth() - 40,
|
||||
m_settings->GetCount() * 15));
|
||||
|
||||
m_logSizer->Add(m_settings, 0, 0, 0);
|
||||
// ------------------------
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// m_PageMain: Radio boxes
|
||||
// -------------------------
|
||||
int m_radioBoxNChoices[3];
|
||||
|
||||
wxString m_radioBoxChoices0[] = { wxT("Show base 10"), wxT("Show base 16") };
|
||||
m_radioBoxNChoices[0] = sizeof( m_radioBoxChoices0 ) / sizeof( wxString );
|
||||
m_RadioBox[0] = new wxRadioBox( m_PageMain, IDC_RADIO0, wxT("Show base"),
|
||||
wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[0], m_radioBoxChoices0, 1, wxRA_SPECIFY_COLS);
|
||||
m_RadioBox[0]->Enable(false);
|
||||
|
||||
wxString m_radioBoxChoices1[] = { wxT("Never"), wxT("5 times/s"), wxT("15 times/s"), wxT("30 times/s") };
|
||||
m_radioBoxNChoices[1] = sizeof( m_radioBoxChoices1 ) / sizeof( wxString );
|
||||
m_RadioBox[1] = new wxRadioBox( m_PageMain, IDC_RADIO1, wxT("Update freq."),
|
||||
wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[1], m_radioBoxChoices1, 1, wxRA_SPECIFY_COLS);
|
||||
|
||||
wxString m_radioBoxChoices2[] = { wxT("Win stretch") };
|
||||
m_radioBoxNChoices[2] = sizeof( m_radioBoxChoices2 ) / sizeof( wxString );
|
||||
m_RadioBox[2] = new wxRadioBox( m_PageMain, IDC_RADIO2, wxT("Presets"),
|
||||
wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[2], m_radioBoxChoices2, 1, wxRA_SPECIFY_COLS);
|
||||
// ------------------------
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Main: Left buttons and checkboxes
|
||||
// ------------------------
|
||||
wxBoxSizer* sButtons = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
//sButtons->AddStretchSpacer(1);
|
||||
|
||||
sButtons->Add(m_updSizer, 0, 0, 5); // update button
|
||||
sButtons->Add(m_buttonSizer, 0, 0, 5); // variables buttons
|
||||
sButtons->Add(m_logSizer, 0, 0, 5); // log settings
|
||||
|
||||
sButtons->Add(m_optionsSizer, 0, 2, 5); // Log options, show console etc.
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Main: Right buttons and checkboxes
|
||||
// ------------------------
|
||||
wxBoxSizer* sButtons2 = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
sButtons2->Add(m_RadioBox[0], 0, 0, 5); // Show base
|
||||
sButtons2->Add(m_RadioBox[1], 0, 0, 5); // Update frequency
|
||||
sButtons2->Add(m_RadioBox[2], 0, 0, 5); // Preset views
|
||||
//sButtons2->AddStretchSpacer(1);
|
||||
//sButtons2->Add(m_checkSizer2, 0, 2, 5);
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Main: Parameter tables view, the big window
|
||||
sLeft = new wxStaticBoxSizer(wxVERTICAL, m_PageMain, wxT("Current Status"));
|
||||
|
||||
m_GPRListView = new CPBView(m_PageMain, ID_GPR, wxDefaultPosition, GetSize(),
|
||||
wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT | wxLC_SINGLE_SEL | wxLC_SORT_ASCENDING);
|
||||
|
||||
sLeft->Add(m_GPRListView, 1, wxEXPAND|wxALL, 5);
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// General container
|
||||
// -----------------------------
|
||||
sGeneral = new wxBoxSizer(wxHORIZONTAL);
|
||||
sGeneral->Add(sLeft, 1, wxEXPAND | wxALL, 5);
|
||||
sGeneral->Add(sButtons, 0, wxEXPAND | (wxUP | wxDOWN), 5);
|
||||
sGeneral->Add(sButtons2, 0, wxEXPAND | (wxUP | wxDOWN | wxRIGHT | wxLEFT), 5);
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Main container
|
||||
// -----------------------------
|
||||
sMain = new wxBoxSizer(wxVERTICAL);
|
||||
sMain->Add(m_Notebook, 1, wxEXPAND | wxALL, 5);
|
||||
|
||||
m_PageMain->SetSizer(sGeneral);
|
||||
this->SetSizer(sMain);
|
||||
//sGeneral->SetSizeHints(this);
|
||||
|
||||
//NotifyUpdate();
|
||||
//Freeze(); // unfreeze this if you want to use it
|
||||
}
|
||||
|
||||
|
||||
// ==========================================================================
|
||||
// System functions
|
||||
// --------------
|
||||
void CDebugger::OnShow(wxShowEvent& /*event*/)
|
||||
{
|
||||
// bring the console back to
|
||||
if(m_Check[2]->IsChecked())
|
||||
{
|
||||
OpenConsole();
|
||||
#ifdef _WIN32
|
||||
MoveWindow(GetConsoleHwnd(), 0,400, 1280,500, true); // Move window TODO: make this
|
||||
// adjustable from the debugging window
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void CDebugger::OnClose(wxCloseEvent& /*event*/)
|
||||
{
|
||||
// save the window position when we hide the window to
|
||||
IniFile file;
|
||||
file.Load(DEBUGGER_CONFIG_FILE);
|
||||
this->Save(file);
|
||||
file.Save(DEBUGGER_CONFIG_FILE);
|
||||
|
||||
EndModal(0); // it seems like this works for Show() to, not just ShowModal();
|
||||
CloseConsole(); // The console goes with the wx window
|
||||
}
|
||||
|
||||
|
||||
void CDebugger::DoHide()
|
||||
{
|
||||
Hide();
|
||||
CloseConsole(); // The console goes with the wx window
|
||||
}
|
||||
|
||||
void CDebugger::DoShow()
|
||||
{
|
||||
Show();
|
||||
DoShowHideConsole(); // The console goes with the wx window
|
||||
}
|
||||
|
||||
|
||||
void CDebugger::OnUpdate(wxCommandEvent& /*event*/)
|
||||
{
|
||||
this->NotifyUpdate();
|
||||
}
|
||||
// ===============
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// Change preset
|
||||
// --------------
|
||||
void CDebugger::ChangePreset(wxCommandEvent& event)
|
||||
{
|
||||
DoChangePreset();
|
||||
}
|
||||
|
||||
void CDebugger::DoChangePreset()
|
||||
{
|
||||
if(m_RadioBox[2]->GetSelection() == 0)
|
||||
gPreset = 0;
|
||||
else if(m_RadioBox[2]->GetSelection() == 1)
|
||||
gPreset = 1;
|
||||
else if(m_RadioBox[2]->GetSelection() == 2)
|
||||
gPreset = 2;
|
||||
else if(m_RadioBox[2]->GetSelection() == 3)
|
||||
gPreset = 3;
|
||||
}
|
||||
// ==============
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// Control variables
|
||||
// --------------
|
||||
void CDebugger::Ap(wxCommandEvent& event)
|
||||
{
|
||||
A += 50;
|
||||
//MessageBox(0, "", "", 0);
|
||||
__Log("%i", A);
|
||||
}
|
||||
void CDebugger::Am(wxCommandEvent& event)
|
||||
{
|
||||
A -= 50;
|
||||
}
|
||||
void CDebugger::Bp(wxCommandEvent& event)
|
||||
{
|
||||
B += 50;
|
||||
}
|
||||
void CDebugger::Bm(wxCommandEvent& event)
|
||||
{
|
||||
B -= 50;
|
||||
}
|
||||
// ==============
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// Change update frequency
|
||||
// --------------
|
||||
void CDebugger::ChangeFrequency(wxCommandEvent& event)
|
||||
{
|
||||
DoChangeFrequency();
|
||||
}
|
||||
|
||||
void CDebugger::DoChangeFrequency()
|
||||
{
|
||||
if(m_RadioBox[1]->GetSelection() == 0)
|
||||
gUpdFreq = 0;
|
||||
else if(m_RadioBox[1]->GetSelection() == 1)
|
||||
gUpdFreq = 5;
|
||||
else if(m_RadioBox[1]->GetSelection() == 2)
|
||||
gUpdFreq = 15;
|
||||
else
|
||||
gUpdFreq = 30;
|
||||
}
|
||||
// ==============
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// General settings
|
||||
// --------------
|
||||
void CDebugger::GeneralSettings(wxCommandEvent& event)
|
||||
{
|
||||
switch (event.GetId())
|
||||
{
|
||||
case ID_SAVETOFILE: // Save to file
|
||||
gSaveFile = m_Check[0]->IsChecked();
|
||||
break;
|
||||
case ID_SHOWCONSOLE:
|
||||
DoShowHideConsole();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// ==============
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// Show or hide console window
|
||||
// --------------
|
||||
void CDebugger::DoShowHideConsole()
|
||||
{
|
||||
if(m_Check[2]->IsChecked())
|
||||
{
|
||||
OpenConsole();
|
||||
#ifdef _WIN32
|
||||
MoveWindow(GetConsoleHwnd(), 0,400, 1280,500, true); // move window, TODO: make this
|
||||
// adjustable from the debugging window
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseConsole();
|
||||
}
|
||||
}
|
||||
// ==============
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// Enable or disable logs
|
||||
// --------------
|
||||
void CDebugger::LogSettings(wxCommandEvent& event)
|
||||
{
|
||||
// Only allow one selected log at a time
|
||||
for (u32 i = 0; i < m_settings->GetCount(); ++i)
|
||||
if(i != (u32)event.GetInt()) m_settings->Check(i, false);
|
||||
|
||||
if(m_settings->IsChecked(0)) g_Config.iLog = CONF_LOG;
|
||||
else if(m_settings->IsChecked(1)) g_Config.iLog = CONF_PRIMLOG;
|
||||
else g_Config.iLog = 0;
|
||||
}
|
||||
// ==============
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// Update the wxListCtrl
|
||||
// --------------
|
||||
void CDebugger::NotifyUpdate()
|
||||
{
|
||||
if (m_GPRListView != NULL)
|
||||
{
|
||||
m_GPRListView->Update();
|
||||
}
|
||||
}
|
||||
// ==============
|
||||
|
||||
@@ -1,124 +1,124 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "../Globals.h"
|
||||
#include "PBView.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern const char* GetGRPName(unsigned int index);
|
||||
|
||||
BEGIN_EVENT_TABLE(CPBView, wxListCtrl)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
CPBView::CPBView(wxWindow* parent, const wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
|
||||
: wxListCtrl(parent, id, pos, size, style)
|
||||
{
|
||||
InsertColumn(0, wxT("Block"), wxLIST_FORMAT_CENTER, 40);
|
||||
|
||||
SetFont(wxFont(8, wxSWISS, wxNORMAL, wxNORMAL, false, wxT("Segoe UI")));
|
||||
|
||||
for (int i = 0; i < 1; i++)
|
||||
{
|
||||
// Print values from 0 to 63
|
||||
char buffer [33];
|
||||
sprintf(buffer, "%02i", i);
|
||||
int Item = InsertItem(0, wxString::FromAscii(buffer));
|
||||
|
||||
|
||||
wxListItem item;
|
||||
item.SetId(Item);
|
||||
item.SetBackgroundColour(0xFFFFFF);
|
||||
item.SetData(i);
|
||||
SetItem(item);
|
||||
}
|
||||
|
||||
// This is a wx call that leads to MSWDrawSubItem
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void CPBView::Update()
|
||||
{
|
||||
|
||||
Refresh();
|
||||
|
||||
}
|
||||
#ifdef _WIN32
|
||||
bool CPBView::MSWDrawSubItem(wxPaintDC& rPainDC, int item, int subitem)
|
||||
{
|
||||
bool Result = false;
|
||||
|
||||
// don't change 0, it has the block values
|
||||
if(subitem > 0)
|
||||
{
|
||||
#ifdef __WXMSW__ // what's this? should I use that?
|
||||
const wxChar* bgColor = _T("#ffffff");
|
||||
wxBrush bgBrush(bgColor);
|
||||
wxPen bgPen(bgColor);
|
||||
|
||||
wxRect SubItemRect;
|
||||
this->GetSubItemRect(item, subitem, SubItemRect);
|
||||
rPainDC.SetBrush(bgBrush);
|
||||
rPainDC.SetPen(bgPen);
|
||||
rPainDC.DrawRectangle(SubItemRect);
|
||||
#endif
|
||||
// A somewhat primitive attempt to show the playing history for a certain block.
|
||||
|
||||
wxString text;
|
||||
if(subitem == 1)
|
||||
{
|
||||
char cbuff [33];
|
||||
|
||||
sprintf(cbuff, "%08i", m_CachedRegs[subitem][item]);
|
||||
std::string c = cbuff;
|
||||
int n[8];
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
|
||||
n[j] = atoi( c.substr(j, 1).c_str());
|
||||
// 149 = dot, 160 = space
|
||||
if (n[j] == 1){
|
||||
n[j] = 149;} else {n[j] = 160;}
|
||||
}
|
||||
// pretty neat huh?
|
||||
text.Printf(wxT("%c%c%c%c%c%c%c%c"), n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
text.Printf(wxT("0x%08x"), m_CachedRegs[subitem][item]);
|
||||
}
|
||||
#ifdef __WXMSW__
|
||||
rPainDC.DrawText(text, SubItemRect.GetLeft() + 10, SubItemRect.GetTop() + 4);
|
||||
#else
|
||||
// May not show up pretty in !Win32
|
||||
rPainDC.DrawText(text, 10, 4);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// what does this mean?
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "../Globals.h"
|
||||
#include "PBView.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern const char* GetGRPName(unsigned int index);
|
||||
|
||||
BEGIN_EVENT_TABLE(CPBView, wxListCtrl)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
CPBView::CPBView(wxWindow* parent, const wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
|
||||
: wxListCtrl(parent, id, pos, size, style)
|
||||
{
|
||||
InsertColumn(0, wxT("Block"), wxLIST_FORMAT_CENTER, 40);
|
||||
|
||||
SetFont(wxFont(8, wxSWISS, wxNORMAL, wxNORMAL, false, wxT("Segoe UI")));
|
||||
|
||||
for (int i = 0; i < 1; i++)
|
||||
{
|
||||
// Print values from 0 to 63
|
||||
char buffer [33];
|
||||
sprintf(buffer, "%02i", i);
|
||||
int Item = InsertItem(0, wxString::FromAscii(buffer));
|
||||
|
||||
|
||||
wxListItem item;
|
||||
item.SetId(Item);
|
||||
item.SetBackgroundColour(0xFFFFFF);
|
||||
item.SetData(i);
|
||||
SetItem(item);
|
||||
}
|
||||
|
||||
// This is a wx call that leads to MSWDrawSubItem
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void CPBView::Update()
|
||||
{
|
||||
|
||||
Refresh();
|
||||
|
||||
}
|
||||
#ifdef _WIN32
|
||||
bool CPBView::MSWDrawSubItem(wxPaintDC& rPainDC, int item, int subitem)
|
||||
{
|
||||
bool Result = false;
|
||||
|
||||
// don't change 0, it has the block values
|
||||
if(subitem > 0)
|
||||
{
|
||||
#ifdef __WXMSW__ // what's this? should I use that?
|
||||
const wxChar* bgColor = _T("#ffffff");
|
||||
wxBrush bgBrush(bgColor);
|
||||
wxPen bgPen(bgColor);
|
||||
|
||||
wxRect SubItemRect;
|
||||
this->GetSubItemRect(item, subitem, SubItemRect);
|
||||
rPainDC.SetBrush(bgBrush);
|
||||
rPainDC.SetPen(bgPen);
|
||||
rPainDC.DrawRectangle(SubItemRect);
|
||||
#endif
|
||||
// A somewhat primitive attempt to show the playing history for a certain block.
|
||||
|
||||
wxString text;
|
||||
if(subitem == 1)
|
||||
{
|
||||
char cbuff [33];
|
||||
|
||||
sprintf(cbuff, "%08i", m_CachedRegs[subitem][item]);
|
||||
std::string c = cbuff;
|
||||
int n[8];
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
|
||||
n[j] = atoi( c.substr(j, 1).c_str());
|
||||
// 149 = dot, 160 = space
|
||||
if (n[j] == 1){
|
||||
n[j] = 149;} else {n[j] = 160;}
|
||||
}
|
||||
// pretty neat huh?
|
||||
text.Printf(wxT("%c%c%c%c%c%c%c%c"), n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
text.Printf(wxT("0x%08x"), m_CachedRegs[subitem][item]);
|
||||
}
|
||||
#ifdef __WXMSW__
|
||||
rPainDC.DrawText(text, SubItemRect.GetLeft() + 10, SubItemRect.GetTop() + 4);
|
||||
#else
|
||||
// May not show up pretty in !Win32
|
||||
rPainDC.DrawText(text, 10, 4);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// what does this mean?
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user