Merge branch 'master' into dsi_camera

# Conflicts:
#	src/DSi_I2C.cpp
This commit is contained in:
Arisotura 2020-10-26 20:47:30 +01:00
commit fc922ffb14
51 changed files with 350 additions and 104 deletions

View File

@ -20,8 +20,10 @@ jobs:
- name: Upgrade system
shell: bash
working-directory: ${{runner.workspace}}
run: |
run: | #Fix grub installation error - https://github.com/actions/virtual-environments/issues/1605
sudo apt update
sudo apt-get install grub-efi
sudo update-grub
sudo apt full-upgrade
- name: Install dependencies
shell: bash
@ -32,7 +34,8 @@ jobs:
sudo rm /etc/apt/sources.list
sudo mv /etc/apt/sources.list{.new,}
sudo apt update
sudo apt install {gcc-10,g++-10,pkg-config}-aarch64-linux-gnu libsdl2-dev:arm64 qtbase5-dev:arm64 libslirp-dev:arm64
sudo apt install aptitude
sudo aptitude install -y {gcc-10,g++-10,pkg-config}-aarch64-linux-gnu libsdl2-dev:arm64 qtbase5-dev:arm64 libslirp-dev:arm64
- name: Create build environment
run: mkdir ${{runner.workspace}}/build
- name: Configure

View File

@ -50,6 +50,12 @@ else()
option(ENABLE_LTO "Enable link-time optimization" OFF)
endif()
option(ENABLE_OGLRENDERER "Enable OpenGL renderer" ON)
if (ENABLE_OGLRENDERER)
add_definitions(-DOGLRENDERER_ENABLED)
endif()
if (CMAKE_BUILD_TYPE STREQUAL Debug)
add_compile_options(-Og)
endif()

View File

@ -38,7 +38,7 @@ As for the rest, the interface should be pretty straightforward. If you have a q
* Install dependencies:
```sh
sudo apt-get install libgtk-3-dev libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev qtbase5-dev qtdeclarative5-dev libslirp-dev
sudo apt-get install cmake libgtk-3-dev libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev qtbase5-dev qtdeclarative5-dev libslirp-dev
```
* Compile:

View File

@ -24,7 +24,10 @@
#include "types.h"
#include "NDS.h"
#define ROR(x, n) (((x) >> (n)) | ((x) << (32-(n))))
inline u32 ROR(u32 x, u32 n)
{
return (x >> (n&0x1F)) | (x << ((32-n)&0x1F));
}
enum
{

View File

@ -1087,7 +1087,10 @@ void ResetBlockCache()
InvalidLiterals.Clear();
for (int i = 0; i < ARMJIT_Memory::memregions_Count; i++)
{
if (FastBlockLookupRegions[i])
memset(FastBlockLookupRegions[i], 0xFF, CodeRegionSizes[i] * sizeof(u64) / 2);
}
for (auto it = RestoreCandidates.begin(); it != RestoreCandidates.end(); it++)
delete it->second;
RestoreCandidates.clear();

View File

@ -436,7 +436,7 @@ void Compiler::A_Comp_GetOp2(bool S, Op2& op2)
Comp_AddCycles_C();
u32 shift = (CurInstr.Instr >> 7) & 0x1E;
u32 imm = ROR(CurInstr.Instr & 0xFF, shift);
u32 imm = ::ROR(CurInstr.Instr & 0xFF, shift);
if (S && shift && (CurInstr.SetFlags & 0x2))
{
@ -447,7 +447,7 @@ void Compiler::A_Comp_GetOp2(bool S, Op2& op2)
ANDI2R(RCPSR, RCPSR, ~(1 << 29));
}
op2 = Op2(ROR(CurInstr.Instr & 0xFF, (CurInstr.Instr >> 7) & 0x1E));
op2 = Op2(imm);
}
else
{
@ -523,7 +523,7 @@ void Compiler::A_Comp_ALUMovOp()
case ST_LSL: LSL(rd, op2.Reg.Rm, op2.Reg.ShiftAmount); break;
case ST_LSR: LSR(rd, op2.Reg.Rm, op2.Reg.ShiftAmount); break;
case ST_ASR: ASR(rd, op2.Reg.Rm, op2.Reg.ShiftAmount); break;
case ST_ROR: ROR_(rd, op2.Reg.Rm, op2.Reg.ShiftAmount); break;
case ST_ROR: ROR(rd, op2.Reg.Rm, op2.Reg.ShiftAmount); break;
}
}
else

View File

@ -76,7 +76,7 @@ void Compiler::A_Comp_MSR()
if (CurInstr.Instr & (1 << 25))
{
val = W0;
MOVI2R(val, ROR((CurInstr.Instr & 0xFF), ((CurInstr.Instr >> 7) & 0x1E)));
MOVI2R(val, ::ROR((CurInstr.Instr & 0xFF), ((CurInstr.Instr >> 7) & 0x1E)));
}
else
{

View File

@ -1,5 +1,5 @@
#ifndef ARMJIT_COMPILER_H
#define ARMJIT_COMPILER_H
#ifndef ARMJIT_A64_COMPILER_H
#define ARMJIT_A64_COMPILER_H
#include "../ARM.h"
#include "../ARMJIT.h"

View File

@ -42,7 +42,7 @@ s64 Compiler::RewriteMemAccess(u64 pc)
return patch.PatchOffset;
}
printf("this is a JIT bug! %08x\n", __builtin_bswap32(*(u32*)pc));
assert(false);
abort();
}
bool Compiler::Comp_MemLoadLiteral(int size, bool signExtend, int rd, u32 addr)
@ -65,7 +65,7 @@ bool Compiler::Comp_MemLoadLiteral(int size, bool signExtend, int rd, u32 addr)
if (size == 32)
{
CurCPU->DataRead32(addr & ~0x3, &val);
val = ROR(val, (addr & 0x3) << 3);
val = ::ROR(val, (addr & 0x3) << 3);
}
else if (size == 16)
{
@ -151,7 +151,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
{
if (offset.Reg.ShiftType == ST_ROR)
{
ROR_(W0, offset.Reg.Rm, offset.Reg.ShiftAmount);
ROR(W0, offset.Reg.Rm, offset.Reg.ShiftAmount);
offset = Op2(W0);
}
@ -220,7 +220,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
if (size == 32)
{
if (staticAddress & 0x3)
ROR_(rdMapped, W0, (staticAddress & 0x3) << 3);
ROR(rdMapped, W0, (staticAddress & 0x3) << 3);
else
MOV(rdMapped, W0);
}

View File

@ -1,3 +1,6 @@
#ifndef ARMJIT_COMPILER_H
#define ARMJIT_COMPILER_H
#if defined(__x86_64__)
#include "ARMJIT_x64/ARMJIT_Compiler.h"
#elif defined(__aarch64__)
@ -10,3 +13,5 @@ namespace ARMJIT
{
extern Compiler* JITCompiler;
}
#endif

View File

@ -279,6 +279,7 @@ bool UnmapFromRange(u32 addr, u32 num, u32 offset, u32 size)
#endif
}
#ifndef __SWITCH__
void SetCodeProtectionRange(u32 addr, u32 size, u32 num, int protection)
{
u8* dst = (u8*)(num == 0 ? FastMem9Start : FastMem7Start) + addr;
@ -303,6 +304,7 @@ void SetCodeProtectionRange(u32 addr, u32 size, u32 num, int protection)
mprotect(dst, size, posixProt);
#endif
}
#endif
struct Mapping
{

View File

@ -61,7 +61,8 @@ public:
}
}
assert("Welp!");
printf("this is a JIT bug! LoadRegister failed\n");
abort();
}
void PutLiteral(int reg, u32 val)

View File

@ -110,7 +110,7 @@ OpArg Compiler::A_Comp_GetALUOp2(bool S, bool& carryUsed)
Comp_AddCycles_C();
u32 shift = (CurInstr.Instr >> 7) & 0x1E;
u32 imm = ROR(CurInstr.Instr & 0xFF, shift);
u32 imm = ::ROR(CurInstr.Instr & 0xFF, shift);
carryUsed = false;
if (S && shift)
@ -209,7 +209,8 @@ void Compiler::A_Comp_Arith()
Comp_ArithTriOp(&Compiler::AND, rd, rn, op2, carryUsed, sFlag|opSymmetric|opInvertOp2);
break;
default:
assert("unimplemented");
printf("this is a JIT bug! %04x\n", op);
abort();
}
if (CurInstr.A_Reg(12) == 15)
@ -493,7 +494,7 @@ OpArg Compiler::Comp_RegShiftReg(int op, Gen::OpArg rs, Gen::OpArg rm, bool S, b
{
if (S)
BT(32, R(RSCRATCH), Imm8(31));
ROR_(32, R(RSCRATCH), R(ECX));
ROR(32, R(RSCRATCH), R(ECX));
if (S)
SETcc(CC_C, R(RSCRATCH2));
}
@ -555,7 +556,7 @@ OpArg Compiler::Comp_RegShiftImm(int op, int amount, OpArg rm, bool S, bool& car
case 3: // ROR
MOV(32, R(RSCRATCH), rm);
if (amount > 0)
ROR_(32, R(RSCRATCH), Imm8(amount));
ROR(32, R(RSCRATCH), Imm8(amount));
else
{
BT(32, R(RCPSR), Imm8(29));
@ -566,7 +567,7 @@ OpArg Compiler::Comp_RegShiftImm(int op, int amount, OpArg rm, bool S, bool& car
return R(RSCRATCH);
}
assert(false);
abort();
}
void Compiler::T_Comp_ShiftImm()

View File

@ -106,7 +106,7 @@ void Compiler::A_Comp_MSR()
Comp_AddCycles_C();
OpArg val = CurInstr.Instr & (1 << 25)
? Imm32(ROR((CurInstr.Instr & 0xFF), ((CurInstr.Instr >> 7) & 0x1E)))
? Imm32(::ROR((CurInstr.Instr & 0xFF), ((CurInstr.Instr >> 7) & 0x1E)))
: MapReg(CurInstr.A_Reg(0));
u32 mask = 0;

View File

@ -1,5 +1,5 @@
#ifndef ARMJIT_COMPILER_H
#define ARMJIT_COMPILER_H
#ifndef ARMJIT_X64_COMPILER_H
#define ARMJIT_X64_COMPILER_H
#include "../dolphin/x64Emitter.h"

View File

@ -39,7 +39,7 @@ s32 Compiler::RewriteMemAccess(u64 pc)
return patch.Offset;
}
printf("this is a JIT bug %x\n", pc);
printf("this is a JIT bug %llx\n", pc);
abort();
}
@ -73,7 +73,7 @@ bool Compiler::Comp_MemLoadLiteral(int size, bool signExtend, int rd, u32 addr)
if (size == 32)
{
CurCPU->DataRead32(addr & ~0x3, &val);
val = ROR(val, (addr & 0x3) << 3);
val = ::ROR(val, (addr & 0x3) << 3);
}
else if (size == 16)
{
@ -225,13 +225,13 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
if (addrIsStatic)
{
if (staticAddress & 0x3)
ROR_(32, rdMapped, Imm8((staticAddress & 0x3) * 8));
ROR(32, rdMapped, Imm8((staticAddress & 0x3) * 8));
}
else
{
AND(32, R(RSCRATCH3), Imm8(0x3));
SHL(32, R(RSCRATCH3), Imm8(3));
ROR_(32, rdMapped, R(RSCRATCH3));
ROR(32, rdMapped, R(RSCRATCH3));
}
}
}
@ -270,7 +270,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
{
MOV(32, rdMapped, R(RSCRATCH));
if (staticAddress & 0x3)
ROR_(32, rdMapped, Imm8((staticAddress & 0x3) * 8));
ROR(32, rdMapped, Imm8((staticAddress & 0x3) * 8));
}
else
{

View File

@ -26,17 +26,12 @@ add_library(core STATIC
FIFO.h
GBACart.cpp
GPU.cpp
GPU_OpenGL.cpp
GPU_OpenGL_shaders.h
GPU2D.cpp
GPU3D.cpp
GPU3D_OpenGL.cpp
GPU3D_OpenGL_shaders.h
GPU3D_Soft.cpp
melonDLDI.h
NDS.cpp
NDSCart.cpp
OpenGLSupport.cpp
Platform.h
ROMList.h
RTC.cpp
@ -52,6 +47,16 @@ add_library(core STATIC
xxhash/xxhash.c
)
if (ENABLE_OGLRENDERER)
target_sources(core PRIVATE
GPU_OpenGL.cpp
GPU_OpenGL_shaders.h
GPU3D_OpenGL.cpp
GPU3D_OpenGL_shaders.h
OpenGLSupport.cpp
)
endif()
if (ENABLE_JIT)
enable_language(ASM)
@ -95,8 +100,16 @@ if (ENABLE_JIT)
endif()
endif()
if (WIN32)
if (ENABLE_OGLRENDERER)
if (WIN32)
target_link_libraries(core ole32 comctl32 ws2_32 opengl32)
else()
else()
target_link_libraries(core GL EGL)
endif()
else()
if (WIN32)
target_link_libraries(core ole32 comctl32 ws2_32)
else()
target_link_libraries(core)
endif()
endif()

View File

@ -46,7 +46,7 @@ int RandomizeMAC;
#ifdef JIT_ENABLED
int JIT_Enable = false;
int JIT_MaxBlockSize = 32;
int JIT_BranchOptimisations = 2;
int JIT_BranchOptimisations = true;
int JIT_LiteralOptimisations = true;
int JIT_FastMemory = true;
#endif
@ -71,7 +71,7 @@ ConfigEntry ConfigFile[] =
#ifdef JIT_ENABLED
{"JIT_Enable", 0, &JIT_Enable, 0, NULL, 0},
{"JIT_MaxBlockSize", 0, &JIT_MaxBlockSize, 32, NULL, 0},
{"JIT_BranchOptimisations", 0, &JIT_BranchOptimisations, 2, NULL, 0},
{"JIT_BranchOptimisations", 0, &JIT_BranchOptimisations, 1, NULL, 0},
{"JIT_LiteralOptimisations", 0, &JIT_LiteralOptimisations, 1, NULL, 0},
{"JIT_FastMemory", 0, &JIT_FastMemory, 1, NULL, 0},
#endif
@ -169,7 +169,7 @@ void Save()
if (entry->Type == 0)
fprintf(f, "%s=%d\n", entry->Name, *(int*)entry->Value);
else
fprintf(f, "%s=%s\n", entry->Name, entry->Value);
fprintf(f, "%s=%s\n", entry->Name, (char*)entry->Value);
entry++;
}

View File

@ -73,6 +73,8 @@ void DMA::Reset()
SrcAddrInc = 0;
DstAddrInc = 0;
Stall = false;
Running = false;
InProgress = false;
@ -111,8 +113,8 @@ void DMA::DoSavestate(Savestate* file)
file->Var32(&DstAddrInc);
file->Var32(&Running);
file->Var32((u32*)&InProgress);
file->Var32((u32*)&IsGXFIFODMA);
file->Bool32(&InProgress);
file->Bool32(&IsGXFIFODMA);
}
void DMA::WriteCnt(u32 val)

View File

@ -1740,7 +1740,7 @@ u8 ARM7IORead8(u32 addr)
case 0x04004501: return DSi_I2C::Cnt;
case 0x04004D00: if (SCFG_BIOS & (1<<10)) return 0; return ConsoleID & 0xFF;
case 0x04004fD01: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 8) & 0xFF;
case 0x04004D01: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 8) & 0xFF;
case 0x04004D02: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 16) & 0xFF;
case 0x04004D03: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 24) & 0xFF;
case 0x04004D04: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 32) & 0xFF;

View File

@ -50,7 +50,7 @@ void Reset()
Registers[0x10] = 0x00; // power btn
Registers[0x11] = 0x00; // reset
Registers[0x12] = 0x00; // power btn tap
Registers[0x20] = 0x83; // battery
Registers[0x20] = 0x8F; // battery
Registers[0x21] = 0x07;
Registers[0x30] = 0x13;
Registers[0x31] = 0x00; // camera power
@ -189,6 +189,8 @@ void WriteCnt(u8 val)
case 0x4A: Data = DSi_BPTWL::Read(islast); break;
case 0x78: Data = DSi_Camera0->I2C_Read(islast); break;
case 0x7A: Data = DSi_Camera1->I2C_Read(islast); break;
case 0xA0:
case 0xE0: Data = 0xFF; break;
default:
printf("I2C: read on unknown device %02X, cnt=%02X, data=%02X, last=%d\n", Device, val, 0, islast);
Data = 0xFF;
@ -213,6 +215,8 @@ void WriteCnt(u8 val)
case 0x4A: DSi_BPTWL::Start(); break;
case 0x78: DSi_Camera0->I2C_Start(); break;
case 0x7A: DSi_Camera1->I2C_Start(); break;
case 0xA0:
case 0xE0: ack = false; break;
default:
printf("I2C: %s start on unknown device %02X\n", (Data&0x01)?"read":"write", Device);
ack = false;
@ -228,6 +232,8 @@ void WriteCnt(u8 val)
case 0x4A: DSi_BPTWL::Write(Data, islast); break;
case 0x78: DSi_Camera0->I2C_Write(Data, islast); break;
case 0x7A: DSi_Camera1->I2C_Write(Data, islast); break;
case 0xA0:
case 0xE0: ack = false; break;
default:
printf("I2C: write on unknown device %02X, cnt=%02X, data=%02X, last=%d\n", Device, val, Data, islast);
ack = false;

View File

@ -778,6 +778,23 @@ void DSi_MMCStorage::SendCMD(u8 cmd, u32 param)
Host->SendResponse(CSR, true);
return;
case 1: // SEND_OP_COND
// CHECKME!!
// also TODO: it's different for the SD card
if (Internal)
{
param &= ~(1<<30);
OCR &= 0xBF000000;
OCR |= (param & 0x40FFFFFF);
Host->SendResponse(OCR, true);
SetState(0x01);
}
else
{
printf("CMD1 on SD card!!\n");
}
return;
case 2:
case 10: // get CID
Host->SendResponse(*(u32*)&CID[12], false);
@ -801,6 +818,11 @@ void DSi_MMCStorage::SendCMD(u8 cmd, u32 param)
}
return;
case 6: // MMC: 'SWITCH'
// TODO!
Host->SendResponse(CSR, true);
return;
case 7: // select card (by RCA)
Host->SendResponse(CSR, true);
return;

View File

@ -103,7 +103,7 @@ class DSi_SDDevice
{
public:
DSi_SDDevice(DSi_SDHost* host) { Host = host; IRQ = false; }
~DSi_SDDevice() {}
virtual ~DSi_SDDevice() {}
virtual void Reset() = 0;

View File

@ -280,6 +280,7 @@ void AssignFramebuffers()
void InitRenderer(int renderer)
{
#ifdef OGLRENDERER_ENABLED
if (renderer == 1)
{
if (!GLCompositor::Init())
@ -292,8 +293,8 @@ void InitRenderer(int renderer)
renderer = 0;
}
}
if (renderer == 0)
else
#endif
{
GPU3D::SoftRenderer::Init();
}
@ -308,11 +309,13 @@ void DeInitRenderer()
{
GPU3D::SoftRenderer::DeInit();
}
#ifdef OGLRENDERER_ENABLED
else
{
GPU3D::GLRenderer::DeInit();
GLCompositor::DeInit();
}
#endif
}
void ResetRenderer()
@ -321,11 +324,13 @@ void ResetRenderer()
{
GPU3D::SoftRenderer::Reset();
}
#ifdef OGLRENDERER_ENABLED
else
{
GLCompositor::Reset();
GPU3D::GLRenderer::Reset();
}
#endif
}
void SetRenderSettings(int renderer, RenderSettings& settings)
@ -364,11 +369,13 @@ void SetRenderSettings(int renderer, RenderSettings& settings)
{
GPU3D::SoftRenderer::SetRenderSettings(settings);
}
#ifdef OGLRENDERER_ENABLED
else
{
GLCompositor::SetRenderSettings(settings);
GPU3D::GLRenderer::SetRenderSettings(settings);
}
#endif
}
@ -1055,7 +1062,9 @@ void StartScanline(u32 line)
GPU2D_B->VBlank();
GPU3D::VBlank();
#ifdef OGLRENDERER_ENABLED
if (Accelerated) GLCompositor::RenderFrame();
#endif
}
else if (VCount == 144)
{

View File

@ -437,6 +437,7 @@ void SetDispStat(u32 cpu, u16 val);
void SetVCount(u16 val);
#ifdef OGLRENDERER_ENABLED
namespace GLCompositor
{
@ -450,6 +451,7 @@ void RenderFrame();
void BindOutputTexture();
}
#endif
}

View File

@ -102,6 +102,7 @@ GPU2D::~GPU2D()
void GPU2D::Reset()
{
Enabled = false;
DispCnt = 0;
memset(BGCnt, 0, 4*2);
memset(BGXPos, 0, 4*2);
@ -814,7 +815,6 @@ void GPU2D::DrawScanline(u32 line)
int i = 0;
for (; i < (stride & ~1); i+=2)
*(u64*)&dst[i] = *(u64*)&BGOBJLine[i];
if (stride & 1) dst[i] = BGOBJLine[i];
}
break;
@ -949,6 +949,7 @@ void GPU2D::VBlankEnd()
//OBJMosaicY = 0;
//OBJMosaicYCount = 0;
#ifdef OGLRENDERER_ENABLED
if (Accelerated)
{
if ((Num == 0) && (CaptureCnt & (1<<31)) && (((CaptureCnt >> 29) & 0x3) != 1))
@ -956,6 +957,7 @@ void GPU2D::VBlankEnd()
GPU3D::GLRenderer::PrepareCaptureFrame();
}
}
#endif
}

View File

@ -470,7 +470,7 @@ void DoSavestate(Savestate* file)
file->VarArray(vtx->Color, sizeof(s32)*3);
file->VarArray(vtx->TexCoords, sizeof(s16)*2);
file->Var32((u32*)&vtx->Clipped);
file->Bool32(&vtx->Clipped);
file->VarArray(vtx->FinalPosition, sizeof(s32)*2);
file->VarArray(vtx->FinalColor, sizeof(s32)*3);
@ -507,7 +507,7 @@ void DoSavestate(Savestate* file)
file->VarArray(vtx->Color, sizeof(s32)*3);
file->VarArray(vtx->TexCoords, sizeof(s16)*2);
file->Var32((u32*)&vtx->Clipped);
file->Bool32(&vtx->Clipped);
file->VarArray(vtx->FinalPosition, sizeof(s32)*2);
file->VarArray(vtx->FinalColor, sizeof(s32)*3);
@ -545,17 +545,17 @@ void DoSavestate(Savestate* file)
file->VarArray(poly->FinalZ, sizeof(s32)*10);
file->VarArray(poly->FinalW, sizeof(s32)*10);
file->Var32((u32*)&poly->WBuffer);
file->Bool32(&poly->WBuffer);
file->Var32(&poly->Attr);
file->Var32(&poly->TexParam);
file->Var32(&poly->TexPalette);
file->Var32((u32*)&poly->FacingView);
file->Var32((u32*)&poly->Translucent);
file->Bool32(&poly->FacingView);
file->Bool32(&poly->Translucent);
file->Var32((u32*)&poly->IsShadowMask);
file->Var32((u32*)&poly->IsShadow);
file->Bool32(&poly->IsShadowMask);
file->Bool32(&poly->IsShadow);
if (file->IsAtleastVersion(4, 1))
file->Var32((u32*)&poly->Type);
@ -2528,13 +2528,19 @@ void VBlank()
void VCount215()
{
if (GPU::Renderer == 0) SoftRenderer::RenderFrame();
#ifdef OGLRENDERER_ENABLED
else GLRenderer::RenderFrame();
#endif
}
u32* GetLine(int line)
{
if (GPU::Renderer == 0) return SoftRenderer::GetLine(line);
#ifdef OGLRENDERER_ENABLED
else return GLRenderer::GetLine(line);
#else
return NULL;
#endif
}

View File

@ -139,6 +139,7 @@ u32* GetLine(int line);
}
#ifdef OGLRENDERER_ENABLED
namespace GLRenderer
{
@ -154,6 +155,7 @@ u32* GetLine(int line);
void SetupAccelFrame();
}
#endif
}

View File

@ -775,7 +775,7 @@ bool DoSavestate(Savestate* file)
file->Var8(&WRAMCnt);
file->Var32((u32*)&RunningGame);
file->Bool32(&RunningGame);
if (!file->Saving)
{
@ -1124,6 +1124,11 @@ void MicInputFrame(s16* data, int samples)
return SPI_TSC::MicInputFrame(data, samples);
}
int ImportSRAM(u8* data, u32 length)
{
return NDSCart::ImportSRAM(data, length);
}
void Halt()
{
@ -2996,6 +3001,7 @@ u32 ARM9IORead32(u32 addr)
case 0x04000130: return (KeyInput & 0xFFFF) | (KeyCnt << 16);
case 0x04000180: return IPCSync9;
case 0x04000184: return ARM9IORead16(addr);
case 0x040001A0: return NDSCart::SPICnt | (NDSCart::ReadSPIData() << 16);
case 0x040001A4: return NDSCart::ROMCnt;
@ -3373,10 +3379,11 @@ void ARM9IOWrite32(u32 addr, u32 val)
case 0x04000130:
KeyCnt = val >> 16;
return;
case 0x04000180:
case 0x04000184:
ARM9IOWrite16(addr, val);
return;
case 0x04000188:
if (IPCFIFOCnt9 & 0x8000)
{
@ -3635,6 +3642,7 @@ u32 ARM7IORead32(u32 addr)
case 0x04000138: return RTC::Read();
case 0x04000180: return IPCSync7;
case 0x04000184: return ARM7IORead16(addr);
case 0x040001A0: return NDSCart::SPICnt | (NDSCart::ReadSPIData() << 16);
case 0x040001A4: return NDSCart::ROMCnt;
@ -3935,6 +3943,7 @@ void ARM7IOWrite32(u32 addr, u32 val)
case 0x04000138: RTC::Write(val & 0xFFFF, false); return;
case 0x04000180:
case 0x04000184:
ARM7IOWrite16(addr, val);
return;
case 0x04000188:
@ -3979,6 +3988,11 @@ void ARM7IOWrite32(u32 addr, u32 val)
case 0x040001B0: *(u32*)&ROMSeed0[8] = val; return;
case 0x040001B4: *(u32*)&ROMSeed1[8] = val; return;
case 0x040001C0:
SPI::WriteCnt(val & 0xFFFF);
SPI::WriteData((val >> 16) & 0xFF);
return;
case 0x04000208: IME[1] = val & 0x1; UpdateIRQ(1); return;
case 0x04000210: IE[1] = val; UpdateIRQ(1); return;
case 0x04000214: IF[1] &= ~val; UpdateIRQ(1); return;

View File

@ -212,6 +212,8 @@ void SetLidClosed(bool closed);
void MicInputFrame(s16* data, int samples);
int ImportSRAM(u8* data, u32 length);
void ScheduleEvent(u32 id, bool periodic, s32 delay, void (*func)(u32), u32 param);
void CancelEvent(u32 id);

View File

@ -1034,6 +1034,19 @@ void RelocateSave(const char* path, bool write)
NDSCart_SRAM::RelocateSave(path, write);
}
int ImportSRAM(const u8* data, u32 length)
{
memcpy(NDSCart_SRAM::SRAM, data, std::min(length, NDSCart_SRAM::SRAMLength));
FILE* f = Platform::OpenFile(NDSCart_SRAM::SRAMPath, "wb");
if (f)
{
fwrite(NDSCart_SRAM::SRAM, NDSCart_SRAM::SRAMLength, 1, f);
fclose(f);
}
return length - NDSCart_SRAM::SRAMLength;
}
void ResetCart()
{
// CHECKME: what if there is a transfer in progress?

View File

@ -48,6 +48,8 @@ void DecryptSecureArea(u8* out);
bool LoadROM(const char* path, const char* sram, bool direct);
void RelocateSave(const char* path, bool write);
int ImportSRAM(const u8* data, u32 length);
void ResetCart();
void WriteROMCnt(u32 val);

View File

@ -16,6 +16,9 @@
with melonDS. If not, see http://www.gnu.org/licenses/.
*/
// Required by MinGW to enable localtime_r in time.h
#define _POSIX_THREAD_SAFE_FUNCTIONS
#include <stdio.h>
#include <string.h>
#include <time.h>
@ -125,31 +128,29 @@ void ByteIn(u8 val)
case 0x20:
{
time_t timestamp;
struct tm* timedata;
time(&timestamp);
timedata = localtime(&timestamp);
time_t timestamp = time(NULL);
struct tm timedata;
localtime_r(&timestamp, &timedata);
Output[0] = BCD(timedata->tm_year - 100);
Output[1] = BCD(timedata->tm_mon + 1);
Output[2] = BCD(timedata->tm_mday);
Output[3] = BCD(timedata->tm_wday);
Output[4] = BCD(timedata->tm_hour);
Output[5] = BCD(timedata->tm_min);
Output[6] = BCD(timedata->tm_sec);
Output[0] = BCD(timedata.tm_year - 100);
Output[1] = BCD(timedata.tm_mon + 1);
Output[2] = BCD(timedata.tm_mday);
Output[3] = BCD(timedata.tm_wday);
Output[4] = BCD(timedata.tm_hour);
Output[5] = BCD(timedata.tm_min);
Output[6] = BCD(timedata.tm_sec);
}
break;
case 0x60:
{
time_t timestamp;
struct tm* timedata;
time(&timestamp);
timedata = localtime(&timestamp);
time_t timestamp = time(NULL);
struct tm timedata;
localtime_r(&timestamp, &timedata);
Output[0] = BCD(timedata->tm_hour);
Output[1] = BCD(timedata->tm_min);
Output[2] = BCD(timedata->tm_sec);
Output[0] = BCD(timedata.tm_hour);
Output[1] = BCD(timedata.tm_min);
Output[2] = BCD(timedata.tm_sec);
}
break;

View File

@ -261,6 +261,22 @@ void Savestate::Var64(u64* var)
}
}
void Savestate::Bool32(bool* var)
{
// for compability
if (Saving)
{
u32 val = *var;
Var32(&val);
}
else
{
u32 val;
Var32(&val);
*var = val != 0;
}
}
void Savestate::VarArray(void* data, u32 len)
{
if (Error) return;

View File

@ -46,6 +46,8 @@ public:
void Var32(u32* var);
void Var64(u64* var);
void Bool32(bool* var);
void VarArray(void* data, u32 len);
bool IsAtleastVersion(u32 major, u32 minor)

View File

@ -237,7 +237,7 @@ void DoSavestate(Savestate* file)
file->Var64(&USCounter);
file->Var64(&USCompare);
file->Var32((u32*)&BlockBeaconIRQ14);
file->Bool32(&BlockBeaconIRQ14);
file->Var32(&ComStatus);
file->Var32(&TXCurSlot);

View File

@ -1631,7 +1631,7 @@ void ARM64XEmitter::ASR(ARM64Reg Rd, ARM64Reg Rm, int shift)
int bits = Is64Bit(Rd) ? 64 : 32;
SBFM(Rd, Rm, shift, bits - 1);
}
void ARM64XEmitter::ROR_(ARM64Reg Rd, ARM64Reg Rm, int shift)
void ARM64XEmitter::ROR(ARM64Reg Rd, ARM64Reg Rm, int shift)
{
EXTR(Rd, Rm, Rm, shift);
}

