begin renovating melonDSi
This commit is contained in:
commit
5eb01f1f15
|
@ -0,0 +1 @@
|
|||
patreon: staplebutter
|
|
@ -6,3 +6,5 @@ obj
|
|||
melon_grc.c
|
||||
melon_grc.h
|
||||
cmake-build
|
||||
cmake-build-debug
|
||||
.idea
|
||||
|
|
|
@ -22,6 +22,11 @@ endif()
|
|||
|
||||
if(ENABLE_LTO)
|
||||
add_compile_options(-O3 -flto)
|
||||
set(CMAKE_AR "gcc-ar")
|
||||
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qcs <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_C_ARCHIVE_FINISH true)
|
||||
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> qcs <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_CXX_ARCHIVE_FINISH true)
|
||||
endif()
|
||||
|
||||
add_compile_options(-fno-pic)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<h2 align="center"><b>melonDS</b></h2>
|
||||
<p align="center">
|
||||
<a href="http://melonds.kuribo64.net/" alt="melonDS website"><img src="https://img.shields.io/badge/website-melonds.kuribo64.net-%2331352e.svg"></a>
|
||||
<a href="http://melonds.kuribo64.net/downloads.php" alt="Release: 0.8.1"><img src="https://img.shields.io/badge/release-0.8.1-%235c913b.svg"></a>
|
||||
<a href="http://melonds.kuribo64.net/downloads.php" alt="Release: 0.8.3"><img src="https://img.shields.io/badge/release-0.8.3-%235c913b.svg"></a>
|
||||
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPLv3"><img src="https://img.shields.io/badge/License-GPL%20v3-%23ff554d.svg"></a>
|
||||
<a href="https://kiwiirc.com/client/irc.badnik.net/?nick=IRC-Source_?#melonds" alt="IRC channel: #melonds"><img src="https://img.shields.io/badge/IRC%20chat-%23melonds-%23dd2e44.svg"></a>
|
||||
</p>
|
||||
|
|
8
melon.rc
8
melon.rc
|
@ -6,8 +6,8 @@
|
|||
|
||||
//include version information in .exe, modify these values to match your needs
|
||||
1 VERSIONINFO
|
||||
FILEVERSION 0,8,1,0
|
||||
PRODUCTVERSION 0,8,1,0
|
||||
FILEVERSION 0,8,3,0
|
||||
PRODUCTVERSION 0,8,3,0
|
||||
FILETYPE VFT_APP
|
||||
{
|
||||
BLOCK "StringFileInfo"
|
||||
|
@ -15,14 +15,14 @@ FILETYPE VFT_APP
|
|||
BLOCK "040904E4"
|
||||
{
|
||||
VALUE "CompanyName", "Melon Factory of Kuribo64"
|
||||
VALUE "FileVersion", "0.8.1"
|
||||
VALUE "FileVersion", "0.8.3"
|
||||
VALUE "FileDescription", "DS emulator, sorta. also 1st quality melon."
|
||||
VALUE "InternalName", "SDnolem"
|
||||
VALUE "LegalCopyright", "2016-2019 Arisotura & co."
|
||||
VALUE "LegalTrademarks", ""
|
||||
VALUE "OriginalFilename", "zafkflzdasd.exe"
|
||||
VALUE "ProductName", "melonDS"
|
||||
VALUE "ProductVersion", "0.8.1"
|
||||
VALUE "ProductVersion", "0.8.3"
|
||||
}
|
||||
}
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -106,12 +106,12 @@ namespace ARMInterpreter
|
|||
x = ROR(x, (s&0x1F));
|
||||
|
||||
#define LSL_REG_S(x, s) \
|
||||
if (s > 31) { cpu->SetC(x & (1<<0)); x = 0; } \
|
||||
else if (s > 0) { cpu->SetC(x & (1<<(32-s))); x <<= s; }
|
||||
if (s > 31) { cpu->SetC((s>32) ? 0 : (x & (1<<0))); x = 0; } \
|
||||
else if (s > 0) { cpu->SetC(x & (1<<(32-s))); x <<= s; }
|
||||
|
||||
#define LSR_REG_S(x, s) \
|
||||
if (s > 31) { cpu->SetC(x & (1<<31)); x = 0; } \
|
||||
else if (s > 0) { cpu->SetC(x & (1<<(s-1))); x >>= s; }
|
||||
if (s > 31) { cpu->SetC((s>32) ? 0 : (x & (1<<31))); x = 0; } \
|
||||
else if (s > 0) { cpu->SetC(x & (1<<(s-1))); x >>= s; }
|
||||
|
||||
#define ASR_REG_S(x, s) \
|
||||
if (s > 31) { cpu->SetC(x & (1<<31)); x = ((s32)x) >> 31; } \
|
||||
|
@ -134,7 +134,7 @@ namespace ARMInterpreter
|
|||
#define A_CALC_OP2_REG_SHIFT_REG(shiftop) \
|
||||
u32 b = cpu->R[cpu->CurInstr&0xF]; \
|
||||
if ((cpu->CurInstr&0xF)==15) b += 4; \
|
||||
shiftop(b, cpu->R[(cpu->CurInstr>>8)&0xF]);
|
||||
shiftop(b, (cpu->R[(cpu->CurInstr>>8)&0xF] & 0xFF));
|
||||
|
||||
|
||||
#define A_IMPLEMENT_ALU_OP(x,s) \
|
||||
|
|
|
@ -284,6 +284,7 @@ void SetDisplaySettings(bool accel)
|
|||
if (Framebuffer[1][0]) delete[] Framebuffer[1][0];
|
||||
if (Framebuffer[0][1]) delete[] Framebuffer[0][1];
|
||||
if (Framebuffer[1][1]) delete[] Framebuffer[1][1];
|
||||
|
||||
Framebuffer[0][0] = new u32[fbsize];
|
||||
Framebuffer[1][0] = new u32[fbsize];
|
||||
Framebuffer[0][1] = new u32[fbsize];
|
||||
|
|
130
src/GPU2D.cpp
130
src/GPU2D.cpp
|
@ -246,6 +246,11 @@ u8 GPU2D::Read8(u32 addr)
|
|||
case 0x049: return WinCnt[1];
|
||||
case 0x04A: return WinCnt[2];
|
||||
case 0x04B: return WinCnt[3];
|
||||
|
||||
// there are games accidentally trying to read those
|
||||
// those are write-only
|
||||
case 0x04C:
|
||||
case 0x04D: return 0;
|
||||
}
|
||||
|
||||
printf("unknown GPU read8 %08X\n", addr);
|
||||
|
@ -299,10 +304,22 @@ void GPU2D::Write8(u32 addr, u8 val)
|
|||
|
||||
switch (addr & 0x00000FFF)
|
||||
{
|
||||
case 0x000: DispCnt = (DispCnt & 0xFFFFFF00) | val; return;
|
||||
case 0x001: DispCnt = (DispCnt & 0xFFFF00FF) | (val << 8); return;
|
||||
case 0x002: DispCnt = (DispCnt & 0xFF00FFFF) | (val << 16); return;
|
||||
case 0x003: DispCnt = (DispCnt & 0x00FFFFFF) | (val << 24); return;
|
||||
case 0x000:
|
||||
DispCnt = (DispCnt & 0xFFFFFF00) | val;
|
||||
if (Num) DispCnt &= 0xC0B1FFF7;
|
||||
return;
|
||||
case 0x001:
|
||||
DispCnt = (DispCnt & 0xFFFF00FF) | (val << 8);
|
||||
if (Num) DispCnt &= 0xC0B1FFF7;
|
||||
return;
|
||||
case 0x002:
|
||||
DispCnt = (DispCnt & 0xFF00FFFF) | (val << 16);
|
||||
if (Num) DispCnt &= 0xC0B1FFF7;
|
||||
return;
|
||||
case 0x003:
|
||||
DispCnt = (DispCnt & 0x00FFFFFF) | (val << 24);
|
||||
if (Num) DispCnt &= 0xC0B1FFF7;
|
||||
return;
|
||||
|
||||
case 0x008: BGCnt[0] = (BGCnt[0] & 0xFF00) | val; return;
|
||||
case 0x009: BGCnt[0] = (BGCnt[0] & 0x00FF) | (val << 8); return;
|
||||
|
@ -381,8 +398,14 @@ void GPU2D::Write16(u32 addr, u16 val)
|
|||
|
||||
switch (addr & 0x00000FFF)
|
||||
{
|
||||
case 0x000: DispCnt = (DispCnt & 0xFFFF0000) | val; return;
|
||||
case 0x002: DispCnt = (DispCnt & 0x0000FFFF) | (val << 16); return;
|
||||
case 0x000:
|
||||
DispCnt = (DispCnt & 0xFFFF0000) | val;
|
||||
if (Num) DispCnt &= 0xC0B1FFF7;
|
||||
return;
|
||||
case 0x002:
|
||||
DispCnt = (DispCnt & 0x0000FFFF) | (val << 16);
|
||||
if (Num) DispCnt &= 0xC0B1FFF7;
|
||||
return;
|
||||
|
||||
case 0x008: BGCnt[0] = val; return;
|
||||
case 0x00A: BGCnt[1] = val; return;
|
||||
|
@ -514,6 +537,7 @@ void GPU2D::Write32(u32 addr, u32 val)
|
|||
{
|
||||
case 0x000:
|
||||
DispCnt = val;
|
||||
if (Num) DispCnt &= 0xC0B1FFF7;
|
||||
return;
|
||||
|
||||
case 0x028:
|
||||
|
@ -704,10 +728,6 @@ void GPU2D::DrawScanline(u32 line)
|
|||
// oddly that's not the case for GPU A
|
||||
if (Num && !Enabled) forceblank = true;
|
||||
|
||||
// forced blank
|
||||
// (checkme: are there still things that can run under this mode? likely not)
|
||||
if (DispCnt & (1<<7)) forceblank = true;
|
||||
|
||||
if (forceblank)
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
|
@ -748,8 +768,10 @@ void GPU2D::DrawScanline(u32 line)
|
|||
|
||||
case 1: // regular display
|
||||
{
|
||||
for (int i = 0; i < stride; i+=2)
|
||||
int i = 0;
|
||||
for (; i < (stride & ~1); i+=2)
|
||||
*(u64*)&dst[i] = *(u64*)&BGOBJLine[i];
|
||||
if (stride & 1) dst[i] = BGOBJLine[i];
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1313,12 +1335,6 @@ void GPU2D::DrawScanlineBGMode(u32 line)
|
|||
|
||||
void GPU2D::DrawScanlineBGMode6(u32 line)
|
||||
{
|
||||
if (Num)
|
||||
{
|
||||
printf("GPU2D: MODE6 ON SUB GPU???\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 3; i >= 0; i--)
|
||||
{
|
||||
if ((BGCnt[2] & 0x3) == i)
|
||||
|
@ -1332,7 +1348,7 @@ void GPU2D::DrawScanlineBGMode6(u32 line)
|
|||
{
|
||||
if (DispCnt & 0x0100)
|
||||
{
|
||||
if (DispCnt & 0x8)
|
||||
if ((!Num) && (DispCnt & 0x8))
|
||||
DrawBG_3D();
|
||||
}
|
||||
}
|
||||
|
@ -1341,8 +1357,45 @@ void GPU2D::DrawScanlineBGMode6(u32 line)
|
|||
}
|
||||
}
|
||||
|
||||
void GPU2D::DrawScanlineBGMode7(u32 line)
|
||||
{
|
||||
// mode 7 only has text-mode BG0 and BG1
|
||||
|
||||
for (int i = 3; i >= 0; i--)
|
||||
{
|
||||
if ((BGCnt[1] & 0x3) == i)
|
||||
{
|
||||
if (DispCnt & 0x0200)
|
||||
{
|
||||
DrawBG_Text(line, 1);
|
||||
}
|
||||
}
|
||||
if ((BGCnt[0] & 0x3) == i)
|
||||
{
|
||||
if (DispCnt & 0x0100)
|
||||
{
|
||||
if ((!Num) && (DispCnt & 0x8))
|
||||
DrawBG_3D();
|
||||
else
|
||||
DrawBG_Text(line, 0);
|
||||
}
|
||||
}
|
||||
if ((DispCnt & 0x1000) && NumSprites)
|
||||
InterleaveSprites(0x8000 | (i<<16));
|
||||
}
|
||||
}
|
||||
|
||||
void GPU2D::DrawScanline_BGOBJ(u32 line)
|
||||
{
|
||||
// forced blank disables BG/OBJ compositing
|
||||
if (DispCnt & (1<<7))
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
BGOBJLine[i] = 0xFF3F3F3F;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
u64 backdrop;
|
||||
if (Num) backdrop = *(u16*)&GPU::Palette[0x400];
|
||||
else backdrop = *(u16*)&GPU::Palette[0];
|
||||
|
@ -1364,7 +1417,6 @@ void GPU2D::DrawScanline_BGOBJ(u32 line)
|
|||
else
|
||||
memset(WindowMask, 0xFF, 256);
|
||||
|
||||
// TODO: what happens in mode 7? mode 6 on the sub engine?
|
||||
switch (DispCnt & 0x7)
|
||||
{
|
||||
case 0: DrawScanlineBGMode<0>(line); break;
|
||||
|
@ -1374,6 +1426,7 @@ void GPU2D::DrawScanline_BGOBJ(u32 line)
|
|||
case 4: DrawScanlineBGMode<4>(line); break;
|
||||
case 5: DrawScanlineBGMode<5>(line); break;
|
||||
case 6: DrawScanlineBGMode6(line); break;
|
||||
case 7: DrawScanlineBGMode7(line); break;
|
||||
}
|
||||
|
||||
// color special effects
|
||||
|
@ -2035,14 +2088,19 @@ void GPU2D::DrawBG_Large(u32 line) // BG is always BG2
|
|||
u32 tilesetaddr, tilemapaddr;
|
||||
u16* pal;
|
||||
|
||||
// large BG sizes:
|
||||
// 0: 512x1024
|
||||
// 1: 1024x512
|
||||
// 2: 512x256
|
||||
// 3: 512x512
|
||||
u32 xmask, ymask;
|
||||
u32 yshift;
|
||||
switch (bgcnt & 0xC000)
|
||||
{
|
||||
case 0x0000: xmask = 0x1FFFF; ymask = 0x3FFFF; yshift = 9; break;
|
||||
case 0x4000: xmask = 0x3FFFF; ymask = 0x1FFFF; yshift = 10; break;
|
||||
case 0x8000: // TODO (most likely the second size bit is just ignored)
|
||||
case 0xC000: printf("bad BG size for large BG: %04X\n", bgcnt); return;
|
||||
case 0x8000: xmask = 0x1FFFF; ymask = 0x0FFFF; yshift = 9; break;
|
||||
case 0xC000: xmask = 0x1FFFF; ymask = 0x1FFFF; yshift = 9; break;
|
||||
}
|
||||
|
||||
u32 ofxmask, ofymask;
|
||||
|
@ -2134,21 +2192,19 @@ void GPU2D::DrawSprites(u32 line)
|
|||
|
||||
const s32 spritewidth[16] =
|
||||
{
|
||||
8, 16, 8, 0,
|
||||
16, 32, 8, 0,
|
||||
32, 32, 16, 0,
|
||||
64, 64, 32, 0
|
||||
8, 16, 8, 8,
|
||||
16, 32, 8, 8,
|
||||
32, 32, 16, 8,
|
||||
64, 64, 32, 8
|
||||
};
|
||||
const s32 spriteheight[16] =
|
||||
{
|
||||
8, 8, 16, 0,
|
||||
16, 8, 32, 0,
|
||||
32, 16, 32, 0,
|
||||
64, 32, 64, 0
|
||||
8, 8, 16, 8,
|
||||
16, 8, 32, 8,
|
||||
32, 16, 32, 8,
|
||||
64, 32, 64, 8
|
||||
};
|
||||
|
||||
u32 nsprites = 0;
|
||||
|
||||
for (int bgnum = 0x0C00; bgnum >= 0x0000; bgnum -= 0x0400)
|
||||
{
|
||||
for (int sprnum = 127; sprnum >= 0; sprnum--)
|
||||
|
@ -2287,8 +2343,10 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32
|
|||
{
|
||||
if (DispCnt & 0x20)
|
||||
{
|
||||
// TODO ("reserved")
|
||||
printf("bad reserved mode\n");
|
||||
// 'reserved'
|
||||
// draws nothing
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2520,8 +2578,10 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos)
|
|||
{
|
||||
if (DispCnt & 0x20)
|
||||
{
|
||||
// TODO ("reserved")
|
||||
printf("bad reserved mode\n");
|
||||
// 'reserved'
|
||||
// draws nothing
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -135,6 +135,7 @@ private:
|
|||
|
||||
template<u32 bgmode> void DrawScanlineBGMode(u32 line);
|
||||
void DrawScanlineBGMode6(u32 line);
|
||||
void DrawScanlineBGMode7(u32 line);
|
||||
void DrawScanline_BGOBJ(u32 line);
|
||||
|
||||
static void DrawPixel_Normal(u32* dst, u16 color, u32 flag);
|
||||
|
|
|
@ -342,36 +342,11 @@ bool Init()
|
|||
SetupDefaultTexParams(FramebufferTex[7]);
|
||||
|
||||
// downscale framebuffer for antialiased mode
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[2]);
|
||||
SetupDefaultTexParams(FramebufferTex[2]);
|
||||
|
||||
// downscale framebuffer for display capture (always 256x192)
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[3]);
|
||||
SetupDefaultTexParams(FramebufferTex[3]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 192, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FramebufferTex[3], 0);
|
||||
|
||||
GLenum fbassign[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[0]);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FramebufferTex[0], 0);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, FramebufferTex[4], 0);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, FramebufferTex[5], 0);
|
||||
glDrawBuffers(2, fbassign);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[1]);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FramebufferTex[1], 0);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, FramebufferTex[4], 0);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, FramebufferTex[5], 0);
|
||||
glDrawBuffers(2, fbassign);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[2]);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FramebufferTex[2], 0);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, FramebufferTex[6], 0);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, FramebufferTex[7], 0);
|
||||
glDrawBuffers(2, fbassign);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[0]);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX);
|
||||
|
@ -475,11 +450,36 @@ void UpdateDisplaySettings()
|
|||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, ScreenW, ScreenH, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, NULL);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[3]);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FramebufferTex[3], 0);
|
||||
|
||||
GLenum fbassign[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[0]);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FramebufferTex[0], 0);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, FramebufferTex[4], 0);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, FramebufferTex[5], 0);
|
||||
glDrawBuffers(2, fbassign);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[1]);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FramebufferTex[1], 0);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, FramebufferTex[4], 0);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, FramebufferTex[5], 0);
|
||||
glDrawBuffers(2, fbassign);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[2]);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FramebufferTex[2], 0);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, FramebufferTex[6], 0);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, FramebufferTex[7], 0);
|
||||
glDrawBuffers(2, fbassign);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[0]);
|
||||
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, PixelbufferID);
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, 256*192*4, NULL, GL_DYNAMIC_READ);
|
||||
|
||||
//glLineWidth(scale);
|
||||
glLineWidth(1.5);
|
||||
//glLineWidth(1.5);
|
||||
}
|
||||
|
||||
|
||||
|
@ -743,6 +743,7 @@ void RenderSceneChunk(int y, int h)
|
|||
// pass 1: opaque pixels
|
||||
|
||||
UseRenderShader(flags);
|
||||
glLineWidth(1.0);
|
||||
|
||||
glColorMaski(1, GL_TRUE, GL_TRUE, fogenable, GL_FALSE);
|
||||
|
||||
|
@ -774,6 +775,7 @@ void RenderSceneChunk(int y, int h)
|
|||
if (RenderDispCnt & (1<<5))
|
||||
{
|
||||
UseRenderShader(flags | RenderFlag_Edge);
|
||||
glLineWidth(1.5);
|
||||
|
||||
glColorMaski(0, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
glColorMaski(1, GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
|
||||
|
@ -806,6 +808,7 @@ void RenderSceneChunk(int y, int h)
|
|||
glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ONE);
|
||||
|
||||
UseRenderShader(flags | RenderFlag_Trans);
|
||||
glLineWidth(1.0);
|
||||
|
||||
if (NumOpaqueFinalPolys > -1)
|
||||
{
|
||||
|
|
|
@ -656,7 +656,7 @@ void main()
|
|||
int zshift = (attr >> 16) & 0x1F;
|
||||
|
||||
vec4 fpos;
|
||||
fpos.xy = (((vec2(vPosition.xy) + 0.5) * 2.0) / uScreenSize) - 1.0;
|
||||
fpos.xy = (((vec2(vPosition.xy) ) * 2.0) / uScreenSize) - 1.0;
|
||||
fpos.z = (float(vPosition.z << zshift) / 8388608.0) - 1.0;
|
||||
fpos.w = float(vPosition.w) / 65536.0f;
|
||||
fpos.xyz *= fpos.w;
|
||||
|
@ -679,7 +679,7 @@ void main()
|
|||
int zshift = (attr >> 16) & 0x1F;
|
||||
|
||||
vec4 fpos;
|
||||
fpos.xy = (((vec2(vPosition.xy) + 0.5) * 2.0) / uScreenSize) - 1.0;
|
||||
fpos.xy = (((vec2(vPosition.xy) ) * 2.0) / uScreenSize) - 1.0;
|
||||
fZ = float(vPosition.z << zshift) / 16777216.0;
|
||||
fpos.w = float(vPosition.w) / 65536.0f;
|
||||
fpos.xy *= fpos.w;
|
||||
|
|
19
src/NDS.cpp
19
src/NDS.cpp
|
@ -72,7 +72,7 @@ u64 FrameStartTimestamp;
|
|||
|
||||
int CurCPU;
|
||||
|
||||
const s32 kMaxIterationCycles = 16;
|
||||
const s32 kMaxIterationCycles = 64;
|
||||
|
||||
u32 ARM9ClockShift;
|
||||
|
||||
|
@ -1516,7 +1516,7 @@ void DivDone(u32 param)
|
|||
if (den == 0)
|
||||
{
|
||||
DivQuotient[0] = (num<0) ? 1:-1;
|
||||
DivQuotient[1] = (num<0) ? -1:1;
|
||||
DivQuotient[1] = (num<0) ? -1:0;
|
||||
*(s64*)&DivRemainder[0] = num;
|
||||
}
|
||||
else if (num == -0x80000000 && den == -1)
|
||||
|
@ -1648,7 +1648,8 @@ void debug(u32 param)
|
|||
// printf("VRAM %c: %02X\n", 'A'+i, GPU::VRAMCNT[i]);
|
||||
|
||||
/*FILE*
|
||||
shit = fopen("debug/card.bin", "wb");
|
||||
shit = fopen("debug/party.bin", "wb");
|
||||
fwrite(ARM9->ITCM, 0x8000, 1, shit);
|
||||
for (u32 i = 0x02000000; i < 0x02400000; i+=4)
|
||||
{
|
||||
u32 val = ARM7Read32(i);
|
||||
|
@ -2936,6 +2937,11 @@ void ARM9IOWrite32(u32 addr, u32 val)
|
|||
{
|
||||
switch (addr)
|
||||
{
|
||||
case 0x04000004:
|
||||
GPU::SetDispStat(0, val & 0xFFFF);
|
||||
GPU::SetVCount(val >> 16);
|
||||
return;
|
||||
|
||||
case 0x04000060: GPU3D::Write32(addr, val); return;
|
||||
case 0x04000064:
|
||||
case 0x04000068: GPU::GPU2D_A->Write32(addr, val); return;
|
||||
|
@ -3500,6 +3506,11 @@ void ARM7IOWrite32(u32 addr, u32 val)
|
|||
{
|
||||
switch (addr)
|
||||
{
|
||||
case 0x04000004:
|
||||
GPU::SetDispStat(1, val & 0xFFFF);
|
||||
GPU::SetVCount(val >> 16);
|
||||
return;
|
||||
|
||||
case 0x040000B0: DMAs[4]->SrcAddr = val; return;
|
||||
case 0x040000B4: DMAs[4]->DstAddr = val; return;
|
||||
case 0x040000B8: DMAs[4]->WriteCnt(val); return;
|
||||
|
@ -3583,6 +3594,8 @@ void ARM7IOWrite32(u32 addr, u32 val)
|
|||
case 0x04000210: IE[1] = val; UpdateIRQ(1); return;
|
||||
case 0x04000214: IF[1] &= ~val; UpdateIRQ(1); return;
|
||||
|
||||
case 0x04000304: PowerControl7 = val & 0xFFFF; return;
|
||||
|
||||
case 0x04000308:
|
||||
if (ARM7BIOSProt == 0)
|
||||
ARM7BIOSProt = val & 0xFFFE;
|
||||
|
|
|
@ -112,8 +112,6 @@
|
|||
func(GLGETUNIFORMLOCATION, glGetUniformLocation); \
|
||||
func(GLGETUNIFORMBLOCKINDEX, glGetUniformBlockIndex); \
|
||||
\
|
||||
func(GLBINDIMAGETEXTURE, glBindImageTexture); \
|
||||
\
|
||||
func(GLDRAWBUFFERS, glDrawBuffers); \
|
||||
\
|
||||
func(GLBLENDFUNCSEPARATE, glBlendFuncSeparate); \
|
||||
|
|
81
src/SPU.cpp
81
src/SPU.cpp
|
@ -28,7 +28,6 @@
|
|||
// * channel hold
|
||||
// * 'length less than 4' glitch
|
||||
|
||||
|
||||
namespace SPU
|
||||
{
|
||||
|
||||
|
@ -66,8 +65,8 @@ const u32 kSamplesPerRun = 1;
|
|||
|
||||
const u32 OutputBufferSize = 2*1024;
|
||||
s16 OutputBuffer[2 * OutputBufferSize];
|
||||
u32 OutputReadOffset;
|
||||
u32 OutputWriteOffset;
|
||||
volatile u32 OutputReadOffset;
|
||||
volatile u32 OutputWriteOffset;
|
||||
|
||||
|
||||
u16 Cnt;
|
||||
|
@ -100,9 +99,7 @@ void DeInit()
|
|||
|
||||
void Reset()
|
||||
{
|
||||
memset(OutputBuffer, 0, 2*OutputBufferSize*2);
|
||||
OutputReadOffset = 0;
|
||||
OutputWriteOffset = OutputBufferSize;
|
||||
InitOutput();
|
||||
|
||||
Cnt = 0;
|
||||
MasterVolume = 0;
|
||||
|
@ -632,7 +629,7 @@ void Mix(u32 samples)
|
|||
else if (val > 0x7FFF) val = 0x7FFF;
|
||||
|
||||
Capture[0]->Run(val);
|
||||
if (!((Capture[0]->Cnt & (1<<7)))) break;
|
||||
if (!(Capture[0]->Cnt & (1<<7))) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -647,7 +644,7 @@ void Mix(u32 samples)
|
|||
else if (val > 0x7FFF) val = 0x7FFF;
|
||||
|
||||
Capture[1]->Run(val);
|
||||
if (!((Capture[1]->Cnt & (1<<7)))) break;
|
||||
if (!(Capture[1]->Cnt & (1<<7))) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -737,12 +734,76 @@ void Mix(u32 samples)
|
|||
OutputBuffer[OutputWriteOffset + 1] = r >> 1;
|
||||
OutputWriteOffset += 2;
|
||||
OutputWriteOffset &= ((2*OutputBufferSize)-1);
|
||||
if (OutputWriteOffset == OutputReadOffset)
|
||||
{
|
||||
//printf("!! SOUND FIFO OVERFLOW %d\n", OutputWriteOffset>>1);
|
||||
// advance the read position too, to avoid losing the entire FIFO
|
||||
OutputReadOffset += 2;
|
||||
OutputReadOffset &= ((2*OutputBufferSize)-1);
|
||||
}
|
||||
}
|
||||
|
||||
NDS::ScheduleEvent(NDS::Event_SPU, true, 1024*kSamplesPerRun, Mix, kSamplesPerRun);
|
||||
}
|
||||
|
||||
|
||||
void TrimOutput()
|
||||
{
|
||||
const int halflimit = (OutputBufferSize / 2);
|
||||
|
||||
int readpos = OutputWriteOffset - (halflimit*2);
|
||||
if (readpos < 0) readpos += (OutputBufferSize*2);
|
||||
|
||||
OutputReadOffset = readpos;
|
||||
}
|
||||
|
||||
void DrainOutput()
|
||||
{
|
||||
OutputReadOffset = 0;
|
||||
OutputWriteOffset = 0;
|
||||
}
|
||||
|
||||
void InitOutput()
|
||||
{
|
||||
memset(OutputBuffer, 0, 2*OutputBufferSize*2);
|
||||
OutputReadOffset = 0;
|
||||
OutputWriteOffset = OutputBufferSize;
|
||||
}
|
||||
|
||||
int GetOutputSize()
|
||||
{
|
||||
int ret;
|
||||
if (OutputWriteOffset >= OutputReadOffset)
|
||||
ret = OutputWriteOffset - OutputReadOffset;
|
||||
else
|
||||
ret = (OutputBufferSize*2) - OutputReadOffset + OutputWriteOffset;
|
||||
|
||||
ret >>= 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Sync(bool wait)
|
||||
{
|
||||
// sync to audio output in case the core is running too fast
|
||||
// * wait=true: wait until enough audio data has been played
|
||||
// * wait=false: merely skip some audio data to avoid a FIFO overflow
|
||||
|
||||
const int halflimit = (OutputBufferSize / 2);
|
||||
|
||||
if (wait)
|
||||
{
|
||||
// TODO: less CPU-intensive wait?
|
||||
while (GetOutputSize() > halflimit);
|
||||
}
|
||||
else if (GetOutputSize() > halflimit)
|
||||
{
|
||||
int readpos = OutputWriteOffset - (halflimit*2);
|
||||
if (readpos < 0) readpos += (OutputBufferSize*2);
|
||||
|
||||
OutputReadOffset = readpos;
|
||||
}
|
||||
}
|
||||
|
||||
int ReadOutput(s16* data, int samples)
|
||||
{
|
||||
if (OutputReadOffset == OutputWriteOffset)
|
||||
|
@ -910,8 +971,8 @@ void Write16(u32 addr, u16 val)
|
|||
return;
|
||||
case 0xA: chan->SetLoopPos(val); return;
|
||||
|
||||
case 0xC: chan->SetLength((chan->Length & 0xFFFF0000) | val); return;
|
||||
case 0xE: chan->SetLength((chan->Length & 0x0000FFFF) | (val << 16)); return;
|
||||
case 0xC: chan->SetLength(((chan->Length >> 2) & 0xFFFF0000) | val); return;
|
||||
case 0xE: chan->SetLength(((chan->Length >> 2) & 0x0000FFFF) | (val << 16)); return;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -35,6 +35,11 @@ void SetBias(u16 bias);
|
|||
|
||||
void Mix(u32 samples);
|
||||
|
||||
void TrimOutput();
|
||||
void DrainOutput();
|
||||
void InitOutput();
|
||||
int GetOutputSize();
|
||||
void Sync(bool wait);
|
||||
int ReadOutput(s16* data, int samples);
|
||||
|
||||
u8 Read8(u32 addr);
|
||||
|
|
|
@ -14,6 +14,10 @@ SET(SOURCES_LIBUI
|
|||
OSD.cpp
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> -i <SOURCE> -o <OBJECT>")
|
||||
endif()
|
||||
|
||||
option(BUILD_SHARED_LIBS "Whether to build libui as a shared library or a static library" ON)
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
add_subdirectory(libui)
|
||||
|
@ -39,11 +43,11 @@ if (UNIX)
|
|||
ADD_DEFINITIONS(${GTK3_CFLAGS_OTHER})
|
||||
|
||||
add_custom_command(OUTPUT melon_grc.c
|
||||
COMMAND glib-compile-resources --sourcedir="${CMAKE_SOURCE_DIR}"
|
||||
--target="${CMAKE_CURRENT_BINARY_DIR}/melon_grc.c"
|
||||
COMMAND glib-compile-resources --sourcedir=${CMAKE_SOURCE_DIR}
|
||||
--target=${CMAKE_CURRENT_BINARY_DIR}/melon_grc.c
|
||||
--generate-source "${CMAKE_SOURCE_DIR}/melon_grc.xml"
|
||||
COMMAND glib-compile-resources --sourcedir="${CMAKE_SOURCE_DIR}"
|
||||
--target="${CMAKE_CURRENT_BINARY_DIR}/melon_grc.h"
|
||||
COMMAND glib-compile-resources --sourcedir=${CMAKE_SOURCE_DIR}
|
||||
--target=${CMAKE_CURRENT_BINARY_DIR}/melon_grc.h
|
||||
--generate-header "${CMAKE_SOURCE_DIR}/melon_grc.xml")
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
|
|
|
@ -125,21 +125,30 @@ void JoyMappingName(int id, char* str)
|
|||
return;
|
||||
}
|
||||
|
||||
if (id & 0x100)
|
||||
{
|
||||
int hatnum = ((id >> 4) & 0xF) + 1;
|
||||
bool hasbtn = ((id & 0xFFFF) != 0xFFFF);
|
||||
|
||||
switch (id & 0xF)
|
||||
if (hasbtn)
|
||||
{
|
||||
if (id & 0x100)
|
||||
{
|
||||
case 0x1: sprintf(str, "Hat %d up", hatnum); break;
|
||||
case 0x2: sprintf(str, "Hat %d right", hatnum); break;
|
||||
case 0x4: sprintf(str, "Hat %d down", hatnum); break;
|
||||
case 0x8: sprintf(str, "Hat %d left", hatnum); break;
|
||||
int hatnum = ((id >> 4) & 0xF) + 1;
|
||||
|
||||
switch (id & 0xF)
|
||||
{
|
||||
case 0x1: sprintf(str, "Hat %d up", hatnum); break;
|
||||
case 0x2: sprintf(str, "Hat %d right", hatnum); break;
|
||||
case 0x4: sprintf(str, "Hat %d down", hatnum); break;
|
||||
case 0x8: sprintf(str, "Hat %d left", hatnum); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(str, "Button %d", (id & 0xFFFF) + 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(str, "Button %d", (id & 0xFFFF) + 1);
|
||||
strcpy(str, "");
|
||||
}
|
||||
|
||||
if (id & 0x10000)
|
||||
|
@ -151,9 +160,9 @@ void JoyMappingName(int id, char* str)
|
|||
|
||||
switch ((id >> 20) & 0xF)
|
||||
{
|
||||
case 0: sprintf(str, "%s / Axis %d +", tmp, axisnum); break;
|
||||
case 1: sprintf(str, "%s / Axis %d -", tmp, axisnum); break;
|
||||
case 2: sprintf(str, "%s / Trigger %d", tmp, axisnum); break;
|
||||
case 0: sprintf(str, "%s%sAxis %d +", tmp, hasbtn?" / ":"", axisnum); break;
|
||||
case 1: sprintf(str, "%s%sAxis %d -", tmp, hasbtn?" / ":"", axisnum); break;
|
||||
case 2: sprintf(str, "%s%sTrigger %d", tmp, hasbtn?" / ":"", axisnum); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -223,10 +232,12 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
|
|||
// set key.
|
||||
if (evt->Scancode != 0x1 || evt->Modifiers != 0) // ESC
|
||||
{
|
||||
int mod = (dlg->type == 0) ? 0 : evt->Modifiers;
|
||||
|
||||
if (evt->Scancode == 0xE && evt->Modifiers == 0) // backspace
|
||||
dlg->keymap[dlg->pollid] = -1;
|
||||
else
|
||||
dlg->keymap[dlg->pollid] = evt->Scancode | (evt->Modifiers << 16);
|
||||
dlg->keymap[dlg->pollid] = evt->Scancode | (mod << 16);
|
||||
}
|
||||
|
||||
char keyname[64];
|
||||
|
@ -287,7 +298,7 @@ Uint32 JoyPoll(Uint32 interval, void* param)
|
|||
}
|
||||
|
||||
int oldmap;
|
||||
if (dlg->joymap[id] == -1) oldmap = 0;
|
||||
if (dlg->joymap[id] == -1) oldmap = 0xFFFF;
|
||||
else oldmap = dlg->joymap[id];
|
||||
|
||||
int nbuttons = SDL_JoystickNumButtons(joy);
|
||||
|
|
|
@ -39,12 +39,14 @@ uiWindow* win;
|
|||
|
||||
uiRadioButtons* rbRenderer;
|
||||
uiCheckbox* cbGLDisplay;
|
||||
uiCheckbox* cbVSync;
|
||||
uiCheckbox* cbThreaded3D;
|
||||
uiCombobox* cbResolution;
|
||||
uiCheckbox* cbAntialias;
|
||||
|
||||
int old_renderer;
|
||||
int old_gldisplay;
|
||||
int old_vsync;
|
||||
int old_threaded3D;
|
||||
int old_resolution;
|
||||
int old_antialias;
|
||||
|
@ -89,6 +91,11 @@ void RevertSettings()
|
|||
{
|
||||
Config::ScreenUseGL = old_gldisplay;
|
||||
}
|
||||
if (old_vsync != Config::ScreenVSync)
|
||||
{
|
||||
Config::ScreenVSync = old_vsync;
|
||||
//ApplyNewSettings(4);
|
||||
}
|
||||
if (old_usegl != new_usegl)
|
||||
{
|
||||
apply2 = true;
|
||||
|
@ -130,21 +137,33 @@ void OnRendererChanged(uiRadioButtons* rb, void* blarg)
|
|||
UpdateControls();
|
||||
|
||||
bool new_usegl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0);
|
||||
|
||||
if (new_usegl) uiControlEnable(uiControl(cbVSync));
|
||||
else uiControlDisable(uiControl(cbVSync));
|
||||
|
||||
if (new_usegl != old_usegl)
|
||||
ApplyNewSettings(2);
|
||||
else
|
||||
ApplyNewSettings(3);
|
||||
|
||||
|
||||
uiControlSetFocus(uiControl(win));
|
||||
}
|
||||
|
||||
void OnGLDisplayChanged(uiCheckbox* cb, void* blarg)
|
||||
{
|
||||
Config::ScreenUseGL = uiCheckboxChecked(cb);
|
||||
if (Config::ScreenUseGL) uiControlEnable(uiControl(cbVSync));
|
||||
else uiControlDisable(uiControl(cbVSync));
|
||||
ApplyNewSettings(2);
|
||||
uiControlSetFocus(uiControl(win));
|
||||
}
|
||||
|
||||
void OnVSyncChanged(uiCheckbox* cb, void* blarg)
|
||||
{
|
||||
Config::ScreenVSync = uiCheckboxChecked(cb);
|
||||
//ApplyNewSettings(4);
|
||||
}
|
||||
|
||||
void OnThreaded3DChanged(uiCheckbox* cb, void* blarg)
|
||||
{
|
||||
Config::Threaded3D = uiCheckboxChecked(cb);
|
||||
|
@ -232,6 +251,10 @@ void Open()
|
|||
cbGLDisplay = uiNewCheckbox("OpenGL display");
|
||||
uiCheckboxOnToggled(cbGLDisplay, OnGLDisplayChanged, NULL);
|
||||
uiBoxAppend(in_ctrl, uiControl(cbGLDisplay), 0);
|
||||
|
||||
cbVSync = uiNewCheckbox("VSync");
|
||||
uiCheckboxOnToggled(cbVSync, OnVSyncChanged, NULL);
|
||||
uiBoxAppend(in_ctrl, uiControl(cbVSync), 0);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -300,17 +323,24 @@ void Open()
|
|||
|
||||
old_renderer = Config::_3DRenderer;
|
||||
old_gldisplay = Config::ScreenUseGL;
|
||||
old_vsync = Config::ScreenVSync;
|
||||
old_threaded3D = Config::Threaded3D;
|
||||
old_resolution = Config::GL_ScaleFactor;
|
||||
old_antialias = Config::GL_Antialias;
|
||||
|
||||
uiCheckboxSetChecked(cbGLDisplay, Config::ScreenUseGL);
|
||||
uiCheckboxSetChecked(cbVSync, Config::ScreenVSync);
|
||||
uiCheckboxSetChecked(cbThreaded3D, Config::Threaded3D);
|
||||
uiComboboxSetSelected(cbResolution, Config::GL_ScaleFactor-1);
|
||||
//uiCheckboxSetChecked(cbAntialias, Config::GL_Antialias);
|
||||
uiRadioButtonsSetSelected(rbRenderer, Config::_3DRenderer);
|
||||
UpdateControls();
|
||||
|
||||
if (Config::ScreenUseGL || Config::_3DRenderer != 0)
|
||||
uiControlEnable(uiControl(cbVSync));
|
||||
else
|
||||
uiControlDisable(uiControl(cbVSync));
|
||||
|
||||
uiControlShow(uiControl(win));
|
||||
}
|
||||
|
||||
|
|
|
@ -43,9 +43,11 @@ int ScreenSizing;
|
|||
int ScreenFilter;
|
||||
|
||||
int ScreenUseGL;
|
||||
int ScreenVSync;
|
||||
int ScreenRatio;
|
||||
|
||||
int LimitFPS;
|
||||
int AudioSync;
|
||||
int ShowOSD;
|
||||
|
||||
int DirectBoot;
|
||||
|
@ -118,9 +120,11 @@ ConfigEntry PlatformConfigFile[] =
|
|||
{"ScreenFilter", 0, &ScreenFilter, 1, NULL, 0},
|
||||
|
||||
{"ScreenUseGL", 0, &ScreenUseGL, 1, NULL, 0},
|
||||
{"ScreenVSync", 0, &ScreenVSync, 0, NULL, 0},
|
||||
{"ScreenRatio", 0, &ScreenRatio, 0, NULL, 0},
|
||||
|
||||
{"LimitFPS", 0, &LimitFPS, 1, NULL, 0},
|
||||
{"LimitFPS", 0, &LimitFPS, 0, NULL, 0},
|
||||
{"AudioSync", 0, &AudioSync, 1, NULL, 0},
|
||||
{"ShowOSD", 0, &ShowOSD, 1, NULL, 0},
|
||||
|
||||
{"DirectBoot", 0, &DirectBoot, 1, NULL, 0},
|
||||
|
|
|
@ -54,9 +54,11 @@ extern int ScreenSizing;
|
|||
extern int ScreenFilter;
|
||||
|
||||
extern int ScreenUseGL;
|
||||
extern int ScreenVSync;
|
||||
extern int ScreenRatio;
|
||||
|
||||
extern int LimitFPS;
|
||||
extern int AudioSync;
|
||||
extern int ShowOSD;
|
||||
|
||||
extern int DirectBoot;
|
||||
|
|
|
@ -620,6 +620,7 @@ _UI_EXTERN void *uiGLGetProcAddress(const char* proc);
|
|||
_UI_EXTERN int uiGLGetFramebuffer(uiGLContext* ctx);
|
||||
_UI_EXTERN float uiGLGetFramebufferScale(uiGLContext* ctx);
|
||||
_UI_EXTERN void uiGLSwapBuffers(uiGLContext* ctx);
|
||||
_UI_EXTERN void uiGLSetVSync(int sync);
|
||||
|
||||
|
||||
_UI_ENUM(uiModifiers) {
|
||||
|
|
|
@ -193,6 +193,11 @@ void uiGLSwapBuffers(uiGLContext* ctx)
|
|||
ctx->backbuffer = ctx->backbuffer ? 0 : 1;
|
||||
}
|
||||
|
||||
void uiGLSetVSync(int sync)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void uiGLMakeContextCurrent(uiGLContext* ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
|
|
|
@ -73,7 +73,7 @@ macro(_handle_static)
|
|||
add_custom_command(
|
||||
TARGET libui POST_BUILD
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy $<TARGET_PROPERTY:libui,BINARY_DIR>/CMakeFiles/libui.dir/windows/resources.rc.* ${_LIBUI_STATIC_RES}
|
||||
${CMAKE_COMMAND} -E copy $<TARGET_PROPERTY:libui,BINARY_DIR>/CMakeFiles/libui.dir/windows/resources.rc.obj ${_LIBUI_STATIC_RES}
|
||||
COMMENT "Copying libui.res")
|
||||
endmacro()
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "area.hpp"
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#include <GL/wglext.h>
|
||||
|
||||
struct uiGLContext
|
||||
|
@ -159,3 +160,37 @@ float uiGLGetFramebufferScale(uiGLContext* ctx)
|
|||
// TODO
|
||||
return 1;
|
||||
}
|
||||
|
||||
void uiGLSetVSync(int sync)
|
||||
{
|
||||
static PFNWGLSWAPINTERVALEXTPROC _wglSwapIntervalEXT = NULL;
|
||||
static bool symloaded = false;
|
||||
|
||||
if (!symloaded)
|
||||
{
|
||||
PFNGLGETSTRINGIPROC _glGetStringi = (PFNGLGETSTRINGIPROC)wglGetProcAddress("glGetStringi");
|
||||
if (_glGetStringi == NULL) return;
|
||||
|
||||
GLint numext;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &numext);
|
||||
|
||||
bool hasswapctrl = false;
|
||||
for (GLint i = 0; i < numext; i++)
|
||||
{
|
||||
const char* ext = (const char*)_glGetStringi(GL_EXTENSIONS, i);
|
||||
if (!stricmp(ext, "WGL_EXT_swap_control"))
|
||||
{
|
||||
hasswapctrl = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasswapctrl)
|
||||
_wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
|
||||
|
||||
symloaded = true;
|
||||
}
|
||||
|
||||
if (_wglSwapIntervalEXT)
|
||||
_wglSwapIntervalEXT(sync);
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ static LRESULT CALLBACK windowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARA
|
|||
// not a menu
|
||||
if (lParam != 0)
|
||||
break;
|
||||
if (HIWORD(wParam) != 0)
|
||||
if (HIWORD(wParam) != 0 || LOWORD(wParam) <= IDCANCEL)
|
||||
break;
|
||||
runMenuEvent(LOWORD(wParam), uiWindow(w));
|
||||
return 0;
|
||||
|
|
|
@ -93,6 +93,7 @@ uiMenuItem* MenuItem_ScreenSizing[4];
|
|||
|
||||
uiMenuItem* MenuItem_ScreenFilter;
|
||||
uiMenuItem* MenuItem_LimitFPS;
|
||||
uiMenuItem* MenuItem_AudioSync;
|
||||
uiMenuItem* MenuItem_ShowOSD;
|
||||
|
||||
SDL_Thread* EmuThread;
|
||||
|
@ -129,6 +130,8 @@ bool GL_ScreenSizeDirty;
|
|||
|
||||
int GL_3DScale;
|
||||
|
||||
bool GL_VSyncStatus;
|
||||
|
||||
int ScreenGap = 0;
|
||||
int ScreenLayout = 0;
|
||||
int ScreenSizing = 0;
|
||||
|
@ -158,8 +161,13 @@ bool LidStatus;
|
|||
int JoystickID;
|
||||
SDL_Joystick* Joystick;
|
||||
|
||||
int AudioFreq;
|
||||
float AudioSampleFrac;
|
||||
SDL_AudioDeviceID AudioDevice, MicDevice;
|
||||
|
||||
SDL_cond* AudioSync;
|
||||
SDL_mutex* AudioSyncLock;
|
||||
|
||||
u32 MicBufferLength = 2048;
|
||||
s16 MicBuffer[2048];
|
||||
u32 MicBufferReadPos, MicBufferWritePos;
|
||||
|
@ -236,6 +244,8 @@ bool GLScreen_InitOSDShader(GLuint* shader)
|
|||
|
||||
bool GLScreen_Init()
|
||||
{
|
||||
GL_VSyncStatus = Config::ScreenVSync;
|
||||
|
||||
// TODO: consider using epoxy?
|
||||
if (!OpenGL_Init())
|
||||
return false;
|
||||
|
@ -298,6 +308,13 @@ void GLScreen_DeInit()
|
|||
|
||||
void GLScreen_DrawScreen()
|
||||
{
|
||||
bool vsync = Config::ScreenVSync && !HotkeyDown(HK_FastForward);
|
||||
if (vsync != GL_VSyncStatus)
|
||||
{
|
||||
GL_VSyncStatus = vsync;
|
||||
uiGLSetVSync(vsync);
|
||||
}
|
||||
|
||||
float scale = uiGLGetFramebufferScale(GLContext);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, uiGLGetFramebuffer(GLContext));
|
||||
|
@ -560,26 +577,42 @@ void MicLoadWav(char* name)
|
|||
|
||||
void AudioCallback(void* data, Uint8* stream, int len)
|
||||
{
|
||||
// resampling:
|
||||
// buffer length is 1024 samples
|
||||
// which is 710 samples at the original sample rate
|
||||
len /= (sizeof(s16) * 2);
|
||||
|
||||
s16 buf_in[710*2];
|
||||
// resample incoming audio to match the output sample rate
|
||||
|
||||
float f_len_in = (len * 32823.6328125) / (float)AudioFreq;
|
||||
f_len_in += AudioSampleFrac;
|
||||
int len_in = (int)floor(f_len_in);
|
||||
AudioSampleFrac = f_len_in - len_in;
|
||||
|
||||
s16 buf_in[1024*2];
|
||||
s16* buf_out = (s16*)stream;
|
||||
|
||||
int num_in = SPU::ReadOutput(buf_in, 710);
|
||||
int num_out = 1024;
|
||||
int num_in;
|
||||
int num_out = len;
|
||||
|
||||
SDL_LockMutex(AudioSyncLock);
|
||||
num_in = SPU::ReadOutput(buf_in, len_in);
|
||||
SDL_CondSignal(AudioSync);
|
||||
SDL_UnlockMutex(AudioSyncLock);
|
||||
|
||||
if (num_in < 1)
|
||||
{
|
||||
memset(stream, 0, len*sizeof(s16)*2);
|
||||
return;
|
||||
}
|
||||
|
||||
int margin = 6;
|
||||
if (num_in < 710-margin)
|
||||
if (num_in < len_in-margin)
|
||||
{
|
||||
int last = num_in-1;
|
||||
if (last < 0) last = 0;
|
||||
|
||||
for (int i = num_in; i < 710-margin; i++)
|
||||
for (int i = num_in; i < len_in-margin; i++)
|
||||
((u32*)buf_in)[i] = ((u32*)buf_in)[last];
|
||||
|
||||
num_in = 710-margin;
|
||||
num_in = len_in-margin;
|
||||
}
|
||||
|
||||
float res_incr = num_in / (float)num_out;
|
||||
|
@ -588,12 +621,22 @@ void AudioCallback(void* data, Uint8* stream, int len)
|
|||
|
||||
int volume = Config::AudioVolume;
|
||||
|
||||
for (int i = 0; i < 1024; i++)
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
// TODO: interp!!
|
||||
buf_out[i*2 ] = (buf_in[res_pos*2 ] * volume) >> 8;
|
||||
buf_out[i*2+1] = (buf_in[res_pos*2+1] * volume) >> 8;
|
||||
|
||||
/*s16 s_l = buf_in[res_pos*2 ];
|
||||
s16 s_r = buf_in[res_pos*2+1];
|
||||
|
||||
float a = res_timer;
|
||||
float b = 1.0 - a;
|
||||
s_l = (s_l * a) + (buf_in[(res_pos-1)*2 ] * b);
|
||||
s_r = (s_r * a) + (buf_in[(res_pos-1)*2+1] * b);
|
||||
|
||||
buf_out[i*2 ] = (s_l * volume) >> 8;
|
||||
buf_out[i*2+1] = (s_r * volume) >> 8;*/
|
||||
|
||||
res_timer += res_incr;
|
||||
while (res_timer >= 1.0)
|
||||
{
|
||||
|
@ -710,26 +753,31 @@ bool JoystickButtonDown(int val)
|
|||
{
|
||||
if (val == -1) return false;
|
||||
|
||||
if (val & 0x100)
|
||||
bool hasbtn = ((val & 0xFFFF) != 0xFFFF);
|
||||
|
||||
if (hasbtn)
|
||||
{
|
||||
int hatnum = (val >> 4) & 0xF;
|
||||
int hatdir = val & 0xF;
|
||||
Uint8 hatval = SDL_JoystickGetHat(Joystick, hatnum);
|
||||
if (val & 0x100)
|
||||
{
|
||||
int hatnum = (val >> 4) & 0xF;
|
||||
int hatdir = val & 0xF;
|
||||
Uint8 hatval = SDL_JoystickGetHat(Joystick, hatnum);
|
||||
|
||||
bool pressed = false;
|
||||
if (hatdir == 0x1) pressed = (hatval & SDL_HAT_UP);
|
||||
else if (hatdir == 0x4) pressed = (hatval & SDL_HAT_DOWN);
|
||||
else if (hatdir == 0x2) pressed = (hatval & SDL_HAT_RIGHT);
|
||||
else if (hatdir == 0x8) pressed = (hatval & SDL_HAT_LEFT);
|
||||
bool pressed = false;
|
||||
if (hatdir == 0x1) pressed = (hatval & SDL_HAT_UP);
|
||||
else if (hatdir == 0x4) pressed = (hatval & SDL_HAT_DOWN);
|
||||
else if (hatdir == 0x2) pressed = (hatval & SDL_HAT_RIGHT);
|
||||
else if (hatdir == 0x8) pressed = (hatval & SDL_HAT_LEFT);
|
||||
|
||||
if (pressed) return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int btnnum = val & 0xFFFF;
|
||||
Uint8 btnval = SDL_JoystickGetButton(Joystick, btnnum);
|
||||
if (pressed) return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int btnnum = val & 0xFFFF;
|
||||
Uint8 btnval = SDL_JoystickGetButton(Joystick, btnnum);
|
||||
|
||||
if (btnval) return true;
|
||||
if (btnval) return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (val & 0x10000)
|
||||
|
@ -833,6 +881,7 @@ bool JoyButtonHeld(int btnid, int njoybuttons, Uint8* joybuttons, Uint32 hat)
|
|||
|
||||
void UpdateWindowTitle(void* data)
|
||||
{
|
||||
if (EmuStatus == 0) return;
|
||||
uiWindowSetTitle(MainWindow, (const char*)data);
|
||||
}
|
||||
|
||||
|
@ -875,6 +924,10 @@ int EmuThreadFunc(void* burp)
|
|||
u32 lasttick = starttick;
|
||||
u32 lastmeasuretick = lasttick;
|
||||
u32 fpslimitcount = 0;
|
||||
u64 perfcount = SDL_GetPerformanceCounter();
|
||||
u64 perffreq = SDL_GetPerformanceFrequency();
|
||||
float samplesleft = 0;
|
||||
u32 nsamples = 0;
|
||||
char melontitle[100];
|
||||
|
||||
while (EmuRunning != 0)
|
||||
|
@ -886,6 +939,7 @@ int EmuThreadFunc(void* burp)
|
|||
Config::LimitFPS = !Config::LimitFPS;
|
||||
uiQueueMain(UpdateFPSLimit, NULL);
|
||||
}
|
||||
// TODO: similar hotkeys for video/audio sync?
|
||||
|
||||
if (HotkeyPressed(HK_Pause)) uiQueueMain(TogglePause, NULL);
|
||||
if (HotkeyPressed(HK_Reset)) uiQueueMain(Reset, NULL);
|
||||
|
@ -954,25 +1008,46 @@ int EmuThreadFunc(void* burp)
|
|||
}
|
||||
uiAreaQueueRedrawAll(MainDrawArea);
|
||||
|
||||
// framerate limiter based off SDL2_gfx
|
||||
float framerate = (1000.0f * nlines) / (60.0f * 263.0f);
|
||||
bool fastforward = HotkeyDown(HK_FastForward);
|
||||
|
||||
fpslimitcount++;
|
||||
u32 curtick = SDL_GetTicks();
|
||||
u32 delay = curtick - lasttick;
|
||||
lasttick = curtick;
|
||||
|
||||
bool limitfps = Config::LimitFPS && !HotkeyDown(HK_FastForward);
|
||||
|
||||
u32 wantedtick = starttick + (u32)((float)fpslimitcount * framerate);
|
||||
if (curtick < wantedtick && limitfps)
|
||||
if (Config::AudioSync && !fastforward)
|
||||
{
|
||||
SDL_Delay(wantedtick - curtick);
|
||||
SDL_LockMutex(AudioSyncLock);
|
||||
while (SPU::GetOutputSize() > 1024)
|
||||
{
|
||||
int ret = SDL_CondWaitTimeout(AudioSync, AudioSyncLock, 500);
|
||||
if (ret == SDL_MUTEX_TIMEDOUT) break;
|
||||
}
|
||||
SDL_UnlockMutex(AudioSyncLock);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpslimitcount = 0;
|
||||
starttick = curtick;
|
||||
// ensure the audio FIFO doesn't overflow
|
||||
//SPU::TrimOutput();
|
||||
}
|
||||
|
||||
float framerate = (1000.0f * nlines) / (60.0f * 263.0f);
|
||||
|
||||
{
|
||||
u32 curtick = SDL_GetTicks();
|
||||
u32 delay = curtick - lasttick;
|
||||
|
||||
bool limitfps = Config::LimitFPS && !fastforward;
|
||||
if (limitfps)
|
||||
{
|
||||
float wantedtickF = starttick + (framerate * (fpslimitcount+1));
|
||||
u32 wantedtick = (u32)ceil(wantedtickF);
|
||||
if (curtick < wantedtick) SDL_Delay(wantedtick - curtick);
|
||||
|
||||
lasttick = SDL_GetTicks();
|
||||
fpslimitcount++;
|
||||
if ((abs(wantedtickF - (float)wantedtick) < 0.001312) || (fpslimitcount > 60))
|
||||
{
|
||||
fpslimitcount = 0;
|
||||
nsamples = 0;
|
||||
starttick = lasttick;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nframes++;
|
||||
|
@ -1044,6 +1119,12 @@ int EmuThreadFunc(void* burp)
|
|||
return 44203;
|
||||
}
|
||||
|
||||
void StopEmuThread()
|
||||
{
|
||||
EmuRunning = 0;
|
||||
SDL_WaitThread(EmuThread, NULL);
|
||||
}
|
||||
|
||||
|
||||
void OnAreaDraw(uiAreaHandler* handler, uiArea* area, uiAreaDrawParams* params)
|
||||
{
|
||||
|
@ -1155,13 +1236,13 @@ void OnAreaDragBroken(uiAreaHandler* handler, uiArea* area)
|
|||
{
|
||||
}
|
||||
|
||||
bool EventMatchesKey(uiAreaKeyEvent* evt, int val)
|
||||
bool EventMatchesKey(uiAreaKeyEvent* evt, int val, bool checkmod)
|
||||
{
|
||||
if (val == -1) return false;
|
||||
|
||||
int key = val & 0xFFFF;
|
||||
int mod = val >> 16;
|
||||
return evt->Scancode == key && evt->Modifiers == mod;
|
||||
return evt->Scancode == key && (!checkmod || evt->Modifiers == mod);
|
||||
}
|
||||
|
||||
int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
|
||||
|
@ -1175,11 +1256,11 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
|
|||
if (evt->Up)
|
||||
{
|
||||
for (int i = 0; i < 12; i++)
|
||||
if (EventMatchesKey(evt, Config::KeyMapping[i]))
|
||||
if (EventMatchesKey(evt, Config::KeyMapping[i], false))
|
||||
KeyInputMask |= (1<<i);
|
||||
|
||||
for (int i = 0; i < HK_MAX; i++)
|
||||
if (EventMatchesKey(evt, Config::HKKeyMapping[i]))
|
||||
if (EventMatchesKey(evt, Config::HKKeyMapping[i], true))
|
||||
KeyHotkeyMask &= ~(1<<i);
|
||||
}
|
||||
else if (!evt->Repeat)
|
||||
|
@ -1202,16 +1283,16 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
|
|||
}
|
||||
|
||||
for (int i = 0; i < 12; i++)
|
||||
if (EventMatchesKey(evt, Config::KeyMapping[i]))
|
||||
if (EventMatchesKey(evt, Config::KeyMapping[i], false))
|
||||
KeyInputMask &= ~(1<<i);
|
||||
|
||||
for (int i = 0; i < HK_MAX; i++)
|
||||
if (EventMatchesKey(evt, Config::HKKeyMapping[i]))
|
||||
if (EventMatchesKey(evt, Config::HKKeyMapping[i], true))
|
||||
KeyHotkeyMask |= (1<<i);
|
||||
|
||||
// REMOVE ME
|
||||
if (evt->Scancode == 0x57) // F11
|
||||
NDS::debug(0);
|
||||
//if (evt->Scancode == 0x57) // F11
|
||||
// NDS::debug(0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -1486,6 +1567,8 @@ void Run()
|
|||
EmuRunning = 1;
|
||||
RunningSomething = true;
|
||||
|
||||
SPU::InitOutput();
|
||||
AudioSampleFrac = 0;
|
||||
SDL_PauseAudioDevice(AudioDevice, 0);
|
||||
SDL_PauseAudioDevice(MicDevice, 0);
|
||||
|
||||
|
@ -1524,6 +1607,7 @@ void TogglePause(void* blarg)
|
|||
EmuRunning = 2;
|
||||
uiMenuItemSetChecked(MenuItem_Pause, 1);
|
||||
|
||||
SPU::DrainOutput();
|
||||
SDL_PauseAudioDevice(AudioDevice, 1);
|
||||
SDL_PauseAudioDevice(MicDevice, 1);
|
||||
|
||||
|
@ -1535,6 +1619,8 @@ void TogglePause(void* blarg)
|
|||
EmuRunning = 1;
|
||||
uiMenuItemSetChecked(MenuItem_Pause, 0);
|
||||
|
||||
SPU::InitOutput();
|
||||
AudioSampleFrac = 0;
|
||||
SDL_PauseAudioDevice(AudioDevice, 0);
|
||||
SDL_PauseAudioDevice(MicDevice, 0);
|
||||
|
||||
|
@ -1585,6 +1671,7 @@ void Stop(bool internal)
|
|||
|
||||
uiAreaQueueRedrawAll(MainDrawArea);
|
||||
|
||||
SPU::DrainOutput();
|
||||
SDL_PauseAudioDevice(AudioDevice, 1);
|
||||
SDL_PauseAudioDevice(MicDevice, 1);
|
||||
|
||||
|
@ -1849,6 +1936,7 @@ int OnCloseWindow(uiWindow* window, void* blarg)
|
|||
while (EmuStatus != 3);
|
||||
|
||||
CloseAllDialogs();
|
||||
StopEmuThread();
|
||||
uiQuit();
|
||||
return 1;
|
||||
}
|
||||
|
@ -1886,6 +1974,7 @@ void OnCloseByMenu(uiMenuItem* item, uiWindow* window, void* blarg)
|
|||
while (EmuStatus != 3);
|
||||
|
||||
CloseAllDialogs();
|
||||
StopEmuThread();
|
||||
DestroyMainWindow();
|
||||
uiQuit();
|
||||
}
|
||||
|
@ -2143,6 +2232,13 @@ void OnSetLimitFPS(uiMenuItem* item, uiWindow* window, void* blarg)
|
|||
else Config::LimitFPS = false;
|
||||
}
|
||||
|
||||
void OnSetAudioSync(uiMenuItem* item, uiWindow* window, void* blarg)
|
||||
{
|
||||
int chk = uiMenuItemChecked(item);
|
||||
if (chk != 0) Config::AudioSync = true;
|
||||
else Config::AudioSync = false;
|
||||
}
|
||||
|
||||
void OnSetShowOSD(uiMenuItem* item, uiWindow* window, void* blarg)
|
||||
{
|
||||
int chk = uiMenuItemChecked(item);
|
||||
|
@ -2206,6 +2302,19 @@ void ApplyNewSettings(int type)
|
|||
GPU3D::InitRenderer(Screen_UseGL);
|
||||
if (Screen_UseGL) uiGLMakeContextCurrent(NULL);
|
||||
}
|
||||
/*else if (type == 4) // vsync
|
||||
{
|
||||
if (Screen_UseGL)
|
||||
{
|
||||
uiGLMakeContextCurrent(GLContext);
|
||||
uiGLSetVSync(Config::ScreenVSync);
|
||||
uiGLMakeContextCurrent(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO eventually: VSync for non-GL screen?
|
||||
}
|
||||
}*/
|
||||
|
||||
EmuRunning = prevstatus;
|
||||
}
|
||||
|
@ -2374,11 +2483,16 @@ void CreateMainWindowMenu()
|
|||
MenuItem_ScreenFilter = uiMenuAppendCheckItem(menu, "Screen filtering");
|
||||
uiMenuItemOnClicked(MenuItem_ScreenFilter, OnSetScreenFiltering, NULL);
|
||||
|
||||
MenuItem_ShowOSD = uiMenuAppendCheckItem(menu, "Show OSD");
|
||||
uiMenuItemOnClicked(MenuItem_ShowOSD, OnSetShowOSD, NULL);
|
||||
|
||||
uiMenuAppendSeparator(menu);
|
||||
|
||||
MenuItem_LimitFPS = uiMenuAppendCheckItem(menu, "Limit framerate");
|
||||
uiMenuItemOnClicked(MenuItem_LimitFPS, OnSetLimitFPS, NULL);
|
||||
|
||||
MenuItem_ShowOSD = uiMenuAppendCheckItem(menu, "Show OSD");
|
||||
uiMenuItemOnClicked(MenuItem_ShowOSD, OnSetShowOSD, NULL);
|
||||
MenuItem_AudioSync = uiMenuAppendCheckItem(menu, "Audio sync");
|
||||
uiMenuItemOnClicked(MenuItem_AudioSync, OnSetAudioSync, NULL);
|
||||
}
|
||||
|
||||
void CreateMainWindow(bool opengl)
|
||||
|
@ -2415,6 +2529,7 @@ void CreateMainWindow(bool opengl)
|
|||
if (opengl_good)
|
||||
{
|
||||
uiGLMakeContextCurrent(GLContext);
|
||||
uiGLSetVSync(Config::ScreenVSync);
|
||||
if (!GLScreen_Init()) opengl_good = false;
|
||||
if (opengl_good)
|
||||
{
|
||||
|
@ -2539,7 +2654,6 @@ int main(int argc, char** argv)
|
|||
SDL_Quit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
FILE* f = Platform::OpenLocalFile("romlist.bin", "rb");
|
||||
if (f)
|
||||
|
@ -2556,6 +2670,13 @@ int main(int argc, char** argv)
|
|||
"You should use the latest version of romlist.bin (provided in melonDS release packages).");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uiMsgBoxError(NULL,
|
||||
"romlist.bin not found.",
|
||||
"Save memory type detection will not work correctly.\n\n"
|
||||
"You should use the latest version of romlist.bin (provided in melonDS release packages).");
|
||||
}
|
||||
}
|
||||
|
||||
CreateMainWindowMenu();
|
||||
|
@ -2613,22 +2734,29 @@ int main(int argc, char** argv)
|
|||
|
||||
uiMenuItemSetChecked(MenuItem_ScreenFilter, Config::ScreenFilter==1);
|
||||
uiMenuItemSetChecked(MenuItem_LimitFPS, Config::LimitFPS==1);
|
||||
uiMenuItemSetChecked(MenuItem_AudioSync, Config::AudioSync==1);
|
||||
uiMenuItemSetChecked(MenuItem_ShowOSD, Config::ShowOSD==1);
|
||||
|
||||
AudioSync = SDL_CreateCond();
|
||||
AudioSyncLock = SDL_CreateMutex();
|
||||
|
||||
AudioFreq = 48000; // TODO: make configurable?
|
||||
SDL_AudioSpec whatIwant, whatIget;
|
||||
memset(&whatIwant, 0, sizeof(SDL_AudioSpec));
|
||||
whatIwant.freq = 47340;
|
||||
whatIwant.freq = AudioFreq;
|
||||
whatIwant.format = AUDIO_S16LSB;
|
||||
whatIwant.channels = 2;
|
||||
whatIwant.samples = 1024;
|
||||
whatIwant.callback = AudioCallback;
|
||||
AudioDevice = SDL_OpenAudioDevice(NULL, 0, &whatIwant, &whatIget, 0);
|
||||
AudioDevice = SDL_OpenAudioDevice(NULL, 0, &whatIwant, &whatIget, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
if (!AudioDevice)
|
||||
{
|
||||
printf("Audio init failed: %s\n", SDL_GetError());
|
||||
}
|
||||
else
|
||||
{
|
||||
AudioFreq = whatIget.freq;
|
||||
printf("Audio output frequency: %d Hz\n", AudioFreq);
|
||||
SDL_PauseAudioDevice(AudioDevice, 1);
|
||||
}
|
||||
|
||||
|
@ -2683,13 +2811,13 @@ int main(int argc, char** argv)
|
|||
|
||||
uiMain();
|
||||
|
||||
EmuRunning = 0;
|
||||
SDL_WaitThread(EmuThread, NULL);
|
||||
|
||||
if (Joystick) SDL_JoystickClose(Joystick);
|
||||
if (AudioDevice) SDL_CloseAudioDevice(AudioDevice);
|
||||
if (MicDevice) SDL_CloseAudioDevice(MicDevice);
|
||||
|
||||
SDL_DestroyCond(AudioSync);
|
||||
SDL_DestroyMutex(AudioSyncLock);
|
||||
|
||||
if (MicWavBuffer) delete[] MicWavBuffer;
|
||||
|
||||
if (ScreenBitmap[0]) uiDrawFreeBitmap(ScreenBitmap[0]);
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#ifndef VERSION_H
|
||||
#define VERSION_H
|
||||
|
||||
#define MELONDS_VERSION "0.8.1-DSi"
|
||||
#define MELONDS_VERSION "0.8.3-DSi"
|
||||
|
||||
#define MELONDS_URL "http://melonds.kuribo64.net/"
|
||||
|
||||
|
|
Loading…
Reference in New Issue