* more thread-safe UI
* config system base * FPS counter and limiter
This commit is contained in:
parent
91f46b00fb
commit
8c059c9953
|
@ -80,6 +80,8 @@
|
||||||
<Unit filename="src/ARM_InstrTable.h" />
|
<Unit filename="src/ARM_InstrTable.h" />
|
||||||
<Unit filename="src/CP15.cpp" />
|
<Unit filename="src/CP15.cpp" />
|
||||||
<Unit filename="src/CP15.h" />
|
<Unit filename="src/CP15.h" />
|
||||||
|
<Unit filename="src/Config.cpp" />
|
||||||
|
<Unit filename="src/Config.h" />
|
||||||
<Unit filename="src/DMA.cpp" />
|
<Unit filename="src/DMA.cpp" />
|
||||||
<Unit filename="src/DMA.h" />
|
<Unit filename="src/DMA.h" />
|
||||||
<Unit filename="src/FIFO.h" />
|
<Unit filename="src/FIFO.h" />
|
||||||
|
|
|
@ -171,6 +171,9 @@ void ARM::JumpTo(u32 addr, bool restorecpsr)
|
||||||
else addr &= ~0x1;
|
else addr &= ~0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (addr == 0x0201764C) printf("capture test %d: R1=%08X\n", R[6], R[1]);
|
||||||
|
if (addr == 0x020175D8) printf("capture test %d: res=%08X\n", R[6], R[0]);
|
||||||
|
|
||||||
if (addr & 0x1)
|
if (addr & 0x1)
|
||||||
{
|
{
|
||||||
addr &= ~0x1;
|
addr &= ~0x1;
|
||||||
|
|
|
@ -38,6 +38,14 @@
|
||||||
//
|
//
|
||||||
// for VRAM display mode, VRAM must be mapped to LCDC
|
// for VRAM display mode, VRAM must be mapped to LCDC
|
||||||
//
|
//
|
||||||
|
// FIFO display mode:
|
||||||
|
// * the 'FIFO' is a circular buffer of 32 bytes (16 pixels)
|
||||||
|
// * the buffer doesn't get empty, the display controller keeps reading from it
|
||||||
|
// -> if it isn't updated, the contents will be repeated every 16 pixels
|
||||||
|
// * the write pointer is incremented when writing to the higher 16 bits of the FIFO register (0x04000068)
|
||||||
|
// * the write pointer is reset upon VBlank
|
||||||
|
// * FIFO DMA (mode 4) is triggered every 8 pixels. start bit is cleared upon VBlank.
|
||||||
|
//
|
||||||
// sprite blending rules
|
// sprite blending rules
|
||||||
// * destination must be selected as 2nd target
|
// * destination must be selected as 2nd target
|
||||||
// * sprite must be semitransparent or bitmap sprite
|
// * sprite must be semitransparent or bitmap sprite
|
||||||
|
|
|
@ -52,6 +52,12 @@
|
||||||
// if (clearZ >= 0x010000 && clearZ < 0xFFFFFF) clearZ++;
|
// if (clearZ >= 0x010000 && clearZ < 0xFFFFFF) clearZ++;
|
||||||
//
|
//
|
||||||
// alpha is 5-bit
|
// alpha is 5-bit
|
||||||
|
//
|
||||||
|
// matrix push/pop on the position matrix are always applied to the vector matrix too, even in position-only mode
|
||||||
|
// store/restore too, probably (TODO: confirm)
|
||||||
|
// (the idea is that each position matrix has an associated vector matrix)
|
||||||
|
//
|
||||||
|
// TODO: check if translate works on the vector matrix? seems pointless
|
||||||
|
|
||||||
|
|
||||||
namespace GPU3D
|
namespace GPU3D
|
||||||
|
@ -729,7 +735,10 @@ void SubmitPolygon()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (farplaneclip && (!(CurPolygonAttr & (1<<12))))
|
if (farplaneclip && (!(CurPolygonAttr & (1<<12))))
|
||||||
|
{
|
||||||
|
LastStripPolygon = NULL;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
nverts = c; c = clipstart;
|
nverts = c; c = clipstart;
|
||||||
for (int i = clipstart; i < nverts; i++)
|
for (int i = clipstart; i < nverts; i++)
|
||||||
|
@ -903,6 +912,8 @@ void SubmitVertex()
|
||||||
s64 vertex[4] = {(s64)CurVertex[0], (s64)CurVertex[1], (s64)CurVertex[2], 0x1000};
|
s64 vertex[4] = {(s64)CurVertex[0], (s64)CurVertex[1], (s64)CurVertex[2], 0x1000};
|
||||||
Vertex* vertextrans = &TempVertexBuffer[VertexNumInPoly];
|
Vertex* vertextrans = &TempVertexBuffer[VertexNumInPoly];
|
||||||
|
|
||||||
|
//printf("vertex: %08X %08X %08X, %d %d %d\n", CurVertex[0], CurVertex[1], CurVertex[2], VertexColor[0], VertexColor[1], VertexColor[2]);
|
||||||
|
|
||||||
UpdateClipMatrix();
|
UpdateClipMatrix();
|
||||||
vertextrans->Position[0] = (vertex[0]*ClipMatrix[0] + vertex[1]*ClipMatrix[4] + vertex[2]*ClipMatrix[8] + vertex[3]*ClipMatrix[12]) >> 12;
|
vertextrans->Position[0] = (vertex[0]*ClipMatrix[0] + vertex[1]*ClipMatrix[4] + vertex[2]*ClipMatrix[8] + vertex[3]*ClipMatrix[12]) >> 12;
|
||||||
vertextrans->Position[1] = (vertex[0]*ClipMatrix[1] + vertex[1]*ClipMatrix[5] + vertex[2]*ClipMatrix[9] + vertex[3]*ClipMatrix[13]) >> 12;
|
vertextrans->Position[1] = (vertex[0]*ClipMatrix[1] + vertex[1]*ClipMatrix[5] + vertex[2]*ClipMatrix[9] + vertex[3]*ClipMatrix[13]) >> 12;
|
||||||
|
|
|
@ -721,7 +721,7 @@ void RenderPolygon(Polygon* polygon)
|
||||||
{
|
{
|
||||||
// edge fill rules for opaque pixels
|
// edge fill rules for opaque pixels
|
||||||
// TODO, eventually: antialiasing
|
// TODO, eventually: antialiasing
|
||||||
if (!wireframe)
|
if (!wireframe)// && !(edge & 0x4))
|
||||||
{
|
{
|
||||||
if ((edge & 0x1) && slope_start > 0x1000)
|
if ((edge & 0x1) && slope_start > 0x1000)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -1780,6 +1780,11 @@ void ARM9IOWrite32(u32 addr, u32 val)
|
||||||
|
|
||||||
case 0x040002B8: SqrtVal[0] = val; StartSqrt(); return;
|
case 0x040002B8: SqrtVal[0] = val; StartSqrt(); return;
|
||||||
case 0x040002BC: SqrtVal[1] = val; StartSqrt(); return;
|
case 0x040002BC: SqrtVal[1] = val; StartSqrt(); return;
|
||||||
|
|
||||||
|
case 0x04000304:
|
||||||
|
PowerControl9 = val & 0xFFFF;
|
||||||
|
GPU::DisplaySwap(PowerControl9>>15);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr >= 0x04000000 && addr < 0x04000060)
|
if (addr >= 0x04000000 && addr < 0x04000060)
|
||||||
|
|
310
src/wx/main.cpp
310
src/wx/main.cpp
|
@ -19,26 +19,15 @@
|
||||||
#include "../types.h"
|
#include "../types.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "../version.h"
|
#include "../version.h"
|
||||||
|
#include "../Config.h"
|
||||||
#include "../NDS.h"
|
#include "../NDS.h"
|
||||||
#include "../GPU.h"
|
#include "../GPU.h"
|
||||||
|
|
||||||
|
|
||||||
const int DefaultKeyMapping[18] =
|
|
||||||
{
|
|
||||||
15, 54,
|
|
||||||
44, 40,
|
|
||||||
22, 4, 26, 29,
|
|
||||||
19, 20,
|
|
||||||
0, 0, 0, 0, 0, 0,
|
|
||||||
18, 14
|
|
||||||
};
|
|
||||||
|
|
||||||
int KeyMapping[18];
|
|
||||||
int JoyMapping[18];
|
|
||||||
|
|
||||||
bool Touching;
|
bool Touching;
|
||||||
|
|
||||||
int WindowX, WindowY;
|
int WindowX, WindowY;
|
||||||
|
int WindowW, WindowH;
|
||||||
|
|
||||||
|
|
||||||
wxIMPLEMENT_APP(wxApp_melonDS);
|
wxIMPLEMENT_APP(wxApp_melonDS);
|
||||||
|
@ -54,6 +43,8 @@ bool wxApp_melonDS::OnInit()
|
||||||
|
|
||||||
printf("melonDS " MELONDS_VERSION "\n" MELONDS_URL "\n");
|
printf("melonDS " MELONDS_VERSION "\n" MELONDS_URL "\n");
|
||||||
|
|
||||||
|
Config::Load();
|
||||||
|
|
||||||
MainFrame* melon = new MainFrame();
|
MainFrame* melon = new MainFrame();
|
||||||
melon->Show(true);
|
melon->Show(true);
|
||||||
|
|
||||||
|
@ -62,13 +53,18 @@ bool wxApp_melonDS::OnInit()
|
||||||
|
|
||||||
|
|
||||||
wxBEGIN_EVENT_TABLE(MainFrame, wxFrame)
|
wxBEGIN_EVENT_TABLE(MainFrame, wxFrame)
|
||||||
|
EVT_CLOSE(MainFrame::OnClose)
|
||||||
|
|
||||||
EVT_MENU(ID_OPENROM, MainFrame::OnOpenROM)
|
EVT_MENU(ID_OPENROM, MainFrame::OnOpenROM)
|
||||||
|
EVT_MENU(ID_EXIT, MainFrame::OnCloseFromMenu)
|
||||||
|
|
||||||
EVT_PAINT(MainFrame::OnPaint)
|
EVT_PAINT(MainFrame::OnPaint)
|
||||||
|
EVT_IDLE(MainFrame::OnIdle)
|
||||||
wxEND_EVENT_TABLE()
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
|
|
||||||
MainFrame::MainFrame()
|
MainFrame::MainFrame()
|
||||||
: wxFrame(NULL, wxID_ANY, "melonDS")
|
: wxFrame(NULL, wxID_ANY, "melonDS " MELONDS_VERSION)
|
||||||
{
|
{
|
||||||
wxMenu* filemenu = new wxMenu();
|
wxMenu* filemenu = new wxMenu();
|
||||||
filemenu->Append(ID_OPENROM, "Open ROM...");
|
filemenu->Append(ID_OPENROM, "Open ROM...");
|
||||||
|
@ -81,18 +77,29 @@ MainFrame::MainFrame()
|
||||||
systemmenu->AppendSeparator();
|
systemmenu->AppendSeparator();
|
||||||
systemmenu->Append(ID_RESET, "Reset");
|
systemmenu->Append(ID_RESET, "Reset");
|
||||||
|
|
||||||
|
wxMenu* settingsmenu = new wxMenu();
|
||||||
|
settingsmenu->Append(ID_INPUTCONFIG, "Input");
|
||||||
|
|
||||||
wxMenuBar* melonbar = new wxMenuBar();
|
wxMenuBar* melonbar = new wxMenuBar();
|
||||||
melonbar->Append(filemenu, "File");
|
melonbar->Append(filemenu, "File");
|
||||||
melonbar->Append(systemmenu, "System");
|
melonbar->Append(systemmenu, "System");
|
||||||
|
melonbar->Append(settingsmenu, "Settings");
|
||||||
|
|
||||||
SetMenuBar(melonbar);
|
SetMenuBar(melonbar);
|
||||||
|
|
||||||
SetClientSize(256, 384);
|
SetClientSize(256, 384);
|
||||||
|
SetMinSize(GetSize());
|
||||||
|
|
||||||
emumutex = new wxMutex();
|
emustatus = 2;
|
||||||
emucond = new wxCondition(*emumutex);
|
|
||||||
|
|
||||||
emuthread = new EmuThread(this, emumutex, emucond);
|
emustatuschangemutex = new wxMutex();
|
||||||
|
emustatuschange = new wxCondition(*emustatuschangemutex);
|
||||||
|
|
||||||
|
emustopmutex = new wxMutex();
|
||||||
|
emustop = new wxCondition(*emustopmutex);
|
||||||
|
emustopmutex->Lock();
|
||||||
|
|
||||||
|
emuthread = new EmuThread(this);
|
||||||
if (emuthread->Run() != wxTHREAD_NO_ERROR)
|
if (emuthread->Run() != wxTHREAD_NO_ERROR)
|
||||||
{
|
{
|
||||||
printf("thread shat itself :( giving up now\n");
|
printf("thread shat itself :( giving up now\n");
|
||||||
|
@ -102,17 +109,53 @@ MainFrame::MainFrame()
|
||||||
|
|
||||||
sdlwin = SDL_CreateWindowFrom(GetHandle());
|
sdlwin = SDL_CreateWindowFrom(GetHandle());
|
||||||
|
|
||||||
sdlrend = SDL_CreateRenderer(sdlwin, -1, SDL_RENDERER_ACCELERATED); // SDL_RENDERER_PRESENTVSYNC
|
sdlrend = SDL_CreateRenderer(sdlwin, -1, SDL_RENDERER_ACCELERATED);// | SDL_RENDERER_PRESENTVSYNC);
|
||||||
sdltex = SDL_CreateTexture(sdlrend, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, 256, 384);
|
sdltex = SDL_CreateTexture(sdlrend, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, 256, 384);
|
||||||
|
|
||||||
NDS::Init();
|
texmutex = new wxMutex();
|
||||||
|
SDL_LockTexture(sdltex, NULL, &texpixels, &texstride);
|
||||||
|
texmutex->Unlock();
|
||||||
|
|
||||||
memcpy(KeyMapping, DefaultKeyMapping, 18*sizeof(int));
|
NDS::Init();
|
||||||
memset(JoyMapping, 0, 18*sizeof(int));
|
|
||||||
|
|
||||||
Touching = false;
|
Touching = false;
|
||||||
|
|
||||||
SDL_GetWindowPosition(sdlwin, &WindowX, &WindowY);
|
SDL_GetWindowPosition(sdlwin, &WindowX, &WindowY);
|
||||||
|
SDL_GetWindowSize(sdlwin, &WindowW, &WindowH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainFrame::OnClose(wxCloseEvent& event)
|
||||||
|
{
|
||||||
|
emustatus = 0;
|
||||||
|
emustatuschangemutex->Lock();
|
||||||
|
emustatuschange->Signal();
|
||||||
|
emustatuschangemutex->Unlock();
|
||||||
|
|
||||||
|
emuthread->Wait();
|
||||||
|
delete emuthread;
|
||||||
|
delete emustatuschange;
|
||||||
|
delete emustatuschangemutex;
|
||||||
|
delete emustop;
|
||||||
|
delete emustopmutex;
|
||||||
|
|
||||||
|
NDS::DeInit();
|
||||||
|
|
||||||
|
SDL_UnlockTexture(sdltex);
|
||||||
|
delete texmutex;
|
||||||
|
|
||||||
|
SDL_DestroyTexture(sdltex);
|
||||||
|
SDL_DestroyRenderer(sdlrend);
|
||||||
|
|
||||||
|
SDL_DestroyWindow(sdlwin);
|
||||||
|
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainFrame::OnCloseFromMenu(wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::OnOpenROM(wxCommandEvent& event)
|
void MainFrame::OnOpenROM(wxCommandEvent& event)
|
||||||
|
@ -121,35 +164,118 @@ void MainFrame::OnOpenROM(wxCommandEvent& event)
|
||||||
if (opener.ShowModal() == wxID_CANCEL)
|
if (opener.ShowModal() == wxID_CANCEL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (emustatus == 1)
|
||||||
|
{
|
||||||
|
emustatus = 2;
|
||||||
|
emustop->Wait();
|
||||||
|
}
|
||||||
|
|
||||||
wxString filename = opener.GetPath();
|
wxString filename = opener.GetPath();
|
||||||
NDS::LoadROM(filename.mb_str(), true);
|
NDS::LoadROM(filename.mb_str(), true);
|
||||||
|
|
||||||
emuthread->EmuStatus = 1;
|
emustatus = 1;
|
||||||
emumutex->Lock();
|
emustatuschangemutex->Lock();
|
||||||
emucond->Signal();
|
emustatuschange->Signal();
|
||||||
emumutex->Unlock();
|
emustatuschangemutex->Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainFrame::ProcessSDLEvents()
|
||||||
|
{
|
||||||
|
bool running = (emustatus == 1);
|
||||||
|
SDL_Event evt;
|
||||||
|
|
||||||
|
while (SDL_PollEvent(&evt))
|
||||||
|
{
|
||||||
|
switch (evt.type)
|
||||||
|
{
|
||||||
|
case SDL_WINDOWEVENT:
|
||||||
|
if (evt.window.event != SDL_WINDOWEVENT_EXPOSED)
|
||||||
|
{
|
||||||
|
SDL_GetWindowPosition(sdlwin, &WindowX, &WindowY);
|
||||||
|
SDL_GetWindowSize(sdlwin, &WindowW, &WindowH);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
if (!running) return;
|
||||||
|
if (evt.button.y >= 192 && evt.button.button == SDL_BUTTON_LEFT)
|
||||||
|
{
|
||||||
|
Touching = true;
|
||||||
|
NDS::PressKey(16+6);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
if (!running) return;
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
if (evt.key.keysym.scancode == Config::KeyMapping[i]) NDS::PressKey(i);
|
||||||
|
if (evt.key.keysym.scancode == Config::KeyMapping[10]) NDS::PressKey(16);
|
||||||
|
if (evt.key.keysym.scancode == Config::KeyMapping[11]) NDS::PressKey(17);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_KEYUP:
|
||||||
|
if (!running) return;
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
if (evt.key.keysym.scancode == Config::KeyMapping[i]) NDS::ReleaseKey(i);
|
||||||
|
if (evt.key.keysym.scancode == Config::KeyMapping[10]) NDS::ReleaseKey(16);
|
||||||
|
if (evt.key.keysym.scancode == Config::KeyMapping[11]) NDS::ReleaseKey(17);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Touching)
|
||||||
|
{
|
||||||
|
int mx, my;
|
||||||
|
u32 btn = SDL_GetGlobalMouseState(&mx, &my);
|
||||||
|
if (!(btn & SDL_BUTTON(SDL_BUTTON_LEFT)))
|
||||||
|
{
|
||||||
|
Touching = false;
|
||||||
|
NDS::ReleaseKey(16+6);
|
||||||
|
NDS::ReleaseScreen();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mx -= WindowX;
|
||||||
|
my -= (WindowY + 192);
|
||||||
|
|
||||||
|
if (mx < 0) mx = 0;
|
||||||
|
else if (mx > 255) mx = 255;
|
||||||
|
|
||||||
|
if (my < 0) my = 0;
|
||||||
|
else if (my > 191) my = 191;
|
||||||
|
|
||||||
|
NDS::TouchScreen(mx, my);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::OnPaint(wxPaintEvent& event)
|
void MainFrame::OnPaint(wxPaintEvent& event)
|
||||||
{
|
{
|
||||||
/*wxPaintDC dc(this);
|
wxPaintDC dc(this);
|
||||||
wxGraphicsContext* gc = wxGraphicsContext::Create(dc);
|
|
||||||
if (!gc) return;
|
|
||||||
|
|
||||||
//
|
texmutex->Lock();
|
||||||
|
SDL_UnlockTexture(sdltex);
|
||||||
|
|
||||||
delete gc;*/
|
//SDL_RenderClear(sdlrend);
|
||||||
|
SDL_RenderCopy(sdlrend, sdltex, NULL, NULL);
|
||||||
|
SDL_RenderPresent(sdlrend);
|
||||||
|
|
||||||
|
SDL_LockTexture(sdltex, NULL, &texpixels, &texstride);
|
||||||
|
texmutex->Unlock();
|
||||||
|
|
||||||
|
ProcessSDLEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainFrame::OnIdle(wxIdleEvent& event)
|
||||||
|
{
|
||||||
|
ProcessSDLEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EmuThread::EmuThread(MainFrame* parent, wxMutex* mutex, wxCondition* cond)
|
EmuThread::EmuThread(MainFrame* parent)
|
||||||
: wxThread(wxTHREAD_JOINABLE)
|
: wxThread(wxTHREAD_JOINABLE)
|
||||||
{
|
{
|
||||||
this->parent = parent;
|
this->parent = parent;
|
||||||
this->mutex = mutex;
|
|
||||||
this->cond = cond;
|
|
||||||
|
|
||||||
EmuStatus = 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EmuThread::~EmuThread()
|
EmuThread::~EmuThread()
|
||||||
|
@ -158,87 +284,75 @@ EmuThread::~EmuThread()
|
||||||
|
|
||||||
wxThread::ExitCode EmuThread::Entry()
|
wxThread::ExitCode EmuThread::Entry()
|
||||||
{
|
{
|
||||||
mutex->Lock();
|
parent->emustatuschangemutex->Lock();
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
cond->Wait();
|
parent->emustatuschange->Wait();
|
||||||
|
|
||||||
if (EmuStatus == 0)
|
if (parent->emustatus == 1)
|
||||||
break;
|
|
||||||
|
|
||||||
while (EmuStatus == 1)
|
|
||||||
{
|
{
|
||||||
NDS::RunFrame();
|
u32 nframes = 0;
|
||||||
|
u32 lasttick = SDL_GetTicks();
|
||||||
|
u32 fpslimitcount = 0;
|
||||||
|
|
||||||
SDL_Event evt;
|
while (parent->emustatus == 1)
|
||||||
while (SDL_PollEvent(&evt))
|
|
||||||
{
|
{
|
||||||
switch (evt.type)
|
u32 starttick = SDL_GetTicks();
|
||||||
|
|
||||||
|
NDS::RunFrame();
|
||||||
|
|
||||||
|
parent->texmutex->Lock();
|
||||||
|
|
||||||
|
if (parent->texstride == 256*4)
|
||||||
{
|
{
|
||||||
case SDL_WINDOWEVENT:
|
memcpy(parent->texpixels, GPU::Framebuffer, 256*384*4);
|
||||||
SDL_GetWindowPosition(parent->sdlwin, &WindowX, &WindowY);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_MOUSEBUTTONDOWN:
|
|
||||||
if (evt.button.y >= 192 && evt.button.button == SDL_BUTTON_LEFT)
|
|
||||||
{
|
|
||||||
Touching = true;
|
|
||||||
NDS::PressKey(16+6);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_KEYDOWN:
|
|
||||||
for (int i = 0; i < 10; i++)
|
|
||||||
if (evt.key.keysym.scancode == KeyMapping[i]) NDS::PressKey(i);
|
|
||||||
if (evt.key.keysym.scancode == KeyMapping[16]) NDS::PressKey(16);
|
|
||||||
if (evt.key.keysym.scancode == KeyMapping[17]) NDS::PressKey(17);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_KEYUP:
|
|
||||||
for (int i = 0; i < 10; i++)
|
|
||||||
if (evt.key.keysym.scancode == KeyMapping[i]) NDS::ReleaseKey(i);
|
|
||||||
if (evt.key.keysym.scancode == KeyMapping[16]) NDS::ReleaseKey(16);
|
|
||||||
if (evt.key.keysym.scancode == KeyMapping[17]) NDS::ReleaseKey(17);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Touching)
|
|
||||||
{
|
|
||||||
int mx, my;
|
|
||||||
u32 btn = SDL_GetGlobalMouseState(&mx, &my);
|
|
||||||
if (!(btn & SDL_BUTTON(SDL_BUTTON_LEFT)))
|
|
||||||
{
|
|
||||||
Touching = false;
|
|
||||||
NDS::ReleaseKey(16+6);
|
|
||||||
NDS::ReleaseScreen();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mx -= WindowX;
|
int dsty = 0;
|
||||||
my -= (WindowY + 192);
|
for (int y = 0; y < 256*384; y+=256)
|
||||||
|
{
|
||||||
|
memcpy(&((u8*)parent->texpixels)[dsty], &GPU::Framebuffer[y], 256*4);
|
||||||
|
dsty += parent->texstride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mx < 0) mx = 0;
|
parent->texmutex->Unlock();
|
||||||
else if (mx > 255) mx = 255;
|
parent->Refresh();
|
||||||
|
|
||||||
if (my < 0) my = 0;
|
fpslimitcount++;
|
||||||
else if (my > 191) my = 191;
|
if (fpslimitcount >= 3) fpslimitcount = 0;
|
||||||
|
u32 frametime = (fpslimitcount == 0) ? 16 : 17;
|
||||||
|
|
||||||
NDS::TouchScreen(mx, my);
|
u32 endtick = SDL_GetTicks();
|
||||||
|
u32 diff = endtick - starttick;
|
||||||
|
if (diff < frametime)
|
||||||
|
Sleep(frametime - diff);
|
||||||
|
|
||||||
|
nframes++;
|
||||||
|
if (nframes >= 30)
|
||||||
|
{
|
||||||
|
u32 tick = SDL_GetTicks();
|
||||||
|
u32 diff = tick - lasttick;
|
||||||
|
lasttick = tick;
|
||||||
|
|
||||||
|
u32 fps = (nframes * 1000) / diff;
|
||||||
|
nframes = 0;
|
||||||
|
|
||||||
|
char melontitle[100];
|
||||||
|
sprintf(melontitle, "%d FPS - melonDS " MELONDS_VERSION, fps);
|
||||||
|
parent->SetTitle(melontitle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* pixels; int zorp;
|
parent->emustopmutex->Lock();
|
||||||
SDL_LockTexture(parent->sdltex, NULL, &pixels, &zorp);
|
parent->emustop->Signal();
|
||||||
memcpy(pixels, GPU::Framebuffer, 256*384*4);
|
parent->emustopmutex->Unlock();
|
||||||
SDL_UnlockTexture(parent->sdltex);
|
|
||||||
|
|
||||||
SDL_SetRenderTarget(parent->sdlrend, parent->sdltex);
|
|
||||||
SDL_RenderClear(parent->sdlrend);
|
|
||||||
SDL_RenderCopy(parent->sdlrend, parent->sdltex, NULL, NULL);
|
|
||||||
SDL_RenderPresent(parent->sdlrend);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parent->emustatus == 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (wxThread::ExitCode)0;
|
return (wxThread::ExitCode)0;
|
||||||
|
|
|
@ -34,6 +34,8 @@ enum
|
||||||
ID_RUN,
|
ID_RUN,
|
||||||
ID_PAUSE,
|
ID_PAUSE,
|
||||||
ID_RESET,
|
ID_RESET,
|
||||||
|
|
||||||
|
ID_INPUTCONFIG,
|
||||||
};
|
};
|
||||||
|
|
||||||
class EmuThread;
|
class EmuThread;
|
||||||
|
@ -53,32 +55,40 @@ public:
|
||||||
SDL_Renderer* sdlrend;
|
SDL_Renderer* sdlrend;
|
||||||
SDL_Texture* sdltex;
|
SDL_Texture* sdltex;
|
||||||
|
|
||||||
|
wxMutex* texmutex;
|
||||||
|
void* texpixels;
|
||||||
|
int texstride;
|
||||||
|
|
||||||
|
int emustatus;
|
||||||
|
EmuThread* emuthread;
|
||||||
|
wxMutex* emustatuschangemutex;
|
||||||
|
wxCondition* emustatuschange;
|
||||||
|
wxMutex* emustopmutex;
|
||||||
|
wxCondition* emustop;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
|
|
||||||
|
void OnClose(wxCloseEvent& event);
|
||||||
|
void OnCloseFromMenu(wxCommandEvent& event);
|
||||||
void OnOpenROM(wxCommandEvent& event);
|
void OnOpenROM(wxCommandEvent& event);
|
||||||
|
|
||||||
void OnPaint(wxPaintEvent& event);
|
void ProcessSDLEvents();
|
||||||
|
|
||||||
EmuThread* emuthread;
|
void OnPaint(wxPaintEvent& event);
|
||||||
wxMutex* emumutex;
|
void OnIdle(wxIdleEvent& event);
|
||||||
wxCondition* emucond;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class EmuThread : public wxThread
|
class EmuThread : public wxThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EmuThread(MainFrame* parent, wxMutex* mutex, wxCondition* cond);
|
EmuThread(MainFrame* parent);
|
||||||
~EmuThread();
|
~EmuThread();
|
||||||
|
|
||||||
u32 EmuStatus;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ExitCode Entry();
|
virtual ExitCode Entry();
|
||||||
|
|
||||||
MainFrame* parent;
|
MainFrame* parent;
|
||||||
wxMutex* mutex;
|
|
||||||
wxCondition* cond;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // WX_MAIN_H
|
#endif // WX_MAIN_H
|
||||||
|
|
Loading…
Reference in New Issue