View File

@ -727,7 +727,7 @@ public:
void LSR(ARM64Reg Rd, ARM64Reg Rm, int shift);
void LSL(ARM64Reg Rd, ARM64Reg Rm, int shift);
void ASR(ARM64Reg Rd, ARM64Reg Rm, int shift);
void ROR_(ARM64Reg Rd, ARM64Reg Rm, int shift);
void ROR(ARM64Reg Rd, ARM64Reg Rm, int shift);
// Logical (immediate)
void AND(ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms, bool invert = false);

View File

@ -1214,7 +1214,7 @@ void XEmitter::ROL(int bits, const OpArg& dest, const OpArg& shift)
{
WriteShift(bits, dest, shift, 0);
}
void XEmitter::ROR_(int bits, const OpArg& dest, const OpArg& shift)
void XEmitter::ROR(int bits, const OpArg& dest, const OpArg& shift)
{
WriteShift(bits, dest, shift, 1);
}

View File

@ -489,7 +489,7 @@ public:
// Shift
void ROL(int bits, const OpArg& dest, const OpArg& shift);
void ROR_(int bits, const OpArg& dest, const OpArg& shift);
void ROR(int bits, const OpArg& dest, const OpArg& shift);
void RCL(int bits, const OpArg& dest, const OpArg& shift);
void RCR(int bits, const OpArg& dest, const OpArg& shift);
void SHL(int bits, const OpArg& dest, const OpArg& shift);

View File

@ -100,6 +100,9 @@ bool SaveState(const char* filename);
// undo the latest savestate load
void UndoStateLoad();
// imports savedata from an external file. Returns the difference between the filesize and the SRAM size
int ImportSRAM(const char* filename);
// enable or disable cheats
void EnableCheats(bool enable);

View File

