Merge branch 'master' into feature/zip-support
This commit is contained in:
commit
8d70d0926c
|
@ -20,8 +20,10 @@ jobs:
|
||||||
- name: Upgrade system
|
- name: Upgrade system
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: ${{runner.workspace}}
|
working-directory: ${{runner.workspace}}
|
||||||
run: |
|
run: | #Fix grub installation error - https://github.com/actions/virtual-environments/issues/1605
|
||||||
sudo apt update
|
sudo apt update
|
||||||
|
sudo apt-get install grub-efi
|
||||||
|
sudo update-grub
|
||||||
sudo apt full-upgrade
|
sudo apt full-upgrade
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
|
@ -32,7 +34,8 @@ jobs:
|
||||||
sudo rm /etc/apt/sources.list
|
sudo rm /etc/apt/sources.list
|
||||||
sudo mv /etc/apt/sources.list{.new,}
|
sudo mv /etc/apt/sources.list{.new,}
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install {gcc-10,g++-10,pkg-config}-aarch64-linux-gnu libsdl2-dev:arm64 qtbase5-dev:arm64 libslirp-dev:arm64 libzip-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 libarchive-dev:arm64
|
||||||
- name: Create build environment
|
- name: Create build environment
|
||||||
run: mkdir ${{runner.workspace}}/build
|
run: mkdir ${{runner.workspace}}/build
|
||||||
- name: Configure
|
- name: Configure
|
||||||
|
|
|
@ -24,8 +24,8 @@ jobs:
|
||||||
working-directory: ${{runner.workspace}}
|
working-directory: ${{runner.workspace}}
|
||||||
run: | # Fetch a new version of CMake, because the default is too old.
|
run: | # Fetch a new version of CMake, because the default is too old.
|
||||||
sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list \
|
sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list \
|
||||||
&& sudo apt-get update \
|
&& sudo apt update \
|
||||||
&& sudo apt-get install cmake libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev qt5-default libslirp-dev libzip-dev
|
&& sudo apt install cmake libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev qt5-default libslirp0=4.1.0-2ubuntu2.1 libslirp-dev libarchive-dev --allow-downgrades
|
||||||
- name: Create build environment
|
- name: Create build environment
|
||||||
run: mkdir ${{runner.workspace}}/build
|
run: mkdir ${{runner.workspace}}/build
|
||||||
- name: Configure
|
- name: Configure
|
||||||
|
|
|
@ -36,9 +36,8 @@ jobs:
|
||||||
- name: Make
|
- name: Make
|
||||||
run: |
|
run: |
|
||||||
C:\tools\msys64\usr\bin\bash.exe -lc "export PATH=`"/mingw64/bin:`$PATH`" \
|
C:\tools\msys64\usr\bin\bash.exe -lc "export PATH=`"/mingw64/bin:`$PATH`" \
|
||||||
&& cd melonDS/build && make -j$(nproc --all) \
|
&& cd melonDS/build && make -j$(nproc --all)"
|
||||||
&& ../msys-dist.sh"
|
|
||||||
- uses: actions/upload-artifact@v1
|
- uses: actions/upload-artifact@v1
|
||||||
with:
|
with:
|
||||||
name: melonDS
|
name: melonDS
|
||||||
path: C:\tools\msys64\home\runneradmin\melonDS\build\dist
|
path: C:\tools\msys64\home\runneradmin\melonDS\build\melonDS.exe
|
||||||
|
|
|
@ -50,6 +50,12 @@ else()
|
||||||
option(ENABLE_LTO "Enable link-time optimization" OFF)
|
option(ENABLE_LTO "Enable link-time optimization" OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
option(ENABLE_OGLRENDERER "Enable OpenGL renderer" ON)
|
||||||
|
|
||||||
|
if (ENABLE_OGLRENDERER)
|
||||||
|
add_definitions(-DOGLRENDERER_ENABLED)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (CMAKE_BUILD_TYPE STREQUAL Debug)
|
if (CMAKE_BUILD_TYPE STREQUAL Debug)
|
||||||
add_compile_options(-Og)
|
add_compile_options(-Og)
|
||||||
endif()
|
endif()
|
||||||
|
|
29
README.md
29
README.md
|
@ -2,7 +2,7 @@
|
||||||
<h2 align="center"><b>melonDS</b></h2>
|
<h2 align="center"><b>melonDS</b></h2>
|
||||||
<p align="center">
|
<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/" 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.3"><img src="https://img.shields.io/badge/release-0.8.3-%235c913b.svg"></a>
|
<a href="http://melonds.kuribo64.net/downloads.php" alt="Release: 0.9"><img src="https://img.shields.io/badge/release-0.9-%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://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>
|
<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>
|
</p>
|
||||||
|
@ -38,7 +38,7 @@ As for the rest, the interface should be pretty straightforward. If you have a q
|
||||||
* Install dependencies:
|
* Install dependencies:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo apt-get install libgtk-3-dev libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev libslirp-dev libzip-dev
|
sudo apt-get install cmake libgtk-3-dev libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev qtbase5-dev qtdeclarative5-dev libslirp-dev libarchive-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
* Compile:
|
* Compile:
|
||||||
|
@ -55,7 +55,23 @@ make -j$(nproc --all)
|
||||||
1. Install [MSYS2](https://www.msys2.org/)
|
1. Install [MSYS2](https://www.msys2.org/)
|
||||||
2. Open the **MSYS2 MinGW 64-bit** terminal
|
2. Open the **MSYS2 MinGW 64-bit** terminal
|
||||||
3. Update the packages using `pacman -Syu` and reopen the terminal if it asks you to
|
3. Update the packages using `pacman -Syu` and reopen the terminal if it asks you to
|
||||||
4. Install dependencies: `pacman -S git make mingw-w64-x86_64-{cmake,mesa,SDL2,libslirp,libzip,toolchain}`
|
|
||||||
|
#### Dynamic builds (with DLLs)
|
||||||
|
4. Install dependencies: `pacman -S git make mingw-w64-x86_64-{cmake,mesa,SDL2,toolchain,qt5,libslirp,libarchive}`
|
||||||
|
5. Run the following commands
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/Arisotura/melonDS.git
|
||||||
|
cd melonDS
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. -G "MSYS Makefiles"
|
||||||
|
make -j$(nproc --all)
|
||||||
|
../msys-dist.sh
|
||||||
|
```
|
||||||
|
If everything went well, melonDS and the libraries it needs should now be in the `dist` folder.
|
||||||
|
|
||||||
|
#### Static builds (without DLLs, standalone executable)
|
||||||
|
4. Install dependencies: `pacman -S git make mingw-w64-x86_64-{cmake,mesa,SDL2,toolchain,qt5-static,libslirp,libarchive}`
|
||||||
5. Run the following commands
|
5. Run the following commands
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/Arisotura/melonDS.git
|
git clone https://github.com/Arisotura/melonDS.git
|
||||||
|
@ -64,10 +80,9 @@ make -j$(nproc --all)
|
||||||
cd build
|
cd build
|
||||||
cmake .. -G 'MSYS Makefiles' -DBUILD_STATIC=ON -DQT5_STATIC_DIR=/mingw64/qt5-static
|
cmake .. -G 'MSYS Makefiles' -DBUILD_STATIC=ON -DQT5_STATIC_DIR=/mingw64/qt5-static
|
||||||
make -j$(nproc --all)
|
make -j$(nproc --all)
|
||||||
../msys-dist.sh
|
mkdir dist && cp melonDS.exe dist
|
||||||
```
|
```
|
||||||
|
If everything went well, melonDS should now be in the `dist` folder.
|
||||||
If everything went well, melonDS and the libraries it needs should now be in the `dist` folder.
|
|
||||||
|
|
||||||
## TODO LIST
|
## TODO LIST
|
||||||
|
|
||||||
|
@ -99,4 +114,4 @@ If everything went well, melonDS and the libraries it needs should now be in the
|
||||||
melonDS is free software: you can redistribute it and/or modify
|
melonDS is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
8
melon.rc
8
melon.rc
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
//include version information in .exe, modify these values to match your needs
|
//include version information in .exe, modify these values to match your needs
|
||||||
1 VERSIONINFO
|
1 VERSIONINFO
|
||||||
FILEVERSION 0,8,3,0
|
FILEVERSION 0,9,0,0
|
||||||
PRODUCTVERSION 0,8,3,0
|
PRODUCTVERSION 0,9,0,0
|
||||||
FILETYPE VFT_APP
|
FILETYPE VFT_APP
|
||||||
{
|
{
|
||||||
BLOCK "StringFileInfo"
|
BLOCK "StringFileInfo"
|
||||||
|
@ -15,14 +15,14 @@ FILETYPE VFT_APP
|
||||||
BLOCK "040904E4"
|
BLOCK "040904E4"
|
||||||
{
|
{
|
||||||
VALUE "CompanyName", "Melon Factory of Kuribo64"
|
VALUE "CompanyName", "Melon Factory of Kuribo64"
|
||||||
VALUE "FileVersion", "0.8.3"
|
VALUE "FileVersion", "0.9"
|
||||||
VALUE "FileDescription", "DS emulator, sorta. also 1st quality melon."
|
VALUE "FileDescription", "DS emulator, sorta. also 1st quality melon."
|
||||||
VALUE "InternalName", "SDnolem"
|
VALUE "InternalName", "SDnolem"
|
||||||
VALUE "LegalCopyright", "2016-2020 Arisotura & co."
|
VALUE "LegalCopyright", "2016-2020 Arisotura & co."
|
||||||
VALUE "LegalTrademarks", ""
|
VALUE "LegalTrademarks", ""
|
||||||
VALUE "OriginalFilename", "zafkflzdasd.exe"
|
VALUE "OriginalFilename", "zafkflzdasd.exe"
|
||||||
VALUE "ProductName", "melonDS"
|
VALUE "ProductName", "melonDS"
|
||||||
VALUE "ProductVersion", "0.8.3"
|
VALUE "ProductVersion", "0.9"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -11,4 +11,5 @@ for lib in $(ldd melonDS.exe | grep mingw | sed "s/.*=> //" | sed "s/(.*)//"); d
|
||||||
cp "${lib}" dist
|
cp "${lib}" dist
|
||||||
done
|
done
|
||||||
|
|
||||||
cp melonDS.exe dist
|
cp melonDS.exe dist
|
||||||
|
windeployqt dist
|
||||||
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016-2020 Arisotura
|
||||||
|
|
||||||
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
melonDS is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "ARCodeFile.h"
|
||||||
|
#include "Platform.h"
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: import codes from other sources (usrcheat.dat, ...)
|
||||||
|
// TODO: more user-friendly error reporting
|
||||||
|
|
||||||
|
|
||||||
|
ARCodeFile::ARCodeFile(const char* filename)
|
||||||
|
{
|
||||||
|
memset(Filename, 0, sizeof(Filename));
|
||||||
|
strncpy(Filename, filename, 1023);
|
||||||
|
|
||||||
|
Error = false;
|
||||||
|
|
||||||
|
Categories.clear();
|
||||||
|
|
||||||
|
if (!Load())
|
||||||
|
Error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ARCodeFile::~ARCodeFile()
|
||||||
|
{
|
||||||
|
Categories.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ARCodeFile::Load()
|
||||||
|
{
|
||||||
|
FILE* f = Platform::OpenFile(Filename, "r");
|
||||||
|
if (!f) return true;
|
||||||
|
|
||||||
|
Categories.clear();
|
||||||
|
|
||||||
|
bool isincat = false;
|
||||||
|
ARCodeCat curcat;
|
||||||
|
|
||||||
|
bool isincode = false;
|
||||||
|
ARCode curcode;
|
||||||
|
|
||||||
|
char linebuf[1024];
|
||||||
|
while (!feof(f))
|
||||||
|
{
|
||||||
|
fgets(linebuf, 1024, f);
|
||||||
|
linebuf[1023] = '\0';
|
||||||
|
|
||||||
|
char* start = linebuf;
|
||||||
|
while (start[0]==' ' || start[0]=='\t')
|
||||||
|
start++;
|
||||||
|
|
||||||
|
if (start[0]=='#' || start[0]=='\r' || start[0]=='\n' || start[0]=='\0')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!strncasecmp(start, "CAT", 3))
|
||||||
|
{
|
||||||
|
char catname[128];
|
||||||
|
int ret = sscanf(start, "CAT %127[^\r\n]", catname);
|
||||||
|
catname[127] = '\0';
|
||||||
|
|
||||||
|
if (ret < 1)
|
||||||
|
{
|
||||||
|
printf("AR: malformed CAT line: %s\n", start);
|
||||||
|
fclose(f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isincode) curcat.Codes.push_back(curcode);
|
||||||
|
isincode = false;
|
||||||
|
|
||||||
|
if (isincat) Categories.push_back(curcat);
|
||||||
|
isincat = true;
|
||||||
|
|
||||||
|
memcpy(curcat.Name, catname, 128);
|
||||||
|
curcat.Codes.clear();
|
||||||
|
}
|
||||||
|
else if (!strncasecmp(start, "CODE", 4))
|
||||||
|
{
|
||||||
|
int enable;
|
||||||
|
char codename[128];
|
||||||
|
int ret = sscanf(start, "CODE %d %127[^\r\n]", &enable, codename);
|
||||||
|
codename[127] = '\0';
|
||||||
|
|
||||||
|
if (ret < 2)
|
||||||
|
{
|
||||||
|
printf("AR: malformed CODE line: %s\n", start);
|
||||||
|
fclose(f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isincat)
|
||||||
|
{
|
||||||
|
printf("AR: encountered CODE line with no category started\n");
|
||||||
|
fclose(f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isincode) curcat.Codes.push_back(curcode);
|
||||||
|
isincode = true;
|
||||||
|
|
||||||
|
memcpy(curcode.Name, codename, 128);
|
||||||
|
curcode.Enabled = enable!=0;
|
||||||
|
curcode.CodeLen = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u32 c0, c1;
|
||||||
|
int ret = sscanf(start, "%08X %08X", &c0, &c1);
|
||||||
|
|
||||||
|
if (ret < 2)
|
||||||
|
{
|
||||||
|
printf("AR: malformed data line: %s\n", start);
|
||||||
|
fclose(f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isincode)
|
||||||
|
{
|
||||||
|
printf("AR: encountered data line with no code started\n");
|
||||||
|
fclose(f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curcode.CodeLen >= 2*64)
|
||||||
|
{
|
||||||
|
printf("AR: code too long!\n");
|
||||||
|
fclose(f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 idx = curcode.CodeLen;
|
||||||
|
curcode.Code[idx+0] = c0;
|
||||||
|
curcode.Code[idx+1] = c1;
|
||||||
|
curcode.CodeLen += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isincode) curcat.Codes.push_back(curcode);
|
||||||
|
if (isincat) Categories.push_back(curcat);
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ARCodeFile::Save()
|
||||||
|
{
|
||||||
|
FILE* f = Platform::OpenFile(Filename, "w");
|
||||||
|
if (!f) return false;
|
||||||
|
|
||||||
|
for (ARCodeCatList::iterator it = Categories.begin(); it != Categories.end(); it++)
|
||||||
|
{
|
||||||
|
ARCodeCat& cat = *it;
|
||||||
|
|
||||||
|
if (it != Categories.begin()) fprintf(f, "\n");
|
||||||
|
fprintf(f, "CAT %s\n\n", cat.Name);
|
||||||
|
|
||||||
|
for (ARCodeList::iterator jt = cat.Codes.begin(); jt != cat.Codes.end(); jt++)
|
||||||
|
{
|
||||||
|
ARCode& code = *jt;
|
||||||
|
fprintf(f, "CODE %d %s\n", code.Enabled, code.Name);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < code.CodeLen; i+=2)
|
||||||
|
{
|
||||||
|
fprintf(f, "%08X %08X\n", code.Code[i], code.Code[i+1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(f, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -16,18 +16,49 @@
|
||||||
with melonDS. If not, see http://www.gnu.org/licenses/.
|
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ARCODELIST_H
|
#ifndef ARCODEFILE_H
|
||||||
#define ARCODELIST_H
|
#define ARCODEFILE_H
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define ARCL_MAJOR 1
|
typedef struct
|
||||||
#define ARCL_MINOR 1
|
{
|
||||||
|
char Name[128];
|
||||||
|
bool Enabled;
|
||||||
|
u32 CodeLen;
|
||||||
|
u32 Code[2*64];
|
||||||
|
|
||||||
class ARCodeList
|
} ARCode;
|
||||||
|
|
||||||
|
typedef std::list<ARCode> ARCodeList;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char Name[128];
|
||||||
|
ARCodeList Codes;
|
||||||
|
|
||||||
|
} ARCodeCat;
|
||||||
|
|
||||||
|
typedef std::list<ARCodeCat> ARCodeCatList;
|
||||||
|
|
||||||
|
|
||||||
|
class ARCodeFile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//
|
ARCodeFile(const char* filename);
|
||||||
|
~ARCodeFile();
|
||||||
|
|
||||||
|
bool Error;
|
||||||
|
|
||||||
|
bool Load();
|
||||||
|
bool Save();
|
||||||
|
|
||||||
|
ARCodeCatList Categories;
|
||||||
|
|
||||||
|
private:
|
||||||
|
char Filename[1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ARCODELIST_H
|
#endif // ARCODEFILE_H
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2016-2020 Arisotura
|
|
||||||
|
|
||||||
This file is part of melonDS.
|
|
||||||
|
|
||||||
melonDS is free software: you can redistribute it and/or modify it under
|
|
||||||
the terms of the GNU General Public License as published by the Free
|
|
||||||
Software Foundation, either version 3 of the License, or (at your option)
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with melonDS. If not, see http://www.gnu.org/licenses/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "ARCodeList.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
Action Replay code list format
|
|
||||||
|
|
||||||
header:
|
|
||||||
00 - magic MLAR
|
|
||||||
04 - version major
|
|
||||||
06 - version minor
|
|
||||||
08 - length
|
|
||||||
0C - number of codes
|
|
||||||
|
|
||||||
code header:
|
|
||||||
00 - magic MLCD
|
|
||||||
04 - name length
|
|
||||||
08 - code length
|
|
||||||
0C - enable flag
|
|
||||||
10 - code data (UTF8 name then actual code)
|
|
||||||
*/
|
|
208
src/AREngine.cpp
208
src/AREngine.cpp
|
@ -19,125 +19,63 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "NDS.h"
|
#include "NDS.h"
|
||||||
|
#include "DSi.h"
|
||||||
#include "AREngine.h"
|
#include "AREngine.h"
|
||||||
|
|
||||||
|
|
||||||
namespace AREngine
|
namespace AREngine
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef struct
|
// AR code file - frontend is responsible for managing this
|
||||||
{
|
ARCodeFile* CodeFile;
|
||||||
u32 Code[2 * 64]; // TODO: more sensible size for this? allocate on demand?
|
|
||||||
bool Enabled;
|
|
||||||
|
|
||||||
} CheatEntry;
|
u8 (*BusRead8)(u32 addr);
|
||||||
|
u16 (*BusRead16)(u32 addr);
|
||||||
// TODO: more sensible size for this? allocate on demand?
|
u32 (*BusRead32)(u32 addr);
|
||||||
CheatEntry CheatCodes[64];
|
void (*BusWrite8)(u32 addr, u8 val);
|
||||||
u32 NumCheatCodes;
|
void (*BusWrite16)(u32 addr, u16 val);
|
||||||
|
void (*BusWrite32)(u32 addr, u32 val);
|
||||||
|
|
||||||
void ParseTextCode(char* text, int tlen, u32* code, int clen) // or whatever this should be named?
|
|
||||||
{
|
|
||||||
u32 cur_word = 0;
|
|
||||||
u32 ndigits = 0;
|
|
||||||
u32 nin = 0;
|
|
||||||
u32 nout = 0;
|
|
||||||
|
|
||||||
char c;
|
|
||||||
while ((c = *text++) != '\0')
|
|
||||||
{
|
|
||||||
u32 val;
|
|
||||||
if (c >= '0' && c <= '9')
|
|
||||||
val = c - '0';
|
|
||||||
else if (c >= 'a' && c <= 'f')
|
|
||||||
val = c - 'a' + 0xA;
|
|
||||||
else if (c >= 'A' && c <= 'F')
|
|
||||||
val = c - 'A' + 0xA;
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
|
|
||||||
cur_word <<= 4;
|
|
||||||
cur_word |= val;
|
|
||||||
|
|
||||||
ndigits++;
|
|
||||||
if (ndigits >= 8)
|
|
||||||
{
|
|
||||||
if (nout >= clen)
|
|
||||||
{
|
|
||||||
printf("AR: code too long!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
*code++ = cur_word;
|
|
||||||
nout++;
|
|
||||||
|
|
||||||
ndigits = 0;
|
|
||||||
cur_word = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
nin++;
|
|
||||||
if (nin >= tlen) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nout & 1)
|
|
||||||
{
|
|
||||||
printf("AR: code was missing one word\n");
|
|
||||||
if (nout >= clen)
|
|
||||||
{
|
|
||||||
printf("AR: code too long!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*code++ = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Init()
|
bool Init()
|
||||||
{
|
{
|
||||||
|
CodeFile = nullptr;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeInit()
|
void DeInit()
|
||||||
{
|
{
|
||||||
//
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset()
|
void Reset()
|
||||||
{
|
{
|
||||||
memset(CheatCodes, 0, sizeof(CheatCodes));
|
CodeFile = nullptr;
|
||||||
NumCheatCodes = 0;
|
|
||||||
|
|
||||||
// TODO: acquire codes from a sensible source!
|
if (NDS::ConsoleType == 1)
|
||||||
CheatEntry* entry = &CheatCodes[0];
|
|
||||||
u32* ptr = &entry->Code[0];
|
|
||||||
|
|
||||||
/*char* test = R"(9209D09A 00000000
|
|
||||||
6209B468 00000000
|
|
||||||
B209B468 00000000
|
|
||||||
10000672 000003FF
|
|
||||||
D2000000 00000000
|
|
||||||
9209D09A 00000000
|
|
||||||
94000130 FCBF0000
|
|
||||||
6209B468 00000000
|
|
||||||
B209B468 00000000
|
|
||||||
200006B3 00000001
|
|
||||||
200006B4 00000001
|
|
||||||
D2000000 00000000
|
|
||||||
9209D09A 00000000
|
|
||||||
94000130 FC7F0000
|
|
||||||
6209B468 00000000
|
|
||||||
B209B468 00000000
|
|
||||||
10000672 00000000
|
|
||||||
D2000000 00000000)";
|
|
||||||
ParseTextCode(test, entry->Code, 2*64);
|
|
||||||
printf("PARSED CODE:\n");
|
|
||||||
for (int i = 0; i < 2*64; i+=2)
|
|
||||||
{
|
{
|
||||||
printf("%08X %08X\n", entry->Code[i], entry->Code[i+1]);
|
BusRead8 = DSi::ARM7Read8;
|
||||||
|
BusRead16 = DSi::ARM7Read16;
|
||||||
|
BusRead32 = DSi::ARM7Read32;
|
||||||
|
BusWrite8 = DSi::ARM7Write8;
|
||||||
|
BusWrite16 = DSi::ARM7Write16;
|
||||||
|
BusWrite32 = DSi::ARM7Write32;
|
||||||
}
|
}
|
||||||
entry->Enabled = true;
|
else
|
||||||
NumCheatCodes++;*/
|
{
|
||||||
|
BusRead8 = NDS::ARM7Read8;
|
||||||
|
BusRead16 = NDS::ARM7Read16;
|
||||||
|
BusRead32 = NDS::ARM7Read32;
|
||||||
|
BusWrite8 = NDS::ARM7Write8;
|
||||||
|
BusWrite16 = NDS::ARM7Write16;
|
||||||
|
BusWrite32 = NDS::ARM7Write32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SetCodeFile(ARCodeFile* file)
|
||||||
|
{
|
||||||
|
CodeFile = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -147,9 +85,9 @@ D2000000 00000000)";
|
||||||
case ((x)+0x08): case ((x)+0x09): case ((x)+0x0A): case ((x)+0x0B): \
|
case ((x)+0x08): case ((x)+0x09): case ((x)+0x0A): case ((x)+0x0B): \
|
||||||
case ((x)+0x0C): case ((x)+0x0D): case ((x)+0x0E): case ((x)+0x0F)
|
case ((x)+0x0C): case ((x)+0x0D): case ((x)+0x0E): case ((x)+0x0F)
|
||||||
|
|
||||||
void RunCheat(CheatEntry* entry)
|
void RunCheat(ARCode& arcode)
|
||||||
{
|
{
|
||||||
u32* code = &entry->Code[0];
|
u32* code = &arcode.Code[0];
|
||||||
|
|
||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
u32 datareg = 0;
|
u32 datareg = 0;
|
||||||
|
@ -166,9 +104,11 @@ void RunCheat(CheatEntry* entry)
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
if (code >= &arcode.Code[arcode.CodeLen])
|
||||||
|
break;
|
||||||
|
|
||||||
u32 a = *code++;
|
u32 a = *code++;
|
||||||
u32 b = *code++;
|
u32 b = *code++;
|
||||||
if ((a|b) == 0) break;
|
|
||||||
|
|
||||||
u8 op = a >> 24;
|
u8 op = a >> 24;
|
||||||
|
|
||||||
|
@ -179,7 +119,7 @@ void RunCheat(CheatEntry* entry)
|
||||||
if ((op & 0xF0) == 0xE0)
|
if ((op & 0xF0) == 0xE0)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < b; i += 8)
|
for (u32 i = 0; i < b; i += 8)
|
||||||
*code += 2;
|
code += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
@ -189,15 +129,15 @@ void RunCheat(CheatEntry* entry)
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case16(0x00): // 32-bit write
|
case16(0x00): // 32-bit write
|
||||||
NDS::ARM7Write32((a & 0x0FFFFFFF) + offset, b);
|
BusWrite32((a & 0x0FFFFFFF) + offset, b);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case16(0x10): // 16-bit write
|
case16(0x10): // 16-bit write
|
||||||
NDS::ARM7Write16((a & 0x0FFFFFFF) + offset, b & 0xFFFF);
|
BusWrite16((a & 0x0FFFFFFF) + offset, b & 0xFFFF);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case16(0x20): // 8-bit write
|
case16(0x20): // 8-bit write
|
||||||
NDS::ARM7Write8((a & 0x0FFFFFFF) + offset, b & 0xFF);
|
BusWrite8((a & 0x0FFFFFFF) + offset, b & 0xFF);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case16(0x30): // IF b > u32[a]
|
case16(0x30): // IF b > u32[a]
|
||||||
|
@ -205,7 +145,7 @@ void RunCheat(CheatEntry* entry)
|
||||||
condstack <<= 1;
|
condstack <<= 1;
|
||||||
condstack |= cond;
|
condstack |= cond;
|
||||||
|
|
||||||
u32 chk = NDS::ARM7Read32(a & 0x0FFFFFFF);
|
u32 chk = BusRead32(a & 0x0FFFFFFF);
|
||||||
|
|
||||||
cond = (b > chk) ? 1:0;
|
cond = (b > chk) ? 1:0;
|
||||||
}
|
}
|
||||||
|
@ -216,7 +156,7 @@ void RunCheat(CheatEntry* entry)
|
||||||
condstack <<= 1;
|
condstack <<= 1;
|
||||||
condstack |= cond;
|
condstack |= cond;
|
||||||
|
|
||||||
u32 chk = NDS::ARM7Read32(a & 0x0FFFFFFF);
|
u32 chk = BusRead32(a & 0x0FFFFFFF);
|
||||||
|
|
||||||
cond = (b < chk) ? 1:0;
|
cond = (b < chk) ? 1:0;
|
||||||
}
|
}
|
||||||
|
@ -227,7 +167,7 @@ void RunCheat(CheatEntry* entry)
|
||||||
condstack <<= 1;
|
condstack <<= 1;
|
||||||
condstack |= cond;
|
condstack |= cond;
|
||||||
|
|
||||||
u32 chk = NDS::ARM7Read32(a & 0x0FFFFFFF);
|
u32 chk = BusRead32(a & 0x0FFFFFFF);
|
||||||
|
|
||||||
cond = (b == chk) ? 1:0;
|
cond = (b == chk) ? 1:0;
|
||||||
}
|
}
|
||||||
|
@ -238,7 +178,7 @@ void RunCheat(CheatEntry* entry)
|
||||||
condstack <<= 1;
|
condstack <<= 1;
|
||||||
condstack |= cond;
|
condstack |= cond;
|
||||||
|
|
||||||
u32 chk = NDS::ARM7Read32(a & 0x0FFFFFFF);
|
u32 chk = BusRead32(a & 0x0FFFFFFF);
|
||||||
|
|
||||||
cond = (b != chk) ? 1:0;
|
cond = (b != chk) ? 1:0;
|
||||||
}
|
}
|
||||||
|
@ -249,7 +189,7 @@ void RunCheat(CheatEntry* entry)
|
||||||
condstack <<= 1;
|
condstack <<= 1;
|
||||||
condstack |= cond;
|
condstack |= cond;
|
||||||
|
|
||||||
u16 val = NDS::ARM7Read16(a & 0x0FFFFFFF);
|
u16 val = BusRead16(a & 0x0FFFFFFF);
|
||||||
u16 chk = ~(b >> 16);
|
u16 chk = ~(b >> 16);
|
||||||
chk &= val;
|
chk &= val;
|
||||||
|
|
||||||
|
@ -262,7 +202,7 @@ void RunCheat(CheatEntry* entry)
|
||||||
condstack <<= 1;
|
condstack <<= 1;
|
||||||
condstack |= cond;
|
condstack |= cond;
|
||||||
|
|
||||||
u16 val = NDS::ARM7Read16(a & 0x0FFFFFFF);
|
u16 val = BusRead16(a & 0x0FFFFFFF);
|
||||||
u16 chk = ~(b >> 16);
|
u16 chk = ~(b >> 16);
|
||||||
chk &= val;
|
chk &= val;
|
||||||
|
|
||||||
|
@ -275,7 +215,7 @@ void RunCheat(CheatEntry* entry)
|
||||||
condstack <<= 1;
|
condstack <<= 1;
|
||||||
condstack |= cond;
|
condstack |= cond;
|
||||||
|
|
||||||
u16 val = NDS::ARM7Read16(a & 0x0FFFFFFF);
|
u16 val = BusRead16(a & 0x0FFFFFFF);
|
||||||
u16 chk = ~(b >> 16);
|
u16 chk = ~(b >> 16);
|
||||||
chk &= val;
|
chk &= val;
|
||||||
|
|
||||||
|
@ -288,7 +228,7 @@ void RunCheat(CheatEntry* entry)
|
||||||
condstack <<= 1;
|
condstack <<= 1;
|
||||||
condstack |= cond;
|
condstack |= cond;
|
||||||
|
|
||||||
u16 val = NDS::ARM7Read16(a & 0x0FFFFFFF);
|
u16 val = BusRead16(a & 0x0FFFFFFF);
|
||||||
u16 chk = ~(b >> 16);
|
u16 chk = ~(b >> 16);
|
||||||
chk &= val;
|
chk &= val;
|
||||||
|
|
||||||
|
@ -297,7 +237,7 @@ void RunCheat(CheatEntry* entry)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case16(0xB0): // offset = u32[a + offset]
|
case16(0xB0): // offset = u32[a + offset]
|
||||||
offset = NDS::ARM7Read32((a & 0x0FFFFFFF) + offset);
|
offset = BusRead32((a & 0x0FFFFFFF) + offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xC0: // FOR 0..b
|
case 0xC0: // FOR 0..b
|
||||||
|
@ -334,7 +274,7 @@ void RunCheat(CheatEntry* entry)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xC6: // u32[b] = offset
|
case 0xC6: // u32[b] = offset
|
||||||
NDS::ARM7Write32(b, offset);
|
BusWrite32(b, offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xD0: // ENDIF
|
case 0xD0: // ENDIF
|
||||||
|
@ -383,30 +323,30 @@ void RunCheat(CheatEntry* entry)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xD6: // u32[b+offset] = datareg / offset += 4
|
case 0xD6: // u32[b+offset] = datareg / offset += 4
|
||||||
NDS::ARM7Write32(b + offset, datareg);
|
BusWrite32(b + offset, datareg);
|
||||||
offset += 4;
|
offset += 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xD7: // u16[b+offset] = datareg / offset += 2
|
case 0xD7: // u16[b+offset] = datareg / offset += 2
|
||||||
NDS::ARM7Write16(b + offset, datareg & 0xFFFF);
|
BusWrite16(b + offset, datareg & 0xFFFF);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xD8: // u8[b+offset] = datareg / offset += 1
|
case 0xD8: // u8[b+offset] = datareg / offset += 1
|
||||||
NDS::ARM7Write8(b + offset, datareg & 0xFF);
|
BusWrite8(b + offset, datareg & 0xFF);
|
||||||
offset += 1;
|
offset += 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xD9: // datareg = u32[b+offset]
|
case 0xD9: // datareg = u32[b+offset]
|
||||||
datareg = NDS::ARM7Read32(b + offset);
|
datareg = BusRead32(b + offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xDA: // datareg = u16[b+offset]
|
case 0xDA: // datareg = u16[b+offset]
|
||||||
datareg = NDS::ARM7Read16(b + offset);
|
datareg = BusRead16(b + offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xDB: // datareg = u8[b+offset]
|
case 0xDB: // datareg = u8[b+offset]
|
||||||
datareg = NDS::ARM7Read8(b + offset);
|
datareg = BusRead8(b + offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xDC: // offset += b
|
case 0xDC: // offset += b
|
||||||
|
@ -421,23 +361,23 @@ void RunCheat(CheatEntry* entry)
|
||||||
u32 bytesleft = b;
|
u32 bytesleft = b;
|
||||||
while (bytesleft >= 8)
|
while (bytesleft >= 8)
|
||||||
{
|
{
|
||||||
NDS::ARM7Write32(dstaddr, *code++); dstaddr += 4;
|
BusWrite32(dstaddr, *code++); dstaddr += 4;
|
||||||
NDS::ARM7Write32(dstaddr, *code++); dstaddr += 4;
|
BusWrite32(dstaddr, *code++); dstaddr += 4;
|
||||||
bytesleft -= 8;
|
bytesleft -= 8;
|
||||||
}
|
}
|
||||||
if (bytesleft > 0)
|
if (bytesleft > 0)
|
||||||
{
|
{
|
||||||
u8* leftover = (u8*)code;
|
u8* leftover = (u8*)code;
|
||||||
*code += 2;
|
code += 2;
|
||||||
if (bytesleft >= 4)
|
if (bytesleft >= 4)
|
||||||
{
|
{
|
||||||
NDS::ARM7Write32(dstaddr, *(u32*)leftover); dstaddr += 4;
|
BusWrite32(dstaddr, *(u32*)leftover); dstaddr += 4;
|
||||||
leftover += 4;
|
leftover += 4;
|
||||||
bytesleft -= 4;
|
bytesleft -= 4;
|
||||||
}
|
}
|
||||||
while (bytesleft > 0)
|
while (bytesleft > 0)
|
||||||
{
|
{
|
||||||
NDS::ARM7Write8(dstaddr, *leftover++); dstaddr++;
|
BusWrite8(dstaddr, *leftover++); dstaddr++;
|
||||||
bytesleft--;
|
bytesleft--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -453,14 +393,14 @@ void RunCheat(CheatEntry* entry)
|
||||||
u32 bytesleft = b;
|
u32 bytesleft = b;
|
||||||
while (bytesleft >= 4)
|
while (bytesleft >= 4)
|
||||||
{
|
{
|
||||||
NDS::ARM7Write32(dstaddr, NDS::ARM7Read32(srcaddr));
|
BusWrite32(dstaddr, BusRead32(srcaddr));
|
||||||
srcaddr += 4;
|
srcaddr += 4;
|
||||||
dstaddr += 4;
|
dstaddr += 4;
|
||||||
bytesleft -= 4;
|
bytesleft -= 4;
|
||||||
}
|
}
|
||||||
while (bytesleft > 0)
|
while (bytesleft > 0)
|
||||||
{
|
{
|
||||||
NDS::ARM7Write8(dstaddr, NDS::ARM7Read8(srcaddr));
|
BusWrite8(dstaddr, BusRead8(srcaddr));
|
||||||
srcaddr++;
|
srcaddr++;
|
||||||
dstaddr++;
|
dstaddr++;
|
||||||
bytesleft--;
|
bytesleft--;
|
||||||
|
@ -477,13 +417,19 @@ void RunCheat(CheatEntry* entry)
|
||||||
|
|
||||||
void RunCheats()
|
void RunCheats()
|
||||||
{
|
{
|
||||||
// TODO: make it disableable in general
|
if (!CodeFile) return;
|
||||||
|
|
||||||
for (u32 i = 0; i < NumCheatCodes; i++)
|
for (ARCodeCatList::iterator i = CodeFile->Categories.begin(); i != CodeFile->Categories.end(); i++)
|
||||||
{
|
{
|
||||||
CheatEntry* entry = &CheatCodes[i];
|
ARCodeCat& cat = *i;
|
||||||
if (entry->Enabled)
|
|
||||||
RunCheat(entry);
|
for (ARCodeList::iterator j = cat.Codes.begin(); j != cat.Codes.end(); j++)
|
||||||
|
{
|
||||||
|
ARCode& code = *j;
|
||||||
|
|
||||||
|
if (code.Enabled)
|
||||||
|
RunCheat(code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#ifndef ARENGINE_H
|
#ifndef ARENGINE_H
|
||||||
#define ARENGINE_H
|
#define ARENGINE_H
|
||||||
|
|
||||||
|
#include "ARCodeFile.h"
|
||||||
|
|
||||||
namespace AREngine
|
namespace AREngine
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -26,6 +28,8 @@ bool Init();
|
||||||
void DeInit();
|
void DeInit();
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
|
void SetCodeFile(ARCodeFile* file);
|
||||||
|
|
||||||
void RunCheats();
|
void RunCheats();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,10 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "NDS.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
|
enum
|
||||||
{
|
{
|
||||||
|
|
156
src/ARMJIT.cpp
156
src/ARMJIT.cpp
|
@ -38,6 +38,14 @@ namespace ARMJIT
|
||||||
|
|
||||||
Compiler* JITCompiler;
|
Compiler* JITCompiler;
|
||||||
|
|
||||||
|
|
||||||
|
std::unordered_map<u32, JitBlock*> JitBlocks9;
|
||||||
|
std::unordered_map<u32, JitBlock*> JitBlocks7;
|
||||||
|
|
||||||
|
std::unordered_map<u32, JitBlock*> RestoreCandidates;
|
||||||
|
|
||||||
|
TinyVector<u32> InvalidLiterals;
|
||||||
|
|
||||||
AddressRange CodeIndexITCM[ITCMPhysicalSize / 512];
|
AddressRange CodeIndexITCM[ITCMPhysicalSize / 512];
|
||||||
AddressRange CodeIndexMainRAM[NDS::MainRAMMaxSize / 512];
|
AddressRange CodeIndexMainRAM[NDS::MainRAMMaxSize / 512];
|
||||||
AddressRange CodeIndexSWRAM[NDS::SharedWRAMSize / 512];
|
AddressRange CodeIndexSWRAM[NDS::SharedWRAMSize / 512];
|
||||||
|
@ -52,9 +60,6 @@ AddressRange CodeIndexNWRAM_A[DSi::NWRAMSize / 512];
|
||||||
AddressRange CodeIndexNWRAM_B[DSi::NWRAMSize / 512];
|
AddressRange CodeIndexNWRAM_B[DSi::NWRAMSize / 512];
|
||||||
AddressRange CodeIndexNWRAM_C[DSi::NWRAMSize / 512];
|
AddressRange CodeIndexNWRAM_C[DSi::NWRAMSize / 512];
|
||||||
|
|
||||||
std::unordered_map<u32, JitBlock*> JitBlocks9;
|
|
||||||
std::unordered_map<u32, JitBlock*> JitBlocks7;
|
|
||||||
|
|
||||||
u64 FastBlockLookupITCM[ITCMPhysicalSize / 2];
|
u64 FastBlockLookupITCM[ITCMPhysicalSize / 2];
|
||||||
u64 FastBlockLookupMainRAM[NDS::MainRAMMaxSize / 2];
|
u64 FastBlockLookupMainRAM[NDS::MainRAMMaxSize / 2];
|
||||||
u64 FastBlockLookupSWRAM[NDS::SharedWRAMSize / 2];
|
u64 FastBlockLookupSWRAM[NDS::SharedWRAMSize / 2];
|
||||||
|
@ -146,8 +151,6 @@ u32 LocaliseCodeAddress(u32 num, u32 addr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TinyVector<u32> InvalidLiterals;
|
|
||||||
|
|
||||||
template <typename T, int ConsoleType>
|
template <typename T, int ConsoleType>
|
||||||
T SlowRead9(u32 addr, ARMv5* cpu)
|
T SlowRead9(u32 addr, ARMv5* cpu)
|
||||||
{
|
{
|
||||||
|
@ -286,97 +289,6 @@ void SlowBlockTransfer7(u32 addr, u64* data, u32 num)
|
||||||
INSTANTIATE_SLOWMEM(0)
|
INSTANTIATE_SLOWMEM(0)
|
||||||
INSTANTIATE_SLOWMEM(1)
|
INSTANTIATE_SLOWMEM(1)
|
||||||
|
|
||||||
template <typename K, typename V, int Size, V InvalidValue>
|
|
||||||
struct UnreliableHashTable
|
|
||||||
{
|
|
||||||
struct Bucket
|
|
||||||
{
|
|
||||||
K KeyA, KeyB;
|
|
||||||
V ValA, ValB;
|
|
||||||
};
|
|
||||||
|
|
||||||
Bucket Table[Size];
|
|
||||||
|
|
||||||
void Reset()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < Size; i++)
|
|
||||||
{
|
|
||||||
Table[i].ValA = Table[i].ValB = InvalidValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UnreliableHashTable()
|
|
||||||
{
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
V Insert(K key, V value)
|
|
||||||
{
|
|
||||||
u32 slot = XXH3_64bits(&key, sizeof(K)) & (Size - 1);
|
|
||||||
Bucket* bucket = &Table[slot];
|
|
||||||
|
|
||||||
if (bucket->ValA == value || bucket->ValB == value)
|
|
||||||
{
|
|
||||||
return InvalidValue;
|
|
||||||
}
|
|
||||||
else if (bucket->ValA == InvalidValue)
|
|
||||||
{
|
|
||||||
bucket->KeyA = key;
|
|
||||||
bucket->ValA = value;
|
|
||||||
}
|
|
||||||
else if (bucket->ValB == InvalidValue)
|
|
||||||
{
|
|
||||||
bucket->KeyB = key;
|
|
||||||
bucket->ValB = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
V prevVal = bucket->ValB;
|
|
||||||
bucket->KeyB = bucket->KeyA;
|
|
||||||
bucket->ValB = bucket->ValA;
|
|
||||||
bucket->KeyA = key;
|
|
||||||
bucket->ValA = value;
|
|
||||||
return prevVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
return InvalidValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Remove(K key)
|
|
||||||
{
|
|
||||||
u32 slot = XXH3_64bits(&key, sizeof(K)) & (Size - 1);
|
|
||||||
Bucket* bucket = &Table[slot];
|
|
||||||
|
|
||||||
if (bucket->KeyA == key && bucket->ValA != InvalidValue)
|
|
||||||
{
|
|
||||||
bucket->ValA = InvalidValue;
|
|
||||||
if (bucket->ValB != InvalidValue)
|
|
||||||
{
|
|
||||||
bucket->KeyA = bucket->KeyB;
|
|
||||||
bucket->ValA = bucket->ValB;
|
|
||||||
bucket->ValB = InvalidValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bucket->KeyB == key && bucket->ValB != InvalidValue)
|
|
||||||
bucket->ValB = InvalidValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
V LookUp(K addr)
|
|
||||||
{
|
|
||||||
u32 slot = XXH3_64bits(&addr, 4) & (Size - 1);
|
|
||||||
Bucket* bucket = &Table[slot];
|
|
||||||
|
|
||||||
if (bucket->ValA != InvalidValue && bucket->KeyA == addr)
|
|
||||||
return bucket->ValA;
|
|
||||||
if (bucket->ValB != InvalidValue && bucket->KeyB == addr)
|
|
||||||
return bucket->ValB;
|
|
||||||
|
|
||||||
return InvalidValue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
UnreliableHashTable<u32, JitBlock*, 0x800, nullptr> RestoreCandidates;
|
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
JITCompiler = new Compiler();
|
JITCompiler = new Compiler();
|
||||||
|
@ -568,7 +480,7 @@ InterpreterFunc InterpretARM[ARMInstrInfo::ak_Count] =
|
||||||
F_ALU(CMN,),
|
F_ALU(CMN,),
|
||||||
|
|
||||||
F(MUL), F(MLA), F(UMULL), F(UMLAL), F(SMULL), F(SMLAL), F(SMLAxy), F(SMLAWy), F(SMULWy), F(SMLALxy), F(SMULxy),
|
F(MUL), F(MLA), F(UMULL), F(UMLAL), F(SMULL), F(SMLAL), F(SMLAxy), F(SMLAWy), F(SMULWy), F(SMLALxy), F(SMULxy),
|
||||||
F(CLZ), F(QADD), F(QDADD), F(QSUB), F(QDSUB),
|
F(CLZ), F(QADD), F(QSUB), F(QDADD), F(QDSUB),
|
||||||
|
|
||||||
F_MEM_WB(STR),
|
F_MEM_WB(STR),
|
||||||
F_MEM_WB(STRB),
|
F_MEM_WB(STRB),
|
||||||
|
@ -622,6 +534,20 @@ InterpreterFunc InterpretTHUMB[ARMInstrInfo::tk_Count] =
|
||||||
};
|
};
|
||||||
#undef F
|
#undef F
|
||||||
|
|
||||||
|
void RetireJitBlock(JitBlock* block)
|
||||||
|
{
|
||||||
|
auto it = RestoreCandidates.find(block->InstrHash);
|
||||||
|
if (it != RestoreCandidates.end())
|
||||||
|
{
|
||||||
|
delete it->second;
|
||||||
|
it->second = block;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RestoreCandidates[block->InstrHash] = block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CompileBlock(ARM* cpu)
|
void CompileBlock(ARM* cpu)
|
||||||
{
|
{
|
||||||
bool thumb = cpu->CPSR & 0x20;
|
bool thumb = cpu->CPSR & 0x20;
|
||||||
|
@ -659,10 +585,7 @@ void CompileBlock(ARM* cpu)
|
||||||
}
|
}
|
||||||
|
|
||||||
// some memory has been remapped
|
// some memory has been remapped
|
||||||
JitBlock* prevBlock = RestoreCandidates.Insert(existingBlockIt->second->InstrHash, existingBlockIt->second);
|
RetireJitBlock(existingBlockIt->second);
|
||||||
if (prevBlock)
|
|
||||||
delete prevBlock;
|
|
||||||
|
|
||||||
map.erase(existingBlockIt);
|
map.erase(existingBlockIt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -906,11 +829,13 @@ void CompileBlock(ARM* cpu)
|
||||||
u32 literalHash = (u32)XXH3_64bits(literalValues, numLiterals * 4);
|
u32 literalHash = (u32)XXH3_64bits(literalValues, numLiterals * 4);
|
||||||
u32 instrHash = (u32)XXH3_64bits(instrValues, i * 4);
|
u32 instrHash = (u32)XXH3_64bits(instrValues, i * 4);
|
||||||
|
|
||||||
JitBlock* prevBlock = RestoreCandidates.LookUp(instrHash);
|
auto prevBlockIt = RestoreCandidates.find(instrHash);
|
||||||
|
JitBlock* prevBlock = NULL;
|
||||||
bool mayRestore = true;
|
bool mayRestore = true;
|
||||||
if (prevBlock)
|
if (prevBlockIt != RestoreCandidates.end())
|
||||||
{
|
{
|
||||||
RestoreCandidates.Remove(instrHash);
|
prevBlock = prevBlockIt->second;
|
||||||
|
RestoreCandidates.erase(prevBlockIt);
|
||||||
|
|
||||||
mayRestore = prevBlock->StartAddr == blockAddr && prevBlock->LiteralHash == literalHash;
|
mayRestore = prevBlock->StartAddr == blockAddr && prevBlock->LiteralHash == literalHash;
|
||||||
|
|
||||||
|
@ -932,7 +857,6 @@ void CompileBlock(ARM* cpu)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mayRestore = false;
|
mayRestore = false;
|
||||||
prevBlock = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JitBlock* block;
|
JitBlock* block;
|
||||||
|
@ -1078,9 +1002,7 @@ void InvalidateByAddr(u32 localAddr)
|
||||||
|
|
||||||
if (!literalInvalidation)
|
if (!literalInvalidation)
|
||||||
{
|
{
|
||||||
JitBlock* prevBlock = RestoreCandidates.Insert(block->InstrHash, block);
|
RetireJitBlock(block);
|
||||||
if (prevBlock)
|
|
||||||
delete prevBlock;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1165,21 +1087,13 @@ void ResetBlockCache()
|
||||||
|
|
||||||
InvalidLiterals.Clear();
|
InvalidLiterals.Clear();
|
||||||
for (int i = 0; i < ARMJIT_Memory::memregions_Count; i++)
|
for (int i = 0; i < ARMJIT_Memory::memregions_Count; i++)
|
||||||
memset(FastBlockLookupRegions[i], 0xFF, CodeRegionSizes[i] * sizeof(u64) / 2);
|
|
||||||
RestoreCandidates.Reset();
|
|
||||||
for (int i = 0; i < sizeof(RestoreCandidates.Table)/sizeof(RestoreCandidates.Table[0]); i++)
|
|
||||||
{
|
{
|
||||||
if (RestoreCandidates.Table[i].ValA)
|
if (FastBlockLookupRegions[i])
|
||||||
{
|
memset(FastBlockLookupRegions[i], 0xFF, CodeRegionSizes[i] * sizeof(u64) / 2);
|
||||||
delete RestoreCandidates.Table[i].ValA;
|
|
||||||
RestoreCandidates.Table[i].ValA = NULL;
|
|
||||||
}
|
|
||||||
if (RestoreCandidates.Table[i].ValA)
|
|
||||||
{
|
|
||||||
delete RestoreCandidates.Table[i].ValB;
|
|
||||||
RestoreCandidates.Table[i].ValB = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
for (auto it = RestoreCandidates.begin(); it != RestoreCandidates.end(); it++)
|
||||||
|
delete it->second;
|
||||||
|
RestoreCandidates.clear();
|
||||||
for (auto it : JitBlocks9)
|
for (auto it : JitBlocks9)
|
||||||
{
|
{
|
||||||
JitBlock* block = it.second;
|
JitBlock* block = it.second;
|
||||||
|
|
|
@ -436,7 +436,7 @@ void Compiler::A_Comp_GetOp2(bool S, Op2& op2)
|
||||||
Comp_AddCycles_C();
|
Comp_AddCycles_C();
|
||||||
|
|
||||||
u32 shift = (CurInstr.Instr >> 7) & 0x1E;
|
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))
|
if (S && shift && (CurInstr.SetFlags & 0x2))
|
||||||
{
|
{
|
||||||
|
@ -447,7 +447,7 @@ void Compiler::A_Comp_GetOp2(bool S, Op2& op2)
|
||||||
ANDI2R(RCPSR, RCPSR, ~(1 << 29));
|
ANDI2R(RCPSR, RCPSR, ~(1 << 29));
|
||||||
}
|
}
|
||||||
|
|
||||||
op2 = Op2(ROR(CurInstr.Instr & 0xFF, (CurInstr.Instr >> 7) & 0x1E));
|
op2 = Op2(imm);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -523,7 +523,7 @@ void Compiler::A_Comp_ALUMovOp()
|
||||||
case ST_LSL: LSL(rd, op2.Reg.Rm, op2.Reg.ShiftAmount); break;
|
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_LSR: LSR(rd, op2.Reg.Rm, op2.Reg.ShiftAmount); break;
|
||||||
case ST_ASR: ASR(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
|
else
|
||||||
|
|
|
@ -76,7 +76,7 @@ void Compiler::A_Comp_MSR()
|
||||||
if (CurInstr.Instr & (1 << 25))
|
if (CurInstr.Instr & (1 << 25))
|
||||||
{
|
{
|
||||||
val = W0;
|
val = W0;
|
||||||
MOVI2R(val, ROR((CurInstr.Instr & 0xFF), ((CurInstr.Instr >> 7) & 0x1E)));
|
MOVI2R(val, ::ROR((CurInstr.Instr & 0xFF), ((CurInstr.Instr >> 7) & 0x1E)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef ARMJIT_COMPILER_H
|
#ifndef ARMJIT_A64_COMPILER_H
|
||||||
#define ARMJIT_COMPILER_H
|
#define ARMJIT_A64_COMPILER_H
|
||||||
|
|
||||||
#include "../ARM.h"
|
#include "../ARM.h"
|
||||||
#include "../ARMJIT.h"
|
#include "../ARMJIT.h"
|
||||||
|
@ -266,4 +266,4 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -42,7 +42,7 @@ s64 Compiler::RewriteMemAccess(u64 pc)
|
||||||
return patch.PatchOffset;
|
return patch.PatchOffset;
|
||||||
}
|
}
|
||||||
printf("this is a JIT bug! %08x\n", __builtin_bswap32(*(u32*)pc));
|
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)
|
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)
|
if (size == 32)
|
||||||
{
|
{
|
||||||
CurCPU->DataRead32(addr & ~0x3, &val);
|
CurCPU->DataRead32(addr & ~0x3, &val);
|
||||||
val = ROR(val, (addr & 0x3) << 3);
|
val = ::ROR(val, (addr & 0x3) << 3);
|
||||||
}
|
}
|
||||||
else if (size == 16)
|
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)
|
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);
|
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 (size == 32)
|
||||||
{
|
{
|
||||||
if (staticAddress & 0x3)
|
if (staticAddress & 0x3)
|
||||||
ROR_(rdMapped, W0, (staticAddress & 0x3) << 3);
|
ROR(rdMapped, W0, (staticAddress & 0x3) << 3);
|
||||||
else
|
else
|
||||||
MOV(rdMapped, W0);
|
MOV(rdMapped, W0);
|
||||||
}
|
}
|
||||||
|
@ -807,4 +807,4 @@ void Compiler::T_Comp_LDMIA_STMIA()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef ARMJIT_COMPILER_H
|
||||||
|
#define ARMJIT_COMPILER_H
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__)
|
||||||
#include "ARMJIT_x64/ARMJIT_Compiler.h"
|
#include "ARMJIT_x64/ARMJIT_Compiler.h"
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
|
@ -9,4 +12,6 @@
|
||||||
namespace ARMJIT
|
namespace ARMJIT
|
||||||
{
|
{
|
||||||
extern Compiler* JITCompiler;
|
extern Compiler* JITCompiler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -279,6 +279,7 @@ bool UnmapFromRange(u32 addr, u32 num, u32 offset, u32 size)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __SWITCH__
|
||||||
void SetCodeProtectionRange(u32 addr, u32 size, u32 num, int protection)
|
void SetCodeProtectionRange(u32 addr, u32 size, u32 num, int protection)
|
||||||
{
|
{
|
||||||
u8* dst = (u8*)(num == 0 ? FastMem9Start : FastMem7Start) + addr;
|
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);
|
mprotect(dst, size, posixProt);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct Mapping
|
struct Mapping
|
||||||
{
|
{
|
||||||
|
@ -524,8 +526,8 @@ bool MapAtAddress(u32 addr)
|
||||||
{
|
{
|
||||||
u32 sectionOffset = offset;
|
u32 sectionOffset = offset;
|
||||||
bool hasCode = isExecutable && ARMJIT::PageContainsCode(&range[offset / 512]);
|
bool hasCode = isExecutable && ARMJIT::PageContainsCode(&range[offset / 512]);
|
||||||
while ((!isExecutable || ARMJIT::PageContainsCode(&range[offset / 512]) == hasCode)
|
while (offset < mirrorSize
|
||||||
&& offset < mirrorSize
|
&& (!isExecutable || ARMJIT::PageContainsCode(&range[offset / 512]) == hasCode)
|
||||||
&& (!skipDTCM || mirrorStart + offset != NDS::ARM9->DTCMBase))
|
&& (!skipDTCM || mirrorStart + offset != NDS::ARM9->DTCMBase))
|
||||||
{
|
{
|
||||||
assert(states[(mirrorStart + offset) >> 12] == memstate_Unmapped);
|
assert(states[(mirrorStart + offset) >> 12] == memstate_Unmapped);
|
||||||
|
@ -773,6 +775,7 @@ bool GetMirrorLocation(int region, u32 num, u32 addr, u32& memoryOffset, u32& mi
|
||||||
{
|
{
|
||||||
mirrorStart = addr & ~0xFFFFF;
|
mirrorStart = addr & ~0xFFFFF;
|
||||||
mirrorSize = 0x100000;
|
mirrorSize = 0x100000;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case memregion_VWRAM:
|
case memregion_VWRAM:
|
||||||
|
@ -1007,7 +1010,7 @@ void WifiWrite32(u32 addr, u32 val)
|
||||||
|
|
||||||
u32 WifiRead32(u32 addr)
|
u32 WifiRead32(u32 addr)
|
||||||
{
|
{
|
||||||
return Wifi::Read(addr) | (Wifi::Read(addr + 2) << 16);
|
return (u32)Wifi::Read(addr) | ((u32)Wifi::Read(addr + 2) << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -61,7 +61,8 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert("Welp!");
|
printf("this is a JIT bug! LoadRegister failed\n");
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PutLiteral(int reg, u32 val)
|
void PutLiteral(int reg, u32 val)
|
||||||
|
|
|
@ -110,7 +110,7 @@ OpArg Compiler::A_Comp_GetALUOp2(bool S, bool& carryUsed)
|
||||||
Comp_AddCycles_C();
|
Comp_AddCycles_C();
|
||||||
|
|
||||||
u32 shift = (CurInstr.Instr >> 7) & 0x1E;
|
u32 shift = (CurInstr.Instr >> 7) & 0x1E;
|
||||||
u32 imm = ROR(CurInstr.Instr & 0xFF, shift);
|
u32 imm = ::ROR(CurInstr.Instr & 0xFF, shift);
|
||||||
|
|
||||||
carryUsed = false;
|
carryUsed = false;
|
||||||
if (S && shift)
|
if (S && shift)
|
||||||
|
@ -209,7 +209,8 @@ void Compiler::A_Comp_Arith()
|
||||||
Comp_ArithTriOp(&Compiler::AND, rd, rn, op2, carryUsed, sFlag|opSymmetric|opInvertOp2);
|
Comp_ArithTriOp(&Compiler::AND, rd, rn, op2, carryUsed, sFlag|opSymmetric|opInvertOp2);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert("unimplemented");
|
printf("this is a JIT bug! %04x\n", op);
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurInstr.A_Reg(12) == 15)
|
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)
|
if (S)
|
||||||
BT(32, R(RSCRATCH), Imm8(31));
|
BT(32, R(RSCRATCH), Imm8(31));
|
||||||
ROR_(32, R(RSCRATCH), R(ECX));
|
ROR(32, R(RSCRATCH), R(ECX));
|
||||||
if (S)
|
if (S)
|
||||||
SETcc(CC_C, R(RSCRATCH2));
|
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
|
case 3: // ROR
|
||||||
MOV(32, R(RSCRATCH), rm);
|
MOV(32, R(RSCRATCH), rm);
|
||||||
if (amount > 0)
|
if (amount > 0)
|
||||||
ROR_(32, R(RSCRATCH), Imm8(amount));
|
ROR(32, R(RSCRATCH), Imm8(amount));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BT(32, R(RCPSR), Imm8(29));
|
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);
|
return R(RSCRATCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(false);
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::T_Comp_ShiftImm()
|
void Compiler::T_Comp_ShiftImm()
|
||||||
|
@ -779,4 +780,4 @@ void Compiler::T_Comp_RelAddr()
|
||||||
MOV(32, rd, Imm32((R15 & ~2) + offset));
|
MOV(32, rd, Imm32((R15 & ~2) + offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ void Compiler::A_Comp_MSR()
|
||||||
Comp_AddCycles_C();
|
Comp_AddCycles_C();
|
||||||
|
|
||||||
OpArg val = CurInstr.Instr & (1 << 25)
|
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));
|
: MapReg(CurInstr.A_Reg(0));
|
||||||
|
|
||||||
u32 mask = 0;
|
u32 mask = 0;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef ARMJIT_COMPILER_H
|
#ifndef ARMJIT_X64_COMPILER_H
|
||||||
#define ARMJIT_COMPILER_H
|
#define ARMJIT_X64_COMPILER_H
|
||||||
|
|
||||||
#include "../dolphin/x64Emitter.h"
|
#include "../dolphin/x64Emitter.h"
|
||||||
|
|
||||||
|
@ -252,4 +252,4 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,7 +39,7 @@ s32 Compiler::RewriteMemAccess(u64 pc)
|
||||||
return patch.Offset;
|
return patch.Offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("this is a JIT bug %x\n", pc);
|
printf("this is a JIT bug %llx\n", pc);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ bool Compiler::Comp_MemLoadLiteral(int size, bool signExtend, int rd, u32 addr)
|
||||||
if (size == 32)
|
if (size == 32)
|
||||||
{
|
{
|
||||||
CurCPU->DataRead32(addr & ~0x3, &val);
|
CurCPU->DataRead32(addr & ~0x3, &val);
|
||||||
val = ROR(val, (addr & 0x3) << 3);
|
val = ::ROR(val, (addr & 0x3) << 3);
|
||||||
}
|
}
|
||||||
else if (size == 16)
|
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 (addrIsStatic)
|
||||||
{
|
{
|
||||||
if (staticAddress & 0x3)
|
if (staticAddress & 0x3)
|
||||||
ROR_(32, rdMapped, Imm8((staticAddress & 0x3) * 8));
|
ROR(32, rdMapped, Imm8((staticAddress & 0x3) * 8));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AND(32, R(RSCRATCH3), Imm8(0x3));
|
AND(32, R(RSCRATCH3), Imm8(0x3));
|
||||||
SHL(32, R(RSCRATCH3), Imm8(3));
|
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));
|
MOV(32, rdMapped, R(RSCRATCH));
|
||||||
if (staticAddress & 0x3)
|
if (staticAddress & 0x3)
|
||||||
ROR_(32, rdMapped, Imm8((staticAddress & 0x3) * 8));
|
ROR(32, rdMapped, Imm8((staticAddress & 0x3) * 8));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -819,4 +819,4 @@ void Compiler::T_Comp_LDMIA_STMIA()
|
||||||
ADD(32, rb, Imm8(offset));
|
ADD(32, rb, Imm8(offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ project(core)
|
||||||
set (CMAKE_CXX_STANDARD 14)
|
set (CMAKE_CXX_STANDARD 14)
|
||||||
|
|
||||||
add_library(core STATIC
|
add_library(core STATIC
|
||||||
ARCodeList.cpp
|
ARCodeFile.cpp
|
||||||
AREngine.cpp
|
AREngine.cpp
|
||||||
ARM.cpp
|
ARM.cpp
|
||||||
ARM_InstrTable.h
|
ARM_InstrTable.h
|
||||||
|
@ -26,16 +26,12 @@ add_library(core STATIC
|
||||||
FIFO.h
|
FIFO.h
|
||||||
GBACart.cpp
|
GBACart.cpp
|
||||||
GPU.cpp
|
GPU.cpp
|
||||||
GPU_OpenGL.cpp
|
|
||||||
GPU_OpenGL_shaders.h
|
|
||||||
GPU2D.cpp
|
GPU2D.cpp
|
||||||
GPU3D.cpp
|
GPU3D.cpp
|
||||||
GPU3D_OpenGL.cpp
|
|
||||||
GPU3D_OpenGL_shaders.h
|
|
||||||
GPU3D_Soft.cpp
|
GPU3D_Soft.cpp
|
||||||
|
melonDLDI.h
|
||||||
NDS.cpp
|
NDS.cpp
|
||||||
NDSCart.cpp
|
NDSCart.cpp
|
||||||
OpenGLSupport.cpp
|
|
||||||
Platform.h
|
Platform.h
|
||||||
ROMList.h
|
ROMList.h
|
||||||
RTC.cpp
|
RTC.cpp
|
||||||
|
@ -51,6 +47,16 @@ add_library(core STATIC
|
||||||
xxhash/xxhash.c
|
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)
|
if (ENABLE_JIT)
|
||||||
enable_language(ASM)
|
enable_language(ASM)
|
||||||
|
|
||||||
|
@ -94,9 +100,16 @@ if (ENABLE_JIT)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (ENABLE_OGLRENDERER)
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_link_libraries(core ole32 comctl32 ws2_32 opengl32)
|
target_link_libraries(core ole32 comctl32 ws2_32 opengl32)
|
||||||
|
else()
|
||||||
|
target_link_libraries(core GL EGL)
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
target_link_libraries(core GL EGL)
|
if (WIN32)
|
||||||
endif()
|
target_link_libraries(core ole32 comctl32 ws2_32)
|
||||||
|
else()
|
||||||
|
target_link_libraries(core)
|
||||||
|
endif()
|
||||||
|
endif()
|
|
@ -616,11 +616,11 @@ void ARMv5::CP15Write(u32 id, u32 val)
|
||||||
case 0xF00:
|
case 0xF00:
|
||||||
//printf("cache debug index register %08X\n", val);
|
//printf("cache debug index register %08X\n", val);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0xF10:
|
case 0xF10:
|
||||||
//printf("cache debug instruction tag %08X\n", val);
|
//printf("cache debug instruction tag %08X\n", val);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0xF20:
|
case 0xF20:
|
||||||
//printf("cache debug data tag %08X\n", val);
|
//printf("cache debug data tag %08X\n", val);
|
||||||
return;
|
return;
|
||||||
|
@ -632,7 +632,7 @@ void ARMv5::CP15Write(u32 id, u32 val)
|
||||||
case 0xF40:
|
case 0xF40:
|
||||||
//printf("cache debug data cache %08X\n", val);
|
//printf("cache debug data cache %08X\n", val);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((id & 0xF00) == 0xF00) // test/debug shit?
|
if ((id & 0xF00) == 0xF00) // test/debug shit?
|
||||||
|
|
|
@ -31,16 +31,22 @@ const char* kConfigFile = "melonDS.ini";
|
||||||
char BIOS9Path[1024];
|
char BIOS9Path[1024];
|
||||||
char BIOS7Path[1024];
|
char BIOS7Path[1024];
|
||||||
char FirmwarePath[1024];
|
char FirmwarePath[1024];
|
||||||
|
int DLDIEnable;
|
||||||
|
char DLDISDPath[1024];
|
||||||
|
|
||||||
char DSiBIOS9Path[1024];
|
char DSiBIOS9Path[1024];
|
||||||
char DSiBIOS7Path[1024];
|
char DSiBIOS7Path[1024];
|
||||||
char DSiFirmwarePath[1024];
|
char DSiFirmwarePath[1024];
|
||||||
char DSiNANDPath[1024];
|
char DSiNANDPath[1024];
|
||||||
|
int DSiSDEnable;
|
||||||
|
char DSiSDPath[1024];
|
||||||
|
|
||||||
|
int RandomizeMAC;
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
int JIT_Enable = false;
|
int JIT_Enable = false;
|
||||||
int JIT_MaxBlockSize = 32;
|
int JIT_MaxBlockSize = 32;
|
||||||
int JIT_BranchOptimisations = 2;
|
int JIT_BranchOptimisations = true;
|
||||||
int JIT_LiteralOptimisations = true;
|
int JIT_LiteralOptimisations = true;
|
||||||
int JIT_FastMemory = true;
|
int JIT_FastMemory = true;
|
||||||
#endif
|
#endif
|
||||||
|
@ -50,16 +56,22 @@ ConfigEntry ConfigFile[] =
|
||||||
{"BIOS9Path", 1, BIOS9Path, 0, "", 1023},
|
{"BIOS9Path", 1, BIOS9Path, 0, "", 1023},
|
||||||
{"BIOS7Path", 1, BIOS7Path, 0, "", 1023},
|
{"BIOS7Path", 1, BIOS7Path, 0, "", 1023},
|
||||||
{"FirmwarePath", 1, FirmwarePath, 0, "", 1023},
|
{"FirmwarePath", 1, FirmwarePath, 0, "", 1023},
|
||||||
|
{"DLDIEnable", 0, &DLDIEnable, 0, NULL, 0},
|
||||||
|
{"DLDISDPath", 1, DLDISDPath, 0, "", 1023},
|
||||||
|
|
||||||
{"DSiBIOS9Path", 1, DSiBIOS9Path, 0, "", 1023},
|
{"DSiBIOS9Path", 1, DSiBIOS9Path, 0, "", 1023},
|
||||||
{"DSiBIOS7Path", 1, DSiBIOS7Path, 0, "", 1023},
|
{"DSiBIOS7Path", 1, DSiBIOS7Path, 0, "", 1023},
|
||||||
{"DSiFirmwarePath", 1, DSiFirmwarePath, 0, "", 1023},
|
{"DSiFirmwarePath", 1, DSiFirmwarePath, 0, "", 1023},
|
||||||
{"DSiNANDPath", 1, DSiNANDPath, 0, "", 1023},
|
{"DSiNANDPath", 1, DSiNANDPath, 0, "", 1023},
|
||||||
|
{"DSiSDEnable", 0, &DSiSDEnable, 0, NULL, 0},
|
||||||
|
{"DSiSDPath", 1, DSiSDPath, 0, "", 1023},
|
||||||
|
|
||||||
|
{"RandomizeMAC", 0, &RandomizeMAC, 0, NULL, 0},
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
{"JIT_Enable", 0, &JIT_Enable, 0, NULL, 0},
|
{"JIT_Enable", 0, &JIT_Enable, 0, NULL, 0},
|
||||||
{"JIT_MaxBlockSize", 0, &JIT_MaxBlockSize, 32, 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_LiteralOptimisations", 0, &JIT_LiteralOptimisations, 1, NULL, 0},
|
||||||
{"JIT_FastMemory", 0, &JIT_FastMemory, 1, NULL, 0},
|
{"JIT_FastMemory", 0, &JIT_FastMemory, 1, NULL, 0},
|
||||||
#endif
|
#endif
|
||||||
|
@ -104,7 +116,7 @@ void Load()
|
||||||
while (!feof(f))
|
while (!feof(f))
|
||||||
{
|
{
|
||||||
fgets(linebuf, 1024, f);
|
fgets(linebuf, 1024, f);
|
||||||
int ret = sscanf(linebuf, "%31[A-Za-z_0-9]=%[^\t\n]", entryname, entryval);
|
int ret = sscanf(linebuf, "%31[A-Za-z_0-9]=%[^\t\r\n]", entryname, entryval);
|
||||||
entryname[31] = '\0';
|
entryname[31] = '\0';
|
||||||
if (ret < 2) continue;
|
if (ret < 2) continue;
|
||||||
|
|
||||||
|
@ -157,7 +169,7 @@ void Save()
|
||||||
if (entry->Type == 0)
|
if (entry->Type == 0)
|
||||||
fprintf(f, "%s=%d\n", entry->Name, *(int*)entry->Value);
|
fprintf(f, "%s=%d\n", entry->Name, *(int*)entry->Value);
|
||||||
else
|
else
|
||||||
fprintf(f, "%s=%s\n", entry->Name, entry->Value);
|
fprintf(f, "%s=%s\n", entry->Name, (char*)entry->Value);
|
||||||
|
|
||||||
entry++;
|
entry++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,11 +45,17 @@ void Save();
|
||||||
extern char BIOS9Path[1024];
|
extern char BIOS9Path[1024];
|
||||||
extern char BIOS7Path[1024];
|
extern char BIOS7Path[1024];
|
||||||
extern char FirmwarePath[1024];
|
extern char FirmwarePath[1024];
|
||||||
|
extern int DLDIEnable;
|
||||||
|
extern char DLDISDPath[1024];
|
||||||
|
|
||||||
extern char DSiBIOS9Path[1024];
|
extern char DSiBIOS9Path[1024];
|
||||||
extern char DSiBIOS7Path[1024];
|
extern char DSiBIOS7Path[1024];
|
||||||
extern char DSiFirmwarePath[1024];
|
extern char DSiFirmwarePath[1024];
|
||||||
extern char DSiNANDPath[1024];
|
extern char DSiNANDPath[1024];
|
||||||
|
extern int DSiSDEnable;
|
||||||
|
extern char DSiSDPath[1024];
|
||||||
|
|
||||||
|
extern int RandomizeMAC;
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
extern int JIT_Enable;
|
extern int JIT_Enable;
|
||||||
|
|
|
@ -73,6 +73,8 @@ void DMA::Reset()
|
||||||
SrcAddrInc = 0;
|
SrcAddrInc = 0;
|
||||||
DstAddrInc = 0;
|
DstAddrInc = 0;
|
||||||
|
|
||||||
|
Stall = false;
|
||||||
|
|
||||||
Running = false;
|
Running = false;
|
||||||
InProgress = false;
|
InProgress = false;
|
||||||
|
|
||||||
|
@ -111,8 +113,8 @@ void DMA::DoSavestate(Savestate* file)
|
||||||
file->Var32(&DstAddrInc);
|
file->Var32(&DstAddrInc);
|
||||||
|
|
||||||
file->Var32(&Running);
|
file->Var32(&Running);
|
||||||
file->Var32((u32*)&InProgress);
|
file->Bool32(&InProgress);
|
||||||
file->Var32((u32*)&IsGXFIFODMA);
|
file->Bool32(&IsGXFIFODMA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA::WriteCnt(u32 val)
|
void DMA::WriteCnt(u32 val)
|
||||||
|
|
87
src/DSi.cpp
87
src/DSi.cpp
|
@ -699,20 +699,37 @@ void MapNWRAMRange(u32 cpu, u32 num, u32 val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApplyNewRAMSize(u32 size)
|
||||||
|
{
|
||||||
|
switch (size)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
NDS::MainRAMMask = 0x3FFFFF;
|
||||||
|
printf("RAM: 4MB\n");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 3: // TODO: debug console w/ 32MB?
|
||||||
|
NDS::MainRAMMask = 0xFFFFFF;
|
||||||
|
printf("RAM: 16MB\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Set_SCFG_Clock9(u16 val)
|
void Set_SCFG_Clock9(u16 val)
|
||||||
{
|
{
|
||||||
SCFG_Clock9 = val & 0x0187;
|
|
||||||
return;
|
|
||||||
|
|
||||||
NDS::ARM9Timestamp >>= NDS::ARM9ClockShift;
|
NDS::ARM9Timestamp >>= NDS::ARM9ClockShift;
|
||||||
|
NDS::ARM9Target >>= NDS::ARM9ClockShift;
|
||||||
|
|
||||||
printf("CLOCK9=%04X\n", val);
|
printf("CLOCK9=%04X\n", val);
|
||||||
SCFG_Clock9 = val & 0x0187;
|
SCFG_Clock9 = val & 0x0187;
|
||||||
|
|
||||||
if (SCFG_Clock9 & (1<<0)) NDS::ARM9ClockShift = 2;
|
if (SCFG_Clock9 & (1<<0)) NDS::ARM9ClockShift = 2;
|
||||||
else NDS::ARM9ClockShift = 1;
|
else NDS::ARM9ClockShift = 1;
|
||||||
|
|
||||||
NDS::ARM9Timestamp <<= NDS::ARM9ClockShift;
|
NDS::ARM9Timestamp <<= NDS::ARM9ClockShift;
|
||||||
|
NDS::ARM9Target <<= NDS::ARM9ClockShift;
|
||||||
NDS::ARM9->UpdateRegionTimings(0x00000000, 0xFFFFFFFF);
|
NDS::ARM9->UpdateRegionTimings(0x00000000, 0xFFFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -895,6 +912,20 @@ void ARM9Write8(u32 addr, u8 val)
|
||||||
case 0x04000000:
|
case 0x04000000:
|
||||||
ARM9IOWrite8(addr, val);
|
ARM9IOWrite8(addr, val);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case 0x06000000:
|
||||||
|
if (!(SCFG_EXT[0] & (1<<13))) return;
|
||||||
|
#ifdef JIT_ENABLED
|
||||||
|
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_VRAM>(addr);
|
||||||
|
#endif
|
||||||
|
switch (addr & 0x00E00000)
|
||||||
|
{
|
||||||
|
case 0x00000000: GPU::WriteVRAM_ABG<u8>(addr, val); return;
|
||||||
|
case 0x00200000: GPU::WriteVRAM_BBG<u8>(addr, val); return;
|
||||||
|
case 0x00400000: GPU::WriteVRAM_AOBJ<u8>(addr, val); return;
|
||||||
|
case 0x00600000: GPU::WriteVRAM_BOBJ<u8>(addr, val); return;
|
||||||
|
default: GPU::WriteVRAM_LCDC<u8>(addr, val); return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NDS::ARM9Write8(addr, val);
|
return NDS::ARM9Write8(addr, val);
|
||||||
|
@ -1549,25 +1580,37 @@ void ARM9IOWrite32(u32 addr, u32 val)
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case 0x04004008:
|
case 0x04004008:
|
||||||
SCFG_EXT[0] &= ~0x8007F19F;
|
|
||||||
SCFG_EXT[0] |= (val & 0x8007F19F);
|
|
||||||
SCFG_EXT[1] &= ~0x0000F080;
|
|
||||||
SCFG_EXT[1] |= (val & 0x0000F080);
|
|
||||||
printf("SCFG_EXT = %08X / %08X (val9 %08X)\n", SCFG_EXT[0], SCFG_EXT[1], val);
|
|
||||||
/*switch ((SCFG_EXT[0] >> 14) & 0x3)
|
|
||||||
{
|
{
|
||||||
case 0:
|
u32 oldram = (SCFG_EXT[0] >> 14) & 0x3;
|
||||||
case 1:
|
u32 newram = (val >> 14) & 0x3;
|
||||||
NDS::MainRAMMask = 0x3FFFFF;
|
|
||||||
printf("RAM: 4MB\n");
|
SCFG_EXT[0] &= ~0x8007F19F;
|
||||||
break;
|
SCFG_EXT[0] |= (val & 0x8007F19F);
|
||||||
case 2:
|
SCFG_EXT[1] &= ~0x0000F080;
|
||||||
case 3: // TODO: debug console w/ 32MB?
|
SCFG_EXT[1] |= (val & 0x0000F080);
|
||||||
NDS::MainRAMMask = 0xFFFFFF;
|
printf("SCFG_EXT = %08X / %08X (val9 %08X)\n", SCFG_EXT[0], SCFG_EXT[1], val);
|
||||||
printf("RAM: 16MB\n");
|
/*switch ((SCFG_EXT[0] >> 14) & 0x3)
|
||||||
break;
|
{
|
||||||
}*/
|
case 0:
|
||||||
printf("from %08X, ARM7 %08X, %08X\n", NDS::GetPC(0), NDS::GetPC(1), NDS::ARM7->R[1]);
|
case 1:
|
||||||
|
NDS::MainRAMMask = 0x3FFFFF;
|
||||||
|
printf("RAM: 4MB\n");
|
||||||
|
//baziderp=true;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 3: // TODO: debug console w/ 32MB?
|
||||||
|
NDS::MainRAMMask = 0xFFFFFF;
|
||||||
|
printf("RAM: 16MB\n");
|
||||||
|
break;
|
||||||
|
}*/
|
||||||
|
// HAX!!
|
||||||
|
// a change to the RAM size setting is supposed to apply immediately (it does so on hardware)
|
||||||
|
// however, doing so will cause DS-mode app startup to break, because the change happens while the ARM7
|
||||||
|
// is still busy clearing/relocating shit
|
||||||
|
//if (newram != oldram)
|
||||||
|
// NDS::ScheduleEvent(NDS::Event_DSi_RAMSizeChange, false, 512*512*512, ApplyNewRAMSize, newram);
|
||||||
|
printf("from %08X, ARM7 %08X, %08X\n", NDS::GetPC(0), NDS::GetPC(1), NDS::ARM7->R[1]);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x04004040:
|
case 0x04004040:
|
||||||
|
@ -1660,7 +1703,7 @@ u8 ARM7IORead8(u32 addr)
|
||||||
case 0x04004501: return DSi_I2C::Cnt;
|
case 0x04004501: return DSi_I2C::Cnt;
|
||||||
|
|
||||||
case 0x04004D00: if (SCFG_BIOS & (1<<10)) return 0; return ConsoleID & 0xFF;
|
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 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 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;
|
case 0x04004D04: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 32) & 0xFF;
|
||||||
|
|
|
@ -52,6 +52,10 @@ u8 KeyY[4][16];
|
||||||
u8 CurKey[16];
|
u8 CurKey[16];
|
||||||
u8 CurMAC[16];
|
u8 CurMAC[16];
|
||||||
|
|
||||||
|
// output MAC for CCM encrypt
|
||||||
|
u8 OutputMAC[16];
|
||||||
|
bool OutputMACDue;
|
||||||
|
|
||||||
AES_ctx Ctx;
|
AES_ctx Ctx;
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,6 +133,9 @@ void Reset()
|
||||||
memset(CurKey, 0, sizeof(CurKey));
|
memset(CurKey, 0, sizeof(CurKey));
|
||||||
memset(CurMAC, 0, sizeof(CurMAC));
|
memset(CurMAC, 0, sizeof(CurMAC));
|
||||||
|
|
||||||
|
memset(OutputMAC, 0, sizeof(OutputMAC));
|
||||||
|
OutputMACDue = false;
|
||||||
|
|
||||||
// initialize keys
|
// initialize keys
|
||||||
|
|
||||||
// slot 0: modcrypt
|
// slot 0: modcrypt
|
||||||
|
@ -272,6 +279,8 @@ void WriteCnt(u32 val)
|
||||||
// transfer start (checkme)
|
// transfer start (checkme)
|
||||||
RemBlocks = BlkCnt >> 16;
|
RemBlocks = BlkCnt >> 16;
|
||||||
|
|
||||||
|
OutputMACDue = false;
|
||||||
|
|
||||||
if (AESMode == 0 && (!(val & (1<<20)))) printf("AES: CCM-DECRYPT MAC FROM WRFIFO, TODO\n");
|
if (AESMode == 0 && (!(val & (1<<20)))) printf("AES: CCM-DECRYPT MAC FROM WRFIFO, TODO\n");
|
||||||
|
|
||||||
if (RemBlocks > 0)
|
if (RemBlocks > 0)
|
||||||
|
@ -347,6 +356,15 @@ u32 ReadOutputFIFO()
|
||||||
DSi::CheckNDMAs(1, 0x2B);
|
DSi::CheckNDMAs(1, 0x2B);
|
||||||
else
|
else
|
||||||
DSi::StopNDMAs(1, 0x2B);
|
DSi::StopNDMAs(1, 0x2B);
|
||||||
|
|
||||||
|
if (OutputMACDue && OutputFIFO->Level() <= 12)
|
||||||
|
{
|
||||||
|
OutputFIFO->Write(*(u32*)&OutputMAC[0]);
|
||||||
|
OutputFIFO->Write(*(u32*)&OutputMAC[4]);
|
||||||
|
OutputFIFO->Write(*(u32*)&OutputMAC[8]);
|
||||||
|
OutputFIFO->Write(*(u32*)&OutputMAC[12]);
|
||||||
|
OutputMACDue = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -429,13 +447,8 @@ void Update()
|
||||||
Ctx.Iv[15] = 0x00;
|
Ctx.Iv[15] = 0x00;
|
||||||
AES_CTR_xcrypt_buffer(&Ctx, CurMAC, 16);
|
AES_CTR_xcrypt_buffer(&Ctx, CurMAC, 16);
|
||||||
|
|
||||||
u8 finalmac[16];
|
Swap16(OutputMAC, CurMAC);
|
||||||
Swap16(finalmac, CurMAC);
|
OutputMACDue = true;
|
||||||
|
|
||||||
OutputFIFO->Write(*(u32*)&finalmac[0]);
|
|
||||||
OutputFIFO->Write(*(u32*)&finalmac[4]);
|
|
||||||
OutputFIFO->Write(*(u32*)&finalmac[8]);
|
|
||||||
OutputFIFO->Write(*(u32*)&finalmac[12]);
|
|
||||||
|
|
||||||
// CHECKME
|
// CHECKME
|
||||||
Cnt &= ~(1<<21);
|
Cnt &= ~(1<<21);
|
||||||
|
|
|
@ -140,7 +140,7 @@ u16 DSi_Camera::ReadReg(u16 addr)
|
||||||
case 0x301A: return ((~StandbyCnt) & 0x4000) >> 12;
|
case 0x301A: return ((~StandbyCnt) & 0x4000) >> 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("DSi_Camera%d: unknown read %04X\n", Num, addr);
|
//printf("DSi_Camera%d: unknown read %04X\n", Num, addr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,5 +162,5 @@ void DSi_Camera::WriteReg(u16 addr, u16 val)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("DSi_Camera%d: unknown write %04X %04X\n", Num, addr, val);
|
//printf("DSi_Camera%d: unknown write %04X %04X\n", Num, addr, val);
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,6 +165,36 @@ void DSi_NWifi::Reset()
|
||||||
printf("NWifi MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
|
printf("NWifi MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
|
||||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||||
|
|
||||||
|
u8 type = SPI_Firmware::GetNWifiVersion();
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case 1: // AR6002
|
||||||
|
ROMID = 0x20000188;
|
||||||
|
ChipID = 0x02000001;
|
||||||
|
HostIntAddr = 0x00500400;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // AR6013
|
||||||
|
ROMID = 0x23000024;
|
||||||
|
ChipID = 0x0D000000;
|
||||||
|
HostIntAddr = 0x00520000;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // AR6014 (3DS)
|
||||||
|
ROMID = 0x2300006F;
|
||||||
|
ChipID = 0x0D000001;
|
||||||
|
HostIntAddr = 0x00520000;
|
||||||
|
printf("NWifi: hardware is 3DS type, unchecked\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("NWifi: unknown hardware type %02X, assuming AR6002\n");
|
||||||
|
ROMID = 0x20000188;
|
||||||
|
ChipID = 0x02000001;
|
||||||
|
HostIntAddr = 0x00500400;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
memset(EEPROM, 0, 0x400);
|
memset(EEPROM, 0, 0x400);
|
||||||
|
|
||||||
*(u32*)&EEPROM[0x000] = 0x300;
|
*(u32*)&EEPROM[0x000] = 0x300;
|
||||||
|
@ -755,8 +785,7 @@ void DSi_NWifi::BMI_Command()
|
||||||
case 0x08: // BMI_GET_TARGET_ID
|
case 0x08: // BMI_GET_TARGET_ID
|
||||||
MB_Write32(4, 0xFFFFFFFF);
|
MB_Write32(4, 0xFFFFFFFF);
|
||||||
MB_Write32(4, 0x0000000C);
|
MB_Write32(4, 0x0000000C);
|
||||||
//MB_Write32(4, 0x20000118);
|
MB_Write32(4, ROMID);
|
||||||
MB_Write32(4, 0x23000024); // ROM version (TODO: how to determine correct one?)
|
|
||||||
MB_Write32(4, 0x00000002);
|
MB_Write32(4, 0x00000002);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1436,7 +1465,7 @@ u32 DSi_NWifi::WindowRead(u32 addr)
|
||||||
{
|
{
|
||||||
printf("NWifi: window read %08X\n", addr);
|
printf("NWifi: window read %08X\n", addr);
|
||||||
|
|
||||||
if ((addr & 0xFFFF00) == 0x520000)
|
if ((addr & 0xFFFF00) == HostIntAddr)
|
||||||
{
|
{
|
||||||
// RAM host interest area
|
// RAM host interest area
|
||||||
// TODO: different base based on hardware version
|
// TODO: different base based on hardware version
|
||||||
|
@ -1462,9 +1491,7 @@ u32 DSi_NWifi::WindowRead(u32 addr)
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case 0x40EC: // chip ID
|
case 0x40EC: // chip ID
|
||||||
// 0D000000 / 0D000001 == AR6013
|
return ChipID;
|
||||||
// TODO: check firmware.bin to determine the correct value
|
|
||||||
return 0x0D000001;
|
|
||||||
|
|
||||||
// SOC_RESET_CAUSE
|
// SOC_RESET_CAUSE
|
||||||
case 0x40C0: return 2;
|
case 0x40C0: return 2;
|
||||||
|
|
|
@ -127,6 +127,10 @@ private:
|
||||||
|
|
||||||
u32 WindowData, WindowReadAddr, WindowWriteAddr;
|
u32 WindowData, WindowReadAddr, WindowWriteAddr;
|
||||||
|
|
||||||
|
u32 ROMID;
|
||||||
|
u32 ChipID;
|
||||||
|
u32 HostIntAddr;
|
||||||
|
|
||||||
u8 EEPROM[0x400];
|
u8 EEPROM[0x400];
|
||||||
u32 EEPROMReady;
|
u32 EEPROMReady;
|
||||||
|
|
||||||
|
|
|
@ -117,13 +117,19 @@ void DSi_SDHost::Reset()
|
||||||
|
|
||||||
if (Num == 0)
|
if (Num == 0)
|
||||||
{
|
{
|
||||||
// TODO: eventually pull from host filesystem
|
DSi_MMCStorage* sd;
|
||||||
/*DSi_MMCStorage* sd = new DSi_MMCStorage(this, false, "sd.bin");
|
DSi_MMCStorage* mmc;
|
||||||
u8 sd_cid[16] = {0xBD, 0x12, 0x34, 0x56, 0x78, 0x03, 0x4D, 0x30, 0x30, 0x46, 0x50, 0x41, 0x00, 0x00, 0x15, 0x00};
|
|
||||||
sd->SetCID(sd_cid);*/
|
|
||||||
DSi_MMCStorage* sd = NULL;
|
|
||||||
|
|
||||||
DSi_MMCStorage* mmc = new DSi_MMCStorage(this, true, Config::DSiNANDPath);
|
if (Config::DSiSDEnable)
|
||||||
|
{
|
||||||
|
sd = new DSi_MMCStorage(this, false, Config::DSiSDPath);
|
||||||
|
u8 sd_cid[16] = {0xBD, 0x12, 0x34, 0x56, 0x78, 0x03, 0x4D, 0x30, 0x30, 0x46, 0x50, 0x41, 0x00, 0x00, 0x15, 0x00};
|
||||||
|
sd->SetCID(sd_cid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sd = nullptr;
|
||||||
|
|
||||||
|
mmc = new DSi_MMCStorage(this, true, Config::DSiNANDPath);
|
||||||
mmc->SetCID(DSi::eMMC_CID);
|
mmc->SetCID(DSi::eMMC_CID);
|
||||||
|
|
||||||
Ports[0] = sd;
|
Ports[0] = sd;
|
||||||
|
@ -429,14 +435,14 @@ u16 DSi_SDHost::Read(u32 addr)
|
||||||
if (!Num)
|
if (!Num)
|
||||||
{
|
{
|
||||||
if (Ports[0]) // basic check of whether the SD card is inserted
|
if (Ports[0]) // basic check of whether the SD card is inserted
|
||||||
ret |= 0x0030;
|
ret |= 0x00B0;
|
||||||
else
|
else
|
||||||
ret |= 0x0008;
|
ret |= 0x0008;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// SDIO wifi is always inserted, I guess
|
// SDIO wifi is always inserted, I guess
|
||||||
ret |= 0x0030;
|
ret |= 0x00B0;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ class DSi_SDDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DSi_SDDevice(DSi_SDHost* host) { Host = host; IRQ = false; }
|
DSi_SDDevice(DSi_SDHost* host) { Host = host; IRQ = false; }
|
||||||
~DSi_SDDevice() {}
|
virtual ~DSi_SDDevice() {}
|
||||||
|
|
||||||
virtual void Reset() = 0;
|
virtual void Reset() = 0;
|
||||||
|
|
||||||
|
|
13
src/GPU.cpp
13
src/GPU.cpp
|
@ -280,6 +280,7 @@ void AssignFramebuffers()
|
||||||
|
|
||||||
void InitRenderer(int renderer)
|
void InitRenderer(int renderer)
|
||||||
{
|
{
|
||||||
|
#ifdef OGLRENDERER_ENABLED
|
||||||
if (renderer == 1)
|
if (renderer == 1)
|
||||||
{
|
{
|
||||||
if (!GLCompositor::Init())
|
if (!GLCompositor::Init())
|
||||||
|
@ -292,8 +293,8 @@ void InitRenderer(int renderer)
|
||||||
renderer = 0;
|
renderer = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (renderer == 0)
|
#endif
|
||||||
{
|
{
|
||||||
GPU3D::SoftRenderer::Init();
|
GPU3D::SoftRenderer::Init();
|
||||||
}
|
}
|
||||||
|
@ -308,11 +309,13 @@ void DeInitRenderer()
|
||||||
{
|
{
|
||||||
GPU3D::SoftRenderer::DeInit();
|
GPU3D::SoftRenderer::DeInit();
|
||||||
}
|
}
|
||||||
|
#ifdef OGLRENDERER_ENABLED
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GPU3D::GLRenderer::DeInit();
|
GPU3D::GLRenderer::DeInit();
|
||||||
GLCompositor::DeInit();
|
GLCompositor::DeInit();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetRenderer()
|
void ResetRenderer()
|
||||||
|
@ -321,11 +324,13 @@ void ResetRenderer()
|
||||||
{
|
{
|
||||||
GPU3D::SoftRenderer::Reset();
|
GPU3D::SoftRenderer::Reset();
|
||||||
}
|
}
|
||||||
|
#ifdef OGLRENDERER_ENABLED
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GLCompositor::Reset();
|
GLCompositor::Reset();
|
||||||
GPU3D::GLRenderer::Reset();
|
GPU3D::GLRenderer::Reset();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetRenderSettings(int renderer, RenderSettings& settings)
|
void SetRenderSettings(int renderer, RenderSettings& settings)
|
||||||
|
@ -364,11 +369,13 @@ void SetRenderSettings(int renderer, RenderSettings& settings)
|
||||||
{
|
{
|
||||||
GPU3D::SoftRenderer::SetRenderSettings(settings);
|
GPU3D::SoftRenderer::SetRenderSettings(settings);
|
||||||
}
|
}
|
||||||
|
#ifdef OGLRENDERER_ENABLED
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GLCompositor::SetRenderSettings(settings);
|
GLCompositor::SetRenderSettings(settings);
|
||||||
GPU3D::GLRenderer::SetRenderSettings(settings);
|
GPU3D::GLRenderer::SetRenderSettings(settings);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1055,7 +1062,9 @@ void StartScanline(u32 line)
|
||||||
GPU2D_B->VBlank();
|
GPU2D_B->VBlank();
|
||||||
GPU3D::VBlank();
|
GPU3D::VBlank();
|
||||||
|
|
||||||
|
#ifdef OGLRENDERER_ENABLED
|
||||||
if (Accelerated) GLCompositor::RenderFrame();
|
if (Accelerated) GLCompositor::RenderFrame();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if (VCount == 144)
|
else if (VCount == 144)
|
||||||
{
|
{
|
||||||
|
|
|
@ -79,6 +79,7 @@ typedef struct
|
||||||
bool Soft_Threaded;
|
bool Soft_Threaded;
|
||||||
|
|
||||||
int GL_ScaleFactor;
|
int GL_ScaleFactor;
|
||||||
|
bool GL_BetterPolygons;
|
||||||
|
|
||||||
} RenderSettings;
|
} RenderSettings;
|
||||||
|
|
||||||
|
@ -436,6 +437,7 @@ void SetDispStat(u32 cpu, u16 val);
|
||||||
|
|
||||||
void SetVCount(u16 val);
|
void SetVCount(u16 val);
|
||||||
|
|
||||||
|
#ifdef OGLRENDERER_ENABLED
|
||||||
namespace GLCompositor
|
namespace GLCompositor
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -449,6 +451,7 @@ void RenderFrame();
|
||||||
void BindOutputTexture();
|
void BindOutputTexture();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,9 +35,6 @@
|
||||||
// * [Gericom] bit15 is used as bottom green bit for palettes. TODO: check where this applies.
|
// * [Gericom] bit15 is used as bottom green bit for palettes. TODO: check where this applies.
|
||||||
// tested on the normal BG palette and applies there
|
// tested on the normal BG palette and applies there
|
||||||
//
|
//
|
||||||
// oh also, changing DISPCNT bit16-17 midframe doesn't work (ignored? applied for next frame?)
|
|
||||||
// TODO, eventually: check whether other DISPCNT bits can be changed midframe
|
|
||||||
//
|
|
||||||
// for VRAM display mode, VRAM must be mapped to LCDC
|
// for VRAM display mode, VRAM must be mapped to LCDC
|
||||||
//
|
//
|
||||||
// FIFO display mode:
|
// FIFO display mode:
|
||||||
|
@ -78,7 +75,10 @@
|
||||||
// * for rotscaled sprites: coordinates that are inside the sprite are clamped to the sprite region
|
// * for rotscaled sprites: coordinates that are inside the sprite are clamped to the sprite region
|
||||||
// after being transformed for mosaic
|
// after being transformed for mosaic
|
||||||
|
|
||||||
// TODO: find which parts of DISPCNT are latched. for example, not possible to change video mode midframe.
|
// TODO: master brightness, display capture and mainmem FIFO are separate circuitry, distinct from
|
||||||
|
// the tile renderers.
|
||||||
|
// for example these aren't affected by POWCNT GPU-disable bits.
|
||||||
|
// to model the hardware more accurately, the relevant logic should be moved to GPU.cpp.
|
||||||
|
|
||||||
|
|
||||||
GPU2D::GPU2D(u32 num)
|
GPU2D::GPU2D(u32 num)
|
||||||
|
@ -102,6 +102,7 @@ GPU2D::~GPU2D()
|
||||||
|
|
||||||
void GPU2D::Reset()
|
void GPU2D::Reset()
|
||||||
{
|
{
|
||||||
|
Enabled = false;
|
||||||
DispCnt = 0;
|
DispCnt = 0;
|
||||||
memset(BGCnt, 0, 4*2);
|
memset(BGCnt, 0, 4*2);
|
||||||
memset(BGXPos, 0, 4*2);
|
memset(BGXPos, 0, 4*2);
|
||||||
|
@ -309,8 +310,6 @@ u32 GPU2D::Read32(u32 addr)
|
||||||
|
|
||||||
void GPU2D::Write8(u32 addr, u8 val)
|
void GPU2D::Write8(u32 addr, u8 val)
|
||||||
{
|
{
|
||||||
if (!Enabled) return;
|
|
||||||
|
|
||||||
switch (addr & 0x00000FFF)
|
switch (addr & 0x00000FFF)
|
||||||
{
|
{
|
||||||
case 0x000:
|
case 0x000:
|
||||||
|
@ -329,7 +328,12 @@ void GPU2D::Write8(u32 addr, u8 val)
|
||||||
DispCnt = (DispCnt & 0x00FFFFFF) | (val << 24);
|
DispCnt = (DispCnt & 0x00FFFFFF) | (val << 24);
|
||||||
if (Num) DispCnt &= 0xC0B1FFF7;
|
if (Num) DispCnt &= 0xC0B1FFF7;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Enabled) return;
|
||||||
|
|
||||||
|
switch (addr & 0x00000FFF)
|
||||||
|
{
|
||||||
case 0x008: BGCnt[0] = (BGCnt[0] & 0xFF00) | val; return;
|
case 0x008: BGCnt[0] = (BGCnt[0] & 0xFF00) | val; return;
|
||||||
case 0x009: BGCnt[0] = (BGCnt[0] & 0x00FF) | (val << 8); return;
|
case 0x009: BGCnt[0] = (BGCnt[0] & 0x00FF) | (val << 8); return;
|
||||||
case 0x00A: BGCnt[1] = (BGCnt[1] & 0xFF00) | val; return;
|
case 0x00A: BGCnt[1] = (BGCnt[1] & 0xFF00) | val; return;
|
||||||
|
@ -405,8 +409,6 @@ void GPU2D::Write8(u32 addr, u8 val)
|
||||||
|
|
||||||
void GPU2D::Write16(u32 addr, u16 val)
|
void GPU2D::Write16(u32 addr, u16 val)
|
||||||
{
|
{
|
||||||
if (!Enabled) return;
|
|
||||||
|
|
||||||
switch (addr & 0x00000FFF)
|
switch (addr & 0x00000FFF)
|
||||||
{
|
{
|
||||||
case 0x000:
|
case 0x000:
|
||||||
|
@ -418,6 +420,22 @@ void GPU2D::Write16(u32 addr, u16 val)
|
||||||
if (Num) DispCnt &= 0xC0B1FFF7;
|
if (Num) DispCnt &= 0xC0B1FFF7;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case 0x068:
|
||||||
|
DispFIFO[DispFIFOWritePtr] = val;
|
||||||
|
return;
|
||||||
|
case 0x06A:
|
||||||
|
DispFIFO[DispFIFOWritePtr+1] = val;
|
||||||
|
DispFIFOWritePtr += 2;
|
||||||
|
DispFIFOWritePtr &= 0xF;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 0x06C: MasterBrightness = val; return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Enabled) return;
|
||||||
|
|
||||||
|
switch (addr & 0x00000FFF)
|
||||||
|
{
|
||||||
case 0x008: BGCnt[0] = val; return;
|
case 0x008: BGCnt[0] = val; return;
|
||||||
case 0x00A: BGCnt[1] = val; return;
|
case 0x00A: BGCnt[1] = val; return;
|
||||||
case 0x00C: BGCnt[2] = val; return;
|
case 0x00C: BGCnt[2] = val; return;
|
||||||
|
@ -526,17 +544,6 @@ void GPU2D::Write16(u32 addr, u16 val)
|
||||||
EVY = val & 0x1F;
|
EVY = val & 0x1F;
|
||||||
if (EVY > 16) EVY = 16;
|
if (EVY > 16) EVY = 16;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x068:
|
|
||||||
DispFIFO[DispFIFOWritePtr] = val;
|
|
||||||
return;
|
|
||||||
case 0x06A:
|
|
||||||
DispFIFO[DispFIFOWritePtr+1] = val;
|
|
||||||
DispFIFOWritePtr += 2;
|
|
||||||
DispFIFOWritePtr &= 0xF;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case 0x06C: MasterBrightness = val; return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("unknown GPU write16 %08X %04X\n", addr, val);
|
//printf("unknown GPU write16 %08X %04X\n", addr, val);
|
||||||
|
@ -544,8 +551,6 @@ void GPU2D::Write16(u32 addr, u16 val)
|
||||||
|
|
||||||
void GPU2D::Write32(u32 addr, u32 val)
|
void GPU2D::Write32(u32 addr, u32 val)
|
||||||
{
|
{
|
||||||
if (!Enabled) return;
|
|
||||||
|
|
||||||
switch (addr & 0x00000FFF)
|
switch (addr & 0x00000FFF)
|
||||||
{
|
{
|
||||||
case 0x000:
|
case 0x000:
|
||||||
|
@ -553,6 +558,24 @@ void GPU2D::Write32(u32 addr, u32 val)
|
||||||
if (Num) DispCnt &= 0xC0B1FFF7;
|
if (Num) DispCnt &= 0xC0B1FFF7;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case 0x064:
|
||||||
|
// TODO: check what happens when writing to it during display
|
||||||
|
// esp. if a capture is happening
|
||||||
|
CaptureCnt = val & 0xEF3F1F1F;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 0x068:
|
||||||
|
DispFIFO[DispFIFOWritePtr] = val & 0xFFFF;
|
||||||
|
DispFIFO[DispFIFOWritePtr+1] = val >> 16;
|
||||||
|
DispFIFOWritePtr += 2;
|
||||||
|
DispFIFOWritePtr &= 0xF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Enabled) return;
|
||||||
|
|
||||||
|
switch (addr & 0x00000FFF)
|
||||||
|
{
|
||||||
case 0x028:
|
case 0x028:
|
||||||
if (val & 0x08000000) val |= 0xF0000000;
|
if (val & 0x08000000) val |= 0xF0000000;
|
||||||
BGXRef[0] = val;
|
BGXRef[0] = val;
|
||||||
|
@ -574,19 +597,6 @@ void GPU2D::Write32(u32 addr, u32 val)
|
||||||
BGYRef[1] = val;
|
BGYRef[1] = val;
|
||||||
if (GPU::VCount < 192) BGYRefInternal[1] = BGYRef[1];
|
if (GPU::VCount < 192) BGYRefInternal[1] = BGYRef[1];
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x064:
|
|
||||||
// TODO: check what happens when writing to it during display
|
|
||||||
// esp. if a capture is happening
|
|
||||||
CaptureCnt = val & 0xEF3F1F1F;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case 0x068:
|
|
||||||
DispFIFO[DispFIFOWritePtr] = val & 0xFFFF;
|
|
||||||
DispFIFO[DispFIFOWritePtr+1] = val >> 16;
|
|
||||||
DispFIFOWritePtr += 2;
|
|
||||||
DispFIFOWritePtr &= 0xF;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Write16(addr, val&0xFFFF);
|
Write16(addr, val&0xFFFF);
|
||||||
|
@ -805,7 +815,6 @@ void GPU2D::DrawScanline(u32 line)
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (; i < (stride & ~1); i+=2)
|
for (; i < (stride & ~1); i+=2)
|
||||||
*(u64*)&dst[i] = *(u64*)&BGOBJLine[i];
|
*(u64*)&dst[i] = *(u64*)&BGOBJLine[i];
|
||||||
if (stride & 1) dst[i] = BGOBJLine[i];
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -940,6 +949,7 @@ void GPU2D::VBlankEnd()
|
||||||
//OBJMosaicY = 0;
|
//OBJMosaicY = 0;
|
||||||
//OBJMosaicYCount = 0;
|
//OBJMosaicYCount = 0;
|
||||||
|
|
||||||
|
#ifdef OGLRENDERER_ENABLED
|
||||||
if (Accelerated)
|
if (Accelerated)
|
||||||
{
|
{
|
||||||
if ((Num == 0) && (CaptureCnt & (1<<31)) && (((CaptureCnt >> 29) & 0x3) != 1))
|
if ((Num == 0) && (CaptureCnt & (1<<31)) && (((CaptureCnt >> 29) & 0x3) != 1))
|
||||||
|
@ -947,6 +957,7 @@ void GPU2D::VBlankEnd()
|
||||||
GPU3D::GLRenderer::PrepareCaptureFrame();
|
GPU3D::GLRenderer::PrepareCaptureFrame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -401,8 +401,33 @@ void DoSavestate(Savestate* file)
|
||||||
file->Var32(&NumTestCommands);
|
file->Var32(&NumTestCommands);
|
||||||
|
|
||||||
file->Var32(&DispCnt);
|
file->Var32(&DispCnt);
|
||||||
|
file->Var8(&AlphaRefVal);
|
||||||
file->Var8(&AlphaRef);
|
file->Var8(&AlphaRef);
|
||||||
|
|
||||||
|
file->VarArray(ToonTable, 32*2);
|
||||||
|
file->VarArray(EdgeTable, 8*2);
|
||||||
|
|
||||||
|
file->Var32(&FogColor);
|
||||||
|
file->Var32(&FogOffset);
|
||||||
|
file->VarArray(FogDensityTable, 32);
|
||||||
|
|
||||||
|
file->Var32(&ClearAttr1);
|
||||||
|
file->Var32(&ClearAttr2);
|
||||||
|
|
||||||
|
file->Var32(&RenderDispCnt);
|
||||||
|
file->Var8(&RenderAlphaRef);
|
||||||
|
|
||||||
|
file->VarArray(RenderToonTable, 32*2);
|
||||||
|
file->VarArray(RenderEdgeTable, 8*2);
|
||||||
|
|
||||||
|
file->Var32(&RenderFogColor);
|
||||||
|
file->Var32(&RenderFogOffset);
|
||||||
|
file->Var32(&RenderFogShift);
|
||||||
|
file->VarArray(RenderFogDensityTable, 34);
|
||||||
|
|
||||||
|
file->Var32(&RenderClearAttr1);
|
||||||
|
file->Var32(&RenderClearAttr2);
|
||||||
|
|
||||||
file->Var32(&ZeroDotWLimit);
|
file->Var32(&ZeroDotWLimit);
|
||||||
|
|
||||||
file->Var32(&GXStat);
|
file->Var32(&GXStat);
|
||||||
|
@ -445,7 +470,7 @@ void DoSavestate(Savestate* file)
|
||||||
file->VarArray(vtx->Color, sizeof(s32)*3);
|
file->VarArray(vtx->Color, sizeof(s32)*3);
|
||||||
file->VarArray(vtx->TexCoords, sizeof(s16)*2);
|
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->FinalPosition, sizeof(s32)*2);
|
||||||
file->VarArray(vtx->FinalColor, sizeof(s32)*3);
|
file->VarArray(vtx->FinalColor, sizeof(s32)*3);
|
||||||
|
@ -471,9 +496,6 @@ void DoSavestate(Savestate* file)
|
||||||
file->Var32(&NumPolygons);
|
file->Var32(&NumPolygons);
|
||||||
file->Var32(&NumOpaquePolygons);
|
file->Var32(&NumOpaquePolygons);
|
||||||
|
|
||||||
file->Var32(&ClearAttr1);
|
|
||||||
file->Var32(&ClearAttr2);
|
|
||||||
|
|
||||||
file->Var32(&FlushRequest);
|
file->Var32(&FlushRequest);
|
||||||
file->Var32(&FlushAttributes);
|
file->Var32(&FlushAttributes);
|
||||||
|
|
||||||
|
@ -485,7 +507,7 @@ void DoSavestate(Savestate* file)
|
||||||
file->VarArray(vtx->Color, sizeof(s32)*3);
|
file->VarArray(vtx->Color, sizeof(s32)*3);
|
||||||
file->VarArray(vtx->TexCoords, sizeof(s16)*2);
|
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->FinalPosition, sizeof(s32)*2);
|
||||||
file->VarArray(vtx->FinalColor, sizeof(s32)*3);
|
file->VarArray(vtx->FinalColor, sizeof(s32)*3);
|
||||||
|
@ -523,17 +545,17 @@ void DoSavestate(Savestate* file)
|
||||||
|
|
||||||
file->VarArray(poly->FinalZ, sizeof(s32)*10);
|
file->VarArray(poly->FinalZ, sizeof(s32)*10);
|
||||||
file->VarArray(poly->FinalW, 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->Attr);
|
||||||
file->Var32(&poly->TexParam);
|
file->Var32(&poly->TexParam);
|
||||||
file->Var32(&poly->TexPalette);
|
file->Var32(&poly->TexPalette);
|
||||||
|
|
||||||
file->Var32((u32*)&poly->FacingView);
|
file->Bool32(&poly->FacingView);
|
||||||
file->Var32((u32*)&poly->Translucent);
|
file->Bool32(&poly->Translucent);
|
||||||
|
|
||||||
file->Var32((u32*)&poly->IsShadowMask);
|
file->Bool32(&poly->IsShadowMask);
|
||||||
file->Var32((u32*)&poly->IsShadow);
|
file->Bool32(&poly->IsShadow);
|
||||||
|
|
||||||
if (file->IsAtleastVersion(4, 1))
|
if (file->IsAtleastVersion(4, 1))
|
||||||
file->Var32((u32*)&poly->Type);
|
file->Var32((u32*)&poly->Type);
|
||||||
|
@ -2506,13 +2528,19 @@ void VBlank()
|
||||||
void VCount215()
|
void VCount215()
|
||||||
{
|
{
|
||||||
if (GPU::Renderer == 0) SoftRenderer::RenderFrame();
|
if (GPU::Renderer == 0) SoftRenderer::RenderFrame();
|
||||||
|
#ifdef OGLRENDERER_ENABLED
|
||||||
else GLRenderer::RenderFrame();
|
else GLRenderer::RenderFrame();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
u32* GetLine(int line)
|
u32* GetLine(int line)
|
||||||
{
|
{
|
||||||
if (GPU::Renderer == 0) return SoftRenderer::GetLine(line);
|
if (GPU::Renderer == 0) return SoftRenderer::GetLine(line);
|
||||||
|
#ifdef OGLRENDERER_ENABLED
|
||||||
else return GLRenderer::GetLine(line);
|
else return GLRenderer::GetLine(line);
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -139,6 +139,7 @@ u32* GetLine(int line);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef OGLRENDERER_ENABLED
|
||||||
namespace GLRenderer
|
namespace GLRenderer
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -154,6 +155,7 @@ u32* GetLine(int line);
|
||||||
void SetupAccelFrame();
|
void SetupAccelFrame();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ GLuint TexMemID;
|
||||||
GLuint TexPalMemID;
|
GLuint TexPalMemID;
|
||||||
|
|
||||||
int ScaleFactor;
|
int ScaleFactor;
|
||||||
bool Antialias;
|
bool BetterPolygons;
|
||||||
int ScreenW, ScreenH;
|
int ScreenW, ScreenH;
|
||||||
|
|
||||||
GLuint FramebufferTex[8];
|
GLuint FramebufferTex[8];
|
||||||
|
@ -342,9 +342,6 @@ bool Init()
|
||||||
SetupDefaultTexParams(FramebufferTex[5]);
|
SetupDefaultTexParams(FramebufferTex[5]);
|
||||||
SetupDefaultTexParams(FramebufferTex[7]);
|
SetupDefaultTexParams(FramebufferTex[7]);
|
||||||
|
|
||||||
// downscale framebuffer for antialiased mode
|
|
||||||
SetupDefaultTexParams(FramebufferTex[2]);
|
|
||||||
|
|
||||||
// downscale framebuffer for display capture (always 256x192)
|
// downscale framebuffer for display capture (always 256x192)
|
||||||
SetupDefaultTexParams(FramebufferTex[3]);
|
SetupDefaultTexParams(FramebufferTex[3]);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 192, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 192, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
@ -372,6 +369,8 @@ bool Init()
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, 1024, 48, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, 1024, 48, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,52 +403,27 @@ void Reset()
|
||||||
void SetRenderSettings(GPU::RenderSettings& settings)
|
void SetRenderSettings(GPU::RenderSettings& settings)
|
||||||
{
|
{
|
||||||
int scale = settings.GL_ScaleFactor;
|
int scale = settings.GL_ScaleFactor;
|
||||||
bool antialias = false; // REMOVE ME!
|
|
||||||
|
|
||||||
if (antialias) scale *= 2;
|
|
||||||
|
|
||||||
ScaleFactor = scale;
|
ScaleFactor = scale;
|
||||||
Antialias = antialias;
|
BetterPolygons = settings.GL_BetterPolygons;
|
||||||
|
|
||||||
ScreenW = 256 * scale;
|
ScreenW = 256 * scale;
|
||||||
ScreenH = 192 * scale;
|
ScreenH = 192 * scale;
|
||||||
|
|
||||||
if (!antialias)
|
glBindTexture(GL_TEXTURE_2D, FramebufferTex[0]);
|
||||||
{
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW, ScreenH, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
glBindTexture(GL_TEXTURE_2D, FramebufferTex[0]);
|
glBindTexture(GL_TEXTURE_2D, FramebufferTex[1]);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW, ScreenH, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW, ScreenH, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
glBindTexture(GL_TEXTURE_2D, FramebufferTex[1]);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW, ScreenH, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
glBindTexture(GL_TEXTURE_2D, FramebufferTex[4]);
|
||||||
glBindTexture(GL_TEXTURE_2D, FramebufferTex[2]);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, ScreenW, ScreenH, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
glBindTexture(GL_TEXTURE_2D, FramebufferTex[5]);
|
||||||
glBindTexture(GL_TEXTURE_2D, FramebufferTex[4]);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ScreenW, ScreenH, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, ScreenW, ScreenH, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
|
|
||||||
//glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH32F_STENCIL8, ScreenW, ScreenH, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL);
|
glBindTexture(GL_TEXTURE_2D, FramebufferTex[6]);
|
||||||
glBindTexture(GL_TEXTURE_2D, FramebufferTex[5]);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, ScreenW, ScreenH, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
|
||||||
//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, ScreenW, ScreenH, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, NULL);
|
glBindTexture(GL_TEXTURE_2D, FramebufferTex[7]);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ScreenW, ScreenH, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ScreenW, ScreenH, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||||
glBindTexture(GL_TEXTURE_2D, FramebufferTex[6]);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 1, 1, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, FramebufferTex[7]);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glBindTexture(GL_TEXTURE_2D, FramebufferTex[0]);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW/2, ScreenH/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, FramebufferTex[1]);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW/2, ScreenH/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, FramebufferTex[2]);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW, ScreenH, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, FramebufferTex[4]);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, ScreenW/2, ScreenH/2, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, FramebufferTex[5]);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, ScreenW/2, ScreenH/2, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, FramebufferTex[6]);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, ScreenW, ScreenH, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, FramebufferTex[7]);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8UI, ScreenW, ScreenH, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[3]);
|
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[3]);
|
||||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FramebufferTex[3], 0);
|
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FramebufferTex[3], 0);
|
||||||
|
@ -464,12 +438,6 @@ void SetRenderSettings(GPU::RenderSettings& settings)
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[1]);
|
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[1]);
|
||||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, FramebufferTex[1], 0);
|
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_DEPTH_STENCIL_ATTACHMENT, FramebufferTex[6], 0);
|
||||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, FramebufferTex[7], 0);
|
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, FramebufferTex[7], 0);
|
||||||
glDrawBuffers(2, fbassign);
|
glDrawBuffers(2, fbassign);
|
||||||
|
@ -479,6 +447,8 @@ void SetRenderSettings(GPU::RenderSettings& settings)
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, PixelbufferID);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, PixelbufferID);
|
||||||
glBufferData(GL_PIXEL_PACK_BUFFER, 256*192*4, NULL, GL_DYNAMIC_READ);
|
glBufferData(GL_PIXEL_PACK_BUFFER, 256*192*4, NULL, GL_DYNAMIC_READ);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
//glLineWidth(scale);
|
//glLineWidth(scale);
|
||||||
//glLineWidth(1.5);
|
//glLineWidth(1.5);
|
||||||
}
|
}
|
||||||
|
@ -527,6 +497,67 @@ void SetupPolygon(RendererPolygon* rp, Polygon* polygon)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32* SetupVertex(Polygon* poly, int vid, Vertex* vtx, u32 vtxattr, u32* vptr)
|
||||||
|
{
|
||||||
|
u32 z = poly->FinalZ[vid];
|
||||||
|
u32 w = poly->FinalW[vid];
|
||||||
|
|
||||||
|
u32 alpha = (poly->Attr >> 16) & 0x1F;
|
||||||
|
|
||||||
|
// Z should always fit within 16 bits, so it's okay to do this
|
||||||
|
u32 zshift = 0;
|
||||||
|
while (z > 0xFFFF) { z >>= 1; zshift++; }
|
||||||
|
|
||||||
|
u32 x, y;
|
||||||
|
if (ScaleFactor > 1)
|
||||||
|
{
|
||||||
|
x = (vtx->HiresPosition[0] * ScaleFactor) >> 4;
|
||||||
|
y = (vtx->HiresPosition[1] * ScaleFactor) >> 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = vtx->FinalPosition[0];
|
||||||
|
y = vtx->FinalPosition[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// correct nearly-vertical edges that would look vertical on the DS
|
||||||
|
/*{
|
||||||
|
int vtopid = vid - 1;
|
||||||
|
if (vtopid < 0) vtopid = poly->NumVertices-1;
|
||||||
|
Vertex* vtop = poly->Vertices[vtopid];
|
||||||
|
if (vtop->FinalPosition[1] >= vtx->FinalPosition[1])
|
||||||
|
{
|
||||||
|
vtopid = vid + 1;
|
||||||
|
if (vtopid >= poly->NumVertices) vtopid = 0;
|
||||||
|
vtop = poly->Vertices[vtopid];
|
||||||
|
}
|
||||||
|
if ((vtop->FinalPosition[1] < vtx->FinalPosition[1]) &&
|
||||||
|
(vtx->FinalPosition[0] == vtop->FinalPosition[0]-1))
|
||||||
|
{
|
||||||
|
if (ScaleFactor > 1)
|
||||||
|
x = (vtop->HiresPosition[0] * ScaleFactor) >> 4;
|
||||||
|
else
|
||||||
|
x = vtop->FinalPosition[0];
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
*vptr++ = x | (y << 16);
|
||||||
|
*vptr++ = z | (w << 16);
|
||||||
|
|
||||||
|
*vptr++ = (vtx->FinalColor[0] >> 1) |
|
||||||
|
((vtx->FinalColor[1] >> 1) << 8) |
|
||||||
|
((vtx->FinalColor[2] >> 1) << 16) |
|
||||||
|
(alpha << 24);
|
||||||
|
|
||||||
|
*vptr++ = (u16)vtx->TexCoords[0] | ((u16)vtx->TexCoords[1] << 16);
|
||||||
|
|
||||||
|
*vptr++ = vtxattr | (zshift << 16);
|
||||||
|
*vptr++ = poly->TexParam;
|
||||||
|
*vptr++ = poly->TexPalette;
|
||||||
|
|
||||||
|
return vptr;
|
||||||
|
}
|
||||||
|
|
||||||
void BuildPolygons(RendererPolygon* polygons, int npolys)
|
void BuildPolygons(RendererPolygon* polygons, int npolys)
|
||||||
{
|
{
|
||||||
u32* vptr = &VertexBuffer[0];
|
u32* vptr = &VertexBuffer[0];
|
||||||
|
@ -564,43 +595,16 @@ void BuildPolygons(RendererPolygon* polygons, int npolys)
|
||||||
{
|
{
|
||||||
Vertex* vtx = poly->Vertices[j];
|
Vertex* vtx = poly->Vertices[j];
|
||||||
|
|
||||||
u32 z = poly->FinalZ[j];
|
|
||||||
u32 w = poly->FinalW[j];
|
|
||||||
|
|
||||||
// Z should always fit within 16 bits, so it's okay to do this
|
|
||||||
u32 zshift = 0;
|
|
||||||
while (z > 0xFFFF) { z >>= 1; zshift++; }
|
|
||||||
|
|
||||||
u32 x, y;
|
|
||||||
if (ScaleFactor > 1)
|
|
||||||
{
|
|
||||||
x = (vtx->HiresPosition[0] * ScaleFactor) >> 4;
|
|
||||||
y = (vtx->HiresPosition[1] * ScaleFactor) >> 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = vtx->FinalPosition[0];
|
|
||||||
y = vtx->FinalPosition[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j > 0)
|
if (j > 0)
|
||||||
{
|
{
|
||||||
if (lastx == x && lasty == y) continue;
|
if (lastx == vtx->FinalPosition[0] &&
|
||||||
|
lasty == vtx->FinalPosition[1]) continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
*vptr++ = x | (y << 16);
|
lastx = vtx->FinalPosition[0];
|
||||||
*vptr++ = z | (w << 16);
|
lasty = vtx->FinalPosition[1];
|
||||||
|
|
||||||
*vptr++ = (vtx->FinalColor[0] >> 1) |
|
vptr = SetupVertex(poly, j, vtx, vtxattr, vptr);
|
||||||
((vtx->FinalColor[1] >> 1) << 8) |
|
|
||||||
((vtx->FinalColor[2] >> 1) << 16) |
|
|
||||||
(alpha << 24);
|
|
||||||
|
|
||||||
*vptr++ = (u16)vtx->TexCoords[0] | ((u16)vtx->TexCoords[1] << 16);
|
|
||||||
|
|
||||||
*vptr++ = vtxattr | (zshift << 16);
|
|
||||||
*vptr++ = poly->TexParam;
|
|
||||||
*vptr++ = poly->TexPalette;
|
|
||||||
|
|
||||||
*iptr++ = vidx;
|
*iptr++ = vidx;
|
||||||
rp->NumIndices++;
|
rp->NumIndices++;
|
||||||
|
@ -610,57 +614,148 @@ void BuildPolygons(RendererPolygon* polygons, int npolys)
|
||||||
if (nout >= 2) break;
|
if (nout >= 2) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (poly->NumVertices == 3) // regular triangle
|
||||||
{
|
{
|
||||||
rp->PrimType = GL_TRIANGLES;
|
rp->PrimType = GL_TRIANGLES;
|
||||||
|
|
||||||
for (int j = 0; j < poly->NumVertices; j++)
|
for (int j = 0; j < 3; j++)
|
||||||
{
|
{
|
||||||
Vertex* vtx = poly->Vertices[j];
|
Vertex* vtx = poly->Vertices[j];
|
||||||
|
|
||||||
u32 z = poly->FinalZ[j];
|
vptr = SetupVertex(poly, j, vtx, vtxattr, vptr);
|
||||||
u32 w = poly->FinalW[j];
|
vidx++;
|
||||||
|
}
|
||||||
|
|
||||||
// Z should always fit within 16 bits, so it's okay to do this
|
// build a triangle
|
||||||
|
*iptr++ = vidx_first;
|
||||||
|
*iptr++ = vidx - 2;
|
||||||
|
*iptr++ = vidx - 1;
|
||||||
|
rp->NumIndices += 3;
|
||||||
|
}
|
||||||
|
else // quad, pentagon, etc
|
||||||
|
{
|
||||||
|
rp->PrimType = GL_TRIANGLES;
|
||||||
|
|
||||||
|
if (!BetterPolygons)
|
||||||
|
{
|
||||||
|
// regular triangle-splitting
|
||||||
|
|
||||||
|
for (int j = 0; j < poly->NumVertices; j++)
|
||||||
|
{
|
||||||
|
Vertex* vtx = poly->Vertices[j];
|
||||||
|
|
||||||
|
vptr = SetupVertex(poly, j, vtx, vtxattr, vptr);
|
||||||
|
|
||||||
|
if (j >= 2)
|
||||||
|
{
|
||||||
|
// build a triangle
|
||||||
|
*iptr++ = vidx_first;
|
||||||
|
*iptr++ = vidx - 1;
|
||||||
|
*iptr++ = vidx;
|
||||||
|
rp->NumIndices += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
vidx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// attempt at 'better' splitting
|
||||||
|
// this doesn't get rid of the error while splitting a bigger polygon into triangles
|
||||||
|
// but we can attempt to reduce it
|
||||||
|
|
||||||
|
u32 cX = 0, cY = 0;
|
||||||
|
float cZ = 0;
|
||||||
|
float cW = 0;
|
||||||
|
|
||||||
|
float cR = 0, cG = 0, cB = 0;
|
||||||
|
float cS = 0, cT = 0;
|
||||||
|
|
||||||
|
for (int j = 0; j < poly->NumVertices; j++)
|
||||||
|
{
|
||||||
|
Vertex* vtx = poly->Vertices[j];
|
||||||
|
|
||||||
|
cX += vtx->HiresPosition[0];
|
||||||
|
cY += vtx->HiresPosition[1];
|
||||||
|
|
||||||
|
float fw = (float)poly->FinalW[j] * poly->NumVertices;
|
||||||
|
cW += 1.0f / fw;
|
||||||
|
|
||||||
|
if (poly->WBuffer) cZ += poly->FinalZ[j] / fw;
|
||||||
|
else cZ += poly->FinalZ[j];
|
||||||
|
|
||||||
|
cR += (vtx->FinalColor[0] >> 1) / fw;
|
||||||
|
cG += (vtx->FinalColor[1] >> 1) / fw;
|
||||||
|
cB += (vtx->FinalColor[2] >> 1) / fw;
|
||||||
|
|
||||||
|
cS += vtx->TexCoords[0] / fw;
|
||||||
|
cT += vtx->TexCoords[1] / fw;
|
||||||
|
}
|
||||||
|
|
||||||
|
cX /= poly->NumVertices;
|
||||||
|
cY /= poly->NumVertices;
|
||||||
|
|
||||||
|
cW = 1.0f / cW;
|
||||||
|
|
||||||
|
if (poly->WBuffer) cZ *= cW;
|
||||||
|
else cZ /= poly->NumVertices;
|
||||||
|
|
||||||
|
cR *= cW;
|
||||||
|
cG *= cW;
|
||||||
|
cB *= cW;
|
||||||
|
|
||||||
|
cS *= cW;
|
||||||
|
cT *= cW;
|
||||||
|
|
||||||
|
cX = (cX * ScaleFactor) >> 4;
|
||||||
|
cY = (cY * ScaleFactor) >> 4;
|
||||||
|
|
||||||
|
u32 w = (u32)cW;
|
||||||
|
|
||||||
|
u32 z = (u32)cZ;
|
||||||
u32 zshift = 0;
|
u32 zshift = 0;
|
||||||
while (z > 0xFFFF) { z >>= 1; zshift++; }
|
while (z > 0xFFFF) { z >>= 1; zshift++; }
|
||||||
|
|
||||||
u32 x, y;
|
// build center vertex
|
||||||
if (ScaleFactor > 1)
|
*vptr++ = cX | (cY << 16);
|
||||||
{
|
|
||||||
x = (vtx->HiresPosition[0] * ScaleFactor) >> 4;
|
|
||||||
y = (vtx->HiresPosition[1] * ScaleFactor) >> 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = vtx->FinalPosition[0];
|
|
||||||
y = vtx->FinalPosition[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
*vptr++ = x | (y << 16);
|
|
||||||
*vptr++ = z | (w << 16);
|
*vptr++ = z | (w << 16);
|
||||||
|
|
||||||
*vptr++ = (vtx->FinalColor[0] >> 1) |
|
*vptr++ = (u32)cR |
|
||||||
((vtx->FinalColor[1] >> 1) << 8) |
|
((u32)cG << 8) |
|
||||||
((vtx->FinalColor[2] >> 1) << 16) |
|
((u32)cB << 16) |
|
||||||
(alpha << 24);
|
(alpha << 24);
|
||||||
|
|
||||||
*vptr++ = (u16)vtx->TexCoords[0] | ((u16)vtx->TexCoords[1] << 16);
|
*vptr++ = (u16)cS | ((u16)cT << 16);
|
||||||
|
|
||||||
*vptr++ = vtxattr | (zshift << 16);
|
*vptr++ = vtxattr | (zshift << 16);
|
||||||
*vptr++ = poly->TexParam;
|
*vptr++ = poly->TexParam;
|
||||||
*vptr++ = poly->TexPalette;
|
*vptr++ = poly->TexPalette;
|
||||||
|
|
||||||
if (j >= 2)
|
vidx++;
|
||||||
|
|
||||||
|
// build the final polygon
|
||||||
|
for (int j = 0; j < poly->NumVertices; j++)
|
||||||
{
|
{
|
||||||
// build a triangle
|
Vertex* vtx = poly->Vertices[j];
|
||||||
*iptr++ = vidx_first;
|
|
||||||
*iptr++ = vidx - 1;
|
vptr = SetupVertex(poly, j, vtx, vtxattr, vptr);
|
||||||
*iptr++ = vidx;
|
|
||||||
rp->NumIndices += 3;
|
if (j >= 1)
|
||||||
|
{
|
||||||
|
// build a triangle
|
||||||
|
*iptr++ = vidx_first;
|
||||||
|
*iptr++ = vidx - 1;
|
||||||
|
*iptr++ = vidx;
|
||||||
|
rp->NumIndices += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
vidx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
vidx++;
|
*iptr++ = vidx_first;
|
||||||
|
*iptr++ = vidx - 1;
|
||||||
|
*iptr++ = vidx_first + 1;
|
||||||
|
rp->NumIndices += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -741,6 +836,10 @@ void RenderSceneChunk(int y, int h)
|
||||||
|
|
||||||
GLboolean fogenable = (RenderDispCnt & (1<<7)) ? GL_TRUE : GL_FALSE;
|
GLboolean fogenable = (RenderDispCnt & (1<<7)) ? GL_TRUE : GL_FALSE;
|
||||||
|
|
||||||
|
// TODO: proper 'equal' depth test!
|
||||||
|
// (has margin of +-0x200 in Z-buffer mode, +-0xFF in W-buffer mode)
|
||||||
|
// for now we're using GL_LEQUAL to make it work to some extent
|
||||||
|
|
||||||
// pass 1: opaque pixels
|
// pass 1: opaque pixels
|
||||||
|
|
||||||
UseRenderShader(flags);
|
UseRenderShader(flags);
|
||||||
|
@ -759,8 +858,10 @@ void RenderSceneChunk(int y, int h)
|
||||||
|
|
||||||
if (rp->PolyData->IsShadowMask) { i++; continue; }
|
if (rp->PolyData->IsShadowMask) { i++; continue; }
|
||||||
|
|
||||||
// zorp
|
if (rp->PolyData->Attr & (1<<14))
|
||||||
glDepthFunc(GL_LESS);
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
else
|
||||||
|
glDepthFunc(GL_LESS);
|
||||||
|
|
||||||
u32 polyattr = rp->PolyData->Attr;
|
u32 polyattr = rp->PolyData->Attr;
|
||||||
u32 polyid = (polyattr >> 24) & 0x3F;
|
u32 polyid = (polyattr >> 24) & 0x3F;
|
||||||
|
@ -845,8 +946,10 @@ void RenderSceneChunk(int y, int h)
|
||||||
{
|
{
|
||||||
UseRenderShader(flags | RenderFlag_Trans);
|
UseRenderShader(flags | RenderFlag_Trans);
|
||||||
|
|
||||||
// zorp
|
if (rp->PolyData->Attr & (1<<14))
|
||||||
glDepthFunc(GL_LESS);
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
else
|
||||||
|
glDepthFunc(GL_LESS);
|
||||||
|
|
||||||
u32 polyattr = rp->PolyData->Attr;
|
u32 polyattr = rp->PolyData->Attr;
|
||||||
u32 polyid = (polyattr >> 24) & 0x3F;
|
u32 polyid = (polyattr >> 24) & 0x3F;
|
||||||
|
@ -936,8 +1039,10 @@ void RenderSceneChunk(int y, int h)
|
||||||
if (!(polyattr & (1<<15))) transfog = fogenable;
|
if (!(polyattr & (1<<15))) transfog = fogenable;
|
||||||
else transfog = GL_FALSE;
|
else transfog = GL_FALSE;
|
||||||
|
|
||||||
// zorp
|
if (rp->PolyData->Attr & (1<<14))
|
||||||
glDepthFunc(GL_LESS);
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
else
|
||||||
|
glDepthFunc(GL_LESS);
|
||||||
|
|
||||||
if (rp->PolyData->IsShadow)
|
if (rp->PolyData->IsShadow)
|
||||||
{
|
{
|
||||||
|
@ -1003,9 +1108,9 @@ void RenderSceneChunk(int y, int h)
|
||||||
glStencilMask(0);
|
glStencilMask(0);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, FramebufferTex[4]);
|
glBindTexture(GL_TEXTURE_2D, FramebufferTex[FrontBuffer ? 6 : 4]);
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
glBindTexture(GL_TEXTURE_2D, FramebufferTex[5]);
|
glBindTexture(GL_TEXTURE_2D, FramebufferTex[FrontBuffer ? 7 : 5]);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, ClearVertexBufferID);
|
glBindBuffer(GL_ARRAY_BUFFER, ClearVertexBufferID);
|
||||||
glBindVertexArray(ClearVertexArrayID);
|
glBindVertexArray(ClearVertexArrayID);
|
||||||
|
@ -1055,8 +1160,8 @@ void RenderFrame()
|
||||||
{
|
{
|
||||||
CurShaderID = -1;
|
CurShaderID = -1;
|
||||||
|
|
||||||
if (Antialias) glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[2]);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||||
else glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[FrontBuffer]);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FramebufferID[FrontBuffer]);
|
||||||
|
|
||||||
ShaderConfig.uScreenSize[0] = ScreenW;
|
ShaderConfig.uScreenSize[0] = ScreenW;
|
||||||
ShaderConfig.uScreenSize[1] = ScreenH;
|
ShaderConfig.uScreenSize[1] = ScreenH;
|
||||||
|
@ -1218,14 +1323,6 @@ void RenderFrame()
|
||||||
RenderSceneChunk(0, 192);
|
RenderSceneChunk(0, 192);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Antialias)
|
|
||||||
{
|
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferID[2]);
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FramebufferID[FrontBuffer]);
|
|
||||||
glBlitFramebuffer(0, 0, ScreenW, ScreenH, 0, 0, ScreenW/2, ScreenH/2, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
//glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[FrontBuffer]);
|
|
||||||
FrontBuffer = FrontBuffer ? 0 : 1;
|
FrontBuffer = FrontBuffer ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,8 @@ bool Init()
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,12 +159,15 @@ void SetRenderSettings(RenderSettings& settings)
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, CompScreenOutputFB);
|
glBindFramebuffer(GL_FRAMEBUFFER, CompScreenOutputFB);
|
||||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, CompScreenOutputTex, 0);
|
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, CompScreenOutputTex, 0);
|
||||||
glDrawBuffers(1, fbassign);
|
glDrawBuffers(1, fbassign);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RenderFrame()
|
void RenderFrame()
|
||||||
{
|
{
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, CompScreenOutputFB);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, CompScreenOutputFB);
|
||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glDisable(GL_STENCIL_TEST);
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
|
21
src/NDS.cpp
21
src/NDS.cpp
|
@ -775,7 +775,7 @@ bool DoSavestate(Savestate* file)
|
||||||
|
|
||||||
file->Var8(&WRAMCnt);
|
file->Var8(&WRAMCnt);
|
||||||
|
|
||||||
file->Var32((u32*)&RunningGame);
|
file->Bool32(&RunningGame);
|
||||||
|
|
||||||
if (!file->Saving)
|
if (!file->Saving)
|
||||||
{
|
{
|
||||||
|
@ -1124,6 +1124,11 @@ void MicInputFrame(s16* data, int samples)
|
||||||
return SPI_TSC::MicInputFrame(data, samples);
|
return SPI_TSC::MicInputFrame(data, samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ImportSRAM(u8* data, u32 length)
|
||||||
|
{
|
||||||
|
return NDSCart::ImportSRAM(data, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Halt()
|
void Halt()
|
||||||
{
|
{
|
||||||
|
@ -1817,15 +1822,16 @@ void debug(u32 param)
|
||||||
fwrite(&val, 4, 1, shit);
|
fwrite(&val, 4, 1, shit);
|
||||||
}
|
}
|
||||||
fclose(shit);*/
|
fclose(shit);*/
|
||||||
|
|
||||||
FILE*
|
FILE*
|
||||||
shit = fopen("debug/dump9.bin", "wb");
|
shit = fopen("debug/picto9.bin", "wb");
|
||||||
for (u32 i = 0x02000000; i < 0x04000000; i+=4)
|
for (u32 i = 0x02000000; i < 0x04000000; i+=4)
|
||||||
{
|
{
|
||||||
u32 val = DSi::ARM9Read32(i);
|
u32 val = DSi::ARM9Read32(i);
|
||||||
fwrite(&val, 4, 1, shit);
|
fwrite(&val, 4, 1, shit);
|
||||||
}
|
}
|
||||||
fclose(shit);
|
fclose(shit);
|
||||||
shit = fopen("debug/dump7.bin", "wb");
|
shit = fopen("debug/picto7.bin", "wb");
|
||||||
for (u32 i = 0x02000000; i < 0x04000000; i+=4)
|
for (u32 i = 0x02000000; i < 0x04000000; i+=4)
|
||||||
{
|
{
|
||||||
u32 val = DSi::ARM7Read32(i);
|
u32 val = DSi::ARM7Read32(i);
|
||||||
|
@ -2536,7 +2542,8 @@ void ARM7Write8(u32 addr, u8 val)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("unknown arm7 write8 %08X %02X @ %08X\n", addr, val, ARM7->R[15]);
|
if (ARM7->R[15] > 0x00002F30) // ARM7 BIOS bug
|
||||||
|
printf("unknown arm7 write8 %08X %02X @ %08X\n", addr, val, ARM7->R[15]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARM7Write16(u32 addr, u16 val)
|
void ARM7Write16(u32 addr, u16 val)
|
||||||
|
@ -3454,6 +3461,10 @@ void ARM9IOWrite32(u32 addr, u32 val)
|
||||||
PowerControl9 = val & 0x820F;
|
PowerControl9 = val & 0x820F;
|
||||||
GPU::SetPowerCnt(PowerControl9);
|
GPU::SetPowerCnt(PowerControl9);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case 0x04100010:
|
||||||
|
NDSCart::WriteROMData(val);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr >= 0x04000000 && addr < 0x04000060)
|
if (addr >= 0x04000000 && addr < 0x04000060)
|
||||||
|
@ -3744,7 +3755,7 @@ void ARM7IOWrite8(u32 addr, u8 val)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x04000301:
|
case 0x04000301:
|
||||||
val & 0xC0;
|
val &= 0xC0;
|
||||||
if (val == 0x40) printf("!! GBA MODE NOT SUPPORTED\n");
|
if (val == 0x40) printf("!! GBA MODE NOT SUPPORTED\n");
|
||||||
else if (val == 0x80) ARM7->Halt(1);
|
else if (val == 0x80) ARM7->Halt(1);
|
||||||
else if (val == 0xC0) EnterSleepMode();
|
else if (val == 0xC0) EnterSleepMode();
|
||||||
|
|
|
@ -47,6 +47,8 @@ enum
|
||||||
Event_DSi_SDIOTransfer,
|
Event_DSi_SDIOTransfer,
|
||||||
Event_DSi_NWifi,
|
Event_DSi_NWifi,
|
||||||
|
|
||||||
|
Event_DSi_RAMSizeChange,
|
||||||
|
|
||||||
Event_MAX
|
Event_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -209,6 +211,8 @@ void SetLidClosed(bool closed);
|
||||||
|
|
||||||
void MicInputFrame(s16* data, int samples);
|
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 ScheduleEvent(u32 id, bool periodic, s32 delay, void (*func)(u32), u32 param);
|
||||||
void CancelEvent(u32 id);
|
void CancelEvent(u32 id);
|
||||||
|
|
||||||
|
|
300
src/NDSCart.cpp
300
src/NDSCart.cpp
|
@ -25,7 +25,9 @@
|
||||||
#include "CRC32.h"
|
#include "CRC32.h"
|
||||||
#include "DSi_AES.h"
|
#include "DSi_AES.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
#include "Config.h"
|
||||||
#include "ROMList.h"
|
#include "ROMList.h"
|
||||||
|
#include "melonDLDI.h"
|
||||||
|
|
||||||
|
|
||||||
namespace NDSCart_SRAM
|
namespace NDSCart_SRAM
|
||||||
|
@ -464,11 +466,13 @@ u16 SPICnt;
|
||||||
u32 ROMCnt;
|
u32 ROMCnt;
|
||||||
|
|
||||||
u8 ROMCommand[8];
|
u8 ROMCommand[8];
|
||||||
u32 ROMDataOut;
|
u32 ROMData;
|
||||||
|
|
||||||
u8 DataOut[0x4000];
|
u8 TransferData[0x4000];
|
||||||
u32 DataOutPos;
|
u32 TransferPos;
|
||||||
u32 DataOutLen;
|
u32 TransferLen;
|
||||||
|
u32 TransferDir;
|
||||||
|
u8 TransferCmd[8];
|
||||||
|
|
||||||
bool CartInserted;
|
bool CartInserted;
|
||||||
u8* CartROM;
|
u8* CartROM;
|
||||||
|
@ -478,6 +482,8 @@ u32 CartID;
|
||||||
bool CartIsHomebrew;
|
bool CartIsHomebrew;
|
||||||
bool CartIsDSi;
|
bool CartIsDSi;
|
||||||
|
|
||||||
|
FILE* CartSD;
|
||||||
|
|
||||||
u32 CmdEncMode;
|
u32 CmdEncMode;
|
||||||
u32 DataEncMode;
|
u32 DataEncMode;
|
||||||
|
|
||||||
|
@ -489,6 +495,7 @@ u64 Key2_Y;
|
||||||
|
|
||||||
void ROMCommand_Retail(u8* cmd);
|
void ROMCommand_Retail(u8* cmd);
|
||||||
void ROMCommand_RetailNAND(u8* cmd);
|
void ROMCommand_RetailNAND(u8* cmd);
|
||||||
|
void ROMCommand_Homebrew(u8* cmd);
|
||||||
|
|
||||||
void (*ROMCommandHandler)(u8* cmd);
|
void (*ROMCommandHandler)(u8* cmd);
|
||||||
|
|
||||||
|
@ -615,6 +622,8 @@ bool Init()
|
||||||
|
|
||||||
CartROM = NULL;
|
CartROM = NULL;
|
||||||
|
|
||||||
|
CartSD = NULL;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,6 +631,8 @@ void DeInit()
|
||||||
{
|
{
|
||||||
if (CartROM) delete[] CartROM;
|
if (CartROM) delete[] CartROM;
|
||||||
|
|
||||||
|
if (CartSD) fclose(CartSD);
|
||||||
|
|
||||||
NDSCart_SRAM::DeInit();
|
NDSCart_SRAM::DeInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -635,6 +646,9 @@ void Reset()
|
||||||
CartIsHomebrew = false;
|
CartIsHomebrew = false;
|
||||||
CartIsDSi = false;
|
CartIsDSi = false;
|
||||||
|
|
||||||
|
if (CartSD) fclose(CartSD);
|
||||||
|
CartSD = NULL;
|
||||||
|
|
||||||
ROMCommandHandler = NULL;
|
ROMCommandHandler = NULL;
|
||||||
|
|
||||||
NDSCart_SRAM::Reset();
|
NDSCart_SRAM::Reset();
|
||||||
|
@ -650,11 +664,13 @@ void DoSavestate(Savestate* file)
|
||||||
file->Var32(&ROMCnt);
|
file->Var32(&ROMCnt);
|
||||||
|
|
||||||
file->VarArray(ROMCommand, 8);
|
file->VarArray(ROMCommand, 8);
|
||||||
file->Var32(&ROMDataOut);
|
file->Var32(&ROMData);
|
||||||
|
|
||||||
file->VarArray(DataOut, 0x4000);
|
file->VarArray(TransferData, 0x4000);
|
||||||
file->Var32(&DataOutPos);
|
file->Var32(&TransferPos);
|
||||||
file->Var32(&DataOutLen);
|
file->Var32(&TransferLen);
|
||||||
|
file->Var32(&TransferDir);
|
||||||
|
file->VarArray(TransferCmd, 8);
|
||||||
|
|
||||||
// cart inserted/len/ROM/etc should be already populated
|
// cart inserted/len/ROM/etc should be already populated
|
||||||
// savestate should be loaded after the right game is loaded
|
// savestate should be loaded after the right game is loaded
|
||||||
|
@ -670,10 +686,8 @@ void DoSavestate(Savestate* file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ApplyDLDIPatch()
|
void ApplyDLDIPatch(const u8* patch, u32 len)
|
||||||
{
|
{
|
||||||
// TODO: embed patches? let the user choose? default to some builtin driver?
|
|
||||||
|
|
||||||
u32 offset = *(u32*)&CartROM[0x20];
|
u32 offset = *(u32*)&CartROM[0x20];
|
||||||
u32 size = *(u32*)&CartROM[0x2C];
|
u32 size = *(u32*)&CartROM[0x2C];
|
||||||
|
|
||||||
|
@ -696,23 +710,7 @@ void ApplyDLDIPatch()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("DLDI shit found at %08X (%08X)\n", dldioffset, offset+dldioffset);
|
printf("DLDI structure found at %08X (%08X)\n", dldioffset, offset+dldioffset);
|
||||||
|
|
||||||
FILE* f = fopen("dldi.bin", "rb");
|
|
||||||
if (!f)
|
|
||||||
{
|
|
||||||
printf("no DLDI patch available. oh well\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 dldisize;
|
|
||||||
fseek(f, 0, SEEK_END);
|
|
||||||
dldisize = ftell(f);
|
|
||||||
fseek(f, 0, SEEK_SET);
|
|
||||||
|
|
||||||
u8* patch = new u8[dldisize];
|
|
||||||
fread(patch, dldisize, 1, f);
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
if (*(u32*)&patch[0] != 0xBF8DA5ED ||
|
if (*(u32*)&patch[0] != 0xBF8DA5ED ||
|
||||||
*(u32*)&patch[4] != 0x69684320 ||
|
*(u32*)&patch[4] != 0x69684320 ||
|
||||||
|
@ -743,7 +741,7 @@ void ApplyDLDIPatch()
|
||||||
u32 patchsize = 1 << patch[0x0D];
|
u32 patchsize = 1 << patch[0x0D];
|
||||||
u32 patchend = patchbase + patchsize;
|
u32 patchend = patchbase + patchsize;
|
||||||
|
|
||||||
memcpy(&binary[dldioffset], patch, dldisize);
|
memcpy(&binary[dldioffset], patch, len);
|
||||||
|
|
||||||
*(u32*)&binary[dldioffset+0x40] += delta;
|
*(u32*)&binary[dldioffset+0x40] += delta;
|
||||||
*(u32*)&binary[dldioffset+0x44] += delta;
|
*(u32*)&binary[dldioffset+0x44] += delta;
|
||||||
|
@ -807,7 +805,6 @@ void ApplyDLDIPatch()
|
||||||
memset(&binary[dldioffset+fixstart], 0, fixend-fixstart);
|
memset(&binary[dldioffset+fixstart], 0, fixend-fixstart);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] patch;
|
|
||||||
printf("applied DLDI patch\n");
|
printf("applied DLDI patch\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,11 +984,13 @@ bool LoadROM(const char* path, const char* sram, bool direct)
|
||||||
Key1_Encrypt((u32*)&CartROM[arm9base]);
|
Key1_Encrypt((u32*)&CartROM[arm9base]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
CartIsHomebrew = true;
|
if ((arm9base < 0x4000) || (gamecode == 0x23232323))
|
||||||
//ApplyDLDIPatch();
|
{
|
||||||
}
|
CartIsHomebrew = true;
|
||||||
|
if (Config::DLDIEnable)
|
||||||
|
ApplyDLDIPatch(melonDLDI, sizeof(melonDLDI));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (direct)
|
if (direct)
|
||||||
|
@ -1005,7 +1004,9 @@ bool LoadROM(const char* path, const char* sram, bool direct)
|
||||||
CartInserted = true;
|
CartInserted = true;
|
||||||
|
|
||||||
// TODO: support more fancy cart types (homebrew?, flashcarts, etc)
|
// TODO: support more fancy cart types (homebrew?, flashcarts, etc)
|
||||||
if (CartID & 0x08000000)
|
if (CartIsHomebrew)
|
||||||
|
ROMCommandHandler = ROMCommand_Homebrew;
|
||||||
|
else if (CartID & 0x08000000)
|
||||||
ROMCommandHandler = ROMCommand_RetailNAND;
|
ROMCommandHandler = ROMCommand_RetailNAND;
|
||||||
else
|
else
|
||||||
ROMCommandHandler = ROMCommand_Retail;
|
ROMCommandHandler = ROMCommand_Retail;
|
||||||
|
@ -1017,6 +1018,13 @@ bool LoadROM(const char* path, const char* sram, bool direct)
|
||||||
printf("Save file: %s\n", sram);
|
printf("Save file: %s\n", sram);
|
||||||
NDSCart_SRAM::LoadSave(sram, romparams.SaveMemType);
|
NDSCart_SRAM::LoadSave(sram, romparams.SaveMemType);
|
||||||
|
|
||||||
|
if (CartIsHomebrew && Config::DLDIEnable)
|
||||||
|
{
|
||||||
|
CartSD = Platform::OpenLocalFile(Config::DLDISDPath, "r+b");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
CartSD = NULL;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1026,6 +1034,19 @@ void RelocateSave(const char* path, bool write)
|
||||||
NDSCart_SRAM::RelocateSave(path, 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()
|
void ResetCart()
|
||||||
{
|
{
|
||||||
// CHECKME: what if there is a transfer in progress?
|
// CHECKME: what if there is a transfer in progress?
|
||||||
|
@ -1034,14 +1055,17 @@ void ResetCart()
|
||||||
ROMCnt = 0;
|
ROMCnt = 0;
|
||||||
|
|
||||||
memset(ROMCommand, 0, 8);
|
memset(ROMCommand, 0, 8);
|
||||||
ROMDataOut = 0;
|
ROMData = 0;
|
||||||
|
|
||||||
Key2_X = 0;
|
Key2_X = 0;
|
||||||
Key2_Y = 0;
|
Key2_Y = 0;
|
||||||
|
|
||||||
memset(DataOut, 0, 0x4000);
|
memset(TransferData, 0, 0x4000);
|
||||||
DataOutPos = 0;
|
TransferPos = 0;
|
||||||
DataOutLen = 0;
|
TransferLen = 0;
|
||||||
|
TransferDir = 0;
|
||||||
|
memset(TransferCmd, 0, 8);
|
||||||
|
TransferCmd[0] = 0xFF;
|
||||||
|
|
||||||
CmdEncMode = 0;
|
CmdEncMode = 0;
|
||||||
DataEncMode = 0;
|
DataEncMode = 0;
|
||||||
|
@ -1055,7 +1079,7 @@ void ReadROM(u32 addr, u32 len, u32 offset)
|
||||||
if ((addr+len) > CartROMSize)
|
if ((addr+len) > CartROMSize)
|
||||||
len = CartROMSize - addr;
|
len = CartROMSize - addr;
|
||||||
|
|
||||||
memcpy(DataOut+offset, CartROM+addr, len);
|
memcpy(TransferData+offset, CartROM+addr, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadROM_B7(u32 addr, u32 len, u32 offset)
|
void ReadROM_B7(u32 addr, u32 len, u32 offset)
|
||||||
|
@ -1069,7 +1093,7 @@ void ReadROM_B7(u32 addr, u32 len, u32 offset)
|
||||||
addr = 0x8000 + (addr & 0x1FF);
|
addr = 0x8000 + (addr & 0x1FF);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(DataOut+offset, CartROM+addr, len);
|
memcpy(TransferData+offset, CartROM+addr, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1079,16 +1103,41 @@ void ROMEndTransfer(u32 param)
|
||||||
|
|
||||||
if (SPICnt & (1<<14))
|
if (SPICnt & (1<<14))
|
||||||
NDS::SetIRQ((NDS::ExMemCnt[0]>>11)&0x1, NDS::IRQ_CartSendDone);
|
NDS::SetIRQ((NDS::ExMemCnt[0]>>11)&0x1, NDS::IRQ_CartSendDone);
|
||||||
|
|
||||||
|
if (TransferDir == 1)
|
||||||
|
{
|
||||||
|
// finish a write
|
||||||
|
|
||||||
|
u8* cmd = TransferCmd;
|
||||||
|
switch (cmd[0])
|
||||||
|
{
|
||||||
|
case 0xC1:
|
||||||
|
{
|
||||||
|
u32 sector = (cmd[1]<<24) | (cmd[2]<<16) | (cmd[3]<<8) | cmd[4];
|
||||||
|
u64 addr = sector * 0x200ULL;
|
||||||
|
|
||||||
|
if (CartSD)
|
||||||
|
{
|
||||||
|
fseek(CartSD, addr, SEEK_SET);
|
||||||
|
fwrite(TransferData, TransferLen, 1, CartSD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ROMPrepareData(u32 param)
|
void ROMPrepareData(u32 param)
|
||||||
{
|
{
|
||||||
if (DataOutPos >= DataOutLen)
|
if (TransferDir == 0)
|
||||||
ROMDataOut = 0;
|
{
|
||||||
else
|
if (TransferPos >= TransferLen)
|
||||||
ROMDataOut = *(u32*)&DataOut[DataOutPos];
|
ROMData = 0;
|
||||||
|
else
|
||||||
|
ROMData = *(u32*)&TransferData[TransferPos];
|
||||||
|
|
||||||
DataOutPos += 4;
|
TransferPos += 4;
|
||||||
|
}
|
||||||
|
|
||||||
ROMCnt |= (1<<23);
|
ROMCnt |= (1<<23);
|
||||||
|
|
||||||
|
@ -1106,16 +1155,16 @@ void ROMCommand_Retail(u8* cmd)
|
||||||
case 0xB7:
|
case 0xB7:
|
||||||
{
|
{
|
||||||
u32 addr = (cmd[1]<<24) | (cmd[2]<<16) | (cmd[3]<<8) | cmd[4];
|
u32 addr = (cmd[1]<<24) | (cmd[2]<<16) | (cmd[3]<<8) | cmd[4];
|
||||||
memset(DataOut, 0, DataOutLen);
|
memset(TransferData, 0, TransferLen);
|
||||||
|
|
||||||
if (((addr + DataOutLen - 1) >> 12) != (addr >> 12))
|
if (((addr + TransferLen - 1) >> 12) != (addr >> 12))
|
||||||
{
|
{
|
||||||
u32 len1 = 0x1000 - (addr & 0xFFF);
|
u32 len1 = 0x1000 - (addr & 0xFFF);
|
||||||
ReadROM_B7(addr, len1, 0);
|
ReadROM_B7(addr, len1, 0);
|
||||||
ReadROM_B7(addr+len1, DataOutLen-len1, len1);
|
ReadROM_B7(addr+len1, TransferLen-len1, len1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ReadROM_B7(addr, DataOutLen, 0);
|
ReadROM_B7(addr, TransferLen, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1136,8 +1185,8 @@ void ROMCommand_RetailNAND(u8* cmd)
|
||||||
|
|
||||||
// Jam with the Band stores words 6-9 of this at 0x02131BB0
|
// Jam with the Band stores words 6-9 of this at 0x02131BB0
|
||||||
// it doesn't seem to use those anywhere later
|
// it doesn't seem to use those anywhere later
|
||||||
for (u32 pos = 0; pos < DataOutLen; pos += 4)
|
for (u32 pos = 0; pos < TransferLen; pos += 4)
|
||||||
*(u32*)&DataOut[pos] = 0;
|
*(u32*)&TransferData[pos] = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1150,16 +1199,16 @@ void ROMCommand_RetailNAND(u8* cmd)
|
||||||
case 0xB7:
|
case 0xB7:
|
||||||
{
|
{
|
||||||
u32 addr = (cmd[1]<<24) | (cmd[2]<<16) | (cmd[3]<<8) | cmd[4];
|
u32 addr = (cmd[1]<<24) | (cmd[2]<<16) | (cmd[3]<<8) | cmd[4];
|
||||||
memset(DataOut, 0, DataOutLen);
|
memset(TransferData, 0, TransferLen);
|
||||||
|
|
||||||
if (((addr + DataOutLen - 1) >> 12) != (addr >> 12))
|
if (((addr + TransferLen - 1) >> 12) != (addr >> 12))
|
||||||
{
|
{
|
||||||
u32 len1 = 0x1000 - (addr & 0xFFF);
|
u32 len1 = 0x1000 - (addr & 0xFFF);
|
||||||
ReadROM_B7(addr, len1, 0);
|
ReadROM_B7(addr, len1, 0);
|
||||||
ReadROM_B7(addr+len1, DataOutLen-len1, len1);
|
ReadROM_B7(addr+len1, TransferLen-len1, len1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ReadROM_B7(addr, DataOutLen, 0);
|
ReadROM_B7(addr, TransferLen, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1169,13 +1218,59 @@ void ROMCommand_RetailNAND(u8* cmd)
|
||||||
// * bit7: busy? error?
|
// * bit7: busy? error?
|
||||||
// * bit5: accessing savemem
|
// * bit5: accessing savemem
|
||||||
|
|
||||||
for (u32 pos = 0; pos < DataOutLen; pos += 4)
|
for (u32 pos = 0; pos < TransferLen; pos += 4)
|
||||||
*(u32*)&DataOut[pos] = NDSCart_SRAM::StatusReg * 0x01010101;
|
*(u32*)&TransferData[pos] = NDSCart_SRAM::StatusReg * 0x01010101;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("unknown NAND command %02X %04Xn", cmd[0], DataOutLen);
|
printf("unknown NAND command %02X %04Xn", cmd[0], TransferLen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ROMCommand_Homebrew(u8* cmd)
|
||||||
|
{
|
||||||
|
switch (cmd[0])
|
||||||
|
{
|
||||||
|
case 0xB7:
|
||||||
|
{
|
||||||
|
u32 addr = (cmd[1]<<24) | (cmd[2]<<16) | (cmd[3]<<8) | cmd[4];
|
||||||
|
memset(TransferData, 0, TransferLen);
|
||||||
|
|
||||||
|
if (((addr + TransferLen - 1) >> 12) != (addr >> 12))
|
||||||
|
{
|
||||||
|
u32 len1 = 0x1000 - (addr & 0xFFF);
|
||||||
|
ReadROM_B7(addr, len1, 0);
|
||||||
|
ReadROM_B7(addr+len1, TransferLen-len1, len1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ReadROM_B7(addr, TransferLen, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xC0: // SD read
|
||||||
|
{
|
||||||
|
u32 sector = (cmd[1]<<24) | (cmd[2]<<16) | (cmd[3]<<8) | cmd[4];
|
||||||
|
u64 addr = sector * 0x200ULL;
|
||||||
|
|
||||||
|
if (CartSD)
|
||||||
|
{
|
||||||
|
fseek(CartSD, addr, SEEK_SET);
|
||||||
|
fread(TransferData, TransferLen, 1, CartSD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xC1: // SD write
|
||||||
|
{
|
||||||
|
TransferDir = 1;
|
||||||
|
memcpy(TransferCmd, cmd, 8);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("unknown homebrew cart command %02X\n", cmd[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1215,8 +1310,8 @@ void WriteROMCnt(u32 val)
|
||||||
else if (datasize > 0)
|
else if (datasize > 0)
|
||||||
datasize = 0x100 << datasize;
|
datasize = 0x100 << datasize;
|
||||||
|
|
||||||
DataOutPos = 0;
|
TransferPos = 0;
|
||||||
DataOutLen = datasize;
|
TransferLen = datasize;
|
||||||
|
|
||||||
// handle KEY1 encryption as needed.
|
// handle KEY1 encryption as needed.
|
||||||
// KEY2 encryption is implemented in hardware and doesn't need to be handled.
|
// KEY2 encryption is implemented in hardware and doesn't need to be handled.
|
||||||
|
@ -1242,28 +1337,32 @@ void WriteROMCnt(u32 val)
|
||||||
cmd[4], cmd[5], cmd[6], cmd[7],
|
cmd[4], cmd[5], cmd[6], cmd[7],
|
||||||
datasize);*/
|
datasize);*/
|
||||||
|
|
||||||
|
// default is read
|
||||||
|
// commands that do writes will change this
|
||||||
|
TransferDir = 0;
|
||||||
|
|
||||||
switch (cmd[0])
|
switch (cmd[0])
|
||||||
{
|
{
|
||||||
case 0x9F:
|
case 0x9F:
|
||||||
memset(DataOut, 0xFF, DataOutLen);
|
memset(TransferData, 0xFF, TransferLen);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x00:
|
case 0x00:
|
||||||
memset(DataOut, 0, DataOutLen);
|
memset(TransferData, 0, TransferLen);
|
||||||
if (DataOutLen > 0x1000)
|
if (TransferLen > 0x1000)
|
||||||
{
|
{
|
||||||
ReadROM(0, 0x1000, 0);
|
ReadROM(0, 0x1000, 0);
|
||||||
for (u32 pos = 0x1000; pos < DataOutLen; pos += 0x1000)
|
for (u32 pos = 0x1000; pos < TransferLen; pos += 0x1000)
|
||||||
memcpy(DataOut+pos, DataOut, 0x1000);
|
memcpy(TransferData+pos, TransferData, 0x1000);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ReadROM(0, DataOutLen, 0);
|
ReadROM(0, TransferLen, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x90:
|
case 0x90:
|
||||||
case 0xB8:
|
case 0xB8:
|
||||||
for (u32 pos = 0; pos < DataOutLen; pos += 4)
|
for (u32 pos = 0; pos < TransferLen; pos += 4)
|
||||||
*(u32*)&DataOut[pos] = CartID;
|
*(u32*)&TransferData[pos] = CartID;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x3C:
|
case 0x3C:
|
||||||
|
@ -1292,8 +1391,8 @@ void WriteROMCnt(u32 val)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x10:
|
case 0x10:
|
||||||
for (u32 pos = 0; pos < DataOutLen; pos += 4)
|
for (u32 pos = 0; pos < TransferLen; pos += 4)
|
||||||
*(u32*)&DataOut[pos] = CartID;
|
*(u32*)&TransferData[pos] = CartID;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x20:
|
case 0x20:
|
||||||
|
@ -1343,29 +1442,52 @@ void WriteROMCnt(u32 val)
|
||||||
NDS::ScheduleEvent(NDS::Event_ROMTransfer, false, xfercycle*(cmddelay+4), ROMPrepareData, 0);
|
NDS::ScheduleEvent(NDS::Event_ROMTransfer, false, xfercycle*(cmddelay+4), ROMPrepareData, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AdvanceROMTransfer()
|
||||||
|
{
|
||||||
|
ROMCnt &= ~(1<<23);
|
||||||
|
|
||||||
|
if (TransferPos < TransferLen)
|
||||||
|
{
|
||||||
|
u32 xfercycle = (ROMCnt & (1<<27)) ? 8 : 5;
|
||||||
|
u32 delay = 4;
|
||||||
|
if (!(ROMCnt & (1<<30)))
|
||||||
|
{
|
||||||
|
if (!(TransferPos & 0x1FF))
|
||||||
|
delay += ((ROMCnt >> 16) & 0x3F);
|
||||||
|
}
|
||||||
|
|
||||||
|
NDS::ScheduleEvent(NDS::Event_ROMTransfer, false, xfercycle*delay, ROMPrepareData, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ROMEndTransfer(0);
|
||||||
|
}
|
||||||
|
|
||||||
u32 ReadROMData()
|
u32 ReadROMData()
|
||||||
{
|
{
|
||||||
if (ROMCnt & (1<<23))
|
if (ROMCnt & (1<<23))
|
||||||
{
|
{
|
||||||
ROMCnt &= ~(1<<23);
|
AdvanceROMTransfer();
|
||||||
|
|
||||||
if (DataOutPos < DataOutLen)
|
|
||||||
{
|
|
||||||
u32 xfercycle = (ROMCnt & (1<<27)) ? 8 : 5;
|
|
||||||
u32 delay = 4;
|
|
||||||
if (!(ROMCnt & (1<<30)))
|
|
||||||
{
|
|
||||||
if (!(DataOutPos & 0x1FF))
|
|
||||||
delay += ((ROMCnt >> 16) & 0x3F);
|
|
||||||
}
|
|
||||||
|
|
||||||
NDS::ScheduleEvent(NDS::Event_ROMTransfer, false, xfercycle*delay, ROMPrepareData, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ROMEndTransfer(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ROMDataOut;
|
return ROMData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteROMData(u32 val)
|
||||||
|
{
|
||||||
|
ROMData = val;
|
||||||
|
|
||||||
|
if (ROMCnt & (1<<23))
|
||||||
|
{
|
||||||
|
if (TransferDir == 1)
|
||||||
|
{
|
||||||
|
if (TransferPos < TransferLen)
|
||||||
|
*(u32*)&TransferData[TransferPos] = ROMData;
|
||||||
|
|
||||||
|
TransferPos += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdvanceROMTransfer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -48,10 +48,13 @@ void DecryptSecureArea(u8* out);
|
||||||
bool LoadROM(const char* path, const char* sram, bool direct);
|
bool LoadROM(const char* path, const char* sram, bool direct);
|
||||||
void RelocateSave(const char* path, bool write);
|
void RelocateSave(const char* path, bool write);
|
||||||
|
|
||||||
|
int ImportSRAM(const u8* data, u32 length);
|
||||||
|
|
||||||
void ResetCart();
|
void ResetCart();
|
||||||
|
|
||||||
void WriteROMCnt(u32 val);
|
void WriteROMCnt(u32 val);
|
||||||
u32 ReadROMData();
|
u32 ReadROMData();
|
||||||
|
void WriteROMData(u32 val);
|
||||||
|
|
||||||
void WriteSPICnt(u16 val);
|
void WriteSPICnt(u16 val);
|
||||||
u8 ReadSPIData();
|
u8 ReadSPIData();
|
||||||
|
|
37
src/RTC.cpp
37
src/RTC.cpp
|
@ -16,6 +16,9 @@
|
||||||
with melonDS. If not, see http://www.gnu.org/licenses/.
|
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 <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -125,31 +128,29 @@ void ByteIn(u8 val)
|
||||||
|
|
||||||
case 0x20:
|
case 0x20:
|
||||||
{
|
{
|
||||||
time_t timestamp;
|
time_t timestamp = time(NULL);
|
||||||
struct tm* timedata;
|
struct tm timedata;
|
||||||
time(×tamp);
|
localtime_r(×tamp, &timedata);
|
||||||
timedata = localtime(×tamp);
|
|
||||||
|
|
||||||
Output[0] = BCD(timedata->tm_year - 100);
|
Output[0] = BCD(timedata.tm_year - 100);
|
||||||
Output[1] = BCD(timedata->tm_mon + 1);
|
Output[1] = BCD(timedata.tm_mon + 1);
|
||||||
Output[2] = BCD(timedata->tm_mday);
|
Output[2] = BCD(timedata.tm_mday);
|
||||||
Output[3] = BCD(timedata->tm_wday);
|
Output[3] = BCD(timedata.tm_wday);
|
||||||
Output[4] = BCD(timedata->tm_hour);
|
Output[4] = BCD(timedata.tm_hour);
|
||||||
Output[5] = BCD(timedata->tm_min);
|
Output[5] = BCD(timedata.tm_min);
|
||||||
Output[6] = BCD(timedata->tm_sec);
|
Output[6] = BCD(timedata.tm_sec);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x60:
|
case 0x60:
|
||||||
{
|
{
|
||||||
time_t timestamp;
|
time_t timestamp = time(NULL);
|
||||||
struct tm* timedata;
|
struct tm timedata;
|
||||||
time(×tamp);
|
localtime_r(×tamp, &timedata);
|
||||||
timedata = localtime(×tamp);
|
|
||||||
|
|
||||||
Output[0] = BCD(timedata->tm_hour);
|
Output[0] = BCD(timedata.tm_hour);
|
||||||
Output[1] = BCD(timedata->tm_min);
|
Output[1] = BCD(timedata.tm_min);
|
||||||
Output[2] = BCD(timedata->tm_sec);
|
Output[2] = BCD(timedata.tm_sec);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
26
src/SPI.cpp
26
src/SPI.cpp
|
@ -179,24 +179,25 @@ void Reset()
|
||||||
//Firmware[userdata+0x64] &= 0xBF;
|
//Firmware[userdata+0x64] &= 0xBF;
|
||||||
|
|
||||||
*(u16*)&Firmware[userdata+0x72] = CRC16(&Firmware[userdata], 0x70, 0xFFFF);
|
*(u16*)&Firmware[userdata+0x72] = CRC16(&Firmware[userdata], 0x70, 0xFFFF);
|
||||||
|
|
||||||
|
if (Config::RandomizeMAC)
|
||||||
|
{
|
||||||
|
// replace MAC address with random address
|
||||||
|
Firmware[0x36] = 0x00;
|
||||||
|
Firmware[0x37] = 0x09;
|
||||||
|
Firmware[0x38] = 0xBF;
|
||||||
|
Firmware[0x39] = rand()&0xFF;
|
||||||
|
Firmware[0x3A] = rand()&0xFF;
|
||||||
|
Firmware[0x3B] = rand()&0xFF;
|
||||||
|
|
||||||
|
*(u16*)&Firmware[0x2A] = CRC16(&Firmware[0x2C], *(u16*)&Firmware[0x2C], 0x0000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
// replace MAC address with random address
|
|
||||||
// TODO: make optional?
|
|
||||||
Firmware[0x36] = 0x00;
|
|
||||||
Firmware[0x37] = 0x09;
|
|
||||||
Firmware[0x38] = 0xBF;
|
|
||||||
Firmware[0x39] = rand()&0xFF;
|
|
||||||
Firmware[0x3A] = rand()&0xFF;
|
|
||||||
Firmware[0x3B] = rand()&0xFF;
|
|
||||||
#endif
|
|
||||||
printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
|
printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
|
||||||
Firmware[0x36], Firmware[0x37], Firmware[0x38],
|
Firmware[0x36], Firmware[0x37], Firmware[0x38],
|
||||||
Firmware[0x39], Firmware[0x3A], Firmware[0x3B]);
|
Firmware[0x39], Firmware[0x3A], Firmware[0x3B]);
|
||||||
|
|
||||||
//*(u16*)&Firmware[0x2A] = CRC16(&Firmware[0x2C], *(u16*)&Firmware[0x2C], 0x0000);
|
|
||||||
|
|
||||||
// verify shit
|
// verify shit
|
||||||
printf("FW: WIFI CRC16 = %s\n", VerifyCRC16(0x0000, 0x2C, *(u16*)&Firmware[0x2C], 0x2A)?"GOOD":"BAD");
|
printf("FW: WIFI CRC16 = %s\n", VerifyCRC16(0x0000, 0x2C, *(u16*)&Firmware[0x2C], 0x2A)?"GOOD":"BAD");
|
||||||
printf("FW: AP1 CRC16 = %s\n", VerifyCRC16(0x0000, 0x7FA00&FirmwareMask, 0xFE, 0x7FAFE&FirmwareMask)?"GOOD":"BAD");
|
printf("FW: AP1 CRC16 = %s\n", VerifyCRC16(0x0000, 0x7FA00&FirmwareMask, 0xFE, 0x7FAFE&FirmwareMask)?"GOOD":"BAD");
|
||||||
|
@ -241,6 +242,7 @@ void SetupDirectBoot()
|
||||||
|
|
||||||
u8 GetConsoleType() { return Firmware[0x1D]; }
|
u8 GetConsoleType() { return Firmware[0x1D]; }
|
||||||
u8 GetWifiVersion() { return Firmware[0x2F]; }
|
u8 GetWifiVersion() { return Firmware[0x2F]; }
|
||||||
|
u8 GetNWifiVersion() { return Firmware[0x1FD]; } // for DSi; will return 0xFF on a DS
|
||||||
u8 GetRFVersion() { return Firmware[0x40]; }
|
u8 GetRFVersion() { return Firmware[0x40]; }
|
||||||
u8* GetWifiMAC() { return &Firmware[0x36]; }
|
u8* GetWifiMAC() { return &Firmware[0x36]; }
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ void SetupDirectBoot();
|
||||||
|
|
||||||
u8 GetConsoleType();
|
u8 GetConsoleType();
|
||||||
u8 GetWifiVersion();
|
u8 GetWifiVersion();
|
||||||
|
u8 GetNWifiVersion();
|
||||||
u8 GetRFVersion();
|
u8 GetRFVersion();
|
||||||
u8* GetWifiMAC();
|
u8* GetWifiMAC();
|
||||||
|
|
||||||
|
|
|
@ -420,6 +420,8 @@ void Channel::Run(s32* buf, u32 samples)
|
||||||
{
|
{
|
||||||
if (!(Cnt & (1<<31))) return;
|
if (!(Cnt & (1<<31))) return;
|
||||||
|
|
||||||
|
if ((type < 3) && ((Length+LoopPos) < 16)) return;
|
||||||
|
|
||||||
if (KeyOn)
|
if (KeyOn)
|
||||||
{
|
{
|
||||||
Start();
|
Start();
|
||||||
|
|
|
@ -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)
|
void Savestate::VarArray(void* data, u32 len)
|
||||||
{
|
{
|
||||||
if (Error) return;
|
if (Error) return;
|
||||||
|
@ -273,4 +289,4 @@ void Savestate::VarArray(void* data, u32 len)
|
||||||
{
|
{
|
||||||
fread(data, len, 1, file);
|
fread(data, len, 1, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -46,6 +46,8 @@ public:
|
||||||
void Var32(u32* var);
|
void Var32(u32* var);
|
||||||
void Var64(u64* var);
|
void Var64(u64* var);
|
||||||
|
|
||||||
|
void Bool32(bool* var);
|
||||||
|
|
||||||
void VarArray(void* data, u32 len);
|
void VarArray(void* data, u32 len);
|
||||||
|
|
||||||
bool IsAtleastVersion(u32 major, u32 minor)
|
bool IsAtleastVersion(u32 major, u32 minor)
|
||||||
|
|
11
src/Wifi.cpp
11
src/Wifi.cpp
|
@ -237,7 +237,7 @@ void DoSavestate(Savestate* file)
|
||||||
|
|
||||||
file->Var64(&USCounter);
|
file->Var64(&USCounter);
|
||||||
file->Var64(&USCompare);
|
file->Var64(&USCompare);
|
||||||
file->Var32((u32*)&BlockBeaconIRQ14);
|
file->Bool32(&BlockBeaconIRQ14);
|
||||||
|
|
||||||
file->Var32(&ComStatus);
|
file->Var32(&ComStatus);
|
||||||
file->Var32(&TXCurSlot);
|
file->Var32(&TXCurSlot);
|
||||||
|
@ -816,6 +816,9 @@ bool CheckRX(bool block)
|
||||||
if (!(IOPORT(W_RXCnt) & 0x8000))
|
if (!(IOPORT(W_RXCnt) & 0x8000))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (IOPORT(W_RXBufBegin) == IOPORT(W_RXBufEnd))
|
||||||
|
return false;
|
||||||
|
|
||||||
u16 framelen;
|
u16 framelen;
|
||||||
u16 framectl;
|
u16 framectl;
|
||||||
u8 txrate;
|
u8 txrate;
|
||||||
|
@ -1049,7 +1052,7 @@ void USTimer(u32 param)
|
||||||
if (!(RXTime & RXHalfwordTimeMask))
|
if (!(RXTime & RXHalfwordTimeMask))
|
||||||
{
|
{
|
||||||
u16 addr = IOPORT(W_RXTXAddr) << 1;
|
u16 addr = IOPORT(W_RXTXAddr) << 1;
|
||||||
*(u16*)&RAM[addr] = *(u16*)&RXBuffer[RXBufferPtr];
|
if (addr < 0x1FFF) *(u16*)&RAM[addr] = *(u16*)&RXBuffer[RXBufferPtr];
|
||||||
|
|
||||||
IncrementRXAddr(addr);
|
IncrementRXAddr(addr);
|
||||||
RXBufferPtr += 2;
|
RXBufferPtr += 2;
|
||||||
|
@ -1146,7 +1149,7 @@ void RFTransfer_Type3()
|
||||||
// TODO: wifi waitstates
|
// TODO: wifi waitstates
|
||||||
|
|
||||||
u16 Read(u32 addr)
|
u16 Read(u32 addr)
|
||||||
{
|
{//printf("WIFI READ %08X\n", addr);
|
||||||
if (addr >= 0x04810000)
|
if (addr >= 0x04810000)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1236,7 +1239,7 @@ u16 Read(u32 addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(u32 addr, u16 val)
|
void Write(u32 addr, u16 val)
|
||||||
{
|
{//printf("WIFI WRITE %08X %04X\n", addr, val);
|
||||||
if (addr >= 0x04810000)
|
if (addr >= 0x04810000)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -1631,7 +1631,7 @@ void ARM64XEmitter::ASR(ARM64Reg Rd, ARM64Reg Rm, int shift)
|
||||||
int bits = Is64Bit(Rd) ? 64 : 32;
|
int bits = Is64Bit(Rd) ? 64 : 32;
|
||||||
SBFM(Rd, Rm, shift, bits - 1);
|
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);
|
EXTR(Rd, Rm, Rm, shift);
|
||||||
}
|
}
|
||||||
|
|
|
@ -727,7 +727,7 @@ public:
|
||||||
void LSR(ARM64Reg Rd, ARM64Reg Rm, int shift);
|
void LSR(ARM64Reg Rd, ARM64Reg Rm, int shift);
|
||||||
void LSL(ARM64Reg Rd, ARM64Reg Rm, int shift);
|
void LSL(ARM64Reg Rd, ARM64Reg Rm, int shift);
|
||||||
void ASR(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)
|
// Logical (immediate)
|
||||||
void AND(ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms, bool invert = false);
|
void AND(ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms, bool invert = false);
|
||||||
|
|
|
@ -1214,7 +1214,7 @@ void XEmitter::ROL(int bits, const OpArg& dest, const OpArg& shift)
|
||||||
{
|
{
|
||||||
WriteShift(bits, dest, shift, 0);
|
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);
|
WriteShift(bits, dest, shift, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -489,7 +489,7 @@ public:
|
||||||
|
|
||||||
// Shift
|
// Shift
|
||||||
void ROL(int bits, const OpArg& dest, const OpArg& 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 RCL(int bits, const OpArg& dest, const OpArg& shift);
|
||||||
void RCR(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);
|
void SHL(int bits, const OpArg& dest, const OpArg& shift);
|
||||||
|
|
|
@ -67,6 +67,9 @@ extern bool SavestateLoaded;
|
||||||
// initialize the ROM handling utility
|
// initialize the ROM handling utility
|
||||||
void Init_ROM();
|
void Init_ROM();
|
||||||
|
|
||||||
|
// deinitialize the ROM handling utility
|
||||||
|
void DeInit_ROM();
|
||||||
|
|
||||||
// load the BIOS/firmware and boot from it
|
// load the BIOS/firmware and boot from it
|
||||||
int LoadBIOS();
|
int LoadBIOS();
|
||||||
|
|
||||||
|
@ -97,6 +100,12 @@ bool SaveState(const char* filename);
|
||||||
// undo the latest savestate load
|
// undo the latest savestate load
|
||||||
void UndoStateLoad();
|
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);
|
||||||
|
|
||||||
|
|
||||||
// setup the display layout based on the provided display size and parameters
|
// setup the display layout based on the provided display size and parameters
|
||||||
// * screenWidth/screenHeight: size of the host display
|
// * screenWidth/screenHeight: size of the host display
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
#include "NDS.h"
|
#include "NDS.h"
|
||||||
#include "GBACart.h"
|
#include "GBACart.h"
|
||||||
|
|
||||||
|
#include "AREngine.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Frontend
|
namespace Frontend
|
||||||
{
|
{
|
||||||
|
@ -37,6 +39,9 @@ char PrevSRAMPath[ROMSlot_MAX][1024]; // for savestate 'undo load'
|
||||||
|
|
||||||
bool SavestateLoaded;
|
bool SavestateLoaded;
|
||||||
|
|
||||||
|
ARCodeFile* CheatFile;
|
||||||
|
bool CheatsOn;
|
||||||
|
|
||||||
|
|
||||||
void Init_ROM()
|
void Init_ROM()
|
||||||
{
|
{
|
||||||
|
@ -48,6 +53,18 @@ void Init_ROM()
|
||||||
memset(SRAMPath[ROMSlot_GBA], 0, 1024);
|
memset(SRAMPath[ROMSlot_GBA], 0, 1024);
|
||||||
memset(PrevSRAMPath[ROMSlot_NDS], 0, 1024);
|
memset(PrevSRAMPath[ROMSlot_NDS], 0, 1024);
|
||||||
memset(PrevSRAMPath[ROMSlot_GBA], 0, 1024);
|
memset(PrevSRAMPath[ROMSlot_GBA], 0, 1024);
|
||||||
|
|
||||||
|
CheatFile = nullptr;
|
||||||
|
CheatsOn = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeInit_ROM()
|
||||||
|
{
|
||||||
|
if (CheatFile)
|
||||||
|
{
|
||||||
|
delete CheatFile;
|
||||||
|
CheatFile = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: currently, when failing to load a ROM for whatever reason, we attempt
|
// TODO: currently, when failing to load a ROM for whatever reason, we attempt
|
||||||
|
@ -198,6 +215,32 @@ int VerifyDSiNAND()
|
||||||
return Load_OK;
|
return Load_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoadCheats()
|
||||||
|
{
|
||||||
|
if (CheatFile)
|
||||||
|
{
|
||||||
|
delete CheatFile;
|
||||||
|
CheatFile = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char filename[1024];
|
||||||
|
if (ROMPath[ROMSlot_NDS][0] != '\0')
|
||||||
|
{
|
||||||
|
strncpy(filename, ROMPath[ROMSlot_NDS], 1023);
|
||||||
|
filename[1023] = '\0';
|
||||||
|
strncpy(filename + strlen(ROMPath[ROMSlot_NDS]) - 3, "mch", 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strncpy(filename, "firmware.mch", 1023);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check for error (malformed cheat file, ...)
|
||||||
|
CheatFile = new ARCodeFile(filename);
|
||||||
|
|
||||||
|
AREngine::SetCodeFile(CheatsOn ? CheatFile : nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
int LoadBIOS()
|
int LoadBIOS()
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
@ -235,6 +278,8 @@ int LoadBIOS()
|
||||||
|
|
||||||
SavestateLoaded = false;
|
SavestateLoaded = false;
|
||||||
|
|
||||||
|
LoadCheats();
|
||||||
|
|
||||||
return Load_OK;
|
return Load_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,6 +340,8 @@ int LoadROM(const char* file, int slot)
|
||||||
{
|
{
|
||||||
SavestateLoaded = false;
|
SavestateLoaded = false;
|
||||||
|
|
||||||
|
LoadCheats();
|
||||||
|
|
||||||
// Reload the inserted GBA cartridge (if any)
|
// Reload the inserted GBA cartridge (if any)
|
||||||
// TODO: report failure there??
|
// TODO: report failure there??
|
||||||
if (ROMPath[ROMSlot_GBA][0] != '\0') NDS::LoadGBAROM(ROMPath[ROMSlot_GBA], SRAMPath[ROMSlot_GBA]);
|
if (ROMPath[ROMSlot_GBA][0] != '\0') NDS::LoadGBAROM(ROMPath[ROMSlot_GBA], SRAMPath[ROMSlot_GBA]);
|
||||||
|
@ -387,6 +434,8 @@ int Reset()
|
||||||
return Load_ROMLoadError;
|
return Load_ROMLoadError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadCheats();
|
||||||
|
|
||||||
return Load_OK;
|
return Load_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,4 +588,26 @@ 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;
|
||||||
|
if (CheatFile)
|
||||||
|
AREngine::SetCodeFile(CheatsOn ? CheatFile : nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ project(qt_sdl)
|
||||||
SET(SOURCES_QT_SDL
|
SET(SOURCES_QT_SDL
|
||||||
main.cpp
|
main.cpp
|
||||||
main_shaders.h
|
main_shaders.h
|
||||||
|
CheatsDialog.cpp
|
||||||
EmuSettingsDialog.cpp
|
EmuSettingsDialog.cpp
|
||||||
InputConfigDialog.cpp
|
InputConfigDialog.cpp
|
||||||
VideoSettingsDialog.cpp
|
VideoSettingsDialog.cpp
|
||||||
|
|
|
@ -0,0 +1,412 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016-2020 Arisotura
|
||||||
|
|
||||||
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
melonDS is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "Platform.h"
|
||||||
|
#include "Config.h"
|
||||||
|
#include "PlatformConfig.h"
|
||||||
|
|
||||||
|
#include "CheatsDialog.h"
|
||||||
|
#include "ui_CheatsDialog.h"
|
||||||
|
|
||||||
|
|
||||||
|
CheatsDialog* CheatsDialog::currentDlg = nullptr;
|
||||||
|
|
||||||
|
extern char* EmuDirectory;
|
||||||
|
|
||||||
|
namespace Frontend { extern ARCodeFile* CheatFile; }
|
||||||
|
|
||||||
|
|
||||||
|
CheatsDialog::CheatsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::CheatsDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
|
codeFile = Frontend::CheatFile;
|
||||||
|
|
||||||
|
QStandardItemModel* model = new QStandardItemModel();
|
||||||
|
ui->tvCodeList->setModel(model);
|
||||||
|
connect(model, &QStandardItemModel::itemChanged, this, &CheatsDialog::onCheatEntryModified);
|
||||||
|
connect(ui->tvCodeList->selectionModel(), &QItemSelectionModel::selectionChanged, this, &CheatsDialog::onCheatSelectionChanged);
|
||||||
|
|
||||||
|
{
|
||||||
|
QStandardItem* root = model->invisibleRootItem();
|
||||||
|
|
||||||
|
for (ARCodeCatList::iterator i = codeFile->Categories.begin(); i != codeFile->Categories.end(); i++)
|
||||||
|
{
|
||||||
|
ARCodeCat& cat = *i;
|
||||||
|
|
||||||
|
QStandardItem* catitem = new QStandardItem(cat.Name);
|
||||||
|
catitem->setEditable(true);
|
||||||
|
catitem->setData(QVariant::fromValue(i));
|
||||||
|
root->appendRow(catitem);
|
||||||
|
|
||||||
|
for (ARCodeList::iterator j = cat.Codes.begin(); j != cat.Codes.end(); j++)
|
||||||
|
{
|
||||||
|
ARCode& code = *j;
|
||||||
|
|
||||||
|
QStandardItem* codeitem = new QStandardItem(code.Name);
|
||||||
|
codeitem->setEditable(true);
|
||||||
|
codeitem->setCheckable(true);
|
||||||
|
codeitem->setCheckState(code.Enabled ? Qt::Checked : Qt::Unchecked);
|
||||||
|
codeitem->setData(QVariant::fromValue(j));
|
||||||
|
catitem->appendRow(codeitem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->txtCode->setPlaceholderText("");
|
||||||
|
codeChecker = new ARCodeChecker(ui->txtCode->document());
|
||||||
|
|
||||||
|
ui->btnNewARCode->setEnabled(false);
|
||||||
|
ui->btnDeleteCode->setEnabled(false);
|
||||||
|
ui->txtCode->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
CheatsDialog::~CheatsDialog()
|
||||||
|
{
|
||||||
|
QAbstractItemModel* model = ui->tvCodeList->model();
|
||||||
|
ui->tvCodeList->setModel(nullptr);
|
||||||
|
delete model;
|
||||||
|
|
||||||
|
delete codeChecker;
|
||||||
|
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatsDialog::on_CheatsDialog_accepted()
|
||||||
|
{
|
||||||
|
codeFile->Save();
|
||||||
|
|
||||||
|
closeDlg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatsDialog::on_CheatsDialog_rejected()
|
||||||
|
{
|
||||||
|
codeFile->Load();
|
||||||
|
|
||||||
|
closeDlg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatsDialog::on_btnNewCat_clicked()
|
||||||
|
{
|
||||||
|
QStandardItem* root = ((QStandardItemModel*)ui->tvCodeList->model())->invisibleRootItem();
|
||||||
|
|
||||||
|
ARCodeCat cat;
|
||||||
|
cat.Codes.clear();
|
||||||
|
memset(cat.Name, 0, 128);
|
||||||
|
strncpy(cat.Name, "(new category)", 127);
|
||||||
|
|
||||||
|
codeFile->Categories.push_back(cat);
|
||||||
|
ARCodeCatList::iterator id = codeFile->Categories.end(); id--;
|
||||||
|
|
||||||
|
QStandardItem* catitem = new QStandardItem(cat.Name);
|
||||||
|
catitem->setEditable(true);
|
||||||
|
catitem->setData(QVariant::fromValue(id));
|
||||||
|
root->appendRow(catitem);
|
||||||
|
|
||||||
|
ui->tvCodeList->selectionModel()->select(catitem->index(), QItemSelectionModel::ClearAndSelect);
|
||||||
|
ui->tvCodeList->edit(catitem->index());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatsDialog::on_btnNewARCode_clicked()
|
||||||
|
{
|
||||||
|
QModelIndexList indices = ui->tvCodeList->selectionModel()->selectedIndexes();
|
||||||
|
if (indices.isEmpty())
|
||||||
|
{
|
||||||
|
// ????
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStandardItemModel* model = (QStandardItemModel*)ui->tvCodeList->model();
|
||||||
|
QStandardItem* item = model->itemFromIndex(indices.first());
|
||||||
|
QStandardItem* parentitem;
|
||||||
|
|
||||||
|
QVariant data = item->data();
|
||||||
|
if (data.canConvert<ARCodeCatList::iterator>())
|
||||||
|
{
|
||||||
|
parentitem = item;
|
||||||
|
}
|
||||||
|
else if (data.canConvert<ARCodeList::iterator>())
|
||||||
|
{
|
||||||
|
parentitem = item->parent();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("what?? :(\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ARCodeCatList::iterator it_cat = parentitem->data().value<ARCodeCatList::iterator>();
|
||||||
|
ARCodeCat& cat = *it_cat;
|
||||||
|
|
||||||
|
ARCode code;
|
||||||
|
memset(code.Name, 0, 128);
|
||||||
|
strncpy(code.Name, "(new AR code)", 127);
|
||||||
|
code.Enabled = true;
|
||||||
|
code.CodeLen = 0;
|
||||||
|
memset(code.Code, 0, sizeof(code.Code));
|
||||||
|
|
||||||
|
cat.Codes.push_back(code);
|
||||||
|
ARCodeList::iterator id = cat.Codes.end(); id--;
|
||||||
|
|
||||||
|
QStandardItem* codeitem = new QStandardItem(code.Name);
|
||||||
|
codeitem->setEditable(true);
|
||||||
|
codeitem->setCheckable(true);
|
||||||
|
codeitem->setCheckState(code.Enabled ? Qt::Checked : Qt::Unchecked);
|
||||||
|
codeitem->setData(QVariant::fromValue(id));
|
||||||
|
parentitem->appendRow(codeitem);
|
||||||
|
|
||||||
|
ui->tvCodeList->selectionModel()->select(codeitem->index(), QItemSelectionModel::ClearAndSelect);
|
||||||
|
ui->tvCodeList->edit(codeitem->index());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatsDialog::on_btnDeleteCode_clicked()
|
||||||
|
{
|
||||||
|
QModelIndexList indices = ui->tvCodeList->selectionModel()->selectedIndexes();
|
||||||
|
if (indices.isEmpty())
|
||||||
|
{
|
||||||
|
// ????
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox::StandardButton res = QMessageBox::question(this,
|
||||||
|
"Confirm deletion",
|
||||||
|
"Really delete the selected item?",
|
||||||
|
QMessageBox::Yes|QMessageBox::No,
|
||||||
|
QMessageBox::No);
|
||||||
|
if (res != QMessageBox::Yes) return;
|
||||||
|
|
||||||
|
QStandardItemModel* model = (QStandardItemModel*)ui->tvCodeList->model();
|
||||||
|
QStandardItem* item = model->itemFromIndex(indices.first());
|
||||||
|
|
||||||
|
QVariant data = item->data();
|
||||||
|
if (data.canConvert<ARCodeCatList::iterator>())
|
||||||
|
{
|
||||||
|
ARCodeCatList::iterator it_cat = data.value<ARCodeCatList::iterator>();
|
||||||
|
|
||||||
|
(*it_cat).Codes.clear();
|
||||||
|
codeFile->Categories.erase(it_cat);
|
||||||
|
|
||||||
|
model->invisibleRootItem()->removeRow(item->row());
|
||||||
|
}
|
||||||
|
else if (data.canConvert<ARCodeList::iterator>())
|
||||||
|
{
|
||||||
|
ARCodeList::iterator it_code = data.value<ARCodeList::iterator>();
|
||||||
|
ARCodeCatList::iterator it_cat = item->parent()->data().value<ARCodeCatList::iterator>();
|
||||||
|
|
||||||
|
(*it_cat).Codes.erase(it_code);
|
||||||
|
|
||||||
|
item->parent()->removeRow(item->row());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatsDialog::onCheatSelectionChanged(const QItemSelection& sel, const QItemSelection& desel)
|
||||||
|
{
|
||||||
|
QModelIndexList indices = sel.indexes();
|
||||||
|
if (indices.isEmpty())
|
||||||
|
{
|
||||||
|
ui->btnNewARCode->setEnabled(false);
|
||||||
|
ui->btnDeleteCode->setEnabled(false);
|
||||||
|
ui->txtCode->setEnabled(false);
|
||||||
|
ui->txtCode->setPlaceholderText("");
|
||||||
|
ui->txtCode->clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QStandardItem* item = ((QStandardItemModel*)ui->tvCodeList->model())->itemFromIndex(indices.first());
|
||||||
|
|
||||||
|
QVariant data = item->data();
|
||||||
|
if (data.canConvert<ARCodeCatList::iterator>())
|
||||||
|
{
|
||||||
|
ui->btnDeleteCode->setEnabled(true);
|
||||||
|
ui->txtCode->setEnabled(false);
|
||||||
|
ui->txtCode->setPlaceholderText("");
|
||||||
|
ui->txtCode->clear();
|
||||||
|
}
|
||||||
|
else if (data.canConvert<ARCodeList::iterator>())
|
||||||
|
{
|
||||||
|
ARCode& code = *(data.value<ARCodeList::iterator>());
|
||||||
|
|
||||||
|
ui->btnDeleteCode->setEnabled(true);
|
||||||
|
ui->txtCode->setEnabled(true);
|
||||||
|
ui->txtCode->setPlaceholderText("(enter AR code here)");
|
||||||
|
|
||||||
|
QString codestr = "";
|
||||||
|
for (u32 i = 0; i < code.CodeLen; i += 2)
|
||||||
|
{
|
||||||
|
u32 c0 = code.Code[i+0];
|
||||||
|
u32 c1 = code.Code[i+1];
|
||||||
|
//codestr += QString("%1 %2\n").arg(c0, 8, 16, '0').arg(c1, 8, 16, '0').toUpper();
|
||||||
|
codestr += QString::asprintf("%08X %08X\n", c0, c1);
|
||||||
|
}
|
||||||
|
ui->txtCode->setPlainText(codestr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->btnNewARCode->setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatsDialog::onCheatEntryModified(QStandardItem* item)
|
||||||
|
{
|
||||||
|
QVariant data = item->data();
|
||||||
|
if (data.canConvert<ARCodeCatList::iterator>())
|
||||||
|
{
|
||||||
|
ARCodeCat& cat = *(data.value<ARCodeCatList::iterator>());
|
||||||
|
|
||||||
|
if (item->text().isEmpty())
|
||||||
|
{
|
||||||
|
QString oldname = QString(cat.Name);
|
||||||
|
item->setText(oldname.isEmpty() ? "(blank category name??)" : oldname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strncpy(cat.Name, item->text().toStdString().c_str(), 127);
|
||||||
|
cat.Name[127] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (data.canConvert<ARCodeList::iterator>())
|
||||||
|
{
|
||||||
|
ARCode& code = *(data.value<ARCodeList::iterator>());
|
||||||
|
|
||||||
|
if (item->text().isEmpty())
|
||||||
|
{
|
||||||
|
QString oldname = QString(code.Name);
|
||||||
|
item->setText(oldname.isEmpty() ? "(blank code name??)" : oldname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strncpy(code.Name, item->text().toStdString().c_str(), 127);
|
||||||
|
code.Name[127] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
code.Enabled = (item->checkState() == Qt::Checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatsDialog::on_txtCode_textChanged()
|
||||||
|
{
|
||||||
|
QModelIndexList indices = ui->tvCodeList->selectionModel()->selectedIndexes();
|
||||||
|
if (indices.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QStandardItem* item = ((QStandardItemModel*)ui->tvCodeList->model())->itemFromIndex(indices.first());
|
||||||
|
QVariant data = item->data();
|
||||||
|
if (!data.canConvert<ARCodeList::iterator>())
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool error = false;
|
||||||
|
u32 codeout[2*64];
|
||||||
|
u32 codelen = 0;
|
||||||
|
|
||||||
|
QString text = ui->txtCode->document()->toPlainText();
|
||||||
|
QStringList lines = text.split('\n', QString::SkipEmptyParts);
|
||||||
|
for (QStringList::iterator it = lines.begin(); it != lines.end(); it++)
|
||||||
|
{
|
||||||
|
QString line = *it;
|
||||||
|
line = line.trimmed();
|
||||||
|
if (line.isEmpty()) continue;
|
||||||
|
|
||||||
|
if (line.length() > 17)
|
||||||
|
{
|
||||||
|
error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList numbers = line.split(' ');
|
||||||
|
if (numbers.length() != 2)
|
||||||
|
{
|
||||||
|
error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList::iterator jt = numbers.begin();
|
||||||
|
QString s0 = *jt++;
|
||||||
|
QString s1 = *jt++;
|
||||||
|
|
||||||
|
bool c0good, c1good;
|
||||||
|
u32 c0, c1;
|
||||||
|
|
||||||
|
c0 = s0.toUInt(&c0good, 16);
|
||||||
|
c1 = s1.toUInt(&c1good, 16);
|
||||||
|
|
||||||
|
if (!c0good || !c1good)
|
||||||
|
{
|
||||||
|
error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (codelen >= 2*64)
|
||||||
|
{
|
||||||
|
error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
codeout[codelen++] = c0;
|
||||||
|
codeout[codelen++] = c1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->btnNewCat->setEnabled(!error);
|
||||||
|
ui->btnNewARCode->setEnabled(!error);
|
||||||
|
ui->btnDeleteCode->setEnabled(!error);
|
||||||
|
ui->tvCodeList->setEnabled(!error);
|
||||||
|
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!error);
|
||||||
|
|
||||||
|
if (error) return;
|
||||||
|
|
||||||
|
ARCode& code = *(data.value<ARCodeList::iterator>());
|
||||||
|
memcpy(code.Code, codeout, codelen*sizeof(u32));
|
||||||
|
code.CodeLen = codelen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARCodeChecker::highlightBlock(const QString& text)
|
||||||
|
{
|
||||||
|
QTextCharFormat errformat; errformat.setForeground(Qt::red);
|
||||||
|
|
||||||
|
{
|
||||||
|
QRegularExpression expr("^\\s*[0-9A-Fa-f]{1,8} [0-9A-Fa-f]{1,8}\\s*$");
|
||||||
|
QRegularExpressionMatchIterator it = expr.globalMatch(text);
|
||||||
|
if (!it.hasNext())
|
||||||
|
{
|
||||||
|
setFormat(0, text.length(), errformat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*{
|
||||||
|
QRegularExpression expr("[^0-9A-Fa-f\\s]+");
|
||||||
|
QRegularExpressionMatchIterator it = expr.globalMatch(text);
|
||||||
|
while (it.hasNext())
|
||||||
|
{
|
||||||
|
QRegularExpressionMatch match = it.next();
|
||||||
|
setFormat(match.capturedStart(), match.capturedLength(), errformat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
QRegularExpression expr("[0-9A-Fa-f]{9,}");
|
||||||
|
QRegularExpressionMatchIterator it = expr.globalMatch(text);
|
||||||
|
while (it.hasNext())
|
||||||
|
{
|
||||||
|
QRegularExpressionMatch match = it.next();
|
||||||
|
setFormat(match.capturedStart(), match.capturedLength(), errformat);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016-2020 Arisotura
|
||||||
|
|
||||||
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
melonDS is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CHEATSDIALOG_H
|
||||||
|
#define CHEATSDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
#include <QItemSelection>
|
||||||
|
#include <QSyntaxHighlighter>
|
||||||
|
|
||||||
|
#include "ARCodeFile.h"
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(ARCodeList::iterator)
|
||||||
|
Q_DECLARE_METATYPE(ARCodeCatList::iterator)
|
||||||
|
|
||||||
|
namespace Ui { class CheatsDialog; }
|
||||||
|
class CheatsDialog;
|
||||||
|
|
||||||
|
class ARCodeChecker : public QSyntaxHighlighter
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ARCodeChecker(QTextDocument* parent) : QSyntaxHighlighter(parent) {}
|
||||||
|
~ARCodeChecker() {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void highlightBlock(const QString& text) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CheatsDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CheatsDialog(QWidget* parent);
|
||||||
|
~CheatsDialog();
|
||||||
|
|
||||||
|
static CheatsDialog* currentDlg;
|
||||||
|
static CheatsDialog* openDlg(QWidget* parent)
|
||||||
|
{
|
||||||
|
if (currentDlg)
|
||||||
|
{
|
||||||
|
currentDlg->activateWindow();
|
||||||
|
return currentDlg;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentDlg = new CheatsDialog(parent);
|
||||||
|
currentDlg->open();
|
||||||
|
return currentDlg;
|
||||||
|
}
|
||||||
|
static void closeDlg()
|
||||||
|
{
|
||||||
|
currentDlg = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_CheatsDialog_accepted();
|
||||||
|
void on_CheatsDialog_rejected();
|
||||||
|
|
||||||
|
void on_btnNewCat_clicked();
|
||||||
|
void on_btnNewARCode_clicked();
|
||||||
|
void on_btnDeleteCode_clicked();
|
||||||
|
|
||||||
|
void onCheatSelectionChanged(const QItemSelection& sel, const QItemSelection& desel);
|
||||||
|
void onCheatEntryModified(QStandardItem* item);
|
||||||
|
|
||||||
|
void on_txtCode_textChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::CheatsDialog* ui;
|
||||||
|
|
||||||
|
ARCodeFile* codeFile;
|
||||||
|
ARCodeChecker* codeChecker;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CHEATSDIALOG_H
|
|
@ -0,0 +1,144 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>CheatsDialog</class>
|
||||||
|
<widget class="QDialog" name="CheatsDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>609</width>
|
||||||
|
<height>417</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Cheat code editor - melonDS</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetDefaultConstraint</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnNewCat">
|
||||||
|
<property name="text">
|
||||||
|
<string>New category</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnNewARCode">
|
||||||
|
<property name="text">
|
||||||
|
<string>New AR code</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnDeleteCode">
|
||||||
|
<property name="text">
|
||||||
|
<string>Delete</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Expanding</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QTreeView" name="tvCodeList">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>2</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="headerHidden">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPlainTextEdit" name="txtCode">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>3</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>CheatsDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>304</x>
|
||||||
|
<y>396</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>304</x>
|
||||||
|
<y>208</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>CheatsDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>304</x>
|
||||||
|
<y>396</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>304</x>
|
||||||
|
<y>208</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
|
@ -44,11 +44,15 @@ EmuSettingsDialog::EmuSettingsDialog(QWidget* parent) : QDialog(parent), ui(new
|
||||||
ui->txtBIOS9Path->setText(Config::BIOS9Path);
|
ui->txtBIOS9Path->setText(Config::BIOS9Path);
|
||||||
ui->txtBIOS7Path->setText(Config::BIOS7Path);
|
ui->txtBIOS7Path->setText(Config::BIOS7Path);
|
||||||
ui->txtFirmwarePath->setText(Config::FirmwarePath);
|
ui->txtFirmwarePath->setText(Config::FirmwarePath);
|
||||||
|
ui->cbDLDIEnable->setChecked(Config::DLDIEnable != 0);
|
||||||
|
ui->txtDLDISDPath->setText(Config::DLDISDPath);
|
||||||
|
|
||||||
ui->txtDSiBIOS9Path->setText(Config::DSiBIOS9Path);
|
ui->txtDSiBIOS9Path->setText(Config::DSiBIOS9Path);
|
||||||
ui->txtDSiBIOS7Path->setText(Config::DSiBIOS7Path);
|
ui->txtDSiBIOS7Path->setText(Config::DSiBIOS7Path);
|
||||||
ui->txtDSiFirmwarePath->setText(Config::DSiFirmwarePath);
|
ui->txtDSiFirmwarePath->setText(Config::DSiFirmwarePath);
|
||||||
ui->txtDSiNANDPath->setText(Config::DSiNANDPath);
|
ui->txtDSiNANDPath->setText(Config::DSiNANDPath);
|
||||||
|
ui->cbDSiSDEnable->setChecked(Config::DSiSDEnable != 0);
|
||||||
|
ui->txtDSiSDPath->setText(Config::DSiSDPath);
|
||||||
|
|
||||||
ui->cbxConsoleType->addItem("DS");
|
ui->cbxConsoleType->addItem("DS");
|
||||||
ui->cbxConsoleType->addItem("DSi (experimental)");
|
ui->cbxConsoleType->addItem("DSi (experimental)");
|
||||||
|
@ -141,10 +145,14 @@ void EmuSettingsDialog::done(int r)
|
||||||
std::string bios9Path = ui->txtBIOS9Path->text().toStdString();
|
std::string bios9Path = ui->txtBIOS9Path->text().toStdString();
|
||||||
std::string bios7Path = ui->txtBIOS7Path->text().toStdString();
|
std::string bios7Path = ui->txtBIOS7Path->text().toStdString();
|
||||||
std::string firmwarePath = ui->txtFirmwarePath->text().toStdString();
|
std::string firmwarePath = ui->txtFirmwarePath->text().toStdString();
|
||||||
|
int dldiEnable = ui->cbDLDIEnable->isChecked() ? 1:0;
|
||||||
|
std::string dldiSDPath = ui->txtDLDISDPath->text().toStdString();
|
||||||
std::string dsiBios9Path = ui->txtDSiBIOS9Path->text().toStdString();
|
std::string dsiBios9Path = ui->txtDSiBIOS9Path->text().toStdString();
|
||||||
std::string dsiBios7Path = ui->txtDSiBIOS7Path->text().toStdString();
|
std::string dsiBios7Path = ui->txtDSiBIOS7Path->text().toStdString();
|
||||||
std::string dsiFirmwarePath = ui->txtDSiFirmwarePath->text().toStdString();
|
std::string dsiFirmwarePath = ui->txtDSiFirmwarePath->text().toStdString();
|
||||||
std::string dsiNANDPath = ui->txtDSiNANDPath->text().toStdString();
|
std::string dsiNANDPath = ui->txtDSiNANDPath->text().toStdString();
|
||||||
|
int dsiSDEnable = ui->cbDSiSDEnable->isChecked() ? 1:0;
|
||||||
|
std::string dsiSDPath = ui->txtDSiSDPath->text().toStdString();
|
||||||
|
|
||||||
if (consoleType != Config::ConsoleType
|
if (consoleType != Config::ConsoleType
|
||||||
|| directBoot != Config::DirectBoot
|
|| directBoot != Config::DirectBoot
|
||||||
|
@ -158,10 +166,14 @@ void EmuSettingsDialog::done(int r)
|
||||||
|| strcmp(Config::BIOS9Path, bios9Path.c_str()) != 0
|
|| strcmp(Config::BIOS9Path, bios9Path.c_str()) != 0
|
||||||
|| strcmp(Config::BIOS7Path, bios7Path.c_str()) != 0
|
|| strcmp(Config::BIOS7Path, bios7Path.c_str()) != 0
|
||||||
|| strcmp(Config::FirmwarePath, firmwarePath.c_str()) != 0
|
|| strcmp(Config::FirmwarePath, firmwarePath.c_str()) != 0
|
||||||
|
|| dldiEnable != Config::DLDIEnable
|
||||||
|
|| strcmp(Config::DLDISDPath, dldiSDPath.c_str()) != 0
|
||||||
|| strcmp(Config::DSiBIOS9Path, dsiBios9Path.c_str()) != 0
|
|| strcmp(Config::DSiBIOS9Path, dsiBios9Path.c_str()) != 0
|
||||||
|| strcmp(Config::DSiBIOS7Path, dsiBios7Path.c_str()) != 0
|
|| strcmp(Config::DSiBIOS7Path, dsiBios7Path.c_str()) != 0
|
||||||
|| strcmp(Config::DSiFirmwarePath, dsiFirmwarePath.c_str()) != 0
|
|| strcmp(Config::DSiFirmwarePath, dsiFirmwarePath.c_str()) != 0
|
||||||
|| strcmp(Config::DSiNANDPath, dsiNANDPath.c_str()) != 0)
|
|| strcmp(Config::DSiNANDPath, dsiNANDPath.c_str()) != 0
|
||||||
|
|| dsiSDEnable != Config::DSiSDEnable
|
||||||
|
|| strcmp(Config::DSiSDPath, dsiSDPath.c_str()) != 0)
|
||||||
{
|
{
|
||||||
if (RunningSomething
|
if (RunningSomething
|
||||||
&& QMessageBox::warning(this, "Reset necessary to apply changes",
|
&& QMessageBox::warning(this, "Reset necessary to apply changes",
|
||||||
|
@ -172,11 +184,15 @@ void EmuSettingsDialog::done(int r)
|
||||||
strncpy(Config::BIOS9Path, bios9Path.c_str(), 1023); Config::BIOS9Path[1023] = '\0';
|
strncpy(Config::BIOS9Path, bios9Path.c_str(), 1023); Config::BIOS9Path[1023] = '\0';
|
||||||
strncpy(Config::BIOS7Path, bios7Path.c_str(), 1023); Config::BIOS7Path[1023] = '\0';
|
strncpy(Config::BIOS7Path, bios7Path.c_str(), 1023); Config::BIOS7Path[1023] = '\0';
|
||||||
strncpy(Config::FirmwarePath, firmwarePath.c_str(), 1023); Config::FirmwarePath[1023] = '\0';
|
strncpy(Config::FirmwarePath, firmwarePath.c_str(), 1023); Config::FirmwarePath[1023] = '\0';
|
||||||
|
Config::DLDIEnable = dldiEnable;
|
||||||
|
strncpy(Config::DLDISDPath, dldiSDPath.c_str(), 1023); Config::DLDISDPath[1023] = '\0';
|
||||||
|
|
||||||
strncpy(Config::DSiBIOS9Path, dsiBios9Path.c_str(), 1023); Config::DSiBIOS9Path[1023] = '\0';
|
strncpy(Config::DSiBIOS9Path, dsiBios9Path.c_str(), 1023); Config::DSiBIOS9Path[1023] = '\0';
|
||||||
strncpy(Config::DSiBIOS7Path, dsiBios7Path.c_str(), 1023); Config::DSiBIOS7Path[1023] = '\0';
|
strncpy(Config::DSiBIOS7Path, dsiBios7Path.c_str(), 1023); Config::DSiBIOS7Path[1023] = '\0';
|
||||||
strncpy(Config::DSiFirmwarePath, dsiFirmwarePath.c_str(), 1023); Config::DSiFirmwarePath[1023] = '\0';
|
strncpy(Config::DSiFirmwarePath, dsiFirmwarePath.c_str(), 1023); Config::DSiFirmwarePath[1023] = '\0';
|
||||||
strncpy(Config::DSiNANDPath, dsiNANDPath.c_str(), 1023); Config::DSiNANDPath[1023] = '\0';
|
strncpy(Config::DSiNANDPath, dsiNANDPath.c_str(), 1023); Config::DSiNANDPath[1023] = '\0';
|
||||||
|
Config::DSiSDEnable = dsiSDEnable;
|
||||||
|
strncpy(Config::DSiSDPath, dsiSDPath.c_str(), 1023); Config::DSiSDPath[1023] = '\0';
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
Config::JIT_Enable = jitEnable;
|
Config::JIT_Enable = jitEnable;
|
||||||
|
@ -260,6 +276,18 @@ void EmuSettingsDialog::on_btnDSiBIOS7Browse_clicked()
|
||||||
ui->txtDSiBIOS7Path->setText(file);
|
ui->txtDSiBIOS7Path->setText(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmuSettingsDialog::on_btnDLDISDBrowse_clicked()
|
||||||
|
{
|
||||||
|
QString file = QFileDialog::getOpenFileName(this,
|
||||||
|
"Select DLDI SD image...",
|
||||||
|
EmuDirectory,
|
||||||
|
"Image files (*.bin *.rom *.img);;Any file (*.*)");
|
||||||
|
|
||||||
|
if (file.isEmpty()) return;
|
||||||
|
|
||||||
|
ui->txtDLDISDPath->setText(file);
|
||||||
|
}
|
||||||
|
|
||||||
void EmuSettingsDialog::on_btnDSiFirmwareBrowse_clicked()
|
void EmuSettingsDialog::on_btnDSiFirmwareBrowse_clicked()
|
||||||
{
|
{
|
||||||
QString file = QFileDialog::getOpenFileName(this,
|
QString file = QFileDialog::getOpenFileName(this,
|
||||||
|
@ -284,6 +312,18 @@ void EmuSettingsDialog::on_btnDSiNANDBrowse_clicked()
|
||||||
ui->txtDSiNANDPath->setText(file);
|
ui->txtDSiNANDPath->setText(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmuSettingsDialog::on_btnDSiSDBrowse_clicked()
|
||||||
|
{
|
||||||
|
QString file = QFileDialog::getOpenFileName(this,
|
||||||
|
"Select DSi SD image...",
|
||||||
|
EmuDirectory,
|
||||||
|
"Image files (*.bin *.rom *.img);;Any file (*.*)");
|
||||||
|
|
||||||
|
if (file.isEmpty()) return;
|
||||||
|
|
||||||
|
ui->txtDSiSDPath->setText(file);
|
||||||
|
}
|
||||||
|
|
||||||
void EmuSettingsDialog::on_chkEnableJIT_toggled()
|
void EmuSettingsDialog::on_chkEnableJIT_toggled()
|
||||||
{
|
{
|
||||||
bool disabled = !ui->chkEnableJIT->isChecked();
|
bool disabled = !ui->chkEnableJIT->isChecked();
|
||||||
|
|
|
@ -42,7 +42,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
currentDlg = new EmuSettingsDialog(parent);
|
currentDlg = new EmuSettingsDialog(parent);
|
||||||
currentDlg->show();
|
currentDlg->open();
|
||||||
return currentDlg;
|
return currentDlg;
|
||||||
}
|
}
|
||||||
static void closeDlg()
|
static void closeDlg()
|
||||||
|
@ -58,11 +58,13 @@ private slots:
|
||||||
void on_btnBIOS9Browse_clicked();
|
void on_btnBIOS9Browse_clicked();
|
||||||
void on_btnBIOS7Browse_clicked();
|
void on_btnBIOS7Browse_clicked();
|
||||||
void on_btnFirmwareBrowse_clicked();
|
void on_btnFirmwareBrowse_clicked();
|
||||||
|
void on_btnDLDISDBrowse_clicked();
|
||||||
|
|
||||||
void on_btnDSiBIOS9Browse_clicked();
|
void on_btnDSiBIOS9Browse_clicked();
|
||||||
void on_btnDSiBIOS7Browse_clicked();
|
void on_btnDSiBIOS7Browse_clicked();
|
||||||
void on_btnDSiFirmwareBrowse_clicked();
|
void on_btnDSiFirmwareBrowse_clicked();
|
||||||
void on_btnDSiNANDBrowse_clicked();
|
void on_btnDSiNANDBrowse_clicked();
|
||||||
|
void on_btnDSiSDBrowse_clicked();
|
||||||
|
|
||||||
void on_chkEnableJIT_toggled();
|
void on_chkEnableJIT_toggled();
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>514</width>
|
<width>575</width>
|
||||||
<height>359</height>
|
<height>254</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -86,209 +86,242 @@
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab_2">
|
<widget class="QWidget" name="tab_2">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>BIOS Files</string>
|
<string>DS-mode</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item>
|
<item row="1" column="1">
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QLineEdit" name="txtBIOS7Path">
|
||||||
<property name="title">
|
<property name="whatsThis">
|
||||||
<string>DS mode</string>
|
<string><html><head/><body><p>DS-mode ARM7 BIOS</p><p>Size should be 16 KB</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>DS firmware:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QLineEdit" name="txtFirmwarePath">
|
|
||||||
<property name="whatsThis">
|
|
||||||
<string><html><head/><body><p>DS-mode firmware</p><p><br/></p><p>Possible firmwares:</p><p>* 128 KB: DS-mode firmware from a DSi or 3DS. Not bootable.</p><p>* 256 KB: regular DS firmware.</p><p>* 512 KB: iQue DS firmware.</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLineEdit" name="txtBIOS7Path">
|
|
||||||
<property name="whatsThis">
|
|
||||||
<string><html><head/><body><p>DS-mode ARM7 BIOS</p><p>Size should be 16 KB</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="2">
|
|
||||||
<widget class="QPushButton" name="btnBIOS9Browse">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Browse...</string>
|
|
||||||
</property>
|
|
||||||
<property name="autoDefault">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="2">
|
|
||||||
<widget class="QPushButton" name="btnFirmwareBrowse">
|
|
||||||
<property name="text">
|
|
||||||
<string>Browse...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>DS ARM7 BIOS:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>DS ARM9 BIOS:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<widget class="QPushButton" name="btnBIOS7Browse">
|
|
||||||
<property name="text">
|
|
||||||
<string>Browse...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="txtBIOS9Path">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>290</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="statusTip">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="whatsThis">
|
|
||||||
<string><html><head/><body><p>DS-mode ARM9 BIOS</p><p>Size should be 4 KB</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="2" column="1">
|
||||||
<widget class="QGroupBox" name="groupBox_3">
|
<widget class="QLineEdit" name="txtFirmwarePath">
|
||||||
<property name="title">
|
<property name="whatsThis">
|
||||||
<string>DSi mode</string>
|
<string><html><head/><body><p>DS-mode firmware</p><p><br/></p><p>Possible firmwares:</p><p>* 128 KB: DS-mode firmware from a DSi or 3DS. Not bootable.</p><p>* 256 KB: regular DS firmware.</p><p>* 512 KB: iQue DS firmware.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>DS firmware:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>DS ARM7 BIOS:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QPushButton" name="btnBIOS7Browse">
|
||||||
|
<property name="text">
|
||||||
|
<string>Browse...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<widget class="QPushButton" name="btnFirmwareBrowse">
|
||||||
|
<property name="text">
|
||||||
|
<string>Browse...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QPushButton" name="btnBIOS9Browse">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Browse...</string>
|
||||||
|
</property>
|
||||||
|
<property name="autoDefault">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>DS ARM9 BIOS:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtBIOS9Path">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>290</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="statusTip">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="whatsThis">
|
||||||
|
<string><html><head/><body><p>DS-mode ARM9 BIOS</p><p>Size should be 4 KB</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<spacer name="verticalSpacer_5">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_4">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>DSi-mode</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtDSiBIOS7Path">
|
||||||
|
<property name="whatsThis">
|
||||||
|
<string><html><head/><body><p>DSi-mode ARM7 BIOS</p><p><br/></p><p>Size should be 64 KB</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="2">
|
||||||
|
<widget class="QPushButton" name="btnDSiSDBrowse">
|
||||||
|
<property name="text">
|
||||||
|
<string>Browse...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="text">
|
||||||
|
<string>DSi NAND:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="2">
|
||||||
|
<widget class="QPushButton" name="btnDSiNANDBrowse">
|
||||||
|
<property name="text">
|
||||||
|
<string>Browse...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>DSi ARM7 BIOS:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<widget class="QPushButton" name="btnDSiFirmwareBrowse">
|
||||||
|
<property name="text">
|
||||||
|
<string>Browse...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtDSiNANDPath">
|
||||||
|
<property name="whatsThis">
|
||||||
|
<string><html><head/><body><p>DSi NAND dump</p><p><br/></p><p>Should have 'nocash footer' at the end</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QPushButton" name="btnDSiBIOS9Browse">
|
||||||
|
<property name="text">
|
||||||
|
<string>Browse...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="text">
|
||||||
|
<string>DSi SD card:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtDSiBIOS9Path">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="whatsThis">
|
||||||
|
<string><html><head/><body><p>DSi-mode ARM9 BIOS</p><p><br/></p><p>Size should be 64 KB</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>DSi firmware:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>DSi ARM9 BIOS:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtDSiFirmwarePath">
|
||||||
|
<property name="whatsThis">
|
||||||
|
<string><html><head/><body><p>DSi-mode firmware (used for DS-mode backwards compatibility)</p><p><br/></p><p>Size should be 128 KB</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtDSiSDPath">
|
||||||
|
<property name="whatsThis">
|
||||||
|
<string><html><head/><body><p>SD image file for emulating the DSi's SD card</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0" colspan="3">
|
||||||
|
<widget class="QCheckBox" name="cbDSiSDEnable">
|
||||||
|
<property name="whatsThis">
|
||||||
|
<string><html><head/><body><p>Simulate a SD card being inserted in the DSi's SD slot. Requires a SD card image.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Enable DSi SD card</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QPushButton" name="btnDSiBIOS7Browse">
|
||||||
|
<property name="text">
|
||||||
|
<string>Browse...</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
|
||||||
<item row="0" column="2">
|
|
||||||
<widget class="QPushButton" name="btnDSiBIOS9Browse">
|
|
||||||
<property name="text">
|
|
||||||
<string>Browse...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="text">
|
|
||||||
<string>DSi ARM9 BIOS:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="2">
|
|
||||||
<widget class="QPushButton" name="btnDSiFirmwareBrowse">
|
|
||||||
<property name="text">
|
|
||||||
<string>Browse...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLineEdit" name="txtDSiBIOS7Path">
|
|
||||||
<property name="whatsThis">
|
|
||||||
<string><html><head/><body><p>DSi-mode ARM7 BIOS</p><p><br/></p><p>Size should be 64 KB</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QLineEdit" name="txtDSiFirmwarePath">
|
|
||||||
<property name="whatsThis">
|
|
||||||
<string><html><head/><body><p>DSi-mode firmware (used for DS-mode backwards compatibility)</p><p><br/></p><p>Size should be 128 KB</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="text">
|
|
||||||
<string>DSi ARM7 BIOS:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_7">
|
|
||||||
<property name="text">
|
|
||||||
<string>DSi firmware:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<widget class="QPushButton" name="btnDSiBIOS7Browse">
|
|
||||||
<property name="text">
|
|
||||||
<string>Browse...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="txtDSiBIOS9Path">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="whatsThis">
|
|
||||||
<string><html><head/><body><p>DSi-mode ARM9 BIOS</p><p><br/></p><p>Size should be 64 KB</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_8">
|
|
||||||
<property name="text">
|
|
||||||
<string>DSi NAND:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QLineEdit" name="txtDSiNANDPath">
|
|
||||||
<property name="whatsThis">
|
|
||||||
<string><html><head/><body><p>DSi NAND dump</p><p><br/></p><p>Should have 'nocash footer' at the end</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="2">
|
|
||||||
<widget class="QPushButton" name="btnDSiNANDBrowse">
|
|
||||||
<property name="text">
|
|
||||||
<string>Browse...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab_3">
|
<widget class="QWidget" name="tab_3">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>CPU Emulation</string>
|
<string>CPU emulation</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QFormLayout" name="formLayout_5">
|
<layout class="QFormLayout" name="formLayout_5">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
|
@ -354,6 +387,53 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_5">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>DLDI</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
|
<item row="0" column="0" colspan="3">
|
||||||
|
<widget class="QCheckBox" name="cbDLDIEnable">
|
||||||
|
<property name="whatsThis">
|
||||||
|
<string><html><head/><body><p>Enable the built-in DLDI driver, to let homebrew access files from a given SD image.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Enable DLDI (for homebrew)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QPushButton" name="btnDLDISDBrowse">
|
||||||
|
<property name="text">
|
||||||
|
<string>Browse...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtDLDISDPath"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_11">
|
||||||
|
<property name="text">
|
||||||
|
<string>DLDI SD card:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<spacer name="verticalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -369,23 +449,8 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>tabWidget</tabstop>
|
|
||||||
<tabstop>cbxConsoleType</tabstop>
|
<tabstop>cbxConsoleType</tabstop>
|
||||||
<tabstop>chkDirectBoot</tabstop>
|
<tabstop>chkDirectBoot</tabstop>
|
||||||
<tabstop>txtBIOS9Path</tabstop>
|
|
||||||
<tabstop>txtBIOS7Path</tabstop>
|
|
||||||
<tabstop>txtFirmwarePath</tabstop>
|
|
||||||
<tabstop>txtDSiBIOS9Path</tabstop>
|
|
||||||
<tabstop>txtDSiBIOS7Path</tabstop>
|
|
||||||
<tabstop>txtDSiFirmwarePath</tabstop>
|
|
||||||
<tabstop>txtDSiNANDPath</tabstop>
|
|
||||||
<tabstop>btnBIOS9Browse</tabstop>
|
|
||||||
<tabstop>btnBIOS7Browse</tabstop>
|
|
||||||
<tabstop>btnFirmwareBrowse</tabstop>
|
|
||||||
<tabstop>btnDSiBIOS9Browse</tabstop>
|
|
||||||
<tabstop>btnDSiBIOS7Browse</tabstop>
|
|
||||||
<tabstop>btnDSiFirmwareBrowse</tabstop>
|
|
||||||
<tabstop>btnDSiNANDBrowse</tabstop>
|
|
||||||
<tabstop>chkEnableJIT</tabstop>
|
<tabstop>chkEnableJIT</tabstop>
|
||||||
<tabstop>spnJITMaximumBlockSize</tabstop>
|
<tabstop>spnJITMaximumBlockSize</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
|
|
|
@ -98,7 +98,9 @@ int GetEventKeyVal(QKeyEvent* event)
|
||||||
void KeyPress(QKeyEvent* event)
|
void KeyPress(QKeyEvent* event)
|
||||||
{
|
{
|
||||||
int keyHK = GetEventKeyVal(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++)
|
for (int i = 0; i < 12; i++)
|
||||||
if (keyKP == Config::KeyMapping[i])
|
if (keyKP == Config::KeyMapping[i])
|
||||||
|
@ -112,7 +114,9 @@ void KeyPress(QKeyEvent* event)
|
||||||
void KeyRelease(QKeyEvent* event)
|
void KeyRelease(QKeyEvent* event)
|
||||||
{
|
{
|
||||||
int keyHK = GetEventKeyVal(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++)
|
for (int i = 0; i < 12; i++)
|
||||||
if (keyKP == Config::KeyMapping[i])
|
if (keyKP == Config::KeyMapping[i])
|
||||||
|
|
|
@ -54,6 +54,7 @@ const int hk_general[] =
|
||||||
HK_Reset,
|
HK_Reset,
|
||||||
HK_FastForward,
|
HK_FastForward,
|
||||||
HK_FastForwardToggle,
|
HK_FastForwardToggle,
|
||||||
|
HK_FullscreenToggle,
|
||||||
HK_Lid,
|
HK_Lid,
|
||||||
HK_Mic,
|
HK_Mic,
|
||||||
};
|
};
|
||||||
|
@ -64,6 +65,7 @@ const char* hk_general_labels[] =
|
||||||
"Reset",
|
"Reset",
|
||||||
"Fast forward",
|
"Fast forward",
|
||||||
"Toggle FPS limit",
|
"Toggle FPS limit",
|
||||||
|
"Toggle Fullscreen",
|
||||||
"Close/open lid",
|
"Close/open lid",
|
||||||
"Microphone",
|
"Microphone",
|
||||||
};
|
};
|
||||||
|
@ -86,7 +88,7 @@ InputConfigDialog::InputConfigDialog(QWidget* parent) : QDialog(parent), ui(new
|
||||||
addonsJoyMap[i] = Config::HKJoyMapping[hk_addons[i]];
|
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]];
|
hkGeneralKeyMap[i] = Config::HKKeyMapping[hk_general[i]];
|
||||||
hkGeneralJoyMap[i] = Config::HKJoyMapping[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->tabInput, 12, dskeylabels, keypadKeyMap, keypadJoyMap);
|
||||||
populatePage(ui->tabAddons, 2, hk_addons_labels, addonsKeyMap, addonsJoyMap);
|
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();
|
int njoy = SDL_NumJoysticks();
|
||||||
if (njoy > 0)
|
if (njoy > 0)
|
||||||
|
@ -177,7 +179,7 @@ void InputConfigDialog::on_InputConfigDialog_accepted()
|
||||||
Config::HKJoyMapping[hk_addons[i]] = addonsJoyMap[i];
|
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::HKKeyMapping[hk_general[i]] = hkGeneralKeyMap[i];
|
||||||
Config::HKJoyMapping[hk_general[i]] = hkGeneralJoyMap[i];
|
Config::HKJoyMapping[hk_general[i]] = hkGeneralJoyMap[i];
|
||||||
|
@ -226,7 +228,7 @@ void KeyMapButton::keyPressEvent(QKeyEvent* event)
|
||||||
{
|
{
|
||||||
if (!isChecked()) return QPushButton::keyPressEvent(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 key = event->key();
|
||||||
int mod = event->modifiers();
|
int mod = event->modifiers();
|
||||||
|
|
|
@ -64,7 +64,7 @@ private:
|
||||||
|
|
||||||
int keypadKeyMap[12], keypadJoyMap[12];
|
int keypadKeyMap[12], keypadJoyMap[12];
|
||||||
int addonsKeyMap[2], addonsJoyMap[2];
|
int addonsKeyMap[2], addonsJoyMap[2];
|
||||||
int hkGeneralKeyMap[6], hkGeneralJoyMap[6];
|
int hkGeneralKeyMap[7], hkGeneralJoyMap[7];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ u8 PacketBuffer[2048];
|
||||||
|
|
||||||
void Init(int argc, char** argv)
|
void Init(int argc, char** argv)
|
||||||
{
|
{
|
||||||
#if defined(__WIN32__) || defined(UNIX_PORTABLE)
|
#if defined(__WIN32__) || defined(PORTABLE)
|
||||||
if (argc > 0 && strlen(argv[0]) > 0)
|
if (argc > 0 && strlen(argv[0]) > 0)
|
||||||
{
|
{
|
||||||
int len = strlen(argv[0]);
|
int len = strlen(argv[0]);
|
||||||
|
@ -137,13 +137,20 @@ FILE* OpenFile(const char* path, const char* mode, bool mustexist)
|
||||||
}
|
}
|
||||||
|
|
||||||
QIODevice::OpenMode qmode;
|
QIODevice::OpenMode qmode;
|
||||||
if (strlen(mode) > 1 && mode[0] == 'r' && mode[1] == '+') {
|
if (strlen(mode) > 1 && mode[0] == 'r' && mode[1] == '+')
|
||||||
|
{
|
||||||
qmode = QIODevice::OpenModeFlag::ReadWrite;
|
qmode = QIODevice::OpenModeFlag::ReadWrite;
|
||||||
} else if (strlen(mode) > 1 && mode[0] == 'w' && mode[1] == '+') {
|
}
|
||||||
|
else if (strlen(mode) > 1 && mode[0] == 'w' && mode[1] == '+')
|
||||||
|
{
|
||||||
qmode = QIODevice::OpenModeFlag::Truncate | QIODevice::OpenModeFlag::ReadWrite;
|
qmode = QIODevice::OpenModeFlag::Truncate | QIODevice::OpenModeFlag::ReadWrite;
|
||||||
} else if (mode[0] == 'w') {
|
}
|
||||||
|
else if (mode[0] == 'w')
|
||||||
|
{
|
||||||
qmode = QIODevice::OpenModeFlag::Truncate | QIODevice::OpenModeFlag::WriteOnly;
|
qmode = QIODevice::OpenModeFlag::Truncate | QIODevice::OpenModeFlag::WriteOnly;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
qmode = QIODevice::OpenModeFlag::ReadOnly;
|
qmode = QIODevice::OpenModeFlag::ReadOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +174,7 @@ FILE* OpenLocalFile(const char* path, const char* mode)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef PORTABLE
|
#ifdef PORTABLE
|
||||||
fullpath = path;
|
fullpath = QString(EmuDirectory) + QDir::separator() + path;
|
||||||
#else
|
#else
|
||||||
// Check user configuration directory
|
// Check user configuration directory
|
||||||
QDir config(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation));
|
QDir config(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation));
|
||||||
|
|
|
@ -51,7 +51,7 @@ int _3DRenderer;
|
||||||
int Threaded3D;
|
int Threaded3D;
|
||||||
|
|
||||||
int GL_ScaleFactor;
|
int GL_ScaleFactor;
|
||||||
int GL_Antialias;
|
int GL_BetterPolygons;
|
||||||
|
|
||||||
int LimitFPS;
|
int LimitFPS;
|
||||||
int AudioSync;
|
int AudioSync;
|
||||||
|
@ -72,6 +72,8 @@ char MicWavPath[1024];
|
||||||
|
|
||||||
char LastROMFolder[1024];
|
char LastROMFolder[1024];
|
||||||
|
|
||||||
|
int EnableCheats;
|
||||||
|
|
||||||
bool EnableJIT;
|
bool EnableJIT;
|
||||||
|
|
||||||
ConfigEntry PlatformConfigFile[] =
|
ConfigEntry PlatformConfigFile[] =
|
||||||
|
@ -108,6 +110,7 @@ ConfigEntry PlatformConfigFile[] =
|
||||||
{"HKKey_Reset", 0, &HKKeyMapping[HK_Reset], -1, NULL, 0},
|
{"HKKey_Reset", 0, &HKKeyMapping[HK_Reset], -1, NULL, 0},
|
||||||
{"HKKey_FastForward", 0, &HKKeyMapping[HK_FastForward], -1, NULL, 0},
|
{"HKKey_FastForward", 0, &HKKeyMapping[HK_FastForward], -1, NULL, 0},
|
||||||
{"HKKey_FastForwardToggle", 0, &HKKeyMapping[HK_FastForwardToggle], -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_SolarSensorDecrease", 0, &HKKeyMapping[HK_SolarSensorDecrease], -1, NULL, 0},
|
||||||
{"HKKey_SolarSensorIncrease", 0, &HKKeyMapping[HK_SolarSensorIncrease], -1, NULL, 0},
|
{"HKKey_SolarSensorIncrease", 0, &HKKeyMapping[HK_SolarSensorIncrease], -1, NULL, 0},
|
||||||
|
|
||||||
|
@ -117,6 +120,7 @@ ConfigEntry PlatformConfigFile[] =
|
||||||
{"HKJoy_Reset", 0, &HKJoyMapping[HK_Reset], -1, NULL, 0},
|
{"HKJoy_Reset", 0, &HKJoyMapping[HK_Reset], -1, NULL, 0},
|
||||||
{"HKJoy_FastForward", 0, &HKJoyMapping[HK_FastForward], -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_FastForwardToggle], -1, NULL, 0},
|
||||||
|
{"HKJoy_FastForwardToggle", 0, &HKJoyMapping[HK_FullscreenToggle], -1, NULL, 0},
|
||||||
{"HKJoy_SolarSensorDecrease", 0, &HKJoyMapping[HK_SolarSensorDecrease], -1, NULL, 0},
|
{"HKJoy_SolarSensorDecrease", 0, &HKJoyMapping[HK_SolarSensorDecrease], -1, NULL, 0},
|
||||||
{"HKJoy_SolarSensorIncrease", 0, &HKJoyMapping[HK_SolarSensorIncrease], -1, NULL, 0},
|
{"HKJoy_SolarSensorIncrease", 0, &HKJoyMapping[HK_SolarSensorIncrease], -1, NULL, 0},
|
||||||
|
|
||||||
|
@ -133,15 +137,15 @@ ConfigEntry PlatformConfigFile[] =
|
||||||
{"IntegerScaling", 0, &IntegerScaling, 0, NULL, 0},
|
{"IntegerScaling", 0, &IntegerScaling, 0, NULL, 0},
|
||||||
{"ScreenFilter", 0, &ScreenFilter, 1, NULL, 0},
|
{"ScreenFilter", 0, &ScreenFilter, 1, NULL, 0},
|
||||||
|
|
||||||
{"ScreenUseGL", 0, &ScreenUseGL, 1, NULL, 0},
|
{"ScreenUseGL", 0, &ScreenUseGL, 0, NULL, 0},
|
||||||
{"ScreenVSync", 0, &ScreenVSync, 0, NULL, 0},
|
{"ScreenVSync", 0, &ScreenVSync, 0, NULL, 0},
|
||||||
{"ScreenVSyncInterval", 0, &ScreenVSyncInterval, 1, NULL, 0},
|
{"ScreenVSyncInterval", 0, &ScreenVSyncInterval, 1, NULL, 0},
|
||||||
|
|
||||||
{"3DRenderer", 0, &_3DRenderer, 1, NULL, 0},
|
{"3DRenderer", 0, &_3DRenderer, 0, NULL, 0},
|
||||||
{"Threaded3D", 0, &Threaded3D, 1, NULL, 0},
|
{"Threaded3D", 0, &Threaded3D, 1, NULL, 0},
|
||||||
|
|
||||||
{"GL_ScaleFactor", 0, &GL_ScaleFactor, 1, NULL, 0},
|
{"GL_ScaleFactor", 0, &GL_ScaleFactor, 1, NULL, 0},
|
||||||
{"GL_Antialias", 0, &GL_Antialias, 0, NULL, 0},
|
{"GL_BetterPolygons", 0, &GL_BetterPolygons, 0, NULL, 0},
|
||||||
|
|
||||||
{"LimitFPS", 0, &LimitFPS, 0, NULL, 0},
|
{"LimitFPS", 0, &LimitFPS, 0, NULL, 0},
|
||||||
{"AudioSync", 0, &AudioSync, 1, NULL, 0},
|
{"AudioSync", 0, &AudioSync, 1, NULL, 0},
|
||||||
|
@ -162,6 +166,8 @@ ConfigEntry PlatformConfigFile[] =
|
||||||
|
|
||||||
{"LastROMFolder", 1, LastROMFolder, 0, "", 1023},
|
{"LastROMFolder", 1, LastROMFolder, 0, "", 1023},
|
||||||
|
|
||||||
|
{"EnableCheats", 0, &EnableCheats, 0, NULL, 0},
|
||||||
|
|
||||||
{"", -1, NULL, 0, NULL, 0}
|
{"", -1, NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ enum
|
||||||
HK_Reset,
|
HK_Reset,
|
||||||
HK_FastForward,
|
HK_FastForward,
|
||||||
HK_FastForwardToggle,
|
HK_FastForwardToggle,
|
||||||
|
HK_FullscreenToggle,
|
||||||
HK_SolarSensorDecrease,
|
HK_SolarSensorDecrease,
|
||||||
HK_SolarSensorIncrease,
|
HK_SolarSensorIncrease,
|
||||||
HK_MAX
|
HK_MAX
|
||||||
|
@ -64,7 +65,7 @@ extern int _3DRenderer;
|
||||||
extern int Threaded3D;
|
extern int Threaded3D;
|
||||||
|
|
||||||
extern int GL_ScaleFactor;
|
extern int GL_ScaleFactor;
|
||||||
extern int GL_Antialias;
|
extern int GL_BetterPolygons;
|
||||||
|
|
||||||
extern int LimitFPS;
|
extern int LimitFPS;
|
||||||
extern int AudioSync;
|
extern int AudioSync;
|
||||||
|
@ -85,6 +86,8 @@ extern char MicWavPath[1024];
|
||||||
|
|
||||||
extern char LastROMFolder[1024];
|
extern char LastROMFolder[1024];
|
||||||
|
|
||||||
|
extern int EnableCheats;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // PLATFORMCONFIG_H
|
#endif // PLATFORMCONFIG_H
|
||||||
|
|
|
@ -42,6 +42,7 @@ VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui(
|
||||||
oldVSyncInterval = Config::ScreenVSyncInterval;
|
oldVSyncInterval = Config::ScreenVSyncInterval;
|
||||||
oldSoftThreaded = Config::Threaded3D;
|
oldSoftThreaded = Config::Threaded3D;
|
||||||
oldGLScale = Config::GL_ScaleFactor;
|
oldGLScale = Config::GL_ScaleFactor;
|
||||||
|
oldGLBetterPolygons = Config::GL_BetterPolygons;
|
||||||
|
|
||||||
grp3DRenderer = new QButtonGroup(this);
|
grp3DRenderer = new QButtonGroup(this);
|
||||||
grp3DRenderer->addButton(ui->rb3DSoftware, 0);
|
grp3DRenderer->addButton(ui->rb3DSoftware, 0);
|
||||||
|
@ -49,6 +50,10 @@ VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui(
|
||||||
connect(grp3DRenderer, SIGNAL(buttonClicked(int)), this, SLOT(onChange3DRenderer(int)));
|
connect(grp3DRenderer, SIGNAL(buttonClicked(int)), this, SLOT(onChange3DRenderer(int)));
|
||||||
grp3DRenderer->button(Config::_3DRenderer)->setChecked(true);
|
grp3DRenderer->button(Config::_3DRenderer)->setChecked(true);
|
||||||
|
|
||||||
|
#ifndef OGLRENDERER_ENABLED
|
||||||
|
ui->rb3DOpenGL->setEnabled(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
ui->cbGLDisplay->setChecked(Config::ScreenUseGL != 0);
|
ui->cbGLDisplay->setChecked(Config::ScreenUseGL != 0);
|
||||||
|
|
||||||
ui->cbVSync->setChecked(Config::ScreenVSync != 0);
|
ui->cbVSync->setChecked(Config::ScreenVSync != 0);
|
||||||
|
@ -60,6 +65,8 @@ VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui(
|
||||||
ui->cbxGLResolution->addItem(QString("%1x native (%2x%3)").arg(i).arg(256*i).arg(192*i));
|
ui->cbxGLResolution->addItem(QString("%1x native (%2x%3)").arg(i).arg(256*i).arg(192*i));
|
||||||
ui->cbxGLResolution->setCurrentIndex(Config::GL_ScaleFactor-1);
|
ui->cbxGLResolution->setCurrentIndex(Config::GL_ScaleFactor-1);
|
||||||
|
|
||||||
|
ui->cbBetterPolygons->setChecked(Config::GL_BetterPolygons != 0);
|
||||||
|
|
||||||
if (!Config::ScreenVSync)
|
if (!Config::ScreenVSync)
|
||||||
ui->sbVSyncInterval->setEnabled(false);
|
ui->sbVSyncInterval->setEnabled(false);
|
||||||
|
|
||||||
|
@ -68,12 +75,14 @@ VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui(
|
||||||
ui->cbGLDisplay->setEnabled(true);
|
ui->cbGLDisplay->setEnabled(true);
|
||||||
ui->cbSoftwareThreaded->setEnabled(true);
|
ui->cbSoftwareThreaded->setEnabled(true);
|
||||||
ui->cbxGLResolution->setEnabled(false);
|
ui->cbxGLResolution->setEnabled(false);
|
||||||
|
ui->cbBetterPolygons->setEnabled(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ui->cbGLDisplay->setEnabled(false);
|
ui->cbGLDisplay->setEnabled(false);
|
||||||
ui->cbSoftwareThreaded->setEnabled(false);
|
ui->cbSoftwareThreaded->setEnabled(false);
|
||||||
ui->cbxGLResolution->setEnabled(true);
|
ui->cbxGLResolution->setEnabled(true);
|
||||||
|
ui->cbBetterPolygons->setEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +108,7 @@ void VideoSettingsDialog::on_VideoSettingsDialog_rejected()
|
||||||
Config::ScreenVSyncInterval = oldVSyncInterval;
|
Config::ScreenVSyncInterval = oldVSyncInterval;
|
||||||
Config::Threaded3D = oldSoftThreaded;
|
Config::Threaded3D = oldSoftThreaded;
|
||||||
Config::GL_ScaleFactor = oldGLScale;
|
Config::GL_ScaleFactor = oldGLScale;
|
||||||
|
Config::GL_BetterPolygons = oldGLBetterPolygons;
|
||||||
|
|
||||||
bool new_gl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0);
|
bool new_gl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0);
|
||||||
emit updateVideoSettings(old_gl != new_gl);
|
emit updateVideoSettings(old_gl != new_gl);
|
||||||
|
@ -117,12 +127,14 @@ void VideoSettingsDialog::onChange3DRenderer(int renderer)
|
||||||
ui->cbGLDisplay->setEnabled(true);
|
ui->cbGLDisplay->setEnabled(true);
|
||||||
ui->cbSoftwareThreaded->setEnabled(true);
|
ui->cbSoftwareThreaded->setEnabled(true);
|
||||||
ui->cbxGLResolution->setEnabled(false);
|
ui->cbxGLResolution->setEnabled(false);
|
||||||
|
ui->cbBetterPolygons->setEnabled(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ui->cbGLDisplay->setEnabled(false);
|
ui->cbGLDisplay->setEnabled(false);
|
||||||
ui->cbSoftwareThreaded->setEnabled(false);
|
ui->cbSoftwareThreaded->setEnabled(false);
|
||||||
ui->cbxGLResolution->setEnabled(true);
|
ui->cbxGLResolution->setEnabled(true);
|
||||||
|
ui->cbBetterPolygons->setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool new_gl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0);
|
bool new_gl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0);
|
||||||
|
@ -167,3 +179,10 @@ void VideoSettingsDialog::on_cbxGLResolution_currentIndexChanged(int idx)
|
||||||
|
|
||||||
emit updateVideoSettings(false);
|
emit updateVideoSettings(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoSettingsDialog::on_cbBetterPolygons_stateChanged(int state)
|
||||||
|
{
|
||||||
|
Config::GL_BetterPolygons = (state != 0);
|
||||||
|
|
||||||
|
emit updateVideoSettings(false);
|
||||||
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ private slots:
|
||||||
void on_sbVSyncInterval_valueChanged(int val);
|
void on_sbVSyncInterval_valueChanged(int val);
|
||||||
|
|
||||||
void on_cbxGLResolution_currentIndexChanged(int idx);
|
void on_cbxGLResolution_currentIndexChanged(int idx);
|
||||||
|
void on_cbBetterPolygons_stateChanged(int state);
|
||||||
|
|
||||||
void on_cbSoftwareThreaded_stateChanged(int state);
|
void on_cbSoftwareThreaded_stateChanged(int state);
|
||||||
|
|
||||||
|
@ -78,6 +79,7 @@ private:
|
||||||
int oldVSyncInterval;
|
int oldVSyncInterval;
|
||||||
int oldSoftThreaded;
|
int oldSoftThreaded;
|
||||||
int oldGLScale;
|
int oldGLScale;
|
||||||
|
int oldGLBetterPolygons;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VIDEOSETTINGSDIALOG_H
|
#endif // VIDEOSETTINGSDIALOG_H
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>482</width>
|
<width>482</width>
|
||||||
<height>237</height>
|
<height>244</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -43,6 +43,16 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QCheckBox" name="cbBetterPolygons">
|
||||||
|
<property name="whatsThis">
|
||||||
|
<string><html><head/><body><p>Enabling this may help reduce distortion on quads and more complex polygons, but may also reduce performance.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Improved polygon splitting</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <QFileDialog>
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
@ -41,6 +41,10 @@
|
||||||
|
|
||||||
WifiSettingsDialog* WifiSettingsDialog::currentDlg = nullptr;
|
WifiSettingsDialog* WifiSettingsDialog::currentDlg = nullptr;
|
||||||
|
|
||||||
|
bool WifiSettingsDialog::needsReset = false;
|
||||||
|
|
||||||
|
extern bool RunningSomething;
|
||||||
|
|
||||||
|
|
||||||
WifiSettingsDialog::WifiSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::WifiSettingsDialog)
|
WifiSettingsDialog::WifiSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::WifiSettingsDialog)
|
||||||
{
|
{
|
||||||
|
@ -53,6 +57,7 @@ WifiSettingsDialog::WifiSettingsDialog(QWidget* parent) : QDialog(parent), ui(ne
|
||||||
ui->cbDirectMode->setText("Direct mode (requires " PCAP_NAME " and ethernet connection)");
|
ui->cbDirectMode->setText("Direct mode (requires " PCAP_NAME " and ethernet connection)");
|
||||||
|
|
||||||
ui->cbBindAnyAddr->setChecked(Config::SocketBindAnyAddr != 0);
|
ui->cbBindAnyAddr->setChecked(Config::SocketBindAnyAddr != 0);
|
||||||
|
ui->cbRandomizeMAC->setChecked(Config::RandomizeMAC != 0);
|
||||||
|
|
||||||
int sel = 0;
|
int sel = 0;
|
||||||
for (int i = 0; i < LAN_PCap::NumAdapters; i++)
|
for (int i = 0; i < LAN_PCap::NumAdapters; i++)
|
||||||
|
@ -77,33 +82,49 @@ WifiSettingsDialog::~WifiSettingsDialog()
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WifiSettingsDialog::on_WifiSettingsDialog_accepted()
|
void WifiSettingsDialog::done(int r)
|
||||||
{
|
{
|
||||||
Config::SocketBindAnyAddr = ui->cbBindAnyAddr->isChecked() ? 1:0;
|
needsReset = false;
|
||||||
Config::DirectLAN = ui->cbDirectMode->isChecked() ? 1:0;
|
|
||||||
|
|
||||||
int sel = ui->cbxDirectAdapter->currentIndex();
|
if (r == QDialog::Accepted)
|
||||||
if (sel < 0 || sel >= LAN_PCap::NumAdapters) sel = 0;
|
|
||||||
if (LAN_PCap::NumAdapters < 1)
|
|
||||||
{
|
{
|
||||||
Config::LANDevice[0] = '\0';
|
int randommac = ui->cbRandomizeMAC->isChecked() ? 1:0;
|
||||||
}
|
|
||||||
else
|
if (randommac != Config::RandomizeMAC)
|
||||||
{
|
{
|
||||||
strncpy(Config::LANDevice, LAN_PCap::Adapters[sel].DeviceName, 127);
|
if (RunningSomething
|
||||||
Config::LANDevice[127] = '\0';
|
&& QMessageBox::warning(this, "Reset necessary to apply changes",
|
||||||
|
"The emulation will be reset for the changes to take place.",
|
||||||
|
QMessageBox::Ok, QMessageBox::Cancel) != QMessageBox::Ok)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Config::SocketBindAnyAddr = ui->cbBindAnyAddr->isChecked() ? 1:0;
|
||||||
|
Config::RandomizeMAC = randommac;
|
||||||
|
Config::DirectLAN = ui->cbDirectMode->isChecked() ? 1:0;
|
||||||
|
|
||||||
|
int sel = ui->cbxDirectAdapter->currentIndex();
|
||||||
|
if (sel < 0 || sel >= LAN_PCap::NumAdapters) sel = 0;
|
||||||
|
if (LAN_PCap::NumAdapters < 1)
|
||||||
|
{
|
||||||
|
Config::LANDevice[0] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strncpy(Config::LANDevice, LAN_PCap::Adapters[sel].DeviceName, 127);
|
||||||
|
Config::LANDevice[127] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
Config::Save();
|
||||||
|
|
||||||
|
needsReset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Config::Save();
|
QDialog::done(r);
|
||||||
|
|
||||||
closeDlg();
|
closeDlg();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WifiSettingsDialog::on_WifiSettingsDialog_rejected()
|
|
||||||
{
|
|
||||||
closeDlg();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WifiSettingsDialog::on_cbDirectMode_stateChanged(int state)
|
void WifiSettingsDialog::on_cbDirectMode_stateChanged(int state)
|
||||||
{
|
{
|
||||||
updateAdapterControls();
|
updateAdapterControls();
|
||||||
|
|
|
@ -42,7 +42,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
currentDlg = new WifiSettingsDialog(parent);
|
currentDlg = new WifiSettingsDialog(parent);
|
||||||
currentDlg->show();
|
currentDlg->open();
|
||||||
return currentDlg;
|
return currentDlg;
|
||||||
}
|
}
|
||||||
static void closeDlg()
|
static void closeDlg()
|
||||||
|
@ -50,9 +50,10 @@ public:
|
||||||
currentDlg = nullptr;
|
currentDlg = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool needsReset;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_WifiSettingsDialog_accepted();
|
void done(int r);
|
||||||
void on_WifiSettingsDialog_rejected();
|
|
||||||
|
|
||||||
void on_cbDirectMode_stateChanged(int state);
|
void on_cbDirectMode_stateChanged(int state);
|
||||||
void on_cbxDirectAdapter_currentIndexChanged(int sel);
|
void on_cbxDirectAdapter_currentIndexChanged(int sel);
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>479</width>
|
<width>479</width>
|
||||||
<height>217</height>
|
<height>240</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -39,6 +39,16 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QCheckBox" name="cbRandomizeMAC">
|
||||||
|
<property name="whatsThis">
|
||||||
|
<string><html><head/><body><p>Randomizes the console's MAC address upon reset. Required for local multiplayer if each melonDS instance uses the same firmware file.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Randomize MAC address</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "Input.h"
|
#include "Input.h"
|
||||||
|
#include "CheatsDialog.h"
|
||||||
#include "EmuSettingsDialog.h"
|
#include "EmuSettingsDialog.h"
|
||||||
#include "InputConfigDialog.h"
|
#include "InputConfigDialog.h"
|
||||||
#include "VideoSettingsDialog.h"
|
#include "VideoSettingsDialog.h"
|
||||||
|
@ -55,7 +56,9 @@
|
||||||
|
|
||||||
#include "NDS.h"
|
#include "NDS.h"
|
||||||
#include "GBACart.h"
|
#include "GBACart.h"
|
||||||
|
#ifdef OGLRENDERER_ENABLED
|
||||||
#include "OpenGLSupport.h"
|
#include "OpenGLSupport.h"
|
||||||
|
#endif
|
||||||
#include "GPU.h"
|
#include "GPU.h"
|
||||||
#include "SPU.h"
|
#include "SPU.h"
|
||||||
#include "Wifi.h"
|
#include "Wifi.h"
|
||||||
|
@ -120,7 +123,6 @@ void audioCallback(void* data, Uint8* stream, int len)
|
||||||
if (num_in < len_in-margin)
|
if (num_in < len_in-margin)
|
||||||
{
|
{
|
||||||
int last = num_in-1;
|
int last = num_in-1;
|
||||||
if (last < 0) last = 0;
|
|
||||||
|
|
||||||
for (int i = num_in; i < len_in-margin; i++)
|
for (int i = num_in; i < len_in-margin; i++)
|
||||||
((u32*)buf_in)[i] = ((u32*)buf_in)[last];
|
((u32*)buf_in)[i] = ((u32*)buf_in)[last];
|
||||||
|
@ -273,6 +275,7 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent)
|
||||||
connect(this, SIGNAL(windowEmuPause()), mainWindow->actPause, SLOT(trigger()));
|
connect(this, SIGNAL(windowEmuPause()), mainWindow->actPause, SLOT(trigger()));
|
||||||
connect(this, SIGNAL(windowEmuReset()), mainWindow->actReset, SLOT(trigger()));
|
connect(this, SIGNAL(windowEmuReset()), mainWindow->actReset, SLOT(trigger()));
|
||||||
connect(this, SIGNAL(screenLayoutChange()), mainWindow->panel, SLOT(onScreenLayoutChanged()));
|
connect(this, SIGNAL(screenLayoutChange()), mainWindow->panel, SLOT(onScreenLayoutChanged()));
|
||||||
|
connect(this, SIGNAL(windowFullscreenToggle()), mainWindow, SLOT(onFullscreenToggled()));
|
||||||
|
|
||||||
if (mainWindow->hasOGL) initOpenGL();
|
if (mainWindow->hasOGL) initOpenGL();
|
||||||
}
|
}
|
||||||
|
@ -342,13 +345,17 @@ void EmuThread::run()
|
||||||
videoSettings.Soft_Threaded = Config::Threaded3D != 0;
|
videoSettings.Soft_Threaded = Config::Threaded3D != 0;
|
||||||
videoSettings.GL_ScaleFactor = Config::GL_ScaleFactor;
|
videoSettings.GL_ScaleFactor = Config::GL_ScaleFactor;
|
||||||
|
|
||||||
|
#ifdef OGLRENDERER_ENABLED
|
||||||
if (hasOGL)
|
if (hasOGL)
|
||||||
{
|
{
|
||||||
oglContext->makeCurrent(oglSurface);
|
oglContext->makeCurrent(oglSurface);
|
||||||
videoRenderer = OpenGL::Init() ? Config::_3DRenderer : 0;
|
videoRenderer = OpenGL::Init() ? Config::_3DRenderer : 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
videoRenderer = 0;
|
videoRenderer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
GPU::InitRenderer(videoRenderer);
|
GPU::InitRenderer(videoRenderer);
|
||||||
GPU::SetRenderSettings(videoRenderer, videoSettings);
|
GPU::SetRenderSettings(videoRenderer, videoSettings);
|
||||||
|
@ -371,6 +378,8 @@ void EmuThread::run()
|
||||||
|
|
||||||
if (Input::HotkeyPressed(HK_Pause)) emit windowEmuPause();
|
if (Input::HotkeyPressed(HK_Pause)) emit windowEmuPause();
|
||||||
if (Input::HotkeyPressed(HK_Reset)) emit windowEmuReset();
|
if (Input::HotkeyPressed(HK_Reset)) emit windowEmuReset();
|
||||||
|
|
||||||
|
if (Input::HotkeyPressed(HK_FullscreenToggle)) emit windowFullscreenToggle();
|
||||||
|
|
||||||
if (GBACart::CartInserted && GBACart::HasSolarSensor)
|
if (GBACart::CartInserted && GBACart::HasSolarSensor)
|
||||||
{
|
{
|
||||||
|
@ -400,20 +409,27 @@ void EmuThread::run()
|
||||||
if (hasOGL != mainWindow->hasOGL)
|
if (hasOGL != mainWindow->hasOGL)
|
||||||
{
|
{
|
||||||
hasOGL = mainWindow->hasOGL;
|
hasOGL = mainWindow->hasOGL;
|
||||||
|
#ifdef OGLRENDERER_ENABLED
|
||||||
if (hasOGL)
|
if (hasOGL)
|
||||||
{
|
{
|
||||||
oglContext->makeCurrent(oglSurface);
|
oglContext->makeCurrent(oglSurface);
|
||||||
videoRenderer = OpenGL::Init() ? Config::_3DRenderer : 0;
|
videoRenderer = OpenGL::Init() ? Config::_3DRenderer : 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
videoRenderer = 0;
|
videoRenderer = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
videoRenderer = hasOGL ? Config::_3DRenderer : 0;
|
videoRenderer = hasOGL ? Config::_3DRenderer : 0;
|
||||||
|
|
||||||
videoSettingsDirty = false;
|
videoSettingsDirty = false;
|
||||||
|
|
||||||
videoSettings.Soft_Threaded = Config::Threaded3D != 0;
|
videoSettings.Soft_Threaded = Config::Threaded3D != 0;
|
||||||
videoSettings.GL_ScaleFactor = Config::GL_ScaleFactor;
|
videoSettings.GL_ScaleFactor = Config::GL_ScaleFactor;
|
||||||
|
videoSettings.GL_BetterPolygons = Config::GL_BetterPolygons;
|
||||||
|
|
||||||
GPU::SetRenderSettings(videoRenderer, videoSettings);
|
GPU::SetRenderSettings(videoRenderer, videoSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -924,12 +940,14 @@ void ScreenPanelGL::paintGL()
|
||||||
int frontbuf = GPU::FrontBuffer;
|
int frontbuf = GPU::FrontBuffer;
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
|
#ifdef OGLRENDERER_ENABLED
|
||||||
if (GPU::Renderer != 0)
|
if (GPU::Renderer != 0)
|
||||||
{
|
{
|
||||||
// hardware-accelerated render
|
// hardware-accelerated render
|
||||||
GPU::GLCompositor::BindOutputTexture();
|
GPU::GLCompositor::BindOutputTexture();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
// regular render
|
// regular render
|
||||||
glBindTexture(GL_TEXTURE_2D, screenTexture);
|
glBindTexture(GL_TEXTURE_2D, screenTexture);
|
||||||
|
@ -1053,6 +1071,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
|
||||||
actUndoStateLoad->setShortcut(QKeySequence(Qt::Key_F12));
|
actUndoStateLoad->setShortcut(QKeySequence(Qt::Key_F12));
|
||||||
connect(actUndoStateLoad, &QAction::triggered, this, &MainWindow::onUndoStateLoad);
|
connect(actUndoStateLoad, &QAction::triggered, this, &MainWindow::onUndoStateLoad);
|
||||||
|
|
||||||
|
actImportSavefile = menu->addAction("Import savefile");
|
||||||
|
connect(actImportSavefile, &QAction::triggered, this, &MainWindow::onImportSavefile);
|
||||||
|
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
|
|
||||||
actQuit = menu->addAction("Quit");
|
actQuit = menu->addAction("Quit");
|
||||||
|
@ -1070,6 +1091,15 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
|
||||||
|
|
||||||
actStop = menu->addAction("Stop");
|
actStop = menu->addAction("Stop");
|
||||||
connect(actStop, &QAction::triggered, this, &MainWindow::onStop);
|
connect(actStop, &QAction::triggered, this, &MainWindow::onStop);
|
||||||
|
|
||||||
|
menu->addSeparator();
|
||||||
|
|
||||||
|
actEnableCheats = menu->addAction("Enable cheats");
|
||||||
|
actEnableCheats->setCheckable(true);
|
||||||
|
connect(actEnableCheats, &QAction::triggered, this, &MainWindow::onEnableCheats);
|
||||||
|
|
||||||
|
actSetupCheats = menu->addAction("Setup cheat codes");
|
||||||
|
connect(actSetupCheats, &QAction::triggered, this, &MainWindow::onSetupCheats);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
QMenu* menu = menubar->addMenu("Config");
|
QMenu* menu = menubar->addMenu("Config");
|
||||||
|
@ -1212,11 +1242,16 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
|
||||||
actLoadState[i]->setEnabled(false);
|
actLoadState[i]->setEnabled(false);
|
||||||
}
|
}
|
||||||
actUndoStateLoad->setEnabled(false);
|
actUndoStateLoad->setEnabled(false);
|
||||||
|
actImportSavefile->setEnabled(false);
|
||||||
|
|
||||||
actPause->setEnabled(false);
|
actPause->setEnabled(false);
|
||||||
actReset->setEnabled(false);
|
actReset->setEnabled(false);
|
||||||
actStop->setEnabled(false);
|
actStop->setEnabled(false);
|
||||||
|
|
||||||
|
actSetupCheats->setEnabled(false);
|
||||||
|
|
||||||
|
|
||||||
|
actEnableCheats->setChecked(Config::EnableCheats != 0);
|
||||||
|
|
||||||
actSavestateSRAMReloc->setChecked(Config::SavestateRelocSRAM != 0);
|
actSavestateSRAMReloc->setChecked(Config::SavestateRelocSRAM != 0);
|
||||||
|
|
||||||
|
@ -1327,7 +1362,7 @@ void MainWindow::dragEnterEvent(QDragEnterEvent* event)
|
||||||
QString filename = urls.at(0).toLocalFile();
|
QString filename = urls.at(0).toLocalFile();
|
||||||
QString ext = filename.right(3);
|
QString ext = filename.right(3);
|
||||||
|
|
||||||
if (ext == "nds" || ext == "srl" || (ext == "gba" && RunningSomething))
|
if (ext == "nds" || ext == "srl" || ext == "dsi" || (ext == "gba" && RunningSomething))
|
||||||
event->acceptProposedAction();
|
event->acceptProposedAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1651,6 +1686,41 @@ void MainWindow::onUndoStateLoad()
|
||||||
OSD::AddMessage(0, "State load undone");
|
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()
|
void MainWindow::onQuit()
|
||||||
{
|
{
|
||||||
QApplication::quit();
|
QApplication::quit();
|
||||||
|
@ -1704,6 +1774,25 @@ void MainWindow::onStop()
|
||||||
NDS::Stop();
|
NDS::Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onEnableCheats(bool checked)
|
||||||
|
{
|
||||||
|
Config::EnableCheats = checked?1:0;
|
||||||
|
Frontend::EnableCheats(Config::EnableCheats != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::onSetupCheats()
|
||||||
|
{
|
||||||
|
emuThread->emuPause();
|
||||||
|
|
||||||
|
CheatsDialog* dlg = CheatsDialog::openDlg(this);
|
||||||
|
connect(dlg, &CheatsDialog::finished, this, &MainWindow::onCheatsDialogFinished);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::onCheatsDialogFinished(int res)
|
||||||
|
{
|
||||||
|
emuThread->emuUnpause();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MainWindow::onOpenEmuSettings()
|
void MainWindow::onOpenEmuSettings()
|
||||||
{
|
{
|
||||||
|
@ -1767,14 +1856,14 @@ void MainWindow::onAudioSettingsFinished(int res)
|
||||||
|
|
||||||
void MainWindow::onOpenWifiSettings()
|
void MainWindow::onOpenWifiSettings()
|
||||||
{
|
{
|
||||||
|
emuThread->emuPause();
|
||||||
|
|
||||||
WifiSettingsDialog* dlg = WifiSettingsDialog::openDlg(this);
|
WifiSettingsDialog* dlg = WifiSettingsDialog::openDlg(this);
|
||||||
connect(dlg, &WifiSettingsDialog::finished, this, &MainWindow::onWifiSettingsFinished);
|
connect(dlg, &WifiSettingsDialog::finished, this, &MainWindow::onWifiSettingsFinished);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onWifiSettingsFinished(int res)
|
void MainWindow::onWifiSettingsFinished(int res)
|
||||||
{
|
{
|
||||||
emuThread->emuPause();
|
|
||||||
|
|
||||||
if (Wifi::MPInited)
|
if (Wifi::MPInited)
|
||||||
{
|
{
|
||||||
Platform::MP_DeInit();
|
Platform::MP_DeInit();
|
||||||
|
@ -1784,6 +1873,9 @@ void MainWindow::onWifiSettingsFinished(int res)
|
||||||
Platform::LAN_DeInit();
|
Platform::LAN_DeInit();
|
||||||
Platform::LAN_Init();
|
Platform::LAN_Init();
|
||||||
|
|
||||||
|
if (WifiSettingsDialog::needsReset)
|
||||||
|
onReset();
|
||||||
|
|
||||||
emuThread->emuUnpause();
|
emuThread->emuUnpause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1892,21 +1984,51 @@ void MainWindow::onTitleUpdate(QString title)
|
||||||
setWindowTitle(title);
|
setWindowTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onFullscreenToggled()
|
||||||
|
{
|
||||||
|
if (!mainWindow->isFullScreen())
|
||||||
|
{
|
||||||
|
mainWindow->showFullScreen();
|
||||||
|
mainWindow->menuBar()->hide();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mainWindow->showNormal();
|
||||||
|
mainWindow->menuBar()->show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::onEmuStart()
|
void MainWindow::onEmuStart()
|
||||||
{
|
{
|
||||||
for (int i = 1; i < 9; i++)
|
// TODO: make savestates work in DSi mode!!
|
||||||
|
if (Config::ConsoleType == 1)
|
||||||
{
|
{
|
||||||
actSaveState[i]->setEnabled(true);
|
for (int i = 0; i < 9; i++)
|
||||||
actLoadState[i]->setEnabled(Frontend::SavestateExists(i));
|
{
|
||||||
|
actSaveState[i]->setEnabled(false);
|
||||||
|
actLoadState[i]->setEnabled(false);
|
||||||
|
}
|
||||||
|
actUndoStateLoad->setEnabled(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 1; i < 9; i++)
|
||||||
|
{
|
||||||
|
actSaveState[i]->setEnabled(true);
|
||||||
|
actLoadState[i]->setEnabled(Frontend::SavestateExists(i));
|
||||||
|
}
|
||||||
|
actSaveState[0]->setEnabled(true);
|
||||||
|
actLoadState[0]->setEnabled(true);
|
||||||
|
actUndoStateLoad->setEnabled(false);
|
||||||
}
|
}
|
||||||
actSaveState[0]->setEnabled(true);
|
|
||||||
actLoadState[0]->setEnabled(true);
|
|
||||||
actUndoStateLoad->setEnabled(false);
|
|
||||||
|
|
||||||
actPause->setEnabled(true);
|
actPause->setEnabled(true);
|
||||||
actPause->setChecked(false);
|
actPause->setChecked(false);
|
||||||
actReset->setEnabled(true);
|
actReset->setEnabled(true);
|
||||||
actStop->setEnabled(true);
|
actStop->setEnabled(true);
|
||||||
|
actImportSavefile->setEnabled(true);
|
||||||
|
|
||||||
|
actSetupCheats->setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onEmuStop()
|
void MainWindow::onEmuStop()
|
||||||
|
@ -1919,10 +2041,13 @@ void MainWindow::onEmuStop()
|
||||||
actLoadState[i]->setEnabled(false);
|
actLoadState[i]->setEnabled(false);
|
||||||
}
|
}
|
||||||
actUndoStateLoad->setEnabled(false);
|
actUndoStateLoad->setEnabled(false);
|
||||||
|
actImportSavefile->setEnabled(false);
|
||||||
|
|
||||||
actPause->setEnabled(false);
|
actPause->setEnabled(false);
|
||||||
actReset->setEnabled(false);
|
actReset->setEnabled(false);
|
||||||
actStop->setEnabled(false);
|
actStop->setEnabled(false);
|
||||||
|
|
||||||
|
actSetupCheats->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onUpdateVideoSettings(bool glchange)
|
void MainWindow::onUpdateVideoSettings(bool glchange)
|
||||||
|
@ -2054,6 +2179,8 @@ int main(int argc, char** argv)
|
||||||
micWavBuffer = nullptr;
|
micWavBuffer = nullptr;
|
||||||
|
|
||||||
Frontend::Init_ROM();
|
Frontend::Init_ROM();
|
||||||
|
Frontend::EnableCheats(Config::EnableCheats != 0);
|
||||||
|
|
||||||
Frontend::Init_Audio(audioFreq);
|
Frontend::Init_Audio(audioFreq);
|
||||||
|
|
||||||
if (Config::MicInputType == 1)
|
if (Config::MicInputType == 1)
|
||||||
|
@ -2080,7 +2207,7 @@ int main(int argc, char** argv)
|
||||||
char* file = argv[1];
|
char* file = argv[1];
|
||||||
char* ext = &file[strlen(file)-3];
|
char* ext = &file[strlen(file)-3];
|
||||||
|
|
||||||
if (!strcasecmp(ext, "nds") || !strcasecmp(ext, "srl"))
|
if (!strcasecmp(ext, "nds") || !strcasecmp(ext, "srl") || !strcasecmp(ext, "dsi"))
|
||||||
{
|
{
|
||||||
int res = Frontend::LoadROM(file, Frontend::ROMSlot_NDS);
|
int res = Frontend::LoadROM(file, Frontend::ROMSlot_NDS);
|
||||||
|
|
||||||
|
@ -2110,6 +2237,8 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
Input::CloseJoystick();
|
Input::CloseJoystick();
|
||||||
|
|
||||||
|
Frontend::DeInit_ROM();
|
||||||
|
|
||||||
if (audioDevice) SDL_CloseAudioDevice(audioDevice);
|
if (audioDevice) SDL_CloseAudioDevice(audioDevice);
|
||||||
if (micDevice) SDL_CloseAudioDevice(micDevice);
|
if (micDevice) SDL_CloseAudioDevice(micDevice);
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,8 @@ signals:
|
||||||
void windowLimitFPSChange();
|
void windowLimitFPSChange();
|
||||||
|
|
||||||
void screenLayoutChange();
|
void screenLayoutChange();
|
||||||
|
|
||||||
|
void windowFullscreenToggle();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
volatile int EmuStatus;
|
volatile int EmuStatus;
|
||||||
|
@ -193,11 +195,15 @@ private slots:
|
||||||
void onSaveState();
|
void onSaveState();
|
||||||
void onLoadState();
|
void onLoadState();
|
||||||
void onUndoStateLoad();
|
void onUndoStateLoad();
|
||||||
|
void onImportSavefile();
|
||||||
void onQuit();
|
void onQuit();
|
||||||
|
|
||||||
void onPause(bool checked);
|
void onPause(bool checked);
|
||||||
void onReset();
|
void onReset();
|
||||||
void onStop();
|
void onStop();
|
||||||
|
void onEnableCheats(bool checked);
|
||||||
|
void onSetupCheats();
|
||||||
|
void onCheatsDialogFinished(int res);
|
||||||
|
|
||||||
void onOpenEmuSettings();
|
void onOpenEmuSettings();
|
||||||
void onEmuSettingsDialogFinished(int res);
|
void onEmuSettingsDialogFinished(int res);
|
||||||
|
@ -226,6 +232,8 @@ private slots:
|
||||||
void onEmuStop();
|
void onEmuStop();
|
||||||
|
|
||||||
void onUpdateVideoSettings(bool glchange);
|
void onUpdateVideoSettings(bool glchange);
|
||||||
|
|
||||||
|
void onFullscreenToggled();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createScreenPanel();
|
void createScreenPanel();
|
||||||
|
@ -240,11 +248,14 @@ public:
|
||||||
QAction* actSaveState[9];
|
QAction* actSaveState[9];
|
||||||
QAction* actLoadState[9];
|
QAction* actLoadState[9];
|
||||||
QAction* actUndoStateLoad;
|
QAction* actUndoStateLoad;
|
||||||
|
QAction* actImportSavefile;
|
||||||
QAction* actQuit;
|
QAction* actQuit;
|
||||||
|
|
||||||
QAction* actPause;
|
QAction* actPause;
|
||||||
QAction* actReset;
|
QAction* actReset;
|
||||||
QAction* actStop;
|
QAction* actStop;
|
||||||
|
QAction* actEnableCheats;
|
||||||
|
QAction* actSetupCheats;
|
||||||
|
|
||||||
QAction* actEmuSettings;
|
QAction* actEmuSettings;
|
||||||
QAction* actInputConfig;
|
QAction* actInputConfig;
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016-2020 Arisotura
|
||||||
|
|
||||||
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
melonDS is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MELONDLDI_H
|
||||||
|
#define MELONDLDI_H
|
||||||
|
|
||||||
|
const u8 melonDLDI[] =
|
||||||
|
{
|
||||||
|
0xED, 0xA5, 0x8D, 0xBF, 0x20, 0x43, 0x68, 0x69, 0x73, 0x68, 0x6D, 0x00, 0x01, 0x01, 0x00, 0x00,
|
||||||
|
0x6D, 0x65, 0x6C, 0x6F, 0x6E, 0x44, 0x53, 0x20, 0x44, 0x4C, 0x44, 0x49, 0x20, 0x64, 0x72, 0x69,
|
||||||
|
0x76, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0xBF, 0xC0, 0x01, 0x80, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x4D, 0x45, 0x4C, 0x4E, 0x23, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0xBF, 0x88, 0x00, 0x80, 0xBF,
|
||||||
|
0x30, 0x01, 0x80, 0xBF, 0x70, 0x01, 0x80, 0xBF, 0xB0, 0x01, 0x80, 0xBF, 0xB8, 0x01, 0x80, 0xBF,
|
||||||
|
0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1, 0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1,
|
||||||
|
0x01, 0xC3, 0xA0, 0xE3, 0x1A, 0xCE, 0x8C, 0xE2, 0x02, 0x39, 0xA0, 0xE3, 0xB0, 0x30, 0xCC, 0xE1,
|
||||||
|
0x08, 0x00, 0xCC, 0xE5, 0x0C, 0x10, 0xCC, 0xE5, 0x21, 0x14, 0xA0, 0xE1, 0x0B, 0x10, 0xCC, 0xE5,
|
||||||
|
0x21, 0x14, 0xA0, 0xE1, 0x0A, 0x10, 0xCC, 0xE5, 0x21, 0x14, 0xA0, 0xE1, 0x09, 0x10, 0xCC, 0xE5,
|
||||||
|
0x21, 0x14, 0xA0, 0xE1, 0x0D, 0x10, 0xCC, 0xE5, 0xBE, 0x10, 0xCC, 0xE1, 0x03, 0x31, 0xA0, 0xE3,
|
||||||
|
0x00, 0x00, 0x52, 0xE3, 0x01, 0x34, 0x83, 0x13, 0x01, 0x35, 0x83, 0xE3, 0x04, 0x30, 0x8C, 0xE5,
|
||||||
|
0x41, 0x36, 0xA0, 0xE3, 0x01, 0x00, 0x10, 0xE3, 0x07, 0x00, 0x00, 0x1A, 0x04, 0x00, 0x9C, 0xE5,
|
||||||
|
0x02, 0x05, 0x10, 0xE3, 0x10, 0x10, 0x93, 0x15, 0x00, 0x00, 0x52, 0x13, 0x04, 0x10, 0x82, 0x14,
|
||||||
|
0x02, 0x01, 0x10, 0xE3, 0xF8, 0xFF, 0xFF, 0x1A, 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x10, 0xA0, 0xE3,
|
||||||
|
0x04, 0x00, 0x9C, 0xE5, 0x02, 0x05, 0x10, 0xE3, 0x00, 0x00, 0x52, 0x13, 0x04, 0x10, 0x92, 0x14,
|
||||||
|
0x10, 0x10, 0x83, 0x15, 0x02, 0x01, 0x10, 0xE3, 0xF8, 0xFF, 0xFF, 0x1A, 0x1E, 0xFF, 0x2F, 0xE1,
|
||||||
|
0x03, 0x00, 0x12, 0xE3, 0x00, 0x00, 0xA0, 0x13, 0x1E, 0xFF, 0x2F, 0x11, 0x78, 0x40, 0x2D, 0xE9,
|
||||||
|
0x00, 0x40, 0xA0, 0xE1, 0x01, 0x50, 0xA0, 0xE1, 0x00, 0x60, 0xA0, 0xE3, 0xC0, 0x00, 0xA0, 0xE3,
|
||||||
|
0x06, 0x10, 0x84, 0xE0, 0xCD, 0xFF, 0xFF, 0xEB, 0x01, 0x60, 0x86, 0xE2, 0x05, 0x00, 0x56, 0xE1,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x3A, 0x78, 0x40, 0xBD, 0xE8, 0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1,
|
||||||
|
0x03, 0x00, 0x12, 0xE3, 0x00, 0x00, 0xA0, 0x13, 0x1E, 0xFF, 0x2F, 0x11, 0x78, 0x40, 0x2D, 0xE9,
|
||||||
|
0x00, 0x40, 0xA0, 0xE1, 0x01, 0x50, 0xA0, 0xE1, 0x00, 0x60, 0xA0, 0xE3, 0xC1, 0x00, 0xA0, 0xE3,
|
||||||
|
0x06, 0x10, 0x84, 0xE0, 0xBD, 0xFF, 0xFF, 0xEB, 0x01, 0x60, 0x86, 0xE2, 0x05, 0x00, 0x56, 0xE1,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x3A, 0x78, 0x40, 0xBD, 0xE8, 0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1,
|
||||||
|
0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1, 0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MELONDLDI_H
|
18
src/types.h
18
src/types.h
|
@ -19,13 +19,15 @@
|
||||||
#ifndef TYPES_H
|
#ifndef TYPES_H
|
||||||
#define TYPES_H
|
#define TYPES_H
|
||||||
|
|
||||||
typedef unsigned char u8;
|
#include <stdint.h>
|
||||||
typedef unsigned short u16;
|
|
||||||
typedef unsigned int u32;
|
typedef uint8_t u8;
|
||||||
typedef unsigned long long int u64;
|
typedef uint16_t u16;
|
||||||
typedef signed char s8;
|
typedef uint32_t u32;
|
||||||
typedef signed short s16;
|
typedef uint64_t u64;
|
||||||
typedef signed int s32;
|
typedef int8_t s8;
|
||||||
typedef signed long long int s64;
|
typedef int16_t s16;
|
||||||
|
typedef int32_t s32;
|
||||||
|
typedef int64_t s64;
|
||||||
|
|
||||||
#endif // TYPES_H
|
#endif // TYPES_H
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#ifndef VERSION_H
|
#ifndef VERSION_H
|
||||||
#define VERSION_H
|
#define VERSION_H
|
||||||
|
|
||||||
#define MELONDS_VERSION "0.8.3-JIT"
|
#define MELONDS_VERSION "0.9"
|
||||||
|
|
||||||
#define MELONDS_URL "http://melonds.kuribo64.net/"
|
#define MELONDS_URL "http://melonds.kuribo64.net/"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue