diff --git a/citra.sln b/citra.sln
index ebba4c2f0..af1f1ee55 100644
--- a/citra.sln
+++ b/citra.sln
@@ -1,5 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Express 2013 for Windows Desktop
+# Visual Studio 2013
VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "src\common\common.vcxproj", "{DFE335FC-755D-4BAA-8452-94434F8A1EDB}"
@@ -10,6 +10,7 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "citra", "src\citra\citra.vcxproj", "{CE7D2C07-21CE-4590-81AB-2ADA88A2B85F}"
ProjectSection(ProjectDependencies) = postProject
{69F00340-5C3D-449F-9A80-958435C6CF06} = {69F00340-5C3D-449F-9A80-958435C6CF06}
+ {6678D1A3-33A6-48A9-878B-48E5D2903D27} = {6678D1A3-33A6-48A9-878B-48E5D2903D27}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core", "src\core\core.vcxproj", "{8AEA7F29-3466-4786-A10D-6A4BD0610977}"
@@ -21,6 +22,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scm_rev_gen", "src\common\s
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "citra_qt", "src\citra_qt\citra_qt.vcxproj", "{A587F714-490F-407A-9E36-7AB7FA0D7BAB}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video_core", "src\video_core\video_core.vcxproj", "{6678D1A3-33A6-48A9-878B-48E5D2903D27}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -69,6 +72,14 @@ Global
{A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Release|Win32.Build.0 = Release|Win32
{A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Release|x64.ActiveCfg = Release|x64
{A587F714-490F-407A-9E36-7AB7FA0D7BAB}.Release|x64.Build.0 = Release|x64
+ {6678D1A3-33A6-48A9-878B-48E5D2903D27}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6678D1A3-33A6-48A9-878B-48E5D2903D27}.Debug|Win32.Build.0 = Debug|Win32
+ {6678D1A3-33A6-48A9-878B-48E5D2903D27}.Debug|x64.ActiveCfg = Debug|x64
+ {6678D1A3-33A6-48A9-878B-48E5D2903D27}.Debug|x64.Build.0 = Debug|x64
+ {6678D1A3-33A6-48A9-878B-48E5D2903D27}.Release|Win32.ActiveCfg = Release|Win32
+ {6678D1A3-33A6-48A9-878B-48E5D2903D27}.Release|Win32.Build.0 = Release|Win32
+ {6678D1A3-33A6-48A9-878B-48E5D2903D27}.Release|x64.ActiveCfg = Release|x64
+ {6678D1A3-33A6-48A9-878B-48E5D2903D27}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/citra/citra.vcxproj b/src/citra/citra.vcxproj
index 8f29e3e63..16157ad04 100644
--- a/src/citra/citra.vcxproj
+++ b/src/citra/citra.vcxproj
@@ -194,6 +194,9 @@
true
false
+
+ {6678d1a3-33a6-48a9-878b-48e5d2903d27}
+
diff --git a/src/citra/src/citra.cpp b/src/citra/src/citra.cpp
index 26f5a74eb..746cf083d 100644
--- a/src/citra/src/citra.cpp
+++ b/src/citra/src/citra.cpp
@@ -52,39 +52,6 @@ int __cdecl main(int argc, char **argv) {
System::Init(emu_window);
- //if (E_OK != Core::Init(emu_window)) {
- // LOG_ERROR(TMASTER, "core initialization failed, exiting...");
- // core::Kill();
- // exit(1);
- //}
-
- //// Load a game or die...
- //if (E_OK == dvd::LoadBootableFile(common::g_config->default_boot_file())) {
- // if (common::g_config->enable_auto_boot()) {
- // core::Start();
- // } else {
- // LOG_ERROR(TMASTER, "Autoboot required in no-GUI mode... Exiting!\n");
- // }
- //} else {
- // LOG_ERROR(TMASTER, "Failed to load a bootable file... Exiting!\n");
- // exit(E_ERR);
- //}
- //// run the game
- //while(core::SYS_DIE != core::g_state) {
- // if (core::SYS_RUNNING == core::g_state) {
- // if(!(cpu->is_on)) {
- // cpu->Start(); // Initialize and start CPU.
- // } else {
- // for(tight_loop = 0; tight_loop < 10000; ++tight_loop) {
- // cpu->execStep();
- // }
- // }
- // } else if (core::SYS_HALTED == core::g_state) {
- // core::Stop();
- // }
- //}
- //core::Kill();
-
std::string boot_filename = "homebrew.elf";
std::string error_str;
@@ -93,7 +60,8 @@ int __cdecl main(int argc, char **argv) {
if (!res) {
ERROR_LOG(BOOT, "Failed to load ROM: %s", error_str.c_str());
}
- for (int tight_loop = 0; tight_loop < 10000; ++tight_loop) {
+
+ for (;;) {
Core::SingleStep();
}
diff --git a/src/citra/src/emu_window/emu_window_glfw.cpp b/src/citra/src/emu_window/emu_window_glfw.cpp
index 8edc745b7..4cdb7fbb0 100644
--- a/src/citra/src/emu_window/emu_window_glfw.cpp
+++ b/src/citra/src/emu_window/emu_window_glfw.cpp
@@ -23,6 +23,7 @@
*/
#include "common.h"
+#include "video_core.h"
#include "emu_window_glfw.h"
static void OnKeyEvent(GLFWwindow* win, int key, int action) {
@@ -54,7 +55,8 @@ EmuWindow_GLFW::EmuWindow_GLFW() {
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
- render_window_ = glfwCreateWindow(640, 480, "citra", NULL, NULL);
+ render_window_ = glfwCreateWindow(VideoCore::kScreenTopWidth,
+ (VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight), "citra", NULL, NULL);
// Setup callbacks
glfwSetWindowUserPointer(render_window_, this);
diff --git a/src/citra/src/emu_window/emu_window_glfw.h b/src/citra/src/emu_window/emu_window_glfw.h
index 0339b5d68..abca9faa8 100644
--- a/src/citra/src/emu_window/emu_window_glfw.h
+++ b/src/citra/src/emu_window/emu_window_glfw.h
@@ -22,8 +22,7 @@
* http://code.google.com/p/gekko-gc-emu/
*/
-#ifndef CITRA_EMUWINDOW_GLFW_
-#define CITRA_EMUWINDOW_GLFW_
+#pragma once
#include
#include
@@ -52,5 +51,3 @@ public:
private:
};
-
-#endif // CITRA_EMUWINDOW_GLFW_
diff --git a/src/common/src/common.h b/src/common/src/common.h
index 1ca34e467..3b71d9b3d 100644
--- a/src/common/src/common.h
+++ b/src/common/src/common.h
@@ -163,4 +163,9 @@ enum EMUSTATE_CHANGE
EMUSTATE_CHANGE_STOP
};
+// This should be used in the private: declarations for a class
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+
#endif // _COMMON_H_
diff --git a/src/common/src/common_types.h b/src/common/src/common_types.h
index cbe556c7e..af1cd0e21 100644
--- a/src/common/src/common_types.h
+++ b/src/common/src/common_types.h
@@ -1,50 +1,125 @@
-// Copyright 2013 Dolphin Emulator Project
-// Licensed under GPLv2
-// Refer to the license.txt file included.
+/**
+ * Copyright (C) 2005-2012 Gekko Emulator
+ *
+ * @file common_types.h
+ * @author ShizZy
+ * @date 2012-02-11
+ * @brief Common types used throughout the project
+ *
+ * @section LICENSE
+ * This program is free software; 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 at
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Official project repository can be found at:
+ * http://code.google.com/p/gekko-gc-emu/
+ */
+#pragma once
-// This header contains type definitions that are shared between the Dolphin core and
-// other parts of the code. Any definitions that are only used by the core should be
-// placed in "common.h" instead.
-
-#ifndef _COMMONTYPES_H_
-#define _COMMONTYPES_H_
+#include
+#include // data_types__m128.cpp
#ifdef _WIN32
#include
-typedef unsigned __int8 u8;
-typedef unsigned __int16 u16;
-typedef unsigned __int32 u32;
-typedef unsigned __int64 u64;
+typedef unsigned __int8 u8; ///< 8-bit unsigned byte
+typedef unsigned __int16 u16; ///< 16-bit unsigned short
+typedef unsigned __int32 u32; ///< 32-bit unsigned word
+typedef unsigned __int64 u64; ///< 64-bit unsigned int
-typedef signed __int8 s8;
-typedef signed __int16 s16;
-typedef signed __int32 s32;
-typedef signed __int64 s64;
+typedef signed __int8 s8; ///< 8-bit signed byte
+typedef signed __int16 s16; ///< 16-bit signed short
+typedef signed __int32 s32; ///< 32-bit signed word
+typedef signed __int64 s64; ///< 64-bit signed int
#else
-#ifndef GEKKO
+typedef unsigned char u8; ///< 8-bit unsigned byte
+typedef unsigned short u16; ///< 16-bit unsigned short
+typedef unsigned int u32; ///< 32-bit unsigned word
+typedef unsigned long long u64; ///< 64-bit unsigned int
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-typedef unsigned long long u64;
+typedef signed char s8; ///< 8-bit signed byte
+typedef signed short s16; ///< 16-bit signed short
+typedef signed int s32; ///< 32-bit signed word
+typedef signed long long s64; ///< 64-bit signed int
-typedef signed char s8;
-typedef signed short s16;
-typedef signed int s32;
-typedef signed long long s64;
-
-#endif
// For using windows lock code
#define TCHAR char
#define LONG int
#endif // _WIN32
+typedef float f32; ///< 32-bit floating point
+typedef double f64; ///< 64-bit floating point
+
#include "swap.h"
-#endif // _COMMONTYPES_H_
+/// Union for fast 16-bit type casting
+union t16 {
+ u8 _u8[2]; ///< 8-bit unsigned char(s)
+ u16 _u16; ///< 16-bit unsigned shorts(s)
+};
+
+/// Union for fast 32-bit type casting
+union t32 {
+ f32 _f32; ///< 32-bit floating point(s)
+ u32 _u32; ///< 32-bit unsigned int(s)
+ s32 _s32; ///< 32-bit signed int(s)
+ u16 _u16[2]; ///< 16-bit unsigned shorts(s)
+ u8 _u8[4]; ///< 8-bit unsigned char(s)
+};
+
+/// Union for fast 64-bit type casting
+union t64 {
+ f64 _f64; ///< 64-bit floating point
+ u64 _u64; ///< 64-bit unsigned long
+ f32 _f32[2]; ///< 32-bit floating point(s)
+ u32 _u32[2]; ///< 32-bit unsigned int(s)
+ s32 _s32[2]; ///< 32-bit signed int(s)
+ u16 _u16[4]; ///< 16-bit unsigned shorts(s)
+ u8 _u8[8]; ///< 8-bit unsigned char(s)
+};
+
+/// Union for fast 128-bit type casting
+union t128 {
+ struct
+ {
+ t64 ps0; ///< 64-bit paired single 0
+ t64 ps1; ///< 64-bit paired single 1
+ };
+ __m128 a; ///< 128-bit floating point (__m128 maps to the XMM[0-7] registers)
+};
+
+/// Rectangle data structure
+class Rect {
+public:
+ Rect(int x0=0, int y0=0, int x1=0, int y1=0) {
+ x0_ = x0;
+ y0_ = y0;
+ x1_ = x1;
+ y1_ = y1;
+ }
+ ~Rect() { }
+
+ int x0_; ///< Rect top left X-coordinate
+ int y0_; ///< Rect top left Y-coordinate
+ int x1_; ///< Rect bottom left X-coordinate
+ int y1_; ///< Rect bottom right Y-coordinate
+
+ inline u32 width() const { return abs(x1_ - x0_); }
+ inline u32 height() const { return abs(y1_ - y0_); }
+
+ inline bool operator == (const Rect& val) const {
+ return (x0_ == val.x0_ && y0_ == val.y0_ && x1_ == val.x1_ && y1_ == val.y1_);
+ }
+};
diff --git a/src/common/src/emu_window.h b/src/common/src/emu_window.h
index 66de75574..f49367057 100644
--- a/src/common/src/emu_window.h
+++ b/src/common/src/emu_window.h
@@ -81,7 +81,7 @@ public:
protected:
EmuWindow() : client_area_width_(640), client_area_height_(480) {
char window_title[255];
- sprintf(window_title, "emu [%s|%s] - %s",
+ sprintf(window_title, "citra [%s|%s] - %s",
"null-cpu",
"null-renderer",
__DATE__);
diff --git a/src/common/src/log.h b/src/common/src/log.h
index 9b2da5016..432a307f0 100644
--- a/src/common/src/log.h
+++ b/src/common/src/log.h
@@ -57,9 +57,9 @@ enum LOG_TYPE {
WII_IPC_NET,
WII_IPC_WC24,
WII_IPC_SSL,
- WII_IPC_SD,
- WII_IPC_STM,
- WII_IPC_WIIMOTE,
+ RENDER,
+ LCD,
+ HW,
TIME,
NETPLAY,
diff --git a/src/common/src/log_manager.cpp b/src/common/src/log_manager.cpp
index 8c8828e8c..b5b034846 100644
--- a/src/common/src/log_manager.cpp
+++ b/src/common/src/log_manager.cpp
@@ -29,53 +29,53 @@ LogManager *LogManager::m_logManager = NULL;
LogManager::LogManager()
{
// create log files
- m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log");
- m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot");
- m_Log[LogTypes::COMMON] = new LogContainer("COMMON", "Common");
- m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO");
- m_Log[LogTypes::FILEMON] = new LogContainer("FileMon", "File Monitor");
- m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad");
- m_Log[LogTypes::PIXELENGINE] = new LogContainer("PE", "PixelEngine");
- m_Log[LogTypes::COMMANDPROCESSOR] = new LogContainer("CP", "CommandProc");
- m_Log[LogTypes::VIDEOINTERFACE] = new LogContainer("VI", "VideoInt");
- m_Log[LogTypes::SERIALINTERFACE] = new LogContainer("SI", "SerialInt");
- m_Log[LogTypes::PROCESSORINTERFACE] = new LogContainer("PI", "ProcessorInt");
- m_Log[LogTypes::MEMMAP] = new LogContainer("MI", "MI & memmap");
- m_Log[LogTypes::SP1] = new LogContainer("SP1", "Serial Port 1");
- m_Log[LogTypes::STREAMINGINTERFACE] = new LogContainer("Stream", "StreamingInt");
- m_Log[LogTypes::DSPINTERFACE] = new LogContainer("DSP", "DSPInterface");
- m_Log[LogTypes::DVDINTERFACE] = new LogContainer("DVD", "DVDInterface");
- m_Log[LogTypes::GPFIFO] = new LogContainer("GP", "GPFifo");
- m_Log[LogTypes::EXPANSIONINTERFACE] = new LogContainer("EXI", "ExpansionInt");
- m_Log[LogTypes::GDB_STUB] = new LogContainer("GDB_STUB", "GDB Stub");
- m_Log[LogTypes::AUDIO_INTERFACE] = new LogContainer("AI", "AudioInt");
- m_Log[LogTypes::ARM11] = new LogContainer("ARM11", "ARM11");
- m_Log[LogTypes::OSHLE] = new LogContainer("HLE", "HLE");
- m_Log[LogTypes::DSPHLE] = new LogContainer("DSPHLE", "DSP HLE");
- m_Log[LogTypes::DSPLLE] = new LogContainer("DSPLLE", "DSP LLE");
- m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails");
- m_Log[LogTypes::VIDEO] = new LogContainer("Video", "Video Backend");
- m_Log[LogTypes::AUDIO] = new LogContainer("Audio", "Audio Emulator");
- m_Log[LogTypes::DYNA_REC] = new LogContainer("JIT", "Dynamic Recompiler");
- m_Log[LogTypes::CONSOLE] = new LogContainer("CONSOLE", "Dolphin Console");
- m_Log[LogTypes::OSREPORT] = new LogContainer("OSREPORT", "OSReport");
- m_Log[LogTypes::TIME] = new LogContainer("Time", "Core Timing");
- m_Log[LogTypes::LOADER] = new LogContainer("Loader", "Loader");
- m_Log[LogTypes::FILESYS] = new LogContainer("FileSys", "File System");
- m_Log[LogTypes::WII_IPC_HID] = new LogContainer("WII_IPC_HID", "WII IPC HID");
- m_Log[LogTypes::WII_IPC_HLE] = new LogContainer("WII_IPC_HLE", "WII IPC HLE");
- m_Log[LogTypes::WII_IPC_DVD] = new LogContainer("WII_IPC_DVD", "WII IPC DVD");
- m_Log[LogTypes::WII_IPC_ES] = new LogContainer("WII_IPC_ES", "WII IPC ES");
- m_Log[LogTypes::WII_IPC_FILEIO] = new LogContainer("WII_IPC_FILEIO","WII IPC FILEIO");
- m_Log[LogTypes::WII_IPC_SD] = new LogContainer("WII_IPC_SD", "WII IPC SD");
- m_Log[LogTypes::WII_IPC_STM] = new LogContainer("WII_IPC_STM", "WII IPC STM");
- m_Log[LogTypes::WII_IPC_NET] = new LogContainer("WII_IPC_NET", "WII IPC NET");
- m_Log[LogTypes::WII_IPC_WC24] = new LogContainer("WII_IPC_WC24", "WII IPC WC24");
- m_Log[LogTypes::WII_IPC_SSL] = new LogContainer("WII_IPC_SSL", "WII IPC SSL");
- m_Log[LogTypes::WII_IPC_WIIMOTE] = new LogContainer("WII_IPC_WIIMOTE","WII IPC WIIMOTE");
- m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay");
- m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager");
- m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay");
+ m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log");
+ m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot");
+ m_Log[LogTypes::COMMON] = new LogContainer("COMMON", "Common");
+ m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO");
+ m_Log[LogTypes::FILEMON] = new LogContainer("FileMon", "File Monitor");
+ m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad");
+ m_Log[LogTypes::PIXELENGINE] = new LogContainer("PE", "PixelEngine");
+ m_Log[LogTypes::COMMANDPROCESSOR] = new LogContainer("CP", "CommandProc");
+ m_Log[LogTypes::VIDEOINTERFACE] = new LogContainer("VI", "VideoInt");
+ m_Log[LogTypes::SERIALINTERFACE] = new LogContainer("SI", "SerialInt");
+ m_Log[LogTypes::PROCESSORINTERFACE] = new LogContainer("PI", "ProcessorInt");
+ m_Log[LogTypes::MEMMAP] = new LogContainer("MI", "MI & memmap");
+ m_Log[LogTypes::SP1] = new LogContainer("SP1", "Serial Port 1");
+ m_Log[LogTypes::STREAMINGINTERFACE] = new LogContainer("Stream", "StreamingInt");
+ m_Log[LogTypes::DSPINTERFACE] = new LogContainer("DSP", "DSPInterface");
+ m_Log[LogTypes::DVDINTERFACE] = new LogContainer("DVD", "DVDInterface");
+ m_Log[LogTypes::GPFIFO] = new LogContainer("GP", "GPFifo");
+ m_Log[LogTypes::EXPANSIONINTERFACE] = new LogContainer("EXI", "ExpansionInt");
+ m_Log[LogTypes::GDB_STUB] = new LogContainer("GDB_STUB", "GDB Stub");
+ m_Log[LogTypes::AUDIO_INTERFACE] = new LogContainer("AI", "AudioInt");
+ m_Log[LogTypes::ARM11] = new LogContainer("ARM11", "ARM11");
+ m_Log[LogTypes::OSHLE] = new LogContainer("HLE", "HLE");
+ m_Log[LogTypes::DSPHLE] = new LogContainer("DSPHLE", "DSP HLE");
+ m_Log[LogTypes::DSPLLE] = new LogContainer("DSPLLE", "DSP LLE");
+ m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails");
+ m_Log[LogTypes::VIDEO] = new LogContainer("Video", "Video Backend");
+ m_Log[LogTypes::AUDIO] = new LogContainer("Audio", "Audio Emulator");
+ m_Log[LogTypes::DYNA_REC] = new LogContainer("JIT", "JIT");
+ m_Log[LogTypes::CONSOLE] = new LogContainer("CONSOLE", "Dolphin Console");
+ m_Log[LogTypes::OSREPORT] = new LogContainer("OSREPORT", "OSReport");
+ m_Log[LogTypes::TIME] = new LogContainer("Time", "Core Timing");
+ m_Log[LogTypes::LOADER] = new LogContainer("Loader", "Loader");
+ m_Log[LogTypes::FILESYS] = new LogContainer("FileSys", "File System");
+ m_Log[LogTypes::WII_IPC_HID] = new LogContainer("WII_IPC_HID", "WII IPC HID");
+ m_Log[LogTypes::WII_IPC_HLE] = new LogContainer("WII_IPC_HLE", "WII IPC HLE");
+ m_Log[LogTypes::WII_IPC_DVD] = new LogContainer("WII_IPC_DVD", "WII IPC DVD");
+ m_Log[LogTypes::WII_IPC_ES] = new LogContainer("WII_IPC_ES", "WII IPC ES");
+ m_Log[LogTypes::WII_IPC_FILEIO] = new LogContainer("WII_IPC_FILEIO", "WII IPC FILEIO");
+ m_Log[LogTypes::RENDER] = new LogContainer("RENDER", "RENDER");
+ m_Log[LogTypes::LCD] = new LogContainer("LCD", "LCD");
+ m_Log[LogTypes::WII_IPC_NET] = new LogContainer("WII_IPC_NET", "WII IPC NET");
+ m_Log[LogTypes::WII_IPC_WC24] = new LogContainer("WII_IPC_WC24", "WII IPC WC24");
+ m_Log[LogTypes::WII_IPC_SSL] = new LogContainer("WII_IPC_SSL", "WII IPC SSL");
+ m_Log[LogTypes::HW] = new LogContainer("HARDWARE", "HARDWARE");
+ m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay");
+ m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager");
+ m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay");
m_fileLog = new FileLogListener(File::GetUserPath(F_MAINLOG_IDX).c_str());
m_consoleLog = new ConsoleListener();
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index bee9f3046..2edb51214 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -152,6 +152,8 @@
+
+
@@ -180,6 +182,8 @@
+
+
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index 45ddf8cf6..0cd208dd6 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -46,6 +46,12 @@
arm\interpreter
+
+ hw
+
+
+ hw
+
@@ -69,6 +75,9 @@
{cca8b763-8a80-4478-9bcc-3c979293c357}
+
+ {d1158fc4-3e0f-431f-9d3b-f30bbfeb4ad5}
+
@@ -136,6 +145,12 @@
arm\interpreter
+
+ hw
+
+
+ hw
+
diff --git a/src/core/src/arm/arm_interface.h b/src/core/src/arm/arm_interface.h
index 785234396..daf35b51d 100644
--- a/src/core/src/arm/arm_interface.h
+++ b/src/core/src/arm/arm_interface.h
@@ -24,24 +24,65 @@
#pragma once
+#include "common.h"
#include "common_types.h"
/// Generic ARM11 CPU interface
class ARM_Interface {
public:
ARM_Interface() {
+ num_instructions_ = 0;
}
~ARM_Interface() {
}
- virtual void ExecuteInstruction() = 0;
-
- virtual void SetPC(u32 pc) = 0;
+ /// Step CPU by one instruction
+ void Step() {
+ ExecuteInstruction();
+ num_instructions_++;
+ }
+
+ /**
+ * Set the Program Counter to an address
+ * @param addr Address to set PC to
+ */
+ virtual void SetPC(u32 addr) = 0;
+ /*
+ * Get the current Program Counter
+ * @return Returns current PC
+ */
virtual u32 PC() = 0;
+ /**
+ * Get an ARM register
+ * @param index Register index (0-15)
+ * @return Returns the value in the register
+ */
virtual u32 Reg(int index) = 0;
- virtual u32 CPSR() = 0;
+ /**
+ * Get the current CPSR register
+ * @return Returns the value of the CPSR register
+ */
+ virtual u32 CPSR() = 0;
+
+ /**
+ * Returns the number of clock ticks since the last rese
+ * @return Returns number of clock ticks
+ */
+ virtual u64 GetTicks() = 0;
+
+ /// Getter for num_instructions_
+ u64 num_instructions() { return num_instructions_; }
+
+private:
+
+ /// Execture next instruction
+ virtual void ExecuteInstruction() = 0;
+
+ u64 num_instructions_; ///< Number of instructions executed
+
+ DISALLOW_COPY_AND_ASSIGN(ARM_Interface);
};
diff --git a/src/core/src/arm/interpreter/arm_interpreter.cpp b/src/core/src/arm/interpreter/arm_interpreter.cpp
index 930506963..a74aa26cc 100644
--- a/src/core/src/arm/interpreter/arm_interpreter.cpp
+++ b/src/core/src/arm/interpreter/arm_interpreter.cpp
@@ -1,26 +1,26 @@
/**
-* Copyright (C) 2013 Citrus Emulator
-*
-* @file arm_interpreter.h
-* @author bunnei
-* @date 2014-04-04
-* @brief ARM interface instance for SkyEye interprerer
-*
-* @section LICENSE
-* This program is free software; 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 at
-* http://www.gnu.org/copyleft/gpl.html
-*
-* Official project repository can be found at:
-* http://code.google.com/p/gekko-gc-emu/
-*/
+ * Copyright (C) 2013 Citrus Emulator
+ *
+ * @file arm_interpreter.h
+ * @author bunnei
+ * @date 2014-04-04
+ * @brief ARM interface instance for SkyEye interprerer
+ *
+ * @section LICENSE
+ * This program is free software; 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 at
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Official project repository can be found at:
+ * http://code.google.com/p/gekko-gc-emu/
+ */
#include "arm_interpreter.h"
diff --git a/src/core/src/arm/interpreter/arm_interpreter.h b/src/core/src/arm/interpreter/arm_interpreter.h
index 89f871fa9..074149f1b 100644
--- a/src/core/src/arm/interpreter/arm_interpreter.h
+++ b/src/core/src/arm/interpreter/arm_interpreter.h
@@ -24,6 +24,7 @@
#pragma once
+#include "common.h"
#include "common_types.h"
#include "arm/arm_interface.h"
@@ -45,6 +46,12 @@ public:
u32 CPSR();
+ u64 GetTicks() {
+ return ARMul_Time(state);
+ }
+
private:
ARMul_State* state;
+
+ DISALLOW_COPY_AND_ASSIGN(ARM_Interpreter);
};
diff --git a/src/core/src/core.cpp b/src/core/src/core.cpp
index 592805134..4261ff3ef 100644
--- a/src/core/src/core.cpp
+++ b/src/core/src/core.cpp
@@ -25,6 +25,7 @@
#include "log.h"
#include "core.h"
#include "mem_map.h"
+#include "hw/hw.h"
#include "arm/disassembler/arm_disasm.h"
#include "arm/interpreter/arm_interpreter.h"
@@ -41,7 +42,8 @@ void RunLoop() {
/// Step the CPU one instruction
void SingleStep() {
- g_app_core->ExecuteInstruction();
+ g_app_core->Step();
+ HW::Update();
}
/// Halt the core
@@ -69,6 +71,8 @@ void Shutdown() {
delete g_disasm;
delete g_app_core;
delete g_sys_core;
+
+ NOTICE_LOG(MASTER_LOG, "Core shutdown OK");
}
} // namespace
diff --git a/src/core/src/core.h b/src/core/src/core.h
index 2e7b355f2..a71e4ed8d 100644
--- a/src/core/src/core.h
+++ b/src/core/src/core.h
@@ -55,6 +55,9 @@ void Stop();
/// Initialize the core
int Init();
+/// Shutdown the core
+void Shutdown();
+
} // namespace
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/src/hw/hw.cpp b/src/core/src/hw/hw.cpp
new file mode 100644
index 000000000..50001c87a
--- /dev/null
+++ b/src/core/src/hw/hw.cpp
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 2013 Citrus Emulator
+ *
+ * @file hw.cpp
+ * @author bunnei
+ * @date 2014-04-04
+ * @brief Hardware interface
+ *
+ * @section LICENSE
+ * This program is free software; 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 at
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Official project repository can be found at:
+ * http://code.google.com/p/gekko-gc-emu/
+ */
+
+#include "log.h"
+#include "hw/hw.h"
+#include "hw/hw_lcd.h"
+
+namespace HW {
+
+template
+inline void Read(T &var, const u32 addr) {
+ NOTICE_LOG(HW, "Hardware read from address %08X", addr);
+}
+
+template
+inline void Write(u32 addr, const T data) {
+ NOTICE_LOG(HW, "Hardware write to address %08X", addr);
+}
+
+// Explicitly instantiate template functions because we aren't defining this in the header:
+
+template void Read(u64 &var, const u32 addr);
+template void Read(u32 &var, const u32 addr);
+template void Read(u16 &var, const u32 addr);
+template void Read(u8 &var, const u32 addr);
+
+template void Write(u32 addr, const u64 data);
+template void Write(u32 addr, const u32 data);
+template void Write(u32 addr, const u16 data);
+template void Write(u32 addr, const u8 data);
+
+/// Update hardware
+void Update() {
+ LCD::Update();
+}
+
+/// Initialize hardware
+void Init() {
+ LCD::Init();
+ NOTICE_LOG(HW, "Hardware initialized OK");
+}
+
+/// Shutdown hardware
+void Shutdown() {
+ NOTICE_LOG(HW, "Hardware shutdown OK");
+}
+
+}
\ No newline at end of file
diff --git a/src/core/src/hw/hw.h b/src/core/src/hw/hw.h
new file mode 100644
index 000000000..245822423
--- /dev/null
+++ b/src/core/src/hw/hw.h
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 2013 Citrus Emulator
+ *
+ * @file hw.h
+ * @author bunnei
+ * @date 2014-04-04
+ * @brief Hardware interface
+ *
+ * @section LICENSE
+ * This program is free software; 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 at
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Official project repository can be found at:
+ * http://code.google.com/p/gekko-gc-emu/
+ */
+
+#include "common_types.h"
+
+namespace HW {
+
+template
+inline void Read(T &var, const u32 addr);
+
+template
+inline void Write(u32 addr, const T data);
+
+/// Update hardware
+void Update();
+
+/// Initialize hardware
+void Init();
+
+/// Shutdown hardware
+void Shutdown();
+
+} // namespace
diff --git a/src/core/src/hw/hw_lcd.cpp b/src/core/src/hw/hw_lcd.cpp
new file mode 100644
index 000000000..ee806d5dc
--- /dev/null
+++ b/src/core/src/hw/hw_lcd.cpp
@@ -0,0 +1,65 @@
+/**
+ * Copyright (C) 2013 Citrus Emulator
+ *
+ * @file hw_lcd.cpp
+ * @author bunnei
+ * @date 2014-04-05
+ * @brief Hardware LCD interface
+ *
+ * @section LICENSE
+ * This program is free software; 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 at
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Official project repository can be found at:
+ * http://code.google.com/p/gekko-gc-emu/
+ */
+
+#include "log.h"
+#include "core.h"
+#include "hw_lcd.h"
+#include "video_core.h"
+
+namespace LCD {
+
+static const u32 kFrameTicks = 268123480 / 60; ///< 268MHz / 60 frames per second
+
+u64 g_last_ticks = 0; ///< Last CPU ticks
+
+template
+inline void Read(T &var, const u32 addr) {
+}
+
+template
+inline void Write(u32 addr, const T data) {
+}
+
+/// Update hardware
+void Update() {
+ u64 current_ticks = Core::g_app_core->GetTicks();
+
+ if ((current_ticks - g_last_ticks) >= kFrameTicks) {
+ g_last_ticks = current_ticks;
+ VideoCore::g_renderer->SwapBuffers();
+ }
+}
+
+/// Initialize hardware
+void Init() {
+ g_last_ticks = Core::g_app_core->GetTicks();
+ NOTICE_LOG(LCD, "LCD initialized OK");
+}
+
+/// Shutdown hardware
+void Shutdown() {
+ NOTICE_LOG(LCD, "LCD shutdown OK");
+}
+
+} // namespace
diff --git a/src/core/src/hw/hw_lcd.h b/src/core/src/hw/hw_lcd.h
new file mode 100644
index 000000000..fa19b1cd4
--- /dev/null
+++ b/src/core/src/hw/hw_lcd.h
@@ -0,0 +1,64 @@
+/**
+ * Copyright (C) 2013 Citrus Emulator
+ *
+ * @file hw_lcd.h
+ * @author bunnei
+ * @date 2014-04-05
+ * @brief Hardware LCD interface
+ *
+ * @section LICENSE
+ * This program is free software; 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 at
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Official project repository can be found at:
+ * http://code.google.com/p/gekko-gc-emu/
+ */
+
+#pragma once
+
+#include "common_types.h"
+
+namespace LCD {
+
+enum {
+ TOP_ASPECT_X = 0x5,
+ TOP_ASPECT_Y = 0x3,
+
+ TOP_HEIGHT = 240,
+ TOP_WIDTH = 400,
+ BOTTOM_WIDTH = 320,
+
+ FRAMEBUFFER_SEL = 0x20184E59,
+ TOP_LEFT_FRAME1 = 0x20184E60,
+ TOP_LEFT_FRAME2 = 0x201CB370,
+ TOP_RIGHT_FRAME1 = 0x20282160,
+ TOP_RIGHT_FRAME2 = 0x202C8670,
+ SUB_FRAME1 = 0x202118E0,
+ SUB_FRAME2 = 0x20249CF0,
+};
+
+template
+inline void Read(T &var, const u32 addr);
+
+template
+inline void Write(u32 addr, const T data);
+
+/// Update hardware
+void Update();
+
+/// Initialize hardware
+void Init();
+
+/// Shutdown hardware
+void Shutdown();
+
+
+} // namespace
diff --git a/src/core/src/mem_map_funcs.cpp b/src/core/src/mem_map_funcs.cpp
index 18959dc70..ee2f79278 100644
--- a/src/core/src/mem_map_funcs.cpp
+++ b/src/core/src/mem_map_funcs.cpp
@@ -25,17 +25,23 @@
#include "common.h"
#include "mem_map.h"
+#include "hw/hw.h"
namespace Memory {
template
-inline void ReadFromHardware(T &var, const u32 addr) {
+inline void _Read(T &var, const u32 addr) {
// TODO: Figure out the fastest order of tests for both read and write (they are probably different).
// TODO: Make sure this represents the mirrors in a correct way.
-
// Could just do a base-relative read, too.... TODO
- if ((addr & 0x3E000000) == 0x08000000) {
+ // Hardware I/O register reads
+ // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
+ if ((addr & 0xFF000000) == 0x10000000 || (addr & 0xFF000000) == 0x1E000000) {
+ HW::Read(var, addr);
+
+ // FCRAM virtual address reads
+ } else if ((addr & 0x3E000000) == 0x08000000) {
var = *((const T*)&g_fcram[addr & MEM_FCRAM_MASK]);
// Scratchpad memory
@@ -54,15 +60,20 @@ inline void ReadFromHardware(T &var, const u32 addr) {
var = *((const T*)&g_fcram[addr & MEM_FCRAM_MASK]);
} else {
- _assert_msg_(MEMMAP, false, "unknown hardware read");
- // WARN_LOG(MEMMAP, "ReadFromHardware: Invalid addr %08x PC %08x LR %08x", addr, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
+ _assert_msg_(MEMMAP, false, "unknown memory read");
}
}
template
-inline void WriteToHardware(u32 addr, const T data) {
+inline void _Write(u32 addr, const T data) {
+
+ // Hardware I/O register writes
+ // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
+ if ((addr & 0xFF000000) == 0x10000000 || (addr & 0xFF000000) == 0x1E000000) {
+ HW::Write(addr, data);
+
// ExeFS:/.code is loaded here:
- if ((addr & 0xFFF00000) == 0x00100000) {
+ } else if ((addr & 0xFFF00000) == 0x00100000) {
// TODO(ShizZy): This is dumb... handle correctly. From 3DBrew:
// http://3dbrew.org/wiki/Memory_layout#ARM11_User-land_memory_regions
// The ExeFS:/.code is loaded here, executables must be loaded to the 0x00100000 region when
@@ -104,7 +115,7 @@ inline void WriteToHardware(u32 addr, const T data) {
// Error out...
} else {
- _assert_msg_(MEMMAP, false, "unknown hardware write");
+ _assert_msg_(MEMMAP, false, "unknown memory write");
}
}
@@ -126,14 +137,21 @@ u8 *GetPointer(const u32 addr) {
// TODO(bunnei): Just a stub for now... ImplementMe!
if ((addr & 0x3E000000) == 0x08000000) {
return g_fcram + (addr & MEM_FCRAM_MASK);
- }
+
+ // HACK(bunnei): There is no layer yet to translate virtual addresses to physical addresses.
+ // Until we progress far enough along, we'll accept all physical address reads here. I think
+ // that this is typically a corner-case from usermode software unless they are trying to do
+ // bare-metal things (e.g. early 3DS homebrew writes directly to the FB @ 0x20184E60, etc.
+ } else if (((addr & 0xF0000000) == MEM_FCRAM_PADDR) && (addr < (MEM_FCRAM_PADDR_END))) {
+ return g_fcram + (addr & MEM_FCRAM_MASK);
+
//else if ((addr & 0x3F800000) == 0x04000000) {
// return g_vram + (addr & MEM_VRAM_MASK);
//}
//else if ((addr & 0x3F000000) >= 0x08000000 && (addr & 0x3F000000) < 0x08000000 + g_MemorySize) {
// return m_pRAM + (addr & g_MemoryMask);
//}
- else {
+ } else {
//ERROR_LOG(MEMMAP, "Unknown GetPointer %08x PC %08x LR %08x", addr, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
ERROR_LOG(MEMMAP, "Unknown GetPointer %08x", addr);
static bool reported = false;
@@ -151,25 +169,25 @@ u8 *GetPointer(const u32 addr) {
u8 Read8(const u32 addr) {
u8 _var = 0;
- ReadFromHardware(_var, addr);
+ _Read(_var, addr);
return (u8)_var;
}
u16 Read16(const u32 addr) {
u16_le _var = 0;
- ReadFromHardware(_var, addr);
+ _Read(_var, addr);
return (u16)_var;
}
u32 Read32(const u32 addr) {
u32_le _var = 0;
- ReadFromHardware(_var, addr);
+ _Read(_var, addr);
return _var;
}
u64 Read64(const u32 addr) {
u64_le _var = 0;
- ReadFromHardware(_var, addr);
+ _Read(_var, addr);
return _var;
}
@@ -182,19 +200,19 @@ u32 Read16_ZX(const u32 addr) {
}
void Write8(const u32 addr, const u8 data) {
- WriteToHardware(addr, data);
+ _Write(addr, data);
}
void Write16(const u32 addr, const u16 data) {
- WriteToHardware(addr, data);
+ _Write(addr, data);
}
void Write32(const u32 addr, const u32 data) {
- WriteToHardware(addr, data);
+ _Write(addr, data);
}
void Write64(const u32 addr, const u64 data) {
- WriteToHardware(addr, data);
+ _Write(addr, data);
}
} // namespace
diff --git a/src/core/src/system.cpp b/src/core/src/system.cpp
index 6a2c13c96..7c829d609 100644
--- a/src/core/src/system.cpp
+++ b/src/core/src/system.cpp
@@ -23,9 +23,11 @@
*/
#include "core.h"
+#include "hw/hw.h"
#include "core_timing.h"
#include "mem_map.h"
#include "system.h"
+#include "video_core.h"
namespace System {
@@ -38,7 +40,9 @@ void UpdateState(State state) {
void Init(EmuWindow* emu_window) {
Core::Init();
Memory::Init();
+ HW::Init();
CoreTiming::Init();
+ VideoCore::Init(emu_window);
}
void RunLoopFor(int cycles) {
@@ -49,9 +53,10 @@ void RunLoopUntil(u64 global_cycles) {
}
void Shutdown() {
+ Core::Shutdown();
+ HW::Shutdown();
+ VideoCore::Shutdown();
g_ctr_file_system.Shutdown();
}
-
-
} // namespace
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
new file mode 100644
index 000000000..3f486b8fe
--- /dev/null
+++ b/src/video_core/CMakeLists.txt
@@ -0,0 +1,19 @@
+set(SRCS
+ src/bp_mem.cpp
+ src/cp_mem.cpp
+ src/xf_mem.cpp
+ src/fifo.cpp
+ src/fifo_player.cpp
+ src/vertex_loader.cpp
+ src/vertex_manager.cpp
+ src/video_core.cpp
+ src/shader_manager.cpp
+ src/texture_decoder.cpp
+ src/texture_manager.cpp
+ src/utils.cpp
+ src/renderer_gl3/renderer_gl3.cpp
+ src/renderer_gl3/shader_interface.cpp
+ src/renderer_gl3/texture_interface.cpp
+ src/renderer_gl3/uniform_manager.cpp)
+
+add_library(video_core STATIC ${SRCS})
diff --git a/src/video_core/src/renderer_base.h b/src/video_core/src/renderer_base.h
new file mode 100644
index 000000000..50f1475b2
--- /dev/null
+++ b/src/video_core/src/renderer_base.h
@@ -0,0 +1,132 @@
+/**
+ * Copyright (C) 2014 Citra Emulator
+ *
+ * @file renderer_base.h
+ * @author bunnei
+ * @date 2014-04-05
+ * @brief Renderer base class for new video core
+ *
+ * @section LICENSE
+ * This program is free software; 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 at
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Official project repository can be found at:
+ * http://code.google.com/p/gekko-gc-emu/
+ */
+
+#pragma once
+
+#include "common.h"
+#include "hash.h"
+
+class RendererBase {
+public:
+
+ /// Used to reference a framebuffer
+ enum kFramebuffer {
+ kFramebuffer_VirtualXFB = 0,
+ kFramebuffer_EFB,
+ kFramebuffer_Texture
+ };
+
+ /// Used for referencing the render modes
+ enum kRenderMode {
+ kRenderMode_None = 0,
+ kRenderMode_Multipass = 1,
+ kRenderMode_ZComp = 2,
+ kRenderMode_UseDstAlpha = 4
+ };
+
+ RendererBase() : current_fps_(0), current_frame_(0) {
+ }
+
+ ~RendererBase() {
+ }
+
+ /// Swap buffers (render frame)
+ virtual void SwapBuffers() = 0;
+
+ /**
+ * Blits the EFB to the external framebuffer (XFB)
+ * @param src_rect Source rectangle in EFB to copy
+ * @param dst_rect Destination rectangle in EFB to copy to
+ * @param dest_height Destination height in pixels
+ */
+ virtual void CopyToXFB(const Rect& src_rect, const Rect& dst_rect) = 0;
+
+ /**
+ * Clear the screen
+ * @param rect Screen rectangle to clear
+ * @param enable_color Enable color clearing
+ * @param enable_alpha Enable alpha clearing
+ * @param enable_z Enable depth clearing
+ * @param color Clear color
+ * @param z Clear depth
+ */
+ virtual void Clear(const Rect& rect, bool enable_color, bool enable_alpha, bool enable_z,
+ u32 color, u32 z) = 0;
+
+ /// Sets the renderer viewport location, width, and height
+ virtual void SetViewport(int x, int y, int width, int height) = 0;
+
+ /// Sets the renderer depthrange, znear and zfar
+ virtual void SetDepthRange(double znear, double zfar) = 0;
+
+ /* Sets the scissor box
+ * @param rect Renderer rectangle to set scissor box to
+ */
+ virtual void SetScissorBox(const Rect& rect) = 0;
+
+ /**
+ * Sets the line and point size
+ * @param line_width Line width to use
+ * @param point_size Point size to use
+ */
+ virtual void SetLinePointSize(f32 line_width, f32 point_size) = 0;
+
+ /**
+ * Set a specific render mode
+ * @param flag Render flags mode to enable
+ */
+ virtual void SetMode(kRenderMode flags) = 0;
+
+ /// Reset the full renderer API to the NULL state
+ virtual void ResetRenderState() = 0;
+
+ /// Restore the full renderer API state - As the game set it
+ virtual void RestoreRenderState() = 0;
+
+ /**
+ * Set the emulator window to use for renderer
+ * @param window EmuWindow handle to emulator window to use for rendering
+ */
+ virtual void SetWindow(EmuWindow* window) = 0;
+
+ /// Initialize the renderer
+ virtual void Init() = 0;
+
+ /// Shutdown the renderer
+ virtual void ShutDown() = 0;
+
+ // Getter/setter functions:
+ // ------------------------
+
+ f32 current_fps() const { return current_fps_; }
+
+ int current_frame() const { return current_frame_; }
+
+protected:
+ f32 current_fps_; ///< Current framerate, should be set by the renderer
+ int current_frame_; ///< Current frame, should be set by the renderer
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(RendererBase);
+};
diff --git a/src/video_core/src/renderer_opengl/renderer_opengl.cpp b/src/video_core/src/renderer_opengl/renderer_opengl.cpp
new file mode 100644
index 000000000..27917a5a2
--- /dev/null
+++ b/src/video_core/src/renderer_opengl/renderer_opengl.cpp
@@ -0,0 +1,461 @@
+/**
+ * Copyright (C) 2014 Citra Emulator
+ *
+ * @file renderer_opengl.cpp
+ * @author bunnei
+ * @date 2014-04-05
+ * @brief Renderer for OpenGL 3.x
+ *
+ * @section LICENSE
+ * This program is free software; 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 at
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Official project repository can be found at:
+ * http://code.google.com/p/gekko-gc-emu/
+ */
+
+#include "mem_map.h"
+#include "video_core.h"
+#include "renderer_opengl/renderer_opengl.h"
+
+/**
+ * Helper function to flip framebuffer from left-to-right to top-to-bottom
+ * @param addr Address of framebuffer in RAM
+ * @param out Pointer to output buffer with flipped framebuffer
+ * @todo Early on hack... I'd like to find a more efficient way of doing this /bunnei
+ */
+inline void _flip_framebuffer(u32 addr, u8* out) {
+ u8* in = Memory::GetPointer(addr);
+ for (int y = 0; y < VideoCore::kScreenTopHeight; y++) {
+ for (int x = 0; x < VideoCore::kScreenTopWidth; x++) {
+ int in_coord = (VideoCore::kScreenTopHeight * 3 * x) + (VideoCore::kScreenTopHeight * 3)
+ - (3 * y + 3);
+ int out_coord = (VideoCore::kScreenTopWidth * y * 3) + (x * 3);
+
+ out[out_coord + 0] = in[in_coord + 0];
+ out[out_coord + 1] = in[in_coord + 1];
+ out[out_coord + 2] = in[in_coord + 2];
+ }
+ }
+}
+
+/// RendererOpenGL constructor
+RendererOpenGL::RendererOpenGL() {
+ memset(fbo_, 0, sizeof(fbo_));
+ memset(fbo_rbo_, 0, sizeof(fbo_rbo_));
+ memset(fbo_depth_buffers_, 0, sizeof(fbo_depth_buffers_));
+
+ resolution_width_ = max(VideoCore::kScreenTopWidth, VideoCore::kScreenBottomWidth);
+ resolution_height_ = VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight;
+
+ xfb_texture_top_ = 0;
+ xfb_texture_bottom_ = 0;
+
+ xfb_top_ = 0;
+ xfb_bottom_ = 0;
+}
+
+/// RendererOpenGL destructor
+RendererOpenGL::~RendererOpenGL() {
+}
+
+/// Swap buffers (render frame)
+void RendererOpenGL::SwapBuffers() {
+
+ ResetRenderState();
+
+ // EFB->XFB copy
+ // TODO(bunnei): This is a hack and does not belong here. The copy should be triggered by some
+ // register write We're also treating both framebuffers as a single one in OpenGL.
+ Rect framebuffer_size(0, 0, resolution_width_, resolution_height_);
+ RenderXFB(framebuffer_size, framebuffer_size);
+
+ // XFB->Window copy
+ RenderFramebuffer();
+
+ // Swap buffers
+ render_window_->PollEvents();
+ render_window_->SwapBuffers();
+
+ // Switch back to EFB and clear
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_[kFramebuffer_EFB]);
+
+ RestoreRenderState();
+}
+
+/**
+ * Renders external framebuffer (XFB)
+ * @param src_rect Source rectangle in XFB to copy
+ * @param dst_rect Destination rectangle in output framebuffer to copy to
+ */
+void RendererOpenGL::RenderXFB(const Rect& src_rect, const Rect& dst_rect) {
+ static u8 xfb_top_flipped[VideoCore::kScreenTopWidth * VideoCore::kScreenTopWidth *3];
+ static u8 xfb_bottom_flipped[VideoCore::kScreenTopWidth * VideoCore::kScreenTopWidth *3];
+
+ _flip_framebuffer(0x20282160, xfb_top_flipped);
+ _flip_framebuffer(0x202118E0, xfb_bottom_flipped);
+
+ ResetRenderState();
+
+ // Blit the top framebuffer
+ // ------------------------
+
+ // Update textures with contents of XFB in RAM - top
+ glBindTexture(GL_TEXTURE_2D, xfb_texture_top_);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight,
+ GL_RGB, GL_UNSIGNED_BYTE, xfb_top_flipped);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ // Render target is destination framebuffer
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_[kFramebuffer_VirtualXFB]);
+ glViewport(0, 0, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight);
+
+ // Render source is our EFB
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, xfb_top_);
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+
+ // Blit
+ glBlitFramebuffer(src_rect.x0_, src_rect.y0_, src_rect.x1_, src_rect.y1_,
+ dst_rect.x0_, dst_rect.y1_, dst_rect.x1_, dst_rect.y0_,
+ GL_COLOR_BUFFER_BIT, GL_LINEAR);
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+
+ // Blit the bottom framebuffer
+ // ---------------------------
+
+ // Update textures with contents of XFB in RAM - bottom
+ glBindTexture(GL_TEXTURE_2D, xfb_texture_bottom_);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight,
+ GL_RGB, GL_UNSIGNED_BYTE, xfb_bottom_flipped);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ // Render target is destination framebuffer
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_[kFramebuffer_VirtualXFB]);
+ glViewport(0, 0,
+ VideoCore::kScreenBottomWidth, VideoCore::kScreenBottomHeight);
+
+ // Render source is our EFB
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, xfb_bottom_);
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+
+ // Blit
+ int offset = (VideoCore::kScreenTopWidth - VideoCore::kScreenBottomWidth) / 2;
+ glBlitFramebuffer(0,0, VideoCore::kScreenBottomWidth, VideoCore::kScreenBottomHeight,
+ offset, VideoCore::kScreenBottomHeight, VideoCore::kScreenBottomWidth + offset, 0,
+ GL_COLOR_BUFFER_BIT, GL_LINEAR);
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+
+ RestoreRenderState();
+}
+
+/**
+ * Blits the EFB to the external framebuffer (XFB)
+ * @param src_rect Source rectangle in EFB to copy
+ * @param dst_rect Destination rectangle in EFB to copy to
+ */
+void RendererOpenGL::CopyToXFB(const Rect& src_rect, const Rect& dst_rect) {
+ ERROR_LOG(RENDER, "CopyToXFB not implemented! No EFB support yet!");
+ //ResetRenderState();
+
+ //// Render target is destination framebuffer
+ //glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_[kFramebuffer_VirtualXFB]);
+ //glViewport(0, 0, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight);
+
+ //// Render source is our EFB
+ //glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_[kFramebuffer_EFB]);
+ //glReadBuffer(GL_COLOR_ATTACHMENT0);
+
+ //// Blit
+ //glBlitFramebuffer(src_rect.x0_, src_rect.y0_, src_rect.x1_, src_rect.y1_,
+ // dst_rect.x0_, dst_rect.y1_, dst_rect.x1_, dst_rect.y0_,
+ // GL_COLOR_BUFFER_BIT, GL_LINEAR);
+
+ //glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+
+ //RestoreRenderState();
+}
+
+/**
+ * Clear the screen
+ * @param rect Screen rectangle to clear
+ * @param enable_color Enable color clearing
+ * @param enable_alpha Enable alpha clearing
+ * @param enable_z Enable depth clearing
+ * @param color Clear color
+ * @param z Clear depth
+ */
+void RendererOpenGL::Clear(const Rect& rect, bool enable_color, bool enable_alpha, bool enable_z,
+ u32 color, u32 z) {
+ GLboolean const color_mask = enable_color ? GL_TRUE : GL_FALSE;
+ GLboolean const alpha_mask = enable_alpha ? GL_TRUE : GL_FALSE;
+
+ ResetRenderState();
+
+ // Clear color
+ glColorMask(color_mask, color_mask, color_mask, alpha_mask);
+ glClearColor(float((color >> 16) & 0xFF) / 255.0f, float((color >> 8) & 0xFF) / 255.0f,
+ float((color >> 0) & 0xFF) / 255.0f, float((color >> 24) & 0xFF) / 255.0f);
+
+ // Clear depth
+ glDepthMask(enable_z ? GL_TRUE : GL_FALSE);
+ glClearDepth(float(z & 0xFFFFFF) / float(0xFFFFFF));
+
+ // Specify the rectangle of the EFB to clear
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(rect.x0_, rect.y1_, rect.width(), rect.height());
+
+ // Clear it!
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ RestoreRenderState();
+}
+
+/// Sets the renderer viewport location, width, and height
+void RendererOpenGL::SetViewport(int x, int y, int width, int height) {
+ glViewport(x, y, width, height);
+}
+
+/// Sets the renderer depthrange, znear and zfar
+void RendererOpenGL::SetDepthRange(double znear, double zfar) {
+ glDepthRange(znear, zfar);
+}
+
+/* Sets the scissor box
+ * @param rect Renderer rectangle to set scissor box to
+ */
+void RendererOpenGL::SetScissorBox(const Rect& rect) {
+ glScissor(rect.x0_, rect.y1_, rect.width(), rect.height());
+}
+
+/**
+ * Sets the line and point size
+ * @param line_width Line width to use
+ * @param point_size Point size to use
+ */
+void RendererOpenGL::SetLinePointSize(f32 line_width, f32 point_size) {
+ glLineWidth((GLfloat)line_width);
+ glPointSize((GLfloat)point_size);
+}
+
+/**
+ * Set a specific render mode
+ * @param flag Render flags mode to enable
+ */
+void RendererOpenGL::SetMode(kRenderMode flags) {
+ if(flags & kRenderMode_ZComp) {
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ }
+ if(flags & kRenderMode_Multipass) {
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+ glDepthFunc(GL_EQUAL);
+ }
+ if (flags & kRenderMode_UseDstAlpha) {
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
+ glDisable(GL_BLEND);
+ }
+ last_mode_ |= flags;
+}
+
+/// Reset the full renderer API to the NULL state
+void RendererOpenGL::ResetRenderState() {
+ glDisable(GL_SCISSOR_TEST);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthMask(GL_FALSE);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+}
+
+/// Restore the full renderer API state - As the game set it
+void RendererOpenGL::RestoreRenderState() {
+
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_[kFramebuffer_EFB]);
+
+ //gp::XF_UpdateViewport();
+ SetViewport(0, 0, resolution_width_, resolution_height_);
+ SetDepthRange(0.0f, 1.0f);
+
+ //SetGenerationMode();
+ glEnable(GL_CULL_FACE);
+ glFrontFace(GL_CCW);
+
+ //glEnable(GL_SCISSOR_TEST);
+ //gp::BP_SetScissorBox();
+ glDisable(GL_SCISSOR_TEST);
+
+ //SetColorMask(gp::g_bp_regs.cmode0);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ //SetDepthMode();
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+
+ //SetBlendMode(gp::g_bp_regs.cmode0, gp::g_bp_regs.cmode1, true);
+ //if (common::g_config->current_renderer_config().enable_wireframe) {
+ // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ //} else {
+ // glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ //}
+}
+
+/// Initialize the FBO
+void RendererOpenGL::InitFramebuffer() {
+ // TODO(en): This should probably be implemented with the top screen and bottom screen as
+ // separate framebuffers
+
+ // Init the FBOs
+ // -------------
+
+ glGenFramebuffers(kMaxFramebuffers, fbo_); // Generate primary framebuffer
+ glGenRenderbuffers(kMaxFramebuffers, fbo_rbo_); // Generate primary RBOs
+ glGenRenderbuffers(kMaxFramebuffers, fbo_depth_buffers_); // Generate primary depth buffer
+
+ for (int i = 0; i < kMaxFramebuffers; i++) {
+ // Generate color buffer storage
+ glBindRenderbuffer(GL_RENDERBUFFER, fbo_rbo_[i]);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, VideoCore::kScreenTopWidth,
+ VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight);
+
+ // Generate depth buffer storage
+ glBindRenderbuffer(GL_RENDERBUFFER, fbo_depth_buffers_[i]);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, VideoCore::kScreenTopWidth,
+ VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight);
+
+ // Attach the buffers
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_[i]);
+ glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, fbo_depth_buffers_[i]);
+ glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, fbo_rbo_[i]);
+
+ // Check for completeness
+ if (GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)) {
+ NOTICE_LOG(RENDER, "framebuffer(%d) initialized ok", i);
+ } else {
+ ERROR_LOG(RENDER, "couldn't create OpenGL frame buffer");
+ exit(1);
+ }
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, 0); // Unbind our frame buffer(s)
+
+ // Initialize framebuffer textures
+ // -------------------------------
+
+ // Create XFB textures
+ glGenTextures(1, &xfb_texture_top_);
+ glGenTextures(1, &xfb_texture_bottom_);
+
+ // Alocate video memorry for XFB textures
+ glBindTexture(GL_TEXTURE_2D, xfb_texture_top_);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight,
+ 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glBindTexture(GL_TEXTURE_2D, xfb_texture_bottom_);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight,
+ 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ // Create the FBO and attach color/depth textures
+ glGenFramebuffers(1, &xfb_top_); // Generate framebuffer
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, xfb_top_);
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ xfb_texture_top_, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ glGenFramebuffers(1, &xfb_bottom_); // Generate framebuffer
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, xfb_bottom_);
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ xfb_texture_bottom_, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
+/// Blit the FBO to the OpenGL default framebuffer
+void RendererOpenGL::RenderFramebuffer() {
+
+ // Render target is default framebuffer
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+ glViewport(0, 0, resolution_width_, resolution_height_);
+
+ // Render source is our XFB
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_[kFramebuffer_VirtualXFB]);
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+
+ // Blit
+ glBlitFramebuffer(0, 0, resolution_width_, resolution_height_, 0, 0,
+ resolution_width_, resolution_height_, GL_COLOR_BUFFER_BIT, GL_LINEAR);
+
+ // Update the FPS count
+ UpdateFramerate();
+
+ // Rebind EFB
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_[kFramebuffer_EFB]);
+
+ current_frame_++;
+}
+
+/// Updates the framerate
+void RendererOpenGL::UpdateFramerate() {
+}
+
+/**
+ * Set the emulator window to use for renderer
+ * @param window EmuWindow handle to emulator window to use for rendering
+ */
+void RendererOpenGL::SetWindow(EmuWindow* window) {
+ render_window_ = window;
+}
+
+/// Initialize the renderer
+void RendererOpenGL::Init() {
+ render_window_->MakeCurrent();
+ glShadeModel(GL_SMOOTH);
+
+
+ glStencilFunc(GL_ALWAYS, 0, 0);
+ glBlendFunc(GL_ONE, GL_ONE);
+
+ glViewport(0, 0, resolution_width_, resolution_height_);
+
+ glClearDepth(1.0f);
+ glEnable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glDepthFunc(GL_LEQUAL);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+ glDisable(GL_STENCIL_TEST);
+ glEnable(GL_SCISSOR_TEST);
+
+ glScissor(0, 0, resolution_width_, resolution_height_);
+ glClearDepth(1.0f);
+
+ GLenum err = glewInit();
+ if (GLEW_OK != err) {
+ ERROR_LOG(RENDER, " Failed to initialize GLEW! Error message: \"%s\". Exiting...",
+ glewGetErrorString(err));
+ exit(-1);
+ }
+
+ // Initialize everything else
+ // --------------------------
+
+ InitFramebuffer();
+
+ NOTICE_LOG(RENDER, "GL_VERSION: %s\n", glGetString(GL_VERSION));
+}
+
+/// Shutdown the renderer
+void RendererOpenGL::ShutDown() {
+}
diff --git a/src/video_core/src/renderer_opengl/renderer_opengl.h b/src/video_core/src/renderer_opengl/renderer_opengl.h
new file mode 100644
index 000000000..b84afc5d2
--- /dev/null
+++ b/src/video_core/src/renderer_opengl/renderer_opengl.h
@@ -0,0 +1,153 @@
+/**
+ * Copyright (C) 2014 Citra Emulator
+ *
+ * @file renderer_opengl.h
+ * @author bunnei
+ * @date 2014-04-05
+ * @brief Renderer for OpenGL 3.x
+ *
+ * @section LICENSE
+ * This program is free software; 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 at
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Official project repository can be found at:
+ * http://code.google.com/p/gekko-gc-emu/
+ */
+
+#pragma once
+
+#include
+
+
+#include "common.h"
+#include "emu_window.h"
+
+#include "renderer_base.h"
+
+
+class RendererOpenGL : virtual public RendererBase {
+public:
+
+ static const int kMaxFramebuffers = 2; ///< Maximum number of framebuffers
+
+ RendererOpenGL();
+ ~RendererOpenGL();
+
+ /// Swap buffers (render frame)
+ void SwapBuffers();
+
+ /**
+ * Renders external framebuffer (XFB)
+ * @param src_rect Source rectangle in XFB to copy
+ * @param dst_rect Destination rectangle in output framebuffer to copy to
+ */
+ void RenderXFB(const Rect& src_rect, const Rect& dst_rect);
+
+ /**
+ * Blits the EFB to the external framebuffer (XFB)
+ * @param src_rect Source rectangle in EFB to copy
+ * @param dst_rect Destination rectangle in EFB to copy to
+ */
+ void CopyToXFB(const Rect& src_rect, const Rect& dst_rect);
+
+ /**
+ * Clear the screen
+ * @param rect Screen rectangle to clear
+ * @param enable_color Enable color clearing
+ * @param enable_alpha Enable alpha clearing
+ * @param enable_z Enable depth clearing
+ * @param color Clear color
+ * @param z Clear depth
+ */
+ void Clear(const Rect& rect, bool enable_color, bool enable_alpha, bool enable_z,
+ u32 color, u32 z);
+
+ /// Sets the renderer viewport location, width, and height
+ void SetViewport(int x, int y, int width, int height);
+
+ /// Sets the renderer depthrange, znear and zfar
+ void SetDepthRange(double znear, double zfar);
+
+ /* Sets the scissor box
+ * @param rect Renderer rectangle to set scissor box to
+ */
+ void SetScissorBox(const Rect& rect);
+
+ /**
+ * Sets the line and point size
+ * @param line_width Line width to use
+ * @param point_size Point size to use
+ */
+ void SetLinePointSize(f32 line_width, f32 point_size);
+
+ /**
+ * Set a specific render mode
+ * @param flag Render flags mode to enable
+ */
+ void SetMode(kRenderMode flags);
+
+ /// Reset the full renderer API to the NULL state
+ void ResetRenderState();
+
+ /// Restore the full renderer API state - As the game set it
+ void RestoreRenderState();
+
+ /**
+ * Set the emulator window to use for renderer
+ * @param window EmuWindow handle to emulator window to use for rendering
+ */
+ void SetWindow(EmuWindow* window);
+
+ /// Initialize the renderer
+ void Init();
+
+ /// Shutdown the renderer
+ void ShutDown();
+
+ // Framebuffer object(s)
+ // ---------------------
+
+ GLuint fbo_[kMaxFramebuffers]; ///< Framebuffer objects
+
+private:
+
+ /// Initialize the FBO
+ void InitFramebuffer();
+
+ // Blit the FBO to the OpenGL default framebuffer
+ void RenderFramebuffer();
+
+ /// Updates the framerate
+ void UpdateFramerate();
+
+ EmuWindow* render_window_;
+ u32 last_mode_; ///< Last render mode
+
+ int resolution_width_;
+ int resolution_height_;
+
+ // Render buffers
+ // --------------
+
+ GLuint fbo_rbo_[kMaxFramebuffers]; ///< Render buffer objects
+ GLuint fbo_depth_buffers_[kMaxFramebuffers]; ///< Depth buffers objects
+
+ // External framebuffers
+ // ---------------------
+
+ GLuint xfb_texture_top_; ///< GL handle to top framebuffer texture
+ GLuint xfb_texture_bottom_; ///< GL handle to bottom framebuffer texture
+
+ GLuint xfb_top_;
+ GLuint xfb_bottom_;
+
+ DISALLOW_COPY_AND_ASSIGN(RendererOpenGL);
+};
\ No newline at end of file
diff --git a/src/video_core/src/utils.cpp b/src/video_core/src/utils.cpp
new file mode 100644
index 000000000..a5e702f67
--- /dev/null
+++ b/src/video_core/src/utils.cpp
@@ -0,0 +1,66 @@
+/**
+ * Copyright (C) 2005-2012 Gekko Emulator
+ *
+ * @file utils.cpp
+ * @author ShizZy
+ * @date 2012-12-28
+ * @brief Utility functions (in general, not related to emulation) useful for video core
+ *
+ * @section LICENSE
+ * This program is free software; 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 at
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Official project repository can be found at:
+ * http://code.google.com/p/gekko-gc-emu/
+ */
+
+#include
+#include
+
+#include "utils.h"
+
+namespace VideoCore {
+
+/**
+ * Dumps a texture to TGA
+ * @param filename String filename to dump texture to
+ * @param width Width of texture in pixels
+ * @param height Height of texture in pixels
+ * @param raw_data Raw RGBA8 texture data to dump
+ * @todo This should be moved to some general purpose/common code
+ */
+void DumpTGA(std::string filename, int width, int height, u8* raw_data) {
+ TGAHeader hdr;
+ FILE* fout;
+ u8 r, g, b;
+
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.datatypecode = 2; // uncompressed RGB
+ hdr.bitsperpixel = 24; // 24 bpp
+ hdr.width = width;
+ hdr.height = height;
+
+ fout = fopen(filename.c_str(), "wb");
+ fwrite(&hdr, sizeof(TGAHeader), 1, fout);
+ for (int i = 0; i < height; i++) {
+ for (int j = 0; j < width; j++) {
+ r = raw_data[(4 * (i * width)) + (4 * j) + 0];
+ g = raw_data[(4 * (i * width)) + (4 * j) + 1];
+ b = raw_data[(4 * (i * width)) + (4 * j) + 2];
+ putc(b, fout);
+ putc(g, fout);
+ putc(r, fout);
+ }
+ }
+ fclose(fout);
+}
+
+} // namespace
diff --git a/src/video_core/src/utils.h b/src/video_core/src/utils.h
new file mode 100644
index 000000000..2d7fa4a3a
--- /dev/null
+++ b/src/video_core/src/utils.h
@@ -0,0 +1,83 @@
+/**
+ * Copyright (C) 2005-2012 Gekko Emulator
+ *
+ * @file utils.h
+ * @author ShizZy
+ * @date 2012-12-28
+ * @brief Utility functions (in general, not related to emulation) useful for video core
+ *
+ * @section LICENSE
+ * This program is free software; 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 at
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Official project repository can be found at:
+ * http://code.google.com/p/gekko-gc-emu/
+ */
+
+#pragma once
+
+#include "common_types.h"
+#include
+
+namespace FormatPrecision {
+
+/// Adjust RGBA8 color with RGBA6 precision
+static inline u32 rgba8_with_rgba6(u32 src) {
+ u32 color = src;
+ color &= 0xFCFCFCFC;
+ color |= (color >> 6) & 0x03030303;
+ return color;
+}
+
+/// Adjust RGBA8 color with RGB565 precision
+static inline u32 rgba8_with_rgb565(u32 src) {
+ u32 color = (src & 0xF8FCF8);
+ color |= (color >> 5) & 0x070007;
+ color |= (color >> 6) & 0x000300;
+ color |= 0xFF000000;
+ return color;
+}
+
+/// Adjust Z24 depth value with Z16 precision
+static inline u32 z24_with_z16(u32 src) {
+ return (src & 0xFFFF00) | (src >> 16);
+}
+
+} // namespace
+
+namespace VideoCore {
+
+/// Structure for the TGA texture format (for dumping)
+struct TGAHeader {
+ char idlength;
+ char colourmaptype;
+ char datatypecode;
+ short int colourmaporigin;
+ short int colourmaplength;
+ short int x_origin;
+ short int y_origin;
+ short width;
+ short height;
+ char bitsperpixel;
+ char imagedescriptor;
+};
+
+/**
+ * Dumps a texture to TGA
+ * @param filename String filename to dump texture to
+ * @param width Width of texture in pixels
+ * @param height Height of texture in pixels
+ * @param raw_data Raw RGBA8 texture data to dump
+ * @todo This should be moved to some general purpose/common code
+ */
+void DumpTGA(std::string filename, int width, int height, u8* raw_data);
+
+} // namespace
diff --git a/src/video_core/src/video_core.cpp b/src/video_core/src/video_core.cpp
new file mode 100644
index 000000000..52ff90488
--- /dev/null
+++ b/src/video_core/src/video_core.cpp
@@ -0,0 +1,88 @@
+/**
+ * Copyright (C) 2014 Citra Emulator
+ *
+ * @file video_core.cpp
+ * @author bunnei
+ * @date 2014-04-05
+ * @brief Main module for new video core
+ *
+ * @section LICENSE
+ * This program is free software; 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 at
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Official project repository can be found at:
+ * http://code.google.com/p/gekko-gc-emu/
+ */
+
+#include "common.h"
+#include "emu_window.h"
+#include "log.h"
+
+#include "core.h"
+
+#include "video_core.h"
+#include "renderer_base.h"
+#include "renderer_opengl/renderer_opengl.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Video Core namespace
+
+namespace VideoCore {
+
+EmuWindow* g_emu_window = NULL; ///< Frontend emulator window
+RendererBase* g_renderer = NULL; ///< Renderer plugin
+int g_current_frame = 0;
+
+int VideoEntry(void*) {
+ if (g_emu_window == NULL) {
+ ERROR_LOG(VIDEO, "VideoCore::VideoEntry called without calling Init()!");
+ }
+ g_emu_window->MakeCurrent();
+ //for(;;) {
+ // gp::Fifo_DecodeCommand();
+ //}
+ return 0;
+}
+
+/// Start the video core
+void Start() {
+ if (g_emu_window == NULL) {
+ ERROR_LOG(VIDEO, "VideoCore::Start called without calling Init()!");
+ }
+ //if (common::g_config->enable_multicore()) {
+ // g_emu_window->DoneCurrent();
+ // g_video_thread = SDL_CreateThread(VideoEntry, NULL, NULL);
+ // if (g_video_thread == NULL) {
+ // LOG_ERROR(TVIDEO, "Unable to create thread: %s... Exiting\n", SDL_GetError());
+ // exit(1);
+ // }
+ //}
+}
+
+/// Initialize the video core
+void Init(EmuWindow* emu_window) {
+ g_emu_window = emu_window;
+ g_emu_window->MakeCurrent();
+ g_renderer = new RendererOpenGL();
+ g_renderer->SetWindow(g_emu_window);
+ g_renderer->Init();
+
+ g_current_frame = 0;
+
+ NOTICE_LOG(VIDEO, "initialized ok");
+}
+
+/// Shutdown the video core
+void Shutdown() {
+ delete g_renderer;
+}
+
+} // namespace
diff --git a/src/video_core/src/video_core.h b/src/video_core/src/video_core.h
new file mode 100644
index 000000000..10b8f1105
--- /dev/null
+++ b/src/video_core/src/video_core.h
@@ -0,0 +1,59 @@
+/*!
+ * Copyright (C) 2014 Citra Emulator
+ *
+ * @file video_core.h
+ * @author bunnei
+ * @date 2014-04-05
+ * @brief Main module for new video core
+ *
+ * @section LICENSE
+ * This program is free software; 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 at
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Official project repository can be found at:
+ * http://code.google.com/p/gekko-gc-emu/
+ */
+
+#pragma once
+
+#include "common.h"
+#include "emu_window.h"
+#include "renderer_base.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Video Core namespace
+
+namespace VideoCore {
+
+// 3DS Video Constants
+// -------------------
+
+static const int kScreenTopWidth = 400; ///< 3DS top screen width
+static const int kScreenTopHeight = 240; ///< 3DS top screen height
+static const int kScreenBottomWidth = 320; ///< 3DS bottom screen width
+static const int kScreenBottomHeight = 240; ///< 3DS bottom screen height
+
+// Video core renderer
+// ---------------------
+
+extern RendererBase* g_renderer; ///< Renderer plugin
+extern int g_current_frame; ///< Current frame
+
+/// Start the video core
+void Start();
+
+/// Initialize the video core
+void Init(EmuWindow* emu_window);
+
+/// Shutdown the video core
+void Shutdown();
+
+} // namespace
diff --git a/src/video_core/video_core.vcxproj b/src/video_core/video_core.vcxproj
new file mode 100644
index 000000000..5c56e9b71
--- /dev/null
+++ b/src/video_core/video_core.vcxproj
@@ -0,0 +1,131 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {6678D1A3-33A6-48A9-878B-48E5D2903D27}
+ input_common
+ video_core
+
+
+
+ StaticLibrary
+ true
+ v120
+
+
+ StaticLibrary
+ true
+ v120
+
+
+ StaticLibrary
+ false
+ v120
+
+
+ StaticLibrary
+ false
+ v120
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+ true
+
+
+
+
+
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+ true
+ true
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/video_core/video_core.vcxproj.filters b/src/video_core/video_core.vcxproj.filters
new file mode 100644
index 000000000..e796fbe21
--- /dev/null
+++ b/src/video_core/video_core.vcxproj.filters
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+ renderer_opengl
+
+
+
+
+
+
+
+ renderer_opengl
+
+
+
+
+
+
+
+ {e0245557-dbd4-423e-9399-513d5e99f1e4}
+
+
+
\ No newline at end of file
diff --git a/vsprops/base.props b/vsprops/base.props
index 0f59b512b..6241bd44b 100644
--- a/vsprops/base.props
+++ b/vsprops/base.props
@@ -12,7 +12,7 @@
16Bytes
true
true
- $(SolutionDir)src\common\src;$(SolutionDir)src\core\src;$(SolutionDir)src\citra\src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)src\common\src;$(SolutionDir)src\core\src;$(SolutionDir)src\video_core\src;%(AdditionalIncludeDirectories)
false