@ -588,6 +588,21 @@ void UndoStateLoad()
}
}
int ImportSRAM(const char* filename)
{
FILE* file = fopen(filename, "rb");
fseek(file, 0, SEEK_END);
u32 size = ftell(file);
u8* importData = new u8[size];
rewind(file);
fread(importData, size, 1, file);
fclose(file);
int diff = NDS::ImportSRAM(importData, size);
delete[] importData;
return diff;
}
void EnableCheats(bool enable)
{
CheatsOn = enable;

View File

@ -98,7 +98,9 @@ int GetEventKeyVal(QKeyEvent* event)
void KeyPress(QKeyEvent* event)
{
int keyHK = GetEventKeyVal(event);
int keyKP = keyHK & ~event->modifiers();
int keyKP = keyHK;
if (event->modifiers() != Qt::KeypadModifier)
keyKP &= ~event->modifiers();
for (int i = 0; i < 12; i++)
if (keyKP == Config::KeyMapping[i])
@ -112,7 +114,9 @@ void KeyPress(QKeyEvent* event)
void KeyRelease(QKeyEvent* event)
{
int keyHK = GetEventKeyVal(event);
int keyKP = keyHK & ~event->modifiers();
int keyKP = keyHK;
if (event->modifiers() != Qt::KeypadModifier)
keyKP &= ~event->modifiers();
for (int i = 0; i < 12; i++)
if (keyKP == Config::KeyMapping[i])

View File

@ -54,6 +54,7 @@ const int hk_general[] =
HK_Reset,
HK_FastForward,
HK_FastForwardToggle,
HK_FullscreenToggle,
HK_Lid,
HK_Mic,
};
@ -64,6 +65,7 @@ const char* hk_general_labels[] =
"Reset",
"Fast forward",
"Toggle FPS limit",
"Toggle Fullscreen",
"Close/open lid",
"Microphone",
};
@ -86,7 +88,7 @@ InputConfigDialog::InputConfigDialog(QWidget* parent) : QDialog(parent), ui(new
addonsJoyMap[i] = Config::HKJoyMapping[hk_addons[i]];
}
for (int i = 0; i < 6; i++)
for (int i = 0; i < 7; i++)
{
hkGeneralKeyMap[i] = Config::HKKeyMapping[hk_general[i]];
hkGeneralJoyMap[i] = Config::HKJoyMapping[hk_general[i]];
@ -94,7 +96,7 @@ InputConfigDialog::InputConfigDialog(QWidget* parent) : QDialog(parent), ui(new
populatePage(ui->tabInput, 12, dskeylabels, keypadKeyMap, keypadJoyMap);
populatePage(ui->tabAddons, 2, hk_addons_labels, addonsKeyMap, addonsJoyMap);
populatePage(ui->tabHotkeysGeneral, 6, hk_general_labels, hkGeneralKeyMap, hkGeneralJoyMap);
populatePage(ui->tabHotkeysGeneral, 7, hk_general_labels, hkGeneralKeyMap, hkGeneralJoyMap);
int njoy = SDL_NumJoysticks();
if (njoy > 0)
@ -177,7 +179,7 @@ void InputConfigDialog::on_InputConfigDialog_accepted()
Config::HKJoyMapping[hk_addons[i]] = addonsJoyMap[i];
}
for (int i = 0; i < 6; i++)
for (int i = 0; i < 7; i++)
{
Config::HKKeyMapping[hk_general[i]] = hkGeneralKeyMap[i];
Config::HKJoyMapping[hk_general[i]] = hkGeneralJoyMap[i];
@ -226,7 +228,7 @@ void KeyMapButton::keyPressEvent(QKeyEvent* event)
{
if (!isChecked()) return QPushButton::keyPressEvent(event);
printf("KEY PRESSED = %08X %08X | %08X %08X %08X\n", event->key(), event->modifiers(), event->nativeVirtualKey(), event->nativeModifiers(), event->nativeScanCode());
printf("KEY PRESSED = %08X %08X | %08X %08X %08X\n", event->key(), (int)event->modifiers(), event->nativeVirtualKey(), event->nativeModifiers(), event->nativeScanCode());
int key = event->key();
int mod = event->modifiers();

View File

@ -64,7 +64,7 @@ private:
int keypadKeyMap[12], keypadJoyMap[12];
int addonsKeyMap[2], addonsJoyMap[2];
int hkGeneralKeyMap[6], hkGeneralJoyMap[6];
int hkGeneralKeyMap[7], hkGeneralJoyMap[7];
};

View File

@ -110,6 +110,7 @@ ConfigEntry PlatformConfigFile[] =
{"HKKey_Reset", 0, &HKKeyMapping[HK_Reset], -1, NULL, 0},
{"HKKey_FastForward", 0, &HKKeyMapping[HK_FastForward], -1, NULL, 0},
{"HKKey_FastForwardToggle", 0, &HKKeyMapping[HK_FastForwardToggle], -1, NULL, 0},
{"HKKey_FullscreenToggle", 0, &HKKeyMapping[HK_FullscreenToggle], -1, NULL, 0},
{"HKKey_SolarSensorDecrease", 0, &HKKeyMapping[HK_SolarSensorDecrease], -1, NULL, 0},
{"HKKey_SolarSensorIncrease", 0, &HKKeyMapping[HK_SolarSensorIncrease], -1, NULL, 0},
@ -119,6 +120,7 @@ ConfigEntry PlatformConfigFile[] =
{"HKJoy_Reset", 0, &HKJoyMapping[HK_Reset], -1, NULL, 0},
{"HKJoy_FastForward", 0, &HKJoyMapping[HK_FastForward], -1, NULL, 0},
{"HKJoy_FastForwardToggle", 0, &HKJoyMapping[HK_FastForwardToggle], -1, NULL, 0},
{"HKJoy_FastForwardToggle", 0, &HKJoyMapping[HK_FullscreenToggle], -1, NULL, 0},
{"HKJoy_SolarSensorDecrease", 0, &HKJoyMapping[HK_SolarSensorDecrease], -1, NULL, 0},
{"HKJoy_SolarSensorIncrease", 0, &HKJoyMapping[HK_SolarSensorIncrease], -1, NULL, 0},

View File

@ -29,6 +29,7 @@ enum
HK_Reset,
HK_FastForward,
HK_FastForwardToggle,
HK_FullscreenToggle,
HK_SolarSensorDecrease,
HK_SolarSensorIncrease,
HK_MAX

View File

@ -50,6 +50,10 @@ VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui(
connect(grp3DRenderer, SIGNAL(buttonClicked(int)), this, SLOT(onChange3DRenderer(int)));
grp3DRenderer->button(Config::_3DRenderer)->setChecked(true);
#ifndef OGLRENDERER_ENABLED
ui->rb3DOpenGL->setEnabled(false);
#endif
ui->cbGLDisplay->setChecked(Config::ScreenUseGL != 0);
ui->cbVSync->setChecked(Config::ScreenVSync != 0);

View File

@ -49,7 +49,9 @@
#include "NDS.h"
#include "GBACart.h"
#ifdef OGLRENDERER_ENABLED
#include "OpenGLSupport.h"
#endif
#include "GPU.h"
#include "SPU.h"
#include "Wifi.h"
@ -113,7 +115,6 @@ void audioCallback(void* data, Uint8* stream, int len)
if (num_in < len_in-margin)
{
int last = num_in-1;
if (last < 0) last = 0;
for (int i = num_in; i < len_in-margin; i++)
((u32*)buf_in)[i] = ((u32*)buf_in)[last];
@ -266,6 +267,7 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent)
connect(this, SIGNAL(windowEmuPause()), mainWindow->actPause, SLOT(trigger()));
connect(this, SIGNAL(windowEmuReset()), mainWindow->actReset, SLOT(trigger()));
connect(this, SIGNAL(screenLayoutChange()), mainWindow->panel, SLOT(onScreenLayoutChanged()));
connect(this, SIGNAL(windowFullscreenToggle()), mainWindow, SLOT(onFullscreenToggled()));
if (mainWindow->hasOGL) initOpenGL();
}
@ -335,13 +337,17 @@ void EmuThread::run()
videoSettings.Soft_Threaded = Config::Threaded3D != 0;
videoSettings.GL_ScaleFactor = Config::GL_ScaleFactor;
#ifdef OGLRENDERER_ENABLED
if (hasOGL)
{
oglContext->makeCurrent(oglSurface);
videoRenderer = OpenGL::Init() ? Config::_3DRenderer : 0;
}
else
#endif
{
videoRenderer = 0;
}
GPU::InitRenderer(videoRenderer);
GPU::SetRenderSettings(videoRenderer, videoSettings);
@ -365,6 +371,8 @@ void EmuThread::run()
if (Input::HotkeyPressed(HK_Pause)) emit windowEmuPause();
if (Input::HotkeyPressed(HK_Reset)) emit windowEmuReset();
if (Input::HotkeyPressed(HK_FullscreenToggle)) emit windowFullscreenToggle();
if (GBACart::CartInserted && GBACart::HasSolarSensor)
{
if (Input::HotkeyPressed(HK_SolarSensorDecrease))
@ -393,14 +401,18 @@ void EmuThread::run()
if (hasOGL != mainWindow->hasOGL)
{
hasOGL = mainWindow->hasOGL;
#ifdef OGLRENDERER_ENABLED
if (hasOGL)
{
oglContext->makeCurrent(oglSurface);
videoRenderer = OpenGL::Init() ? Config::_3DRenderer : 0;
}
else
#endif
{
videoRenderer = 0;
}
}
else
videoRenderer = hasOGL ? Config::_3DRenderer : 0;
@ -920,12 +932,14 @@ void ScreenPanelGL::paintGL()
int frontbuf = GPU::FrontBuffer;
glActiveTexture(GL_TEXTURE0);
#ifdef OGLRENDERER_ENABLED
if (GPU::Renderer != 0)
{
// hardware-accelerated render
GPU::GLCompositor::BindOutputTexture();
}
else
#endif
{
// regular render
glBindTexture(GL_TEXTURE_2D, screenTexture);
@ -1049,6 +1063,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actUndoStateLoad->setShortcut(QKeySequence(Qt::Key_F12));
connect(actUndoStateLoad, &QAction::triggered, this, &MainWindow::onUndoStateLoad);
actImportSavefile = menu->addAction("Import savefile");
connect(actImportSavefile, &QAction::triggered, this, &MainWindow::onImportSavefile);
menu->addSeparator();
actQuit = menu->addAction("Quit");
@ -1217,6 +1234,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actLoadState[i]->setEnabled(false);
}
actUndoStateLoad->setEnabled(false);
actImportSavefile->setEnabled(false);
actPause->setEnabled(false);
actReset->setEnabled(false);
@ -1615,6 +1633,41 @@ void MainWindow::onUndoStateLoad()
OSD::AddMessage(0, "State load undone");
}
void MainWindow::onImportSavefile()
{
if (!RunningSomething) return;
emuThread->emuPause();
QString path = QFileDialog::getOpenFileName(this,
"Select savefile",
Config::LastROMFolder,
"Savefiles (*.sav *.bin *.dsv);;Any file (*.*)");
if (!path.isEmpty())
{
if (QMessageBox::warning(this,
"Emulation will be reset and data overwritten",
"The emulation will be reset and the current savefile overwritten.",
QMessageBox::Ok, QMessageBox::Cancel) == QMessageBox::Ok)
{
int res = Frontend::Reset();
if (res != Frontend::Load_OK)
{
QMessageBox::critical(this, "melonDS", "Reset failed\n" + loadErrorStr(res));
}
else
{
int diff = Frontend::ImportSRAM(path.toStdString().c_str());
if (diff > 0)
OSD::AddMessage(0, "Trimmed savefile");
else if (diff < 0)
OSD::AddMessage(0, "Savefile shorter than SRAM");
}
}
}
emuThread->emuUnpause();
}
void MainWindow::onQuit()
{
QApplication::quit();
@ -1878,6 +1931,20 @@ void MainWindow::onTitleUpdate(QString title)
setWindowTitle(title);
}
void MainWindow::onFullscreenToggled()
{
if (!mainWindow->isFullScreen())
{
mainWindow->showFullScreen();
mainWindow->menuBar()->hide();
}
else
{
mainWindow->showNormal();
mainWindow->menuBar()->show();
}
}
void MainWindow::onEmuStart()
{
// TODO: make savestates work in DSi mode!!
@ -1906,6 +1973,7 @@ void MainWindow::onEmuStart()
actPause->setChecked(false);
actReset->setEnabled(true);
actStop->setEnabled(true);
actImportSavefile->setEnabled(true);
actSetupCheats->setEnabled(true);
}
@ -1920,6 +1988,7 @@ void MainWindow::onEmuStop()
actLoadState[i]->setEnabled(false);
}
actUndoStateLoad->setEnabled(false);
actImportSavefile->setEnabled(false);
actPause->setEnabled(false);
actReset->setEnabled(false);

View File

@ -70,6 +70,8 @@ signals:
void screenLayoutChange();
void windowFullscreenToggle();
private:
volatile int EmuStatus;
int PrevEmuStatus;
@ -193,6 +195,7 @@ private slots:
void onSaveState();
void onLoadState();
void onUndoStateLoad();
void onImportSavefile();
void onQuit();
void onPause(bool checked);
@ -230,6 +233,8 @@ private slots:
void onUpdateVideoSettings(bool glchange);
void onFullscreenToggled();
private:
void createScreenPanel();
@ -243,6 +248,7 @@ public:
QAction* actSaveState[9];
QAction* actLoadState[9];
QAction* actUndoStateLoad;
QAction* actImportSavefile;
QAction* actQuit;
QAction* actPause;

View File

@ -19,13 +19,15 @@
#ifndef TYPES_H
#define TYPES_H
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long int u64;
typedef signed char s8;
typedef signed short s16;
typedef signed int s32;
typedef signed long long int s64;
#include <stdint.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
#endif // TYPES_H