aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--melonDS.cbp2
-rw-r--r--src/ARM.cpp3
-rw-r--r--src/GPU2D.cpp8
-rw-r--r--src/GPU3D.cpp11
-rw-r--r--src/GPU3D_Soft.cpp2
-rw-r--r--src/NDS.cpp5
-rw-r--r--src/wx/main.cpp306
-rw-r--r--src/wx/main.h28
8 files changed, 259 insertions, 106 deletions
diff --git a/melonDS.cbp b/melonDS.cbp
index c838beb..71156cb 100644
--- a/melonDS.cbp
+++ b/melonDS.cbp
@@ -80,6 +80,8 @@
<Unit filename="src/ARM_InstrTable.h" />
<Unit filename="src/CP15.cpp" />
<Unit filename="src/CP15.h" />
+ <Unit filename="src/Config.cpp" />
+ <Unit filename="src/Config.h" />
<Unit filename="src/DMA.cpp" />
<Unit filename="src/DMA.h" />
<Unit filename="src/FIFO.h" />
diff --git a/src/ARM.cpp b/src/ARM.cpp
index 382f56e..f15ce74 100644
--- a/src/ARM.cpp
+++ b/src/ARM.cpp
@@ -171,6 +171,9 @@ void ARM::JumpTo(u32 addr, bool restorecpsr)
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)
{
addr &= ~0x1;
diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp
index 55c3e94..799714a 100644
--- a/src/GPU2D.cpp
+++ b/src/GPU2D.cpp
@@ -38,6 +38,14 @@
//
// 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
// * destination must be selected as 2nd target
// * sprite must be semitransparent or bitmap sprite
diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp
index 6f7e7b7..9881760 100644
--- a/src/GPU3D.cpp
+++ b/src/GPU3D.cpp
@@ -52,6 +52,12 @@
// if (clearZ >= 0x010000 && clearZ < 0xFFFFFF) clearZ++;
//
// 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
@@ -729,7 +735,10 @@ void SubmitPolygon()
}
if (farplaneclip && (!(CurPolygonAttr & (1<<12))))
+ {
+ LastStripPolygon = NULL;
return;
+ }
nverts = c; c = clipstart;
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};
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();
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;
diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp
index 5c9dc8e..a981bd5 100644
--- a/src/GPU3D_Soft.cpp
+++ b/src/GPU3D_Soft.cpp
@@ -721,7 +721,7 @@ void RenderPolygon(Polygon* polygon)
{
// edge fill rules for opaque pixels
// TODO, eventually: antialiasing
- if (!wireframe)
+ if (!wireframe)// && !(edge & 0x4))
{
if ((edge & 0x1) && slope_start > 0x1000)
continue;
diff --git a/src/NDS.cpp b/src/NDS.cpp
index 39136ec..0a5afb4 100644
--- a/src/NDS.cpp
+++ b/src/NDS.cpp
@@ -1780,6 +1780,11 @@ void ARM9IOWrite32(u32 addr, u32 val)
case 0x040002B8: SqrtVal[0] = 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)
diff --git a/src/wx/main.cpp b/src/wx/main.cpp
index b195636..b4813af 100644
--- a/src/wx/main.cpp
+++ b/src/wx/main.cpp
@@ -19,26 +19,15 @@
#include "../types.h"
#include "main.h"
#include "../version.h"
+#include "../Config.h"
#include "../NDS.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;
int WindowX, WindowY;
+int WindowW, WindowH;
wxIMPLEMENT_APP(wxApp_melonDS);
@@ -54,6 +43,8 @@ bool wxApp_melonDS::OnInit()
printf("melonDS " MELONDS_VERSION "\n" MELONDS_URL "\n");
+ Config::Load();
+
MainFrame* melon = new MainFrame();
melon->Show(true);
@@ -62,13 +53,18 @@ bool wxApp_melonDS::OnInit()
wxBEGIN_EVENT_TABLE(MainFrame, wxFrame)
+ EVT_CLOSE(MainFrame::OnClose)
+
EVT_MENU(ID_OPENROM, MainFrame::OnOpenROM)
+ EVT_MENU(ID_EXIT, MainFrame::OnCloseFromMenu)
+
EVT_PAINT(MainFrame::OnPaint)
+ EVT_IDLE(MainFrame::OnIdle)
wxEND_EVENT_TABLE()
MainFrame::MainFrame()
- : wxFrame(NULL, wxID_ANY, "melonDS")
+ : wxFrame(NULL, wxID_ANY, "melonDS " MELONDS_VERSION)
{
wxMenu* filemenu = new wxMenu();
filemenu->Append(ID_OPENROM, "Open ROM...");
@@ -81,18 +77,29 @@ MainFrame::MainFrame()
systemmenu->AppendSeparator();
systemmenu->Append(ID_RESET, "Reset");
+ wxMenu* settingsmenu = new wxMenu();
+ settingsmenu->Append(ID_INPUTCONFIG, "Input");
+
wxMenuBar* melonbar = new wxMenuBar();
melonbar->Append(filemenu, "File");
melonbar->Append(systemmenu, "System");
+ melonbar->Append(settingsmenu, "Settings");
SetMenuBar(melonbar);
SetClientSize(256, 384);
+ SetMinSize(GetSize());
+
+ emustatus = 2;
+
+ emustatuschangemutex = new wxMutex();
+ emustatuschange = new wxCondition(*emustatuschangemutex);
- emumutex = new wxMutex();
- emucond = new wxCondition(*emumutex);
+ emustopmutex = new wxMutex();
+ emustop = new wxCondition(*emustopmutex);
+ emustopmutex->Lock();
- emuthread = new EmuThread(this, emumutex, emucond);
+ emuthread = new EmuThread(this);
if (emuthread->Run() != wxTHREAD_NO_ERROR)
{
printf("thread shat itself :( giving up now\n");
@@ -102,17 +109,53 @@ MainFrame::MainFrame()
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);
- NDS::Init();
+ texmutex = new wxMutex();
+ SDL_LockTexture(sdltex, NULL, &texpixels, &texstride);
+ texmutex->Unlock();
- memcpy(KeyMapping, DefaultKeyMapping, 18*sizeof(int));
- memset(JoyMapping, 0, 18*sizeof(int));
+ NDS::Init();
Touching = false;
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)
@@ -121,35 +164,118 @@ void MainFrame::OnOpenROM(wxCommandEvent& event)
if (opener.ShowModal() == wxID_CANCEL)
return;
+ if (emustatus == 1)
+ {
+ emustatus = 2;
+ emustop->Wait();
+ }
+
wxString filename = opener.GetPath();
NDS::LoadROM(filename.mb_str(), true);
- emuthread->EmuStatus = 1;
- emumutex->Lock();
- emucond->Signal();
- emumutex->Unlock();
+ emustatus = 1;
+ emustatuschangemutex->Lock();
+ emustatuschange->Signal();
+ 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)
{
- /*wxPaintDC dc(this);
- wxGraphicsContext* gc = wxGraphicsContext::Create(dc);
- if (!gc) return;
+ wxPaintDC dc(this);
- //
+ 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)
{
this->parent = parent;
- this->mutex = mutex;
- this->cond = cond;
-
- EmuStatus = 2;
}
EmuThread::~EmuThread()
@@ -158,87 +284,75 @@ EmuThread::~EmuThread()
wxThread::ExitCode EmuThread::Entry()
{
- mutex->Lock();
+ parent->emustatuschangemutex->Lock();
for (;;)
{
- cond->Wait();
-
- if (EmuStatus == 0)
- break;
+ parent->emustatuschange->Wait();
- while (EmuStatus == 1)
+ if (parent->emustatus == 1)
{
- NDS::RunFrame();
+ u32 nframes = 0;
+ u32 lasttick = SDL_GetTicks();
+ u32 fpslimitcount = 0;
- SDL_Event evt;
- while (SDL_PollEvent(&evt))
+ while (parent->emustatus == 1)
{
- switch (evt.type)
- {
- case SDL_WINDOWEVENT:
- SDL_GetWindowPosition(parent->sdlwin, &WindowX, &WindowY);
- break;
+ u32 starttick = SDL_GetTicks();
- 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;
- }
- }
+ NDS::RunFrame();
- if (Touching)
- {
- int mx, my;
- u32 btn = SDL_GetGlobalMouseState(&mx, &my);
- if (!(btn & SDL_BUTTON(SDL_BUTTON_LEFT)))
+ parent->texmutex->Lock();
+
+ if (parent->texstride == 256*4)
{
- Touching = false;
- NDS::ReleaseKey(16+6);
- NDS::ReleaseScreen();
+ memcpy(parent->texpixels, GPU::Framebuffer, 256*384*4);
}
else
{
- mx -= WindowX;
- my -= (WindowY + 192);
+ int dsty = 0;
+ for (int y = 0; y < 256*384; y+=256)
+ {
+ memcpy(&((u8*)parent->texpixels)[dsty], &GPU::Framebuffer[y], 256*4);
+ dsty += parent->texstride;
+ }
+ }
+
+ parent->texmutex->Unlock();
+ parent->Refresh();
+
+ fpslimitcount++;
+ if (fpslimitcount >= 3) fpslimitcount = 0;
+ u32 frametime = (fpslimitcount == 0) ? 16 : 17;
- if (mx < 0) mx = 0;
- else if (mx > 255) mx = 255;
+ u32 endtick = SDL_GetTicks();
+ u32 diff = endtick - starttick;
+ if (diff < frametime)
+ Sleep(frametime - diff);
- if (my < 0) my = 0;
- else if (my > 191) my = 191;
+ nframes++;
+ if (nframes >= 30)
+ {
+ u32 tick = SDL_GetTicks();
+ u32 diff = tick - lasttick;
+ lasttick = tick;
+
+ u32 fps = (nframes * 1000) / diff;
+ nframes = 0;
- NDS::TouchScreen(mx, my);
+ char melontitle[100];
+ sprintf(melontitle, "%d FPS - melonDS " MELONDS_VERSION, fps);
+ parent->SetTitle(melontitle);
}
}
- void* pixels; int zorp;
- SDL_LockTexture(parent->sdltex, NULL, &pixels, &zorp);
- memcpy(pixels, GPU::Framebuffer, 256*384*4);
- 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);
+ parent->emustopmutex->Lock();
+ parent->emustop->Signal();
+ parent->emustopmutex->Unlock();
}
+
+ if (parent->emustatus == 0)
+ break;
}
return (wxThread::ExitCode)0;
diff --git a/src/wx/main.h b/src/wx/main.h
index 0ee41be..f60e381 100644
--- a/src/wx/main.h
+++ b/src/wx/main.h
@@ -34,6 +34,8 @@ enum
ID_RUN,
ID_PAUSE,
ID_RESET,
+
+ ID_INPUTCONFIG,
};
class EmuThread;
@@ -53,32 +55,40 @@ public:
SDL_Renderer* sdlrend;
SDL_Texture* sdltex;
+ wxMutex* texmutex;
+ void* texpixels;
+ int texstride;
+
+ int emustatus;
+ EmuThread* emuthread;
+ wxMutex* emustatuschangemutex;
+ wxCondition* emustatuschange;
+ wxMutex* emustopmutex;
+ wxCondition* emustop;
+
private:
wxDECLARE_EVENT_TABLE();
+ void OnClose(wxCloseEvent& event);
+ void OnCloseFromMenu(wxCommandEvent& event);
void OnOpenROM(wxCommandEvent& event);
- void OnPaint(wxPaintEvent& event);
+ void ProcessSDLEvents();
- EmuThread* emuthread;
- wxMutex* emumutex;
- wxCondition* emucond;
+ void OnPaint(wxPaintEvent& event);
+ void OnIdle(wxIdleEvent& event);
};
class EmuThread : public wxThread
{
public:
- EmuThread(MainFrame* parent, wxMutex* mutex, wxCondition* cond);
+ EmuThread(MainFrame* parent);
~EmuThread();
- u32 EmuStatus;
-
protected:
virtual ExitCode Entry();
MainFrame* parent;
- wxMutex* mutex;
- wxCondition* cond;
};
#endif // WX_MAIN_H