mirror of
https://github.com/Rosalie241/RMG.git
synced 2026-07-11 09:34:00 +02:00
Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7725daffd4 | |||
| 232a962989 | |||
| cbb432b4ff | |||
| 6306d7a96e | |||
| 460188e1c3 | |||
| a89be55a0a | |||
| f6264336f9 | |||
| 572792a1c8 | |||
| 3570200e53 | |||
| e11d1884c8 | |||
| 77a201f52a | |||
| 4416343761 | |||
| 88a6685a6b | |||
| e0def96cb7 | |||
| dfca82520d | |||
| ea9313aa1b | |||
| 9ef92c3578 | |||
| ef3a68f509 | |||
| 2060facc2a | |||
| 474eff65fb | |||
| 6345ec6eb3 | |||
| b65692f12b | |||
| 8615c5efe1 | |||
| ae5813a635 | |||
| 219f74bb8b | |||
| 91b4213044 | |||
| 297968f319 | |||
| a40d1d34f5 | |||
| b964415ac7 | |||
| 4707fe143c | |||
| 66fc3492ca | |||
| 45e0231214 | |||
| b05b0faeea | |||
| 7b4b8c5c90 | |||
| 97bd81c287 | |||
| 3222b962cc | |||
| 37f89b448f | |||
| f91ed8d848 | |||
| 437733c9fd | |||
| 8f6496db86 | |||
| e1cd2f8400 | |||
| 94341526d7 | |||
| e1bc2e4a89 | |||
| 7a28f1df17 | |||
| 4a67f98a3b | |||
| 9908431e0a | |||
| a6dca6618e | |||
| 56ebe38849 | |||
| 32a1a26fcf | |||
| cbdfa2b307 | |||
| 2be09f9e03 | |||
| 51ce612bd9 | |||
| e37bc3faf9 | |||
| 7059a974ed |
@@ -1,6 +1,6 @@
|
||||
# Maintainer: Rosalie Wanders <rosalie@mailbox.org>
|
||||
pkgname=rmg
|
||||
pkgver=0.7.3
|
||||
pkgver=0.7.6
|
||||
pkgrel=1
|
||||
pkgdesc="Rosalie's Mupen GUI"
|
||||
arch=('x86_64' 'aarch64')
|
||||
@@ -8,7 +8,7 @@ url="https://github.com/Rosalie241/$pkgname"
|
||||
license=('GPL3')
|
||||
|
||||
depends=("hidapi" "libsamplerate" "speexdsp" "minizip" "sdl2" "sdl2_net" "zlib" "freetype2" "qt6-base" "qt6-svg" "qt6-websockets")
|
||||
makedepends=("git" "nasm" "cmake" "ninja")
|
||||
makedepends=("git" "nasm" "cmake")
|
||||
|
||||
source=("git+https://github.com/Rosalie241/$pkgname.git#tag=v$pkgver")
|
||||
sha256sums=('SKIP')
|
||||
@@ -25,7 +25,7 @@ build()
|
||||
-DPORTABLE_INSTALL="OFF" \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DNO_RUST="ON" \
|
||||
-G "Ninja"
|
||||
-G "Unix Makefiles"
|
||||
|
||||
cmake --build "$srcdir/$pkgname/build"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: RMG
|
||||
Version: 0.7.3
|
||||
Version: 0.7.6
|
||||
Release: %autorelease
|
||||
Summary: Rosalie's Mupen GUI
|
||||
|
||||
|
||||
@@ -29,6 +29,41 @@
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<releases>
|
||||
<release version="v0.7.6" date="2025-02-22" type="stable">
|
||||
<description>
|
||||
<p>Changes:</p>
|
||||
<ul>
|
||||
<li>Fix possible crash in parallel when vulkan initialization fails</li>
|
||||
<li>Remove support for hotplugging controllers while in-game in RMG-Input</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="v0.7.5" date="2025-02-16" type="stable">
|
||||
<description>
|
||||
<p>Changes:</p>
|
||||
<ul>
|
||||
<li>Fix incorrect error message in RMG-Core</li>
|
||||
<li>Fix possible crash on Windows (thank you Thirteen1355 for assisting with debugging)</li>
|
||||
<li>Fix missing space between 'L-Shoulder' and 'R-Shoulder' in RMG-Input</li>
|
||||
<li>Fix 'L-Trigger' and 'R-Trigger' names by changing it to 'L-Shoulder' and 'R-Shoulder' in RMG-Input</li>
|
||||
<li>Improve opening time of 'Edit Game Input Settings' by utilizing the ROM browser cache</li>
|
||||
<li>Improve configuration dialogs from plugins by setting the parent window</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="v0.7.4" date="2025-02-15" type="stable">
|
||||
<description>
|
||||
<p>Changes:</p>
|
||||
<ul>
|
||||
<li>Fix covers in JPEG format not loading on windows since v0.7.3</li>
|
||||
<li>Fix RMG not inhibiting the screensaver during emulation</li>
|
||||
<li>Fix not having supported archives listed when opening 64DD Disks through 'Open Combo'</li>
|
||||
<li>Fix RMG-Audio spamming the log with sample warnings</li>
|
||||
<li>Add captions to all file and directory dialogs</li>
|
||||
<li>Improve logging when retrieving OpenGL context fails</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="v0.7.3" date="2025-02-09" type="stable">
|
||||
<description>
|
||||
<p>Changes:</p>
|
||||
|
||||
@@ -75,7 +75,7 @@ cmake --install "$build_dir" --prefix="/usr"
|
||||
#### Windows
|
||||
* Download & Install [MSYS2](https://www.msys2.org/)
|
||||
```bash
|
||||
pacman -S --needed make mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-hidapi mingw-w64-ucrt-x86_64-freetype mingw-w64-ucrt-x86_64-libpng mingw-w64-ucrt-x86_64-qt6 mingw-w64-ucrt-x86_64-SDL2 mingw-w64-ucrt-x86_64-SDL2_net mingw-w64-ucrt-x86_64-speexdsp mingw-w64-ucrt-x86_64-libsamplerate mingw-w64-ucrt-x86_64-nasm mingw-w64-ucrt-x86_64-minizip mingw-w64-x86_64-vulkan-headers git
|
||||
pacman -S --needed make mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-hidapi mingw-w64-ucrt-x86_64-freetype mingw-w64-ucrt-x86_64-libpng mingw-w64-ucrt-x86_64-qt6 mingw-w64-ucrt-x86_64-SDL2 mingw-w64-ucrt-x86_64-SDL2_net mingw-w64-ucrt-x86_64-speexdsp mingw-w64-ucrt-x86_64-libsamplerate mingw-w64-ucrt-x86_64-nasm mingw-w64-ucrt-x86_64-minizip mingw-w64-ucrt-x86_64-vulkan-headers git
|
||||
./Source/Script/Build.sh Release
|
||||
```
|
||||
|
||||
|
||||
@@ -12442,6 +12442,7 @@ Transferpak=Yes
|
||||
GoodName=Pokemon Stadium (E) (V1.0) [f1]
|
||||
CRC=9DFE20E9 18894032
|
||||
RefMD5=2859090D78581E0925A3AF8045E81E4B
|
||||
SiDmaDuration=8192
|
||||
|
||||
[31EE2DE8E65E30F5934C450DBAA924F0]
|
||||
GoodName=Pokemon Stadium (E) (V1.1) [!]
|
||||
@@ -12449,6 +12450,7 @@ CRC=91C9E05D AD3AAFB9
|
||||
Players=4
|
||||
SaveType=Flash RAM
|
||||
Transferpak=Yes
|
||||
SiDmaDuration=8192
|
||||
|
||||
[0E85A098D0F0E8A7EB572A69612A6873]
|
||||
GoodName=Pokemon Stadium (F) [!]
|
||||
@@ -12456,6 +12458,7 @@ CRC=A23553A3 42BF2D39
|
||||
Players=4
|
||||
SaveType=Flash RAM
|
||||
Transferpak=Yes
|
||||
SiDmaDuration=8192
|
||||
|
||||
[4688C66F8C13EDA13DD5678176A7FD8A]
|
||||
GoodName=Pokemon Stadium (F) [f1]
|
||||
@@ -12468,6 +12471,7 @@ CRC=42011E1B E3552DB5
|
||||
Players=4
|
||||
SaveType=Flash RAM
|
||||
Transferpak=Yes
|
||||
SiDmaDuration=8192
|
||||
|
||||
[8FAA825507E6CD3F388CC33343FAE547]
|
||||
GoodName=Pokemon Stadium (G) [f1]
|
||||
@@ -12480,6 +12484,7 @@ CRC=A53FA82D DAE2C15D
|
||||
Players=4
|
||||
SaveType=Flash RAM
|
||||
Transferpak=Yes
|
||||
SiDmaDuration=8192
|
||||
|
||||
[D14A499BC4E324974EAE3E42DEC58625]
|
||||
GoodName=Pokemon Stadium (S) [!]
|
||||
@@ -12487,6 +12492,7 @@ CRC=B6E549CE DC8134C0
|
||||
Players=4
|
||||
SaveType=Flash RAM
|
||||
Transferpak=Yes
|
||||
SiDmaDuration=8192
|
||||
|
||||
[8D296A614A47AC99B80D1EDE669E62B3]
|
||||
GoodName=Pokemon Stadium (S) [f1]
|
||||
@@ -12499,6 +12505,7 @@ CRC=90F5D9B3 9D0EDCF0
|
||||
Players=4
|
||||
SaveType=Flash RAM
|
||||
Transferpak=Yes
|
||||
SiDmaDuration=8192
|
||||
|
||||
[C9214988B08511D2F44FAC2FAD2EE67A]
|
||||
GoodName=Pokemon Stadium (U) (V1.0) [f1]
|
||||
@@ -12511,6 +12518,7 @@ CRC=1A122D43 C17DAF0F
|
||||
Players=4
|
||||
SaveType=Flash RAM
|
||||
Transferpak=Yes
|
||||
SiDmaDuration=8192
|
||||
|
||||
[A7087A96A709E4C662A459B4B4159094]
|
||||
GoodName=Pokemon Stadium (U) (V1.1) [b1]
|
||||
@@ -12528,6 +12536,7 @@ CRC=9C8FB2FA 9B84A09B
|
||||
Players=4
|
||||
SaveType=Flash RAM
|
||||
Transferpak=Yes
|
||||
SiDmaDuration=8192
|
||||
|
||||
[B1271DB50D6EF8F6B53CC640C3743E4F]
|
||||
GoodName=Pokemon Stadium 2 (E) [!]
|
||||
|
||||
+218
-124
@@ -37,7 +37,7 @@
|
||||
|
||||
static uint16_t gb_cart_address(unsigned int bank, uint16_t address)
|
||||
{
|
||||
return (address & 0x3fff) | ((bank & 0x3) * 0x4000) ;
|
||||
return 0x4000 * bank + (address & 0x7fff) - 0x4000;
|
||||
}
|
||||
|
||||
void init_transferpak(struct transferpak* tpk, struct gb_cart* gb_cart)
|
||||
@@ -49,10 +49,7 @@ void poweron_transferpak(struct transferpak* tpk)
|
||||
{
|
||||
tpk->enabled = 0;
|
||||
tpk->bank = 0;
|
||||
tpk->access_mode = (tpk->gb_cart == NULL)
|
||||
? CART_NOT_INSERTED
|
||||
: CART_ACCESS_MODE_0;
|
||||
tpk->access_mode_changed = 0x44;
|
||||
tpk->reset_state = 3;
|
||||
|
||||
if (tpk->gb_cart != NULL) {
|
||||
poweron_gb_cart(tpk->gb_cart);
|
||||
@@ -68,9 +65,11 @@ void change_gb_cart(struct transferpak* tpk, struct gb_cart* gb_cart)
|
||||
}
|
||||
else {
|
||||
tpk->access_mode = CART_ACCESS_MODE_0;
|
||||
poweron_gb_cart(gb_cart);
|
||||
// poweron_gb_cart(gb_cart);
|
||||
}
|
||||
|
||||
|
||||
tpk->reset_state = 3;
|
||||
tpk->gb_cart = gb_cart;
|
||||
}
|
||||
|
||||
@@ -84,131 +83,225 @@ static void unplug_transferpak(void* pak)
|
||||
{
|
||||
}
|
||||
|
||||
static void read_transferpak(void* pak, uint16_t address, uint8_t* data, size_t size)
|
||||
{
|
||||
struct transferpak* tpk = (struct transferpak*)pak;
|
||||
uint8_t value;
|
||||
|
||||
DebugMessage(M64MSG_VERBOSE, "tpak read: %04x", address);
|
||||
|
||||
switch(address >> 12)
|
||||
{
|
||||
case 0x8:
|
||||
/* get gb cart state (enabled/disabled) */
|
||||
value = (tpk->enabled)
|
||||
? 0x84
|
||||
: 0x00;
|
||||
|
||||
DebugMessage(M64MSG_VERBOSE, "tpak get cart state: %02x", value);
|
||||
memset(data, value, size);
|
||||
break;
|
||||
|
||||
case 0xb:
|
||||
/* get gb cart access mode */
|
||||
if (tpk->enabled)
|
||||
{
|
||||
DebugMessage(M64MSG_VERBOSE, "tpak get access mode: %02x", tpk->access_mode);
|
||||
memset(data, tpk->access_mode, size);
|
||||
if (tpk->access_mode != CART_NOT_INSERTED)
|
||||
{
|
||||
data[0] |= tpk->access_mode_changed;
|
||||
}
|
||||
tpk->access_mode_changed = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xc:
|
||||
case 0xd:
|
||||
case 0xe:
|
||||
case 0xf:
|
||||
/* read gb cart */
|
||||
if (tpk->enabled)
|
||||
{
|
||||
DebugMessage(M64MSG_VERBOSE, "tpak read cart: %04x", address);
|
||||
|
||||
if (tpk->gb_cart != NULL) {
|
||||
read_gb_cart(tpk->gb_cart, gb_cart_address(tpk->bank, address), data, size);
|
||||
}
|
||||
}
|
||||
break;
|
||||
/* Reads from the Transfer Pak. */
|
||||
static void read_transferpak(void* pak, uint16_t address, uint8_t* data, size_t size)
|
||||
{
|
||||
struct transferpak* tpk = (struct transferpak*)pak;
|
||||
uint8_t value;
|
||||
|
||||
|
||||
|
||||
switch (address >> 12)
|
||||
{
|
||||
case 0x8:
|
||||
/*
|
||||
* 0x8 => read the TPak "enabled" status
|
||||
* In Rust code: if (enabled) => 0x84 else => 0x00
|
||||
*/
|
||||
value = (tpk->enabled) ? 0x84 : 0x00;
|
||||
DebugMessage(M64MSG_VERBOSE, "TPak returning cart state: %02x", value);
|
||||
memset(data, value, size);
|
||||
return;
|
||||
|
||||
default:
|
||||
DebugMessage(M64MSG_WARNING, "Unknown tpak read: %04x", address);
|
||||
if (!tpk->enabled) {
|
||||
DebugMessage(M64MSG_VERBOSE, "TPak read ignored because disabled");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void write_transferpak(void* pak, uint16_t address, const uint8_t* data, size_t size)
|
||||
{
|
||||
struct transferpak* tpk = (struct transferpak*)pak;
|
||||
uint8_t value = data[size-1];
|
||||
|
||||
DebugMessage(M64MSG_VERBOSE, "tpak write: %04x <- %02x", address, value);
|
||||
|
||||
switch(address >> 12)
|
||||
switch (address >> 12)
|
||||
{
|
||||
case 0x8:
|
||||
/* enable / disable gb cart */
|
||||
switch(value)
|
||||
{
|
||||
case 0xfe:
|
||||
tpk->enabled = 0;
|
||||
DebugMessage(M64MSG_VERBOSE, "tpak disabled");
|
||||
break;
|
||||
case 0x84:
|
||||
tpk->enabled = 1;
|
||||
DebugMessage(M64MSG_VERBOSE, "tpak enabled");
|
||||
break;
|
||||
default:
|
||||
DebugMessage(M64MSG_WARNING, "Unknown tpak write: %04x <- %02x", address, value);
|
||||
case 0xB:
|
||||
{
|
||||
uint8_t val = 0;
|
||||
|
||||
if (tpk->gb_cart && tpk->gb_cart->enabled) {
|
||||
val |= (1 << 0); /* bit0 => cart enabled? */
|
||||
}
|
||||
val |= (uint8_t)((tpk->reset_state & 3) << 2);
|
||||
|
||||
if (tpk->enabled) {
|
||||
val |= (1 << 7);
|
||||
}
|
||||
|
||||
/* Simple state machine for reset_state (mirroring Rust logic). */
|
||||
if ( tpk->gb_cart->enabled && tpk->reset_state == 3) {
|
||||
tpk->reset_state = 2;
|
||||
}
|
||||
else if (!tpk->gb_cart->enabled && tpk->reset_state == 2) {
|
||||
tpk->reset_state = 1;
|
||||
}
|
||||
else if (!tpk->gb_cart->enabled && tpk->reset_state == 1) {
|
||||
tpk->reset_state = 0;
|
||||
}
|
||||
|
||||
DebugMessage(M64MSG_VERBOSE, "TPak read 0xB => %02x", val);
|
||||
|
||||
memset(data, val, size);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xC:
|
||||
case 0xD:
|
||||
case 0xE:
|
||||
case 0xF:
|
||||
/*
|
||||
* Read from the Game Boy cart.
|
||||
* The address is computed as bank-based offset
|
||||
* (0x4000 * bank + ((address & 0x7FFF) - 0x4000)).
|
||||
*/
|
||||
if (tpk->gb_cart != NULL)
|
||||
{
|
||||
const uint16_t cart_addr = gb_cart_address(tpk->bank, address);
|
||||
read_gb_cart(tpk->gb_cart, cart_addr, data, size);
|
||||
//DebugMessage(M64MSG_VERBOSE,
|
||||
// "TPak reading cart: bank=%d, raw_addr=%04x => gb_addr=%04x -> %02x", tpk->bank, address, cart_addr, data[0]);
|
||||
/*for(int i = 0; i < size; i++)
|
||||
{
|
||||
DebugMessage(M64MSG_VERBOSE, "TPak reading cart: bank=%d, raw_addr=%04x => gb_addr=%04x -> %02x", tpk->bank, address, cart_addr, data[i]);
|
||||
}*/
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugMessage(M64MSG_WARNING, "TPak read: no GB cart present");
|
||||
memset(data, 0x00, size);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DebugMessage(M64MSG_WARNING, "Unknown TPak read at %04x", address);
|
||||
memset(data, 0x00, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Writes to the Transfer Pak. */
|
||||
static void write_transferpak(void* pak, uint16_t address, const uint8_t* buf, size_t size)
|
||||
{
|
||||
struct transferpak* tpk = (struct transferpak*)pak;
|
||||
/* The Rust code always uses the last byte as the "value" for multi-byte writes. */
|
||||
uint16_t value = buf[size - 1];
|
||||
|
||||
DebugMessage(M64MSG_VERBOSE, "TransferPak write: %04x <- %02x", address, value);
|
||||
|
||||
switch (address >> 12)
|
||||
{
|
||||
case 0x8:
|
||||
/*
|
||||
* Matches the Rust approach: 0xFE => disable, 0x84 => enable
|
||||
*/
|
||||
switch (value)
|
||||
{
|
||||
case 0xFE:
|
||||
tpk->enabled = 0;
|
||||
DebugMessage(M64MSG_VERBOSE, "TPak disabled");
|
||||
return;
|
||||
|
||||
case 0x84:
|
||||
if (!tpk->enabled)
|
||||
{
|
||||
tpk->bank = 3;
|
||||
tpk->reset_state = 0;
|
||||
|
||||
if (tpk->gb_cart != NULL)
|
||||
{
|
||||
tpk->gb_cart->enabled = 0;
|
||||
}
|
||||
}
|
||||
tpk->enabled = 1;
|
||||
DebugMessage(M64MSG_VERBOSE, "TPak enabled (0x84)");
|
||||
return;
|
||||
|
||||
default:
|
||||
DebugMessage(M64MSG_WARNING,
|
||||
"Unknown write to TPak (0x8 region): %02x", value);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
default:
|
||||
/* If TPak not enabled, ignore writes (as in your Rust example). */
|
||||
if (!tpk->enabled) {
|
||||
DebugMessage(M64MSG_VERBOSE, "TPak write ignored because disabled");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0xA:
|
||||
if (!tpk->enabled) {
|
||||
DebugMessage(M64MSG_VERBOSE, "TPak write ignored because disabled");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xa:
|
||||
/* set gb cart bank */
|
||||
if (tpk->enabled)
|
||||
{
|
||||
tpk->bank = value;
|
||||
DebugMessage(M64MSG_VERBOSE, "tpak set bank %02x", tpk->bank);
|
||||
tpk->bank = (uint16_t)value;
|
||||
if (tpk->bank > 3) {
|
||||
DebugMessage(M64MSG_WARNING, "TPak: invalid bank %d", tpk->bank);
|
||||
tpk->bank = 0;
|
||||
}
|
||||
DebugMessage(M64MSG_VERBOSE, "TPak set bank => %d", tpk->bank);
|
||||
break;
|
||||
|
||||
case 0xB:
|
||||
if (value & 1)
|
||||
{
|
||||
if (tpk->gb_cart != NULL && !tpk->gb_cart->enabled)
|
||||
{
|
||||
/* Reset state to 3, and do any "power-on" type logic on the cart. */
|
||||
tpk->reset_state = 3;
|
||||
tpk->gb_cart->enabled = 1;
|
||||
tpk->gb_cart->rom_bank = 1;
|
||||
tpk->gb_cart->ram_bank = 0;
|
||||
tpk->gb_cart->ram_enable = 0;
|
||||
|
||||
/* e.g. set cart type if needed:
|
||||
* tpk->gb_cart->cart_type = get_cart_type(tpk->gb_cart->rom[0x147]);
|
||||
* (This depends on your real code.)
|
||||
*/
|
||||
DebugMessage(M64MSG_VERBOSE, "TPak: cart enabled, reset_state=3");
|
||||
}
|
||||
else if (tpk->gb_cart)
|
||||
{
|
||||
tpk->gb_cart->enabled = 1;
|
||||
DebugMessage(M64MSG_VERBOSE, "TPak: cart already enabled");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tpk->gb_cart) {
|
||||
tpk->gb_cart->enabled = 0;
|
||||
}
|
||||
DebugMessage(M64MSG_VERBOSE, "TPak: cart disabled via write to 0xB");
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC:
|
||||
case 0xD:
|
||||
case 0xE:
|
||||
case 0xF:
|
||||
{
|
||||
if (!tpk->enabled) {
|
||||
DebugMessage(M64MSG_VERBOSE, "TPak write ignored because disabled");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xb:
|
||||
/* set gb cart access mode */
|
||||
if (tpk->enabled)
|
||||
{
|
||||
tpk->access_mode_changed = 0x04;
|
||||
|
||||
tpk->access_mode = ((value & 1) == 0)
|
||||
? CART_ACCESS_MODE_0
|
||||
: CART_ACCESS_MODE_1;
|
||||
|
||||
if ((value & 0xfe) != 0)
|
||||
{
|
||||
DebugMessage(M64MSG_WARNING, "Unknown tpak write: %04x <- %02x", address, value);
|
||||
}
|
||||
|
||||
DebugMessage(M64MSG_VERBOSE, "tpak set access mode %02x", tpk->access_mode);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xc:
|
||||
case 0xd:
|
||||
case 0xe:
|
||||
case 0xf:
|
||||
/* write gb cart */
|
||||
// if (tpk->enabled)
|
||||
{
|
||||
DebugMessage(M64MSG_VERBOSE, "tpak write gb: %04x <- %02x", address, value);
|
||||
|
||||
if (tpk->gb_cart != NULL) {
|
||||
write_gb_cart(tpk->gb_cart, gb_cart_address(tpk->bank, address), data, size);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DebugMessage(M64MSG_WARNING, "Unknown tpak write: %04x <- %02x", address, value);
|
||||
}
|
||||
}
|
||||
/* Write to GB cart memory. */
|
||||
if (tpk->gb_cart != NULL)
|
||||
{
|
||||
uint16_t cart_addr = gb_cart_address(tpk->bank, address);
|
||||
DebugMessage(M64MSG_VERBOSE,
|
||||
"TPak write to cart: bank=%d, raw_addr=%04x => gb_addr=%04x val=%02x",
|
||||
tpk->bank, address, cart_addr, value);
|
||||
write_gb_cart(tpk->gb_cart, cart_addr, buf, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugMessage(M64MSG_WARNING,
|
||||
"TPak write to 0xC..0xF, but no GB cart present");
|
||||
}
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Transfer pak definition */
|
||||
const struct pak_interface g_itransferpak =
|
||||
@@ -219,3 +312,4 @@ const struct pak_interface g_itransferpak =
|
||||
read_transferpak,
|
||||
write_transferpak
|
||||
};
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ struct transferpak
|
||||
unsigned int bank;
|
||||
unsigned int access_mode;
|
||||
unsigned int access_mode_changed;
|
||||
unsigned int reset_state;
|
||||
|
||||
struct gb_cart* gb_cart;
|
||||
};
|
||||
|
||||
+2
-1
@@ -129,6 +129,7 @@ void init_device(struct device* dev,
|
||||
{ &dev->dd, dd_mecha_int_handler }, /* DD MECHA */
|
||||
{ &dev->dd, dd_bm_int_handler }, /* DD BM */
|
||||
{ &dev->dd, dd_dv_int_handler }, /* DD DRIVE */
|
||||
{ &dev->sp, rsp_task_event },
|
||||
};
|
||||
|
||||
#define R(x) read_ ## x
|
||||
@@ -141,7 +142,7 @@ void init_device(struct device* dev,
|
||||
/* memory map */
|
||||
{ A(MM_RDRAM_DRAM, 0x3efffff), M64P_MEM_RDRAM, { &dev->rdram, RW(rdram_dram) } },
|
||||
{ A(MM_RDRAM_REGS, 0xfffff), M64P_MEM_RDRAMREG, { &dev->rdram, RW(rdram_regs) } },
|
||||
{ A(MM_RSP_MEM, 0xffff), M64P_MEM_RSPMEM, { &dev->sp, RW(rsp_mem) } },
|
||||
{ A(MM_RSP_MEM, 0x3ffff), M64P_MEM_RSPMEM, { &dev->sp, RW(rsp_mem) } },
|
||||
{ A(MM_RSP_REGS, 0xffff), M64P_MEM_RSPREG, { &dev->sp, RW(rsp_regs) } },
|
||||
{ A(MM_RSP_REGS2, 0xffff), M64P_MEM_RSP, { &dev->sp, RW(rsp_regs2) } },
|
||||
{ A(MM_DPC_REGS, 0xffff), M64P_MEM_DP, { &dev->dp, RW(dpc_regs) } },
|
||||
|
||||
+93
-68
@@ -54,7 +54,7 @@ enum gbcart_extra_devices
|
||||
/* various helper functions for ram, rom, or MBC uses */
|
||||
|
||||
|
||||
static void read_rom(const void* rom_storage, const struct storage_backend_interface* irom_storage, uint16_t address, uint8_t* data, size_t size)
|
||||
static void read_rom(const void* rom_storage, const struct storage_backend_interface* irom_storage, uint32_t address, uint8_t* data, size_t size)
|
||||
{
|
||||
assert(size > 0);
|
||||
|
||||
@@ -68,14 +68,14 @@ static void read_rom(const void* rom_storage, const struct storage_backend_inter
|
||||
}
|
||||
|
||||
|
||||
static void read_ram(const void* ram_storage, const struct storage_backend_interface* iram_storage, unsigned int enabled, uint16_t address, uint8_t* data, size_t size, uint8_t mask)
|
||||
static void read_ram(const void* ram_storage, const struct storage_backend_interface* iram_storage, unsigned int enabled, uint32_t address, uint8_t* data, size_t size, uint8_t mask)
|
||||
{
|
||||
size_t i;
|
||||
assert(size > 0);
|
||||
|
||||
/* RAM has to be enabled before use */
|
||||
if (!enabled) {
|
||||
DebugMessage(M64MSG_WARNING, "Trying to read from non enabled GB RAM %04x", address);
|
||||
DebugMessage(M64MSG_WARNING, "read_ram Trying to read from non enabled GB RAM %04x", address);
|
||||
memset(data, 0xff, size);
|
||||
return;
|
||||
}
|
||||
@@ -240,7 +240,7 @@ static int write_gb_cart_mbc1(struct gb_cart* gb_cart, uint16_t address, const u
|
||||
/* 0x2000-0x3fff: ROM bank select (low 5 bits) */
|
||||
case (0x2000 >> 13):
|
||||
bank = value & 0x1f;
|
||||
gb_cart->rom_bank = (gb_cart->rom_bank & ~UINT8_C(0x1f)) | ((bank == 0) ? 1 : bank);
|
||||
gb_cart->rom_bank = (gb_cart->rom_bank & ~UINT8_C(0x1f)) | (bank == 0) ? 1 : bank;
|
||||
DebugMessage(M64MSG_VERBOSE, "MBC1 set rom bank %02x", gb_cart->rom_bank);
|
||||
break;
|
||||
|
||||
@@ -345,25 +345,32 @@ static int write_gb_cart_mbc2(struct gb_cart* gb_cart, uint16_t address, const u
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int read_gb_cart_mbc3(struct gb_cart* gb_cart, uint16_t address, uint8_t* data, size_t size)
|
||||
static int read_gb_cart_mbc3(struct gb_cart* gb_cart,
|
||||
uint16_t address,
|
||||
uint8_t* dst,
|
||||
size_t size)
|
||||
{
|
||||
switch(address >> 13)
|
||||
|
||||
if (address < 0x4000)
|
||||
{
|
||||
/* 0x0000-0x3fff: ROM bank 00 */
|
||||
case (0x0000 >> 13):
|
||||
case (0x2000 >> 13):
|
||||
read_rom(gb_cart->rom_storage, gb_cart->irom_storage, address, data, size);
|
||||
break;
|
||||
/* Bank 0 (0x0000 - 0x3FFF) */
|
||||
uint32_t banked_address = address & 0x3FFF; /* same as just address, but & 0x3FFF is explicit */
|
||||
|
||||
read_rom(gb_cart->rom_storage, gb_cart->irom_storage, banked_address, dst, size);
|
||||
|
||||
/* 0x4000-0x7fff: ROM bank 01-7f */
|
||||
case (0x4000 >> 13):
|
||||
case (0x6000 >> 13):
|
||||
read_rom(gb_cart->rom_storage, gb_cart->irom_storage, (address - 0x4000) + (gb_cart->rom_bank * 0x4000), data, size);
|
||||
break;
|
||||
|
||||
/* 0xa000-0xbfff: RAM bank 00-07 or RTC register 08-0c */
|
||||
case (0xa000 >> 13):
|
||||
//DebugMessage(M64MSG_VERBOSE, "MBC3 read from ROM bank 0: %04x", address);
|
||||
}
|
||||
else if (address < 0x8000)
|
||||
{
|
||||
/* Switched ROM bank (0x4000 - 0x7FFF) */
|
||||
size_t banked_address = (size_t)((uint32_t)address - 0x4000)
|
||||
+ (gb_cart->rom_bank * 0x4000);
|
||||
read_rom(gb_cart->rom_storage, gb_cart->irom_storage, banked_address, dst, size);
|
||||
//DebugMessage(M64MSG_VERBOSE, "MBC3 read from ROM bank %02x: %04x", gb_cart->rom_bank, address);
|
||||
}
|
||||
else if (address >= 0xA000 && address < 0xC000)
|
||||
{
|
||||
|
||||
switch(gb_cart->ram_bank)
|
||||
{
|
||||
/* RAM banks */
|
||||
@@ -375,8 +382,12 @@ static int read_gb_cart_mbc3(struct gb_cart* gb_cart, uint16_t address, uint8_t*
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
read_ram(gb_cart->ram_storage, gb_cart->iram_storage, gb_cart->ram_enable, (address - 0xa000) + (gb_cart->ram_bank * 0x2000), data, size, UINT8_C(0xff));
|
||||
{
|
||||
size_t banked_address = (size_t)((uint32_t)address - 0xA000)
|
||||
+ (gb_cart->ram_bank * 0x2000);
|
||||
read_ram(gb_cart->ram_storage, gb_cart->iram_storage, gb_cart->ram_enable, banked_address, dst, size, UINT8_C(0xff));
|
||||
break;
|
||||
}
|
||||
|
||||
/* RTC registers */
|
||||
case 0x08:
|
||||
@@ -387,68 +398,78 @@ static int read_gb_cart_mbc3(struct gb_cart* gb_cart, uint16_t address, uint8_t*
|
||||
/* RAM has to be enabled before use */
|
||||
if (!gb_cart->ram_enable) {
|
||||
DebugMessage(M64MSG_WARNING, "Trying to read from non enabled GB RAM %04x", address);
|
||||
memset(data, 0xff, size);
|
||||
memset(dst, 0xff, size);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(gb_cart->extra_devices & GED_RTC)) {
|
||||
DebugMessage(M64MSG_WARNING, "Trying to read from absent RTC %04x", address);
|
||||
memset(data, 0xff, size);
|
||||
memset(dst, 0xff, size);
|
||||
break;
|
||||
}
|
||||
|
||||
memset(data, read_mbc3_rtc_regs(&gb_cart->rtc, gb_cart->ram_bank - 0x08), size);
|
||||
memset(dst, read_mbc3_rtc_regs(&gb_cart->rtc, gb_cart->ram_bank - 0x08), size);
|
||||
break;
|
||||
|
||||
default:
|
||||
DebugMessage(M64MSG_WARNING, "Unknown device mapped in RAM/RTC space: %04x", address);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DebugMessage(M64MSG_WARNING, "Invalid cart read (MBC3): %04x", address);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The Rust code does a panic!("Unsupported read address {:x}", address); */
|
||||
DebugMessage(M64MSG_WARNING, "Unsupported read address %04x", address);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_gb_cart_mbc3(struct gb_cart* gb_cart, uint16_t address, const uint8_t* data, size_t size)
|
||||
|
||||
static int write_gb_cart_mbc3(struct gb_cart* gb_cart,
|
||||
uint16_t address,
|
||||
const uint8_t* src,
|
||||
size_t size)
|
||||
{
|
||||
uint8_t bank;
|
||||
uint8_t value = data[size-1];
|
||||
if (size == 0) {
|
||||
/* Nothing to write, just return */
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(address >> 13)
|
||||
uint8_t value = src[size - 1];
|
||||
|
||||
if (address < 0x2000)
|
||||
{
|
||||
/* 0x0000-0x1fff: RAM/RTC enable */
|
||||
case (0x0000 >> 13):
|
||||
/* Enable or disable RAM */
|
||||
set_ram_enable(gb_cart, value);
|
||||
break;
|
||||
|
||||
/* 0x2000-0x3fff: ROM bank select */
|
||||
case (0x2000 >> 13):
|
||||
bank = value & 0x7f;
|
||||
gb_cart->rom_bank = (bank == 0) ? 1 : bank;
|
||||
DebugMessage(M64MSG_VERBOSE, "MBC3 set rom bank %02x", gb_cart->rom_bank);
|
||||
break;
|
||||
|
||||
/* 0x4000-0x5fff: RAM bank / RTC register select */
|
||||
case (0x4000 >> 13):
|
||||
gb_cart->ram_bank = value;
|
||||
}
|
||||
else if (address < 0x4000)
|
||||
{
|
||||
/* Select ROM bank (0x01..0x7F) */
|
||||
uint8_t bank = value & 0x7F;
|
||||
gb_cart->rom_bank = bank;
|
||||
if (gb_cart->rom_bank == 0) {
|
||||
gb_cart->rom_bank = 1;
|
||||
}
|
||||
DebugMessage(M64MSG_VERBOSE, "MBC3 set rom bank %02x addr %04x", gb_cart->rom_bank, address);
|
||||
}
|
||||
else if (address < 0x6000)
|
||||
{
|
||||
/* Select RAM bank or RTC register */
|
||||
gb_cart->ram_bank = (value & 0x0F);
|
||||
DebugMessage(M64MSG_VERBOSE, "MBC3 set ram bank %02x", gb_cart->ram_bank);
|
||||
break;
|
||||
|
||||
/* 0x6000-0x7fff: latch clock registers */
|
||||
case (0x6000 >> 13):
|
||||
}
|
||||
else if (address < 0x8000)
|
||||
{
|
||||
/* RTC latch (not implemented here) */
|
||||
/* The Rust code simply does nothing. */
|
||||
if (!(gb_cart->extra_devices & GED_RTC)) {
|
||||
DebugMessage(M64MSG_WARNING, "Trying to latch to absent RTC %04x", address);
|
||||
break;
|
||||
}
|
||||
|
||||
latch_mbc3_rtc_regs(&gb_cart->rtc, value);
|
||||
break;
|
||||
|
||||
/* 0xa000-0xbfff: RAM bank 00-07 or RTC register 08-0c */
|
||||
case (0xa000 >> 13):
|
||||
else
|
||||
latch_mbc3_rtc_regs(&gb_cart->rtc, value);
|
||||
}
|
||||
else if (address >= 0xA000 && address < 0xC000)
|
||||
{
|
||||
DebugMessage(M64MSG_VERBOSE, "MBC3 write to RAM: %04x <- %02x (bank %02x)", address, value, gb_cart->ram_bank);
|
||||
switch(gb_cart->ram_bank)
|
||||
{
|
||||
/* RAM banks */
|
||||
@@ -460,7 +481,7 @@ static int write_gb_cart_mbc3(struct gb_cart* gb_cart, uint16_t address, const u
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
write_ram(gb_cart->ram_storage, gb_cart->iram_storage, gb_cart->ram_enable, (address - 0xa000) + (gb_cart->ram_bank * 0x2000), data, size, UINT8_C(0xff));
|
||||
write_ram(gb_cart->ram_storage, gb_cart->iram_storage, gb_cart->ram_enable, (address - 0xa000) + (gb_cart->ram_bank * 0x2000), src, size, UINT8_C(0xff));
|
||||
break;
|
||||
|
||||
/* RTC registers */
|
||||
@@ -469,11 +490,11 @@ static int write_gb_cart_mbc3(struct gb_cart* gb_cart, uint16_t address, const u
|
||||
case 0x0a:
|
||||
case 0x0b:
|
||||
case 0x0c:
|
||||
/* RAM has to be enabled before use */
|
||||
if (!gb_cart->ram_enable) {
|
||||
DebugMessage(M64MSG_WARNING, "Trying to write to non enabled GB RAM %04x", address);
|
||||
break;
|
||||
}
|
||||
/* RAM has to be enabled before use */
|
||||
if (!gb_cart->ram_enable) {
|
||||
DebugMessage(M64MSG_WARNING, "Trying to write to non enabled GB RAM %04x", address);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(gb_cart->extra_devices & GED_RTC)) {
|
||||
DebugMessage(M64MSG_WARNING, "Trying to write to absent RTC %04x", address);
|
||||
@@ -486,15 +507,18 @@ static int write_gb_cart_mbc3(struct gb_cart* gb_cart, uint16_t address, const u
|
||||
default:
|
||||
DebugMessage(M64MSG_WARNING, "Unknwown device mapped in RAM/RTC space: %04x", address);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DebugMessage(M64MSG_WARNING, "Invalid cart write (MBC3): %04x", address);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The Rust code does panic!("Unsupported write address {:x}", address); */
|
||||
DebugMessage(M64MSG_WARNING, "Unsupported write address %04x", address);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int read_gb_cart_mbc5(struct gb_cart* gb_cart, uint16_t address, uint8_t* data, size_t size)
|
||||
{
|
||||
switch(address >> 13)
|
||||
@@ -1117,3 +1141,4 @@ int write_gb_cart(struct gb_cart* gb_cart, uint16_t address, const uint8_t* data
|
||||
return gb_cart->write_gb_cart(gb_cart, address, data, size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ struct gb_cart
|
||||
void* ram_storage;
|
||||
const struct storage_backend_interface* iram_storage;
|
||||
|
||||
unsigned int enabled;
|
||||
unsigned int rom_bank;
|
||||
unsigned int ram_bank;
|
||||
|
||||
|
||||
+3
-2
@@ -173,11 +173,12 @@ struct interrupt_handler
|
||||
void (*callback)(void*);
|
||||
};
|
||||
|
||||
enum { CP0_INTERRUPT_HANDLERS_COUNT = 16 };
|
||||
enum { CP0_INTERRUPT_HANDLERS_COUNT = 17 };
|
||||
|
||||
enum {
|
||||
INTR_UNSAFE_R4300 = 0x01,
|
||||
INTR_UNSAFE_RSP = 0x02,
|
||||
INTR_UNSAFE_RSP = 0x02,
|
||||
INTR_UNSAFE_RDP = 0x04,
|
||||
};
|
||||
|
||||
struct cp0
|
||||
|
||||
@@ -656,6 +656,11 @@ void gen_interrupt(struct r4300_core* r4300)
|
||||
call_interrupt_handler(&r4300->cp0, 15);
|
||||
break;
|
||||
|
||||
case RSP_TSK_EVT:
|
||||
remove_interrupt_event(&r4300->cp0);
|
||||
call_interrupt_handler(&r4300->cp0, 16);
|
||||
break;
|
||||
|
||||
default:
|
||||
DebugMessage(M64MSG_ERROR, "Unknown interrupt queue event type %.8X.", r4300->cp0.q.first->data.type);
|
||||
remove_interrupt_event(&r4300->cp0);
|
||||
|
||||
@@ -69,5 +69,6 @@ void nmi_int_handler(void* opaque);
|
||||
#define DD_MC_INT 0x1000
|
||||
#define DD_BM_INT 0x2000
|
||||
#define DD_DV_INT 0x4000
|
||||
#define RSP_TSK_EVT 0x8000
|
||||
|
||||
#endif /* M64P_DEVICE_R4300_INTERRUPT_H */
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "device/memory/memory.h"
|
||||
#include "device/rcp/mi/mi_controller.h"
|
||||
#include "device/rcp/rsp/rsp_core.h"
|
||||
#include "device/r4300/r4300_core.h"
|
||||
#include "plugin/plugin.h"
|
||||
|
||||
static void update_dpc_status(struct rdp_core* dp, uint32_t w)
|
||||
@@ -40,7 +41,13 @@ static void update_dpc_status(struct rdp_core* dp, uint32_t w)
|
||||
dp->dpc_regs[DPC_STATUS_REG] &= ~DPC_STATUS_FREEZE;
|
||||
|
||||
if (dp->do_on_unfreeze & DELAY_DP_INT)
|
||||
{
|
||||
dp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RDP;
|
||||
|
||||
signal_rcp_interrupt(dp->mi, MI_INTR_DP);
|
||||
|
||||
clear_rsp_wait(dp->sp, WAIT_PENDING_DP_SYNC);
|
||||
}
|
||||
if (dp->do_on_unfreeze & DELAY_UPDATESCREEN)
|
||||
gfx.updateScreen();
|
||||
dp->do_on_unfreeze = 0;
|
||||
@@ -51,6 +58,22 @@ static void update_dpc_status(struct rdp_core* dp, uint32_t w)
|
||||
if (w & DPC_CLR_FLUSH) dp->dpc_regs[DPC_STATUS_REG] &= ~DPC_STATUS_FLUSH;
|
||||
if (w & DPC_SET_FLUSH) dp->dpc_regs[DPC_STATUS_REG] |= DPC_STATUS_FLUSH;
|
||||
|
||||
if (w & DPC_CLR_TMEM_CTR)
|
||||
{
|
||||
dp->dpc_regs[DPC_STATUS_REG] &= ~DPC_STATUS_TMEM_BUSY;
|
||||
dp->dpc_regs[DPC_TMEM_REG] = 0;
|
||||
}
|
||||
if (w & DPC_CLR_PIPE_CTR)
|
||||
{
|
||||
dp->dpc_regs[DPC_STATUS_REG] &= ~DPC_STATUS_PIPE_BUSY;
|
||||
dp->dpc_regs[DPC_PIPEBUSY_REG] = 0;
|
||||
}
|
||||
if (w & DPC_CLR_CMD_CTR)
|
||||
{
|
||||
dp->dpc_regs[DPC_STATUS_REG] &= ~DPC_STATUS_CMD_BUSY;
|
||||
dp->dpc_regs[DPC_BUFBUSY_REG] = 0;
|
||||
}
|
||||
|
||||
/* clear clock counter */
|
||||
if (w & DPC_CLR_CLOCK_CTR) dp->dpc_regs[DPC_CLOCK_REG] = 0;
|
||||
}
|
||||
@@ -73,11 +96,13 @@ void poweron_rdp(struct rdp_core* dp)
|
||||
{
|
||||
memset(dp->dpc_regs, 0, DPC_REGS_COUNT*sizeof(uint32_t));
|
||||
memset(dp->dps_regs, 0, DPS_REGS_COUNT*sizeof(uint32_t));
|
||||
dp->dpc_regs[DPC_STATUS_REG] |= DPC_STATUS_START_GCLK;
|
||||
dp->dpc_regs[DPC_STATUS_REG] |= DPC_STATUS_START_GCLK | DPC_STATUS_PIPE_BUSY | DPC_STATUS_CBUF_READY;
|
||||
|
||||
dp->do_on_unfreeze = 0;
|
||||
|
||||
poweron_fb(&dp->fb);
|
||||
|
||||
dp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RDP;
|
||||
}
|
||||
|
||||
|
||||
@@ -106,18 +131,35 @@ void write_dpc_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mas
|
||||
return;
|
||||
}
|
||||
|
||||
masked_write(&dp->dpc_regs[reg], value, mask);
|
||||
|
||||
switch(reg)
|
||||
{
|
||||
case DPC_START_REG:
|
||||
dp->dpc_regs[DPC_CURRENT_REG] = dp->dpc_regs[DPC_START_REG];
|
||||
if (!(dp->dpc_regs[DPC_STATUS_REG] & DPC_STATUS_START_VALID))
|
||||
{
|
||||
masked_write(&dp->dpc_regs[reg], value & UINT32_C(0xFFFFF8), mask);
|
||||
}
|
||||
dp->dpc_regs[DPC_STATUS_REG] |= DPC_STATUS_START_VALID;
|
||||
break;
|
||||
case DPC_END_REG:
|
||||
masked_write(&dp->dpc_regs[reg], value & UINT32_C(0xFFFFF8), mask);
|
||||
if (dp->dpc_regs[DPC_STATUS_REG] & DPC_STATUS_START_VALID)
|
||||
{
|
||||
dp->dpc_regs[DPC_CURRENT_REG] = dp->dpc_regs[DPC_START_REG];
|
||||
dp->dpc_regs[DPC_STATUS_REG] &= ~DPC_STATUS_START_VALID;
|
||||
}
|
||||
unprotect_framebuffers(&dp->fb);
|
||||
gfx.processRDPList();
|
||||
protect_framebuffers(&dp->fb);
|
||||
signal_rcp_interrupt(dp->mi, MI_INTR_DP);
|
||||
if (dp->mi->regs[MI_INTR_REG] & MI_INTR_DP)
|
||||
{
|
||||
dp->mi->regs[MI_INTR_REG] &= ~MI_INTR_DP;
|
||||
dp->mi->r4300->cp0.interrupt_unsafe_state |= INTR_UNSAFE_RDP;
|
||||
if (dp->dpc_regs[DPC_STATUS_REG] & DPC_STATUS_FREEZE) {
|
||||
dp->do_on_unfreeze |= DELAY_DP_INT;
|
||||
} else {
|
||||
add_interrupt_event(&dp->mi->r4300->cp0, DP_INT, dp->dpc_regs[DPC_CLOCK_REG]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -149,6 +191,9 @@ void rdp_interrupt_event(void* opaque)
|
||||
{
|
||||
struct rdp_core* dp = (struct rdp_core*)opaque;
|
||||
|
||||
dp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RDP;
|
||||
raise_rcp_interrupt(dp->mi, MI_INTR_DP);
|
||||
|
||||
clear_rsp_wait(dp->sp, WAIT_PENDING_DP_SYNC);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,11 @@ enum
|
||||
DPC_STATUS_FREEZE = 0x002,
|
||||
DPC_STATUS_FLUSH = 0x004,
|
||||
DPC_STATUS_START_GCLK = 0x008,
|
||||
DPC_STATUS_TMEM_BUSY = 0x010,
|
||||
DPC_STATUS_PIPE_BUSY = 0x020,
|
||||
DPC_STATUS_CMD_BUSY = 0x040,
|
||||
DPC_STATUS_CBUF_READY = 0x080,
|
||||
DPC_STATUS_DMA_BUSY = 0x100,
|
||||
DPC_STATUS_END_VALID = 0x200,
|
||||
DPC_STATUS_START_VALID = 0x400,
|
||||
/* DPC status - write */
|
||||
|
||||
+119
-104
@@ -76,13 +76,16 @@ static void do_sp_dma(struct rsp_core* sp, const struct sp_dma* dma)
|
||||
pre_framebuffer_read(&sp->dp->fb, dramaddr);
|
||||
|
||||
for(i=0; i<length; i++) {
|
||||
spmem[(memaddr^S8) & 0xfff] = dram[(dramaddr^S8) & 0x7fffff];
|
||||
spmem[(memaddr & 0xfff)^S8] = dram[(dramaddr^S8) & 0x7fffff];
|
||||
memaddr++;
|
||||
dramaddr++;
|
||||
}
|
||||
dramaddr+=skip;
|
||||
}
|
||||
|
||||
sp->regs[SP_MEM_ADDR_REG] = (memaddr & 0xfff) + (dma->memaddr & 0x1000);
|
||||
sp->regs[SP_DRAM_ADDR_REG] = dramaddr;
|
||||
|
||||
sp->regs[SP_MEM_ADDR_REG] = memaddr & 0xfff;
|
||||
sp->regs[SP_DRAM_ADDR_REG] = dramaddr & 0xffffff;
|
||||
sp->regs[SP_RD_LEN_REG] = 0xff8;
|
||||
@@ -146,69 +149,87 @@ static void fifo_pop(struct rsp_core* sp)
|
||||
static void update_sp_status(struct rsp_core* sp, uint32_t w)
|
||||
{
|
||||
/* clear / set halt */
|
||||
if ((w & 0x3) == 0x1) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_HALT;
|
||||
if ((w & 0x3) == 0x2) sp->regs[SP_STATUS_REG] |= SP_STATUS_HALT;
|
||||
if ((w & SP_CLR_HALT) && !(w & SP_SET_HALT))
|
||||
{
|
||||
sp->rsp_wait &= ~WAIT_HALTED;
|
||||
sp->regs[SP_STATUS_REG] &= ~SP_STATUS_HALT;
|
||||
}
|
||||
if ((w & SP_SET_HALT) && !(w & SP_CLR_HALT))
|
||||
{
|
||||
remove_event(&sp->mi->r4300->cp0.q, SP_INT);
|
||||
sp->rsp_status = 0;
|
||||
sp->first_run = 1;
|
||||
sp->rsp_wait |= WAIT_HALTED;
|
||||
sp->regs[SP_STATUS_REG] |= SP_STATUS_HALT;
|
||||
}
|
||||
|
||||
/* clear broke */
|
||||
if (w & 0x4) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_BROKE;
|
||||
if (w & SP_CLR_BROKE) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_BROKE;
|
||||
|
||||
/* clear SP interrupt */
|
||||
if ((w & 0x18) == 0x8)
|
||||
if ((w & SP_CLR_INTR) && !(w & SP_SET_INTR))
|
||||
{
|
||||
clear_rcp_interrupt(sp->mi, MI_INTR_SP);
|
||||
}
|
||||
/* set SP interrupt */
|
||||
if ((w & 0x18) == 0x10)
|
||||
if ((w & SP_SET_INTR) && !(w & SP_CLR_INTR))
|
||||
{
|
||||
signal_rcp_interrupt(sp->mi, MI_INTR_SP);
|
||||
}
|
||||
|
||||
/* clear / set single step */
|
||||
if ((w & 0x60) == 0x20) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SSTEP;
|
||||
if ((w & 0x60) == 0x40) sp->regs[SP_STATUS_REG] |= SP_STATUS_SSTEP;
|
||||
if ((w & SP_CLR_SSTEP) && !(w & SP_SET_SSTEP)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SSTEP;
|
||||
if ((w & SP_SET_SSTEP) && !(w & SP_CLR_SSTEP)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SSTEP;
|
||||
|
||||
/* clear / set interrupt on break */
|
||||
if ((w & 0x180) == 0x80) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_INTR_BREAK;
|
||||
if ((w & 0x180) == 0x100) sp->regs[SP_STATUS_REG] |= SP_STATUS_INTR_BREAK;
|
||||
if ((w & SP_CLR_INTR_BREAK) && !(w & SP_SET_INTR_BREAK))
|
||||
{
|
||||
if (sp->rsp_wait & WAIT_PENDING_SP_INT_BROKE)
|
||||
{
|
||||
// If a game clears SP_SET_INTR_BREAK before the interrupt happens,
|
||||
// that means it would have been cleared before the BREAK command
|
||||
remove_event(&sp->mi->r4300->cp0.q, SP_INT);
|
||||
sp->rsp_wait &= ~WAIT_PENDING_SP_INT_BROKE;
|
||||
sp->regs[SP_STATUS_REG] = sp->rsp_status;
|
||||
sp->rsp_status = 0;
|
||||
}
|
||||
sp->regs[SP_STATUS_REG] &= ~SP_STATUS_INTR_BREAK;
|
||||
}
|
||||
if ((w & SP_SET_INTR_BREAK) && !(w & SP_CLR_INTR_BREAK)) sp->regs[SP_STATUS_REG] |= SP_STATUS_INTR_BREAK;
|
||||
|
||||
/* clear / set signal 0 */
|
||||
if ((w & 0x600) == 0x200) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG0;
|
||||
if ((w & 0x600) == 0x400) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG0;
|
||||
if ((w & SP_CLR_SIG0) && !(w & SP_SET_SIG0)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG0;
|
||||
if ((w & SP_SET_SIG0) && !(w & SP_CLR_SIG0)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG0;
|
||||
|
||||
/* clear / set signal 1 */
|
||||
if ((w & 0x1800) == 0x800) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG1;
|
||||
if ((w & 0x1800) == 0x1000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG1;
|
||||
if ((w & SP_CLR_SIG1) && !(w & SP_SET_SIG1)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG1;
|
||||
if ((w & SP_SET_SIG1) && !(w & SP_CLR_SIG1)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG1;
|
||||
|
||||
/* clear / set signal 2 */
|
||||
if ((w & 0x6000) == 0x2000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG2;
|
||||
if ((w & 0x6000) == 0x4000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG2;
|
||||
if ((w & SP_CLR_SIG2) && !(w & SP_SET_SIG2)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG2;
|
||||
if ((w & SP_SET_SIG2) && !(w & SP_CLR_SIG2)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG2;
|
||||
|
||||
/* clear / set signal 3 */
|
||||
if ((w & 0x18000) == 0x8000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG3;
|
||||
if ((w & 0x18000) == 0x10000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG3;
|
||||
if ((w & SP_CLR_SIG3) && !(w & SP_SET_SIG3)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG3;
|
||||
if ((w & SP_SET_SIG3) && !(w & SP_CLR_SIG3)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG3;
|
||||
|
||||
/* clear / set signal 4 */
|
||||
if ((w & 0x60000) == 0x20000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG4;
|
||||
if ((w & 0x60000) == 0x40000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG4;
|
||||
if ((w & SP_CLR_SIG4) && !(w & SP_SET_SIG4)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG4;
|
||||
if ((w & SP_SET_SIG4) && !(w & SP_CLR_SIG4)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG4;
|
||||
|
||||
/* clear / set signal 5 */
|
||||
if ((w & 0x180000) == 0x80000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG5;
|
||||
if ((w & 0x180000) == 0x100000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG5;
|
||||
if ((w & SP_CLR_SIG5) && !(w & SP_SET_SIG5)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG5;
|
||||
if ((w & SP_SET_SIG5) && !(w & SP_CLR_SIG5)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG5;
|
||||
|
||||
/* clear / set signal 6 */
|
||||
if ((w & 0x600000) == 0x200000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG6;
|
||||
if ((w & 0x600000) == 0x400000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG6;
|
||||
if ((w & SP_CLR_SIG6) && !(w & SP_SET_SIG6)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG6;
|
||||
if ((w & SP_SET_SIG6) && !(w & SP_CLR_SIG6)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG6;
|
||||
|
||||
/* clear / set signal 7 */
|
||||
if ((w & 0x1800000) == 0x800000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG7;
|
||||
if ((w & 0x1800000) == 0x1000000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG7;
|
||||
if ((w & SP_CLR_SIG7) && !(w & SP_SET_SIG7)) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG7;
|
||||
if ((w & SP_SET_SIG7) && !(w & SP_CLR_SIG7)) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG7;
|
||||
|
||||
if (sp->rsp_task_locked && (get_event(&sp->mi->r4300->cp0.q, SP_INT))) return;
|
||||
if (!((w & 0x3) == 1) && !(w & 0x4) && !sp->rsp_task_locked)
|
||||
return;
|
||||
|
||||
if (!(sp->regs[SP_STATUS_REG] & SP_STATUS_HALT))
|
||||
do_SP_Task(sp);
|
||||
do_SP_Task(sp);
|
||||
}
|
||||
|
||||
void init_rsp(struct rsp_core* sp,
|
||||
@@ -230,7 +251,9 @@ void poweron_rsp(struct rsp_core* sp)
|
||||
memset(sp->regs2, 0, SP_REGS2_COUNT*sizeof(uint32_t));
|
||||
memset(sp->fifo, 0, SP_DMA_FIFO_SIZE*sizeof(struct sp_dma));
|
||||
|
||||
sp->rsp_task_locked = 0;
|
||||
sp->rsp_status = 0;
|
||||
sp->first_run = 1;
|
||||
sp->rsp_wait = 0;
|
||||
sp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RSP;
|
||||
sp->regs[SP_STATUS_REG] = 1;
|
||||
sp->regs[SP_RD_LEN_REG] = 0xff8;
|
||||
@@ -286,6 +309,12 @@ void write_rsp_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mas
|
||||
|
||||
switch(reg)
|
||||
{
|
||||
case SP_MEM_ADDR_REG:
|
||||
sp->regs[SP_MEM_ADDR_REG] &= 0x1ff8;
|
||||
break;
|
||||
case SP_DRAM_ADDR_REG:
|
||||
sp->regs[SP_DRAM_ADDR_REG] &= 0xfffff8;
|
||||
break;
|
||||
case SP_RD_LEN_REG:
|
||||
fifo_push(sp, SP_DMA_WRITE);
|
||||
break;
|
||||
@@ -317,7 +346,10 @@ void write_rsp_regs2(void* opaque, uint32_t address, uint32_t value, uint32_t ma
|
||||
uint32_t reg = rsp_reg2(address);
|
||||
|
||||
if (reg == SP_PC_REG)
|
||||
mask &= 0xffc;
|
||||
{
|
||||
masked_write(&sp->regs2[SP_PC_REG], value & 0xffc, mask);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reg < SP_REGS2_COUNT)
|
||||
masked_write(&sp->regs2[reg], value, mask);
|
||||
@@ -325,97 +357,66 @@ void write_rsp_regs2(void* opaque, uint32_t address, uint32_t value, uint32_t ma
|
||||
|
||||
void do_SP_Task(struct rsp_core* sp)
|
||||
{
|
||||
uint32_t save_pc = sp->regs2[SP_PC_REG] & ~0xfff;
|
||||
if (sp->rsp_wait)
|
||||
return;
|
||||
if (get_event(&sp->mi->r4300->cp0.q, RSP_TSK_EVT))
|
||||
return;
|
||||
|
||||
uint32_t sp_delay_time;
|
||||
uint32_t saved_status = sp->regs[SP_STATUS_REG];
|
||||
uint32_t sp_bit_set = sp->mi->regs[MI_INTR_REG] & MI_INTR_SP;
|
||||
uint32_t dp_bit_set = sp->mi->regs[MI_INTR_REG] & MI_INTR_DP;
|
||||
|
||||
if (sp->mem[0xfc0/4] == 1)
|
||||
uint32_t rsp_cycles = rsp.doRspCycles(sp->first_run) / 2;
|
||||
|
||||
if (sp->mi->regs[MI_INTR_REG] & MI_INTR_DP && !dp_bit_set)
|
||||
{
|
||||
unprotect_framebuffers(&sp->dp->fb);
|
||||
|
||||
//gfx.processDList();
|
||||
sp->regs2[SP_PC_REG] &= 0xfff;
|
||||
#if defined(PROFILE)
|
||||
timed_section_start(TIMED_SECTION_GFX);
|
||||
#endif
|
||||
rsp.doRspCycles(0xffffffff);
|
||||
#if defined(PROFILE)
|
||||
timed_section_end(TIMED_SECTION_GFX);
|
||||
#endif
|
||||
sp->regs2[SP_PC_REG] |= save_pc;
|
||||
new_frame();
|
||||
|
||||
if (sp->mi->regs[MI_INTR_REG] & MI_INTR_DP)
|
||||
{
|
||||
sp->mi->regs[MI_INTR_REG] &= ~MI_INTR_DP;
|
||||
if (sp->dp->dpc_regs[DPC_STATUS_REG] & DPC_STATUS_FREEZE) {
|
||||
sp->dp->do_on_unfreeze |= DELAY_DP_INT;
|
||||
} else {
|
||||
cp0_update_count(sp->mi->r4300);
|
||||
add_interrupt_event(&sp->mi->r4300->cp0, DP_INT, 4000);
|
||||
}
|
||||
sp->mi->regs[MI_INTR_REG] &= ~MI_INTR_DP;
|
||||
sp->mi->r4300->cp0.interrupt_unsafe_state |= INTR_UNSAFE_RDP;
|
||||
sp->rsp_wait |= WAIT_PENDING_DP_SYNC;
|
||||
if (sp->dp->dpc_regs[DPC_STATUS_REG] & DPC_STATUS_FREEZE) {
|
||||
sp->dp->do_on_unfreeze |= DELAY_DP_INT;
|
||||
} else {
|
||||
add_interrupt_event(&sp->mi->r4300->cp0, DP_INT, rsp_cycles + sp->dp->dpc_regs[DPC_CLOCK_REG]);
|
||||
}
|
||||
sp_delay_time = 1000;
|
||||
|
||||
protect_framebuffers(&sp->dp->fb);
|
||||
}
|
||||
else if (sp->mem[0xfc0/4] == 2)
|
||||
{
|
||||
//audio.processAList();
|
||||
sp->regs2[SP_PC_REG] &= 0xfff;
|
||||
#if defined(PROFILE)
|
||||
timed_section_start(TIMED_SECTION_AUDIO);
|
||||
#endif
|
||||
rsp.doRspCycles(0xffffffff);
|
||||
#if defined(PROFILE)
|
||||
timed_section_end(TIMED_SECTION_AUDIO);
|
||||
#endif
|
||||
sp->regs2[SP_PC_REG] |= save_pc;
|
||||
|
||||
sp_delay_time = 4000;
|
||||
sp->rsp_status = sp->regs[SP_STATUS_REG];
|
||||
if ((sp->regs[SP_STATUS_REG] & SP_STATUS_HALT) == 0)
|
||||
{
|
||||
add_interrupt_event(&sp->mi->r4300->cp0, RSP_TSK_EVT, rsp_cycles);
|
||||
sp->first_run = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sp->regs2[SP_PC_REG] &= 0xfff;
|
||||
rsp.doRspCycles(0xffffffff);
|
||||
sp->regs2[SP_PC_REG] |= save_pc;
|
||||
|
||||
sp_delay_time = 0;
|
||||
sp->rsp_wait |= WAIT_HALTED;
|
||||
sp->first_run = 1;
|
||||
}
|
||||
|
||||
sp->rsp_task_locked = 0;
|
||||
sp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RSP;
|
||||
if ((sp->regs[SP_STATUS_REG] & (SP_STATUS_HALT | SP_STATUS_BROKE)) == 0)
|
||||
if ((sp->regs[SP_STATUS_REG] & SP_STATUS_BROKE) && (sp->regs[SP_STATUS_REG] & SP_STATUS_INTR_BREAK))
|
||||
{
|
||||
sp->rsp_task_locked = 1;
|
||||
sp->mi->r4300->cp0.interrupt_unsafe_state |= INTR_UNSAFE_RSP;
|
||||
sp->mi->regs[MI_INTR_REG] |= MI_INTR_SP;
|
||||
sp->rsp_wait |= WAIT_PENDING_SP_INT_BROKE;
|
||||
add_interrupt_event(&sp->mi->r4300->cp0, SP_INT, rsp_cycles);
|
||||
sp->regs[SP_STATUS_REG] = saved_status;
|
||||
}
|
||||
if (sp->mi->regs[MI_INTR_REG] & MI_INTR_SP)
|
||||
else if (sp->mi->regs[MI_INTR_REG] & MI_INTR_SP && !sp_bit_set)
|
||||
{
|
||||
cp0_update_count(sp->mi->r4300);
|
||||
add_interrupt_event(&sp->mi->r4300->cp0, SP_INT, sp_delay_time);
|
||||
sp->rsp_wait |= WAIT_PENDING_SP_INT;
|
||||
add_interrupt_event(&sp->mi->r4300->cp0, SP_INT, rsp_cycles);
|
||||
}
|
||||
sp->mi->r4300->cp0.interrupt_unsafe_state |= INTR_UNSAFE_RSP;
|
||||
if (!sp_bit_set)
|
||||
sp->mi->regs[MI_INTR_REG] &= ~MI_INTR_SP;
|
||||
}
|
||||
|
||||
sp->regs[SP_STATUS_REG] &=
|
||||
~(SP_STATUS_TASKDONE | SP_STATUS_BROKE | SP_STATUS_HALT);
|
||||
}
|
||||
|
||||
void rsp_interrupt_event(void* opaque)
|
||||
{
|
||||
struct rsp_core* sp = (struct rsp_core*)opaque;
|
||||
|
||||
if (!sp->rsp_task_locked)
|
||||
{
|
||||
sp->regs[SP_STATUS_REG] |=
|
||||
SP_STATUS_TASKDONE | SP_STATUS_BROKE | SP_STATUS_HALT;
|
||||
}
|
||||
sp->regs[SP_STATUS_REG] = sp->rsp_status;
|
||||
sp->rsp_status = 0;
|
||||
sp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RSP;
|
||||
raise_rcp_interrupt(sp->mi, MI_INTR_SP);
|
||||
|
||||
if ((sp->regs[SP_STATUS_REG] & SP_STATUS_INTR_BREAK) != 0)
|
||||
{
|
||||
raise_rcp_interrupt(sp->mi, MI_INTR_SP);
|
||||
}
|
||||
clear_rsp_wait(sp, WAIT_PENDING_SP_INT | WAIT_PENDING_SP_INT_BROKE);
|
||||
}
|
||||
|
||||
void rsp_end_of_dma_event(void* opaque)
|
||||
@@ -423,3 +424,17 @@ void rsp_end_of_dma_event(void* opaque)
|
||||
struct rsp_core* sp = (struct rsp_core*)opaque;
|
||||
fifo_pop(sp);
|
||||
}
|
||||
|
||||
void rsp_task_event(void* opaque)
|
||||
{
|
||||
struct rsp_core* sp = (struct rsp_core*)opaque;
|
||||
|
||||
do_SP_Task(sp);
|
||||
}
|
||||
|
||||
void clear_rsp_wait(struct rsp_core* sp, uint32_t value)
|
||||
{
|
||||
sp->rsp_wait &= ~value;
|
||||
|
||||
do_SP_Task(sp);
|
||||
}
|
||||
|
||||
@@ -55,6 +55,36 @@ enum
|
||||
SP_STATUS_SIG7 = 0x4000,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
/* SP_STATUS - write */
|
||||
SP_CLR_HALT = 0x0000001,
|
||||
SP_SET_HALT = 0x0000002,
|
||||
SP_CLR_BROKE = 0x0000004,
|
||||
SP_CLR_INTR = 0x0000008,
|
||||
SP_SET_INTR = 0x0000010,
|
||||
SP_CLR_SSTEP = 0x0000020,
|
||||
SP_SET_SSTEP = 0x0000040,
|
||||
SP_CLR_INTR_BREAK = 0x0000080,
|
||||
SP_SET_INTR_BREAK = 0x0000100,
|
||||
SP_CLR_SIG0 = 0x0000200,
|
||||
SP_SET_SIG0 = 0x0000400,
|
||||
SP_CLR_SIG1 = 0x0000800,
|
||||
SP_SET_SIG1 = 0x0001000,
|
||||
SP_CLR_SIG2 = 0x0002000,
|
||||
SP_SET_SIG2 = 0x0004000,
|
||||
SP_CLR_SIG3 = 0x0008000,
|
||||
SP_SET_SIG3 = 0x0010000,
|
||||
SP_CLR_SIG4 = 0x0020000,
|
||||
SP_SET_SIG4 = 0x0040000,
|
||||
SP_CLR_SIG5 = 0x0080000,
|
||||
SP_SET_SIG5 = 0x0100000,
|
||||
SP_CLR_SIG6 = 0x0200000,
|
||||
SP_SET_SIG6 = 0x0400000,
|
||||
SP_CLR_SIG7 = 0x0800000,
|
||||
SP_SET_SIG7 = 0x1000000,
|
||||
};
|
||||
|
||||
enum sp_registers
|
||||
{
|
||||
SP_MEM_ADDR_REG,
|
||||
@@ -81,6 +111,14 @@ enum sp_dma_dir
|
||||
SP_DMA_WRITE
|
||||
};
|
||||
|
||||
enum sp_rsp_wait
|
||||
{
|
||||
WAIT_PENDING_SP_INT_BROKE = 0x1,
|
||||
WAIT_PENDING_SP_INT = 0x2,
|
||||
WAIT_PENDING_DP_SYNC = 0x4,
|
||||
WAIT_HALTED = 0x8
|
||||
};
|
||||
|
||||
enum { SP_DMA_FIFO_SIZE = 2} ;
|
||||
|
||||
struct sp_dma
|
||||
@@ -96,7 +134,9 @@ struct rsp_core
|
||||
uint32_t* mem;
|
||||
uint32_t regs[SP_REGS_COUNT];
|
||||
uint32_t regs2[SP_REGS2_COUNT];
|
||||
uint32_t rsp_task_locked;
|
||||
uint32_t rsp_status;
|
||||
uint32_t first_run;
|
||||
uint32_t rsp_wait;
|
||||
|
||||
struct mi_controller* mi;
|
||||
struct rdp_core* dp;
|
||||
@@ -141,4 +181,7 @@ void do_SP_Task(struct rsp_core* sp);
|
||||
void rsp_interrupt_event(void* opaque);
|
||||
void rsp_end_of_dma_event(void* opaque);
|
||||
|
||||
void rsp_task_event(void* opaque);
|
||||
void clear_rsp_wait(struct rsp_core* sp, uint32_t value);
|
||||
|
||||
#endif
|
||||
|
||||
+2
-2
@@ -949,7 +949,7 @@ static int savestates_load_m64p(struct device* dev, char *filepath)
|
||||
/* reset fb state */
|
||||
poweron_fb(&dev->dp.fb);
|
||||
|
||||
dev->sp.rsp_task_locked = 0;
|
||||
//dev->sp.rsp_task_locked = 0;
|
||||
dev->r4300.cp0.interrupt_unsafe_state = 0;
|
||||
|
||||
*r4300_cp0_last_addr(&dev->r4300.cp0) = *r4300_pc(&dev->r4300);
|
||||
@@ -1253,7 +1253,7 @@ static int savestates_load_pj64(struct device* dev,
|
||||
// No flashram info in pj64 savestate.
|
||||
poweron_flashram(&dev->cart.flashram);
|
||||
|
||||
dev->sp.rsp_task_locked = 0;
|
||||
//dev->sp.rsp_task_locked = 0;
|
||||
dev->r4300.cp0.interrupt_unsafe_state = 0;
|
||||
|
||||
/* extra fb state */
|
||||
|
||||
@@ -127,4 +127,3 @@ void dummyvideo_ResizeVideoOutput(int width, int height)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ extern void dummyvideo_ViWidthChanged(void);
|
||||
extern void dummyvideo_ReadScreen2(void *dest, int *width, int *height, int front);
|
||||
extern void dummyvideo_SetRenderingCallback(void (*callback)(int));
|
||||
extern void dummyvideo_ResizeVideoOutput(int width, int height);
|
||||
extern void dummyvideo_FullSync(void);
|
||||
|
||||
extern void dummyvideo_FBRead(unsigned int addr);
|
||||
extern void dummyvideo_FBWrite(unsigned int addr, unsigned int size);
|
||||
|
||||
+10
-29
@@ -20,8 +20,6 @@ RSP::CPU cpu;
|
||||
#else
|
||||
RSP::JIT::CPU cpu;
|
||||
#endif
|
||||
short MFC0_count[32];
|
||||
int SP_STATUS_TIMEOUT;
|
||||
} // namespace RSP
|
||||
|
||||
extern "C"
|
||||
@@ -53,47 +51,33 @@ extern "C"
|
||||
|
||||
EXPORT unsigned int CALL DoRspCycles(unsigned int cycles)
|
||||
{
|
||||
if (*RSP::rsp.SP_STATUS_REG & (SP_STATUS_HALT | SP_STATUS_BROKE))
|
||||
return 0;
|
||||
|
||||
// We don't know if Mupen from the outside invalidated our IMEM.
|
||||
RSP::cpu.invalidate_imem();
|
||||
if (cycles)
|
||||
{
|
||||
RSP::cpu.get_state().last_instruction_type = RSP::VU_INSTRUCTION;
|
||||
RSP::cpu.get_state().instruction_pipeline = 0;
|
||||
RSP::cpu.invalidate_imem();
|
||||
}
|
||||
|
||||
// Run CPU until we either break or we need to fire an IRQ.
|
||||
RSP::cpu.get_state().pc = *RSP::rsp.SP_PC_REG & 0xfff;
|
||||
RSP::cpu.get_state().instruction_count = 0;
|
||||
|
||||
#ifdef INTENSE_DEBUG
|
||||
fprintf(stderr, "RUN TASK: %u\n", RSP::cpu.get_state().pc);
|
||||
log_rsp_mem_parallel();
|
||||
#endif
|
||||
|
||||
for (auto &count : RSP::MFC0_count)
|
||||
count = 0;
|
||||
|
||||
while (!(*RSP::rsp.SP_STATUS_REG & SP_STATUS_HALT))
|
||||
{
|
||||
auto mode = RSP::cpu.run();
|
||||
if (mode == RSP::MODE_CHECK_FLAGS && (*RSP::cpu.get_state().cp0.irq & 1))
|
||||
break;
|
||||
if (mode == RSP::MODE_EXIT)
|
||||
break;
|
||||
}
|
||||
|
||||
*RSP::rsp.SP_PC_REG = 0x04001000 | (RSP::cpu.get_state().pc & 0xffc);
|
||||
|
||||
// From CXD4.
|
||||
if (*RSP::rsp.SP_STATUS_REG & SP_STATUS_BROKE)
|
||||
return cycles;
|
||||
else if (*RSP::cpu.get_state().cp0.irq & 1)
|
||||
RSP::rsp.CheckInterrupts();
|
||||
else if (*RSP::rsp.SP_STATUS_REG & SP_STATUS_HALT)
|
||||
return cycles;
|
||||
else if (*RSP::rsp.SP_SEMAPHORE_REG != 0) // Semaphore lock fixes.
|
||||
{
|
||||
}
|
||||
else
|
||||
RSP::SP_STATUS_TIMEOUT = 16; // From now on, wait 16 times, not 0x7fff
|
||||
|
||||
// CPU restarts with the correct SIGs.
|
||||
*RSP::rsp.SP_STATUS_REG &= ~SP_STATUS_HALT;
|
||||
*RSP::rsp.SP_PC_REG = (RSP::cpu.get_state().pc & 0xffc);
|
||||
|
||||
return cycles;
|
||||
}
|
||||
@@ -157,9 +141,6 @@ extern "C"
|
||||
*cr[RSP::CP0_REGISTER_SP_STATUS] = SP_STATUS_HALT;
|
||||
RSP::cpu.get_state().cp0.irq = RSP::rsp.MI_INTR_REG;
|
||||
|
||||
// From CXD4.
|
||||
RSP::SP_STATUS_TIMEOUT = 0x7fff;
|
||||
|
||||
RSP::cpu.set_dmem(reinterpret_cast<uint32_t *>(Rsp_Info.DMEM));
|
||||
RSP::cpu.set_imem(reinterpret_cast<uint32_t *>(Rsp_Info.IMEM));
|
||||
RSP::cpu.set_rdram(reinterpret_cast<uint32_t *>(Rsp_Info.RDRAM));
|
||||
|
||||
+130
-87
@@ -6,8 +6,6 @@
|
||||
namespace RSP
|
||||
{
|
||||
extern RSP_INFO rsp;
|
||||
extern short MFC0_count[32];
|
||||
extern int SP_STATUS_TIMEOUT;
|
||||
} // namespace RSP
|
||||
#endif
|
||||
|
||||
@@ -28,34 +26,15 @@ extern "C"
|
||||
rsp->sr[rt] = res;
|
||||
|
||||
#ifdef PARALLEL_INTEGRATION
|
||||
if (rd == CP0_REGISTER_SP_STATUS)
|
||||
{
|
||||
// Might be waiting for the CPU to set a signal bit on the STATUS register. Increment timeout
|
||||
RSP::MFC0_count[rt] += 1;
|
||||
if (RSP::MFC0_count[rt] >= RSP::SP_STATUS_TIMEOUT)
|
||||
{
|
||||
*RSP::rsp.SP_STATUS_REG |= SP_STATUS_HALT;
|
||||
return MODE_CHECK_FLAGS;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 // FIXME: this is broken with upstream mupen64plus-core
|
||||
if (rd == CP0_REGISTER_SP_SEMAPHORE)
|
||||
{
|
||||
if (*rsp->cp0.cr[CP0_REGISTER_SP_SEMAPHORE])
|
||||
{
|
||||
#ifdef PARALLEL_INTEGRATION
|
||||
RSP::MFC0_count[rt] += 8; // Almost certainly waiting on the CPU. Timeout faster.
|
||||
if (RSP::MFC0_count[rt] >= RSP::SP_STATUS_TIMEOUT)
|
||||
{
|
||||
*RSP::rsp.SP_STATUS_REG |= SP_STATUS_HALT;
|
||||
return MODE_CHECK_FLAGS;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
*rsp->cp0.cr[CP0_REGISTER_SP_SEMAPHORE] = 1;
|
||||
*rsp->cp0.cr[CP0_REGISTER_SP_SEMAPHORE] = 1;
|
||||
return MODE_EXIT;
|
||||
}
|
||||
// We don't return control to the CPU if the RDP FREEZE bit is set, doing so seems to cause flickering
|
||||
else if (rd == CP0_REGISTER_SP_STATUS && (*rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] & DPC_STATUS_FREEZE) == 0)
|
||||
{
|
||||
return MODE_EXIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -65,12 +44,44 @@ extern "C"
|
||||
return MODE_CONTINUE;
|
||||
}
|
||||
|
||||
#define RSP_HANDLE_STATUS_WRITE(flag) \
|
||||
switch (rt & (SP_SET_##flag | SP_CLR_##flag)) \
|
||||
{ \
|
||||
case SP_SET_##flag: status |= SP_STATUS_##flag; break; \
|
||||
case SP_CLR_##flag: status &= ~SP_STATUS_##flag; break; \
|
||||
default: break; \
|
||||
static inline void rdp_status_write(RSP::CPUState *rsp, uint32_t rt)
|
||||
{
|
||||
uint32_t status = *rsp->cp0.cr[CP0_REGISTER_CMD_STATUS];
|
||||
if (rt & DPC_CLR_XBUS_DMEM_DMA)
|
||||
status &= ~DPC_STATUS_XBUS_DMEM_DMA;
|
||||
else if (rt & DPC_SET_XBUS_DMEM_DMA)
|
||||
status |= DPC_STATUS_XBUS_DMEM_DMA;
|
||||
|
||||
if (rt & DPC_CLR_FREEZE)
|
||||
status &= ~DPC_STATUS_FREEZE;
|
||||
else if (rt & DPC_SET_FREEZE)
|
||||
status |= DPC_STATUS_FREEZE;
|
||||
|
||||
if (rt & DPC_CLR_FLUSH)
|
||||
status &= ~DPC_STATUS_FLUSH;
|
||||
else if (rt & DPC_SET_FLUSH)
|
||||
status |= DPC_STATUS_FLUSH;
|
||||
|
||||
if (rt & DPC_CLR_TMEM_CTR)
|
||||
{
|
||||
status &= ~DPC_STATUS_TMEM_BUSY;
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_TMEM_BUSY] = 0;
|
||||
}
|
||||
if (rt & DPC_CLR_PIPE_CTR)
|
||||
{
|
||||
status &= ~DPC_STATUS_PIPE_BUSY;
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_PIPE_BUSY] = 0;
|
||||
}
|
||||
if (rt & DPC_CLR_CMD_CTR)
|
||||
{
|
||||
status &= ~DPC_STATUS_CMD_BUSY;
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_BUSY] = 0;
|
||||
}
|
||||
|
||||
if (rt & DPC_CLR_CLOCK_CTR)
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_CLOCK] = 0;
|
||||
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] = status;
|
||||
}
|
||||
|
||||
static inline int rsp_status_write(RSP::CPUState *rsp, uint32_t rt)
|
||||
@@ -79,28 +90,69 @@ extern "C"
|
||||
|
||||
uint32_t status = *rsp->cp0.cr[CP0_REGISTER_SP_STATUS];
|
||||
|
||||
RSP_HANDLE_STATUS_WRITE(HALT)
|
||||
RSP_HANDLE_STATUS_WRITE(SSTEP)
|
||||
RSP_HANDLE_STATUS_WRITE(INTR_BREAK)
|
||||
RSP_HANDLE_STATUS_WRITE(SIG0)
|
||||
RSP_HANDLE_STATUS_WRITE(SIG1)
|
||||
RSP_HANDLE_STATUS_WRITE(SIG2)
|
||||
RSP_HANDLE_STATUS_WRITE(SIG3)
|
||||
RSP_HANDLE_STATUS_WRITE(SIG4)
|
||||
RSP_HANDLE_STATUS_WRITE(SIG5)
|
||||
RSP_HANDLE_STATUS_WRITE(SIG6)
|
||||
RSP_HANDLE_STATUS_WRITE(SIG7)
|
||||
|
||||
switch (rt & (SP_SET_INTR | SP_CLR_INTR))
|
||||
{
|
||||
case SP_SET_INTR: *rsp->cp0.irq |= 1; break;
|
||||
case SP_CLR_INTR: *rsp->cp0.irq &= ~1; break;
|
||||
default: break;
|
||||
}
|
||||
if ((rt & SP_CLR_HALT) && !(rt & SP_SET_HALT))
|
||||
status &= ~SP_STATUS_HALT;
|
||||
if ((rt & SP_SET_HALT) && !(rt & SP_CLR_HALT))
|
||||
status |= SP_STATUS_HALT;
|
||||
|
||||
if (rt & SP_CLR_BROKE)
|
||||
status &= ~SP_STATUS_BROKE;
|
||||
|
||||
if ((rt & SP_CLR_INTR) && !(rt & SP_SET_INTR))
|
||||
*rsp->cp0.irq &= ~1;
|
||||
if ((rt & SP_SET_INTR) && !(rt & SP_CLR_INTR))
|
||||
*rsp->cp0.irq |= 1;
|
||||
|
||||
if ((rt & SP_CLR_SSTEP) && !(rt & SP_SET_SSTEP))
|
||||
status &= ~SP_STATUS_SSTEP;
|
||||
if ((rt & SP_SET_SSTEP) && !(rt & SP_CLR_SSTEP))
|
||||
status |= SP_STATUS_SSTEP;
|
||||
|
||||
if ((rt & SP_CLR_INTR_BREAK) && !(rt & SP_SET_INTR_BREAK))
|
||||
status &= ~SP_STATUS_INTR_BREAK;
|
||||
if ((rt & SP_SET_INTR_BREAK) && !(rt & SP_CLR_INTR_BREAK))
|
||||
status |= SP_STATUS_INTR_BREAK;
|
||||
|
||||
if ((rt & SP_CLR_SIG0) && !(rt & SP_SET_SIG0))
|
||||
status &= ~SP_STATUS_SIG0;
|
||||
if ((rt & SP_SET_SIG0) && !(rt & SP_CLR_SIG0))
|
||||
status |= SP_STATUS_SIG0;
|
||||
|
||||
if ((rt & SP_CLR_SIG1) && !(rt & SP_SET_SIG1))
|
||||
status &= ~SP_STATUS_SIG1;
|
||||
if ((rt & SP_SET_SIG1) && !(rt & SP_CLR_SIG1))
|
||||
status |= SP_STATUS_SIG1;
|
||||
|
||||
if ((rt & SP_CLR_SIG2) && !(rt & SP_SET_SIG2))
|
||||
status &= ~SP_STATUS_SIG2;
|
||||
if ((rt & SP_SET_SIG2) && !(rt & SP_CLR_SIG2))
|
||||
status |= SP_STATUS_SIG2;
|
||||
|
||||
if ((rt & SP_CLR_SIG3) && !(rt & SP_SET_SIG3))
|
||||
status &= ~SP_STATUS_SIG3;
|
||||
if ((rt & SP_SET_SIG3) && !(rt & SP_CLR_SIG3))
|
||||
status |= SP_STATUS_SIG3;
|
||||
|
||||
if ((rt & SP_CLR_SIG4) && !(rt & SP_SET_SIG4))
|
||||
status &= ~SP_STATUS_SIG4;
|
||||
if ((rt & SP_SET_SIG4) && !(rt & SP_CLR_SIG4))
|
||||
status |= SP_STATUS_SIG4;
|
||||
|
||||
if ((rt & SP_CLR_SIG5) && !(rt & SP_SET_SIG5))
|
||||
status &= ~SP_STATUS_SIG5;
|
||||
if ((rt & SP_SET_SIG5) && !(rt & SP_CLR_SIG5))
|
||||
status |= SP_STATUS_SIG5;
|
||||
|
||||
if ((rt & SP_CLR_SIG6) && !(rt & SP_SET_SIG6))
|
||||
status &= ~SP_STATUS_SIG6;
|
||||
if ((rt & SP_SET_SIG6) && !(rt & SP_CLR_SIG6))
|
||||
status |= SP_STATUS_SIG6;
|
||||
|
||||
if ((rt & SP_CLR_SIG7) && !(rt & SP_SET_SIG7))
|
||||
status &= ~SP_STATUS_SIG7;
|
||||
if ((rt & SP_SET_SIG7) && !(rt & SP_CLR_SIG7))
|
||||
status |= SP_STATUS_SIG7;
|
||||
|
||||
*rsp->cp0.cr[CP0_REGISTER_SP_STATUS] = status;
|
||||
return ((*rsp->cp0.irq & 1) || (status & SP_STATUS_HALT)) ? MODE_CHECK_FLAGS : MODE_CONTINUE;
|
||||
}
|
||||
@@ -109,14 +161,9 @@ extern "C"
|
||||
static int rsp_dma_read(RSP::CPUState *rsp)
|
||||
{
|
||||
uint32_t length_reg = *rsp->cp0.cr[CP0_REGISTER_DMA_READ_LENGTH];
|
||||
uint32_t length = (length_reg & 0xFFF) + 1;
|
||||
uint32_t skip = (length_reg >> 20) & 0xFFF;
|
||||
unsigned count = (length_reg >> 12) & 0xFF;
|
||||
|
||||
// Force alignment.
|
||||
length = (length + 0x7) & ~0x7;
|
||||
*rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] &= ~0x3;
|
||||
*rsp->cp0.cr[CP0_REGISTER_DMA_DRAM] &= ~0x7;
|
||||
uint32_t length = ((length_reg & 0xFFF) | 7) + 1;
|
||||
uint32_t skip = (length_reg >> 20) & 0xFF8;
|
||||
unsigned count = ((length_reg >> 12) & 0xFF) + 1;
|
||||
|
||||
// Check length.
|
||||
if (((*rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] & 0xFFF) + length) > 0x1000)
|
||||
@@ -156,7 +203,7 @@ extern "C"
|
||||
|
||||
source += length + skip;
|
||||
dest += length;
|
||||
} while (++i <= count);
|
||||
} while (++i < count);
|
||||
|
||||
*rsp->cp0.cr[CP0_REGISTER_DMA_DRAM] = source;
|
||||
*rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] = dest;
|
||||
@@ -171,14 +218,9 @@ extern "C"
|
||||
static void rsp_dma_write(RSP::CPUState *rsp)
|
||||
{
|
||||
uint32_t length_reg = *rsp->cp0.cr[CP0_REGISTER_DMA_WRITE_LENGTH];
|
||||
uint32_t length = (length_reg & 0xFFF) + 1;
|
||||
uint32_t skip = (length_reg >> 20) & 0xFFF;
|
||||
unsigned count = (length_reg >> 12) & 0xFF;
|
||||
|
||||
// Force alignment.
|
||||
length = (length + 0x7) & ~0x7;
|
||||
*rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] &= ~0x3;
|
||||
*rsp->cp0.cr[CP0_REGISTER_DMA_DRAM] &= ~0x7;
|
||||
uint32_t length = ((length_reg & 0xFFF) | 7) + 1;
|
||||
uint32_t skip = (length_reg >> 20) & 0xFF8;
|
||||
unsigned count = ((length_reg >> 12) & 0xFF) + 1;
|
||||
|
||||
// Check length.
|
||||
if (((*rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] & 0xFFF) + length) > 0x1000)
|
||||
@@ -210,7 +252,7 @@ extern "C"
|
||||
|
||||
source += length;
|
||||
dest += length + skip;
|
||||
} while (++i <= count);
|
||||
} while (++i < count);
|
||||
|
||||
*rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] = source;
|
||||
*rsp->cp0.cr[CP0_REGISTER_DMA_DRAM] = dest;
|
||||
@@ -228,11 +270,11 @@ extern "C"
|
||||
switch (static_cast<CP0Registers>(rd & 15))
|
||||
{
|
||||
case CP0_REGISTER_DMA_CACHE:
|
||||
*rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] = val & 0x1fff;
|
||||
*rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] = val & 0x1ff8;
|
||||
break;
|
||||
|
||||
case CP0_REGISTER_DMA_DRAM:
|
||||
*rsp->cp0.cr[CP0_REGISTER_DMA_DRAM] = val & 0xffffff;
|
||||
*rsp->cp0.cr[CP0_REGISTER_DMA_DRAM] = val & 0xfffff8;
|
||||
break;
|
||||
|
||||
case CP0_REGISTER_DMA_READ_LENGTH:
|
||||
@@ -254,26 +296,34 @@ extern "C"
|
||||
return rsp_status_write(rsp, val);
|
||||
|
||||
case CP0_REGISTER_SP_SEMAPHORE:
|
||||
// Any write to the semaphore register, regardless of value, sets it to 0 for the next read
|
||||
*rsp->cp0.cr[CP0_REGISTER_SP_SEMAPHORE] = 0;
|
||||
break;
|
||||
|
||||
case CP0_REGISTER_CMD_START:
|
||||
#ifdef INTENSE_DEBUG
|
||||
fprintf(stderr, "CMD_START 0x%x\n", val & 0xfffffff8u);
|
||||
fprintf(stderr, "CMD_START 0x%x\n", val & 0xfffff8u);
|
||||
#endif
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_START] = *rsp->cp0.cr[CP0_REGISTER_CMD_CURRENT] =
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_END] = val & 0xfffffff8u;
|
||||
if (!(*rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] & DPC_STATUS_START_VALID))
|
||||
{
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_START] = val & 0xfffff8u;
|
||||
}
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] |= DPC_STATUS_START_VALID;
|
||||
break;
|
||||
|
||||
case CP0_REGISTER_CMD_END:
|
||||
#ifdef INTENSE_DEBUG
|
||||
fprintf(stderr, "CMD_END 0x%x\n", val & 0xfffffff8u);
|
||||
fprintf(stderr, "CMD_END 0x%x\n", val & 0xfffff8u);
|
||||
#endif
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_END] = val & 0xfffffff8u;
|
||||
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_END] = val & 0xfffff8u;
|
||||
if (*rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] & DPC_STATUS_START_VALID)
|
||||
{
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_CURRENT] = *rsp->cp0.cr[CP0_REGISTER_CMD_START];
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] &= ~DPC_STATUS_START_VALID;
|
||||
}
|
||||
#ifdef PARALLEL_INTEGRATION
|
||||
RSP::rsp.ProcessRdpList();
|
||||
if (*rsp->cp0.irq & 0x20)
|
||||
return MODE_EXIT;
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -282,14 +332,7 @@ extern "C"
|
||||
break;
|
||||
|
||||
case CP0_REGISTER_CMD_STATUS:
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] &= ~(!!(val & 0x1) << 0);
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] |= (!!(val & 0x2) << 0);
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] &= ~(!!(val & 0x4) << 1);
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] |= (!!(val & 0x8) << 1);
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] &= ~(!!(val & 0x10) << 2);
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] |= (!!(val & 0x20) << 2);
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_TMEM_BUSY] &= !(val & 0x40) * -1;
|
||||
*rsp->cp0.cr[CP0_REGISTER_CMD_CLOCK] &= !(val & 0x200) * -1;
|
||||
rdp_status_write(rsp, val);
|
||||
break;
|
||||
|
||||
case CP0_REGISTER_CMD_CURRENT:
|
||||
|
||||
+1
-2
@@ -1927,14 +1927,13 @@ ReturnMode CPU::run()
|
||||
{
|
||||
case MODE_BREAK:
|
||||
*state.cp0.cr[CP0_REGISTER_SP_STATUS] |= SP_STATUS_BROKE | SP_STATUS_HALT;
|
||||
if (*state.cp0.cr[CP0_REGISTER_SP_STATUS] & SP_STATUS_INTR_BREAK)
|
||||
*state.cp0.irq |= 1;
|
||||
#ifndef PARALLEL_INTEGRATION
|
||||
print_registers();
|
||||
#endif
|
||||
return MODE_BREAK;
|
||||
|
||||
case MODE_CHECK_FLAGS:
|
||||
case MODE_EXIT:
|
||||
case MODE_DMA_READ:
|
||||
return static_cast<ReturnMode>(ret);
|
||||
|
||||
|
||||
+36
-1
@@ -48,6 +48,31 @@ enum CP0Registers
|
||||
CP0_REGISTER_CMD_TMEM_BUSY = 15,
|
||||
};
|
||||
|
||||
// CMD_STATUS read bits.
|
||||
#define DPC_STATUS_XBUS_DMEM_DMA 0x001
|
||||
#define DPC_STATUS_FREEZE 0x002
|
||||
#define DPC_STATUS_FLUSH 0x004
|
||||
#define DPC_STATUS_START_GCLK 0x008
|
||||
#define DPC_STATUS_TMEM_BUSY 0x010
|
||||
#define DPC_STATUS_PIPE_BUSY 0x020
|
||||
#define DPC_STATUS_CMD_BUSY 0x040
|
||||
#define DPC_STATUS_CBUF_READY 0x080
|
||||
#define DPC_STATUS_DMA_BUSY 0x100
|
||||
#define DPC_STATUS_END_VALID 0x200
|
||||
#define DPC_STATUS_START_VALID 0x400
|
||||
|
||||
// CMD_STATUS write bits.
|
||||
#define DPC_CLR_XBUS_DMEM_DMA 0x001
|
||||
#define DPC_SET_XBUS_DMEM_DMA 0x002
|
||||
#define DPC_CLR_FREEZE 0x004
|
||||
#define DPC_SET_FREEZE 0x008
|
||||
#define DPC_CLR_FLUSH 0x010
|
||||
#define DPC_SET_FLUSH 0x020
|
||||
#define DPC_CLR_TMEM_CTR 0x040
|
||||
#define DPC_CLR_PIPE_CTR 0x080
|
||||
#define DPC_CLR_CMD_CTR 0x100
|
||||
#define DPC_CLR_CLOCK_CTR 0x200
|
||||
|
||||
// SP_STATUS read bits.
|
||||
#define SP_STATUS_HALT 0x0001
|
||||
#define SP_STATUS_BROKE 0x0002
|
||||
@@ -117,6 +142,9 @@ struct alignas(64) CP2
|
||||
struct CPUState
|
||||
{
|
||||
uint32_t pc = 0;
|
||||
uint32_t instruction_count = 0;
|
||||
uint32_t last_instruction_type = 0;
|
||||
uint32_t instruction_pipeline = 0;
|
||||
uint32_t dirty_blocks = 0;
|
||||
static_assert(CODE_BLOCKS <= 32, "Code blocks must fit in 32-bit register.");
|
||||
|
||||
@@ -138,7 +166,14 @@ enum ReturnMode
|
||||
MODE_CONTINUE = 1,
|
||||
MODE_BREAK = 2,
|
||||
MODE_DMA_READ = 3,
|
||||
MODE_CHECK_FLAGS = 4
|
||||
MODE_CHECK_FLAGS = 4,
|
||||
MODE_EXIT = 5
|
||||
};
|
||||
|
||||
enum InstructionType
|
||||
{
|
||||
VU_INSTRUCTION = 0,
|
||||
SU_INSTRUCTION = 1
|
||||
};
|
||||
|
||||
} // namespace RSP
|
||||
|
||||
+1
-1
@@ -288,7 +288,7 @@ extern Config config;
|
||||
|
||||
void Config_LoadConfig();
|
||||
#if defined(M64P_GLIDENUI) || !defined(MUPENPLUSAPI)
|
||||
void Config_DoConfig(/*HWND hParent*/);
|
||||
void Config_DoConfig(void* parent);
|
||||
#endif
|
||||
|
||||
bool isHWLightingAllowed();
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@
|
||||
|
||||
Config config;
|
||||
|
||||
void Config_DoConfig(/*HWND hParent*/)
|
||||
void Config_DoConfig(void* parent)
|
||||
{
|
||||
if (ConfigOpen)
|
||||
return;
|
||||
@@ -27,7 +27,7 @@ void Config_DoConfig(/*HWND hParent*/)
|
||||
ConfigOpen = true;
|
||||
const u32 maxMsaa = dwnd().maxMSAALevel();
|
||||
const u32 maxAnisotropy = dwnd().maxAnisotropy();
|
||||
const bool bRestart = RunConfig(strIniFolderPath, strSharedIniFolderPath, api().isRomOpen() ? RSP.romname : nullptr, maxMsaa, maxAnisotropy);
|
||||
const bool bRestart = RunConfig(parent, strIniFolderPath, strSharedIniFolderPath, api().isRomOpen() ? RSP.romname : nullptr, maxMsaa, maxAnisotropy);
|
||||
if (config.generalEmulation.enableCustomSettings != 0)
|
||||
LoadCustomRomSettings(strIniFolderPath, strSharedIniFolderPath, RSP.romname);
|
||||
config.validate();
|
||||
|
||||
@@ -21,7 +21,7 @@ inline void initMyResource() { Q_INIT_RESOURCE(icon); }
|
||||
inline void cleanMyResource() { Q_CLEANUP_RESOURCE(icon); }
|
||||
|
||||
static
|
||||
int openConfigDialog(const wchar_t * _strFileName, const wchar_t * _strSharedFileName, const char * _romName, unsigned int _maxMSAALevel, float _maxAnisotropy, bool & _accepted)
|
||||
int openConfigDialog(void* parent, const wchar_t * _strFileName, const wchar_t * _strSharedFileName, const char * _romName, unsigned int _maxMSAALevel, float _maxAnisotropy, bool & _accepted)
|
||||
{
|
||||
cleanMyResource();
|
||||
initMyResource();
|
||||
@@ -46,12 +46,20 @@ int openConfigDialog(const wchar_t * _strFileName, const wchar_t * _strSharedFil
|
||||
if (translator.load(getTranslationFile(), strSharedIniFileName))
|
||||
pApp->installTranslator(&translator);
|
||||
|
||||
ConfigDialog w(Q_NULLPTR, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint, _maxMSAALevel, _maxAnisotropy);
|
||||
/* only use parent when we've found an existing qt instance */
|
||||
QWidget* parentWidget = Q_NULLPTR;
|
||||
if (parent && !pQApp)
|
||||
parentWidget = (QWidget*)parent;
|
||||
|
||||
ConfigDialog w(parentWidget, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint, _maxMSAALevel, _maxAnisotropy);
|
||||
|
||||
w.setIniPath(strIniFileName, strSharedIniFileName);
|
||||
w.setRomName(_romName);
|
||||
w.setTitle();
|
||||
w.show();
|
||||
|
||||
if (pQApp) {
|
||||
w.show();
|
||||
}
|
||||
|
||||
int res = pQApp ? pQApp->exec() : w.exec();
|
||||
_accepted = w.isAccepted();
|
||||
@@ -78,13 +86,13 @@ int openAboutDialog(const wchar_t * _strFileName)
|
||||
return a.exec();
|
||||
}
|
||||
|
||||
bool runConfigThread(const wchar_t * _strFileName, const wchar_t * _strSharedFileName, const char * _romName, unsigned int _maxMSAALevel, unsigned int _maxAnisotropy) {
|
||||
bool runConfigThread(void* parent, const wchar_t * _strFileName, const wchar_t * _strSharedFileName, const char * _romName, unsigned int _maxMSAALevel, unsigned int _maxAnisotropy) {
|
||||
bool accepted = false;
|
||||
#ifdef RUN_DIALOG_IN_THREAD
|
||||
std::thread configThread(openConfigDialog, _strFileName, _strSharedFileName, _maxMSAALevel, std::ref(accepted));
|
||||
configThread.join();
|
||||
#else
|
||||
openConfigDialog(_strFileName, _strSharedFileName, _romName, _maxMSAALevel, _maxAnisotropy, accepted);
|
||||
openConfigDialog(parent, _strFileName, _strSharedFileName, _romName, _maxMSAALevel, _maxAnisotropy, accepted);
|
||||
#endif
|
||||
return accepted;
|
||||
|
||||
@@ -100,9 +108,9 @@ int runAboutThread(const wchar_t * _strFileName) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT bool CALL RunConfig(const wchar_t * _strFileName, const wchar_t * _strUserFileName, const char * _romName, unsigned int _maxMSAALevel, unsigned int _maxAnisotropy)
|
||||
EXPORT bool CALL RunConfig(void* parent, const wchar_t * _strFileName, const wchar_t * _strUserFileName, const char * _romName, unsigned int _maxMSAALevel, unsigned int _maxAnisotropy)
|
||||
{
|
||||
return runConfigThread(_strFileName, _strUserFileName, _romName, _maxMSAALevel, _maxAnisotropy);
|
||||
return runConfigThread(parent, _strFileName, _strUserFileName, _romName, _maxMSAALevel, _maxAnisotropy);
|
||||
}
|
||||
|
||||
EXPORT int CALL RunAbout(const wchar_t * _strFileName)
|
||||
|
||||
@@ -13,7 +13,7 @@ extern "C" {
|
||||
#define CALL
|
||||
#endif
|
||||
|
||||
EXPORT bool CALL RunConfig(const wchar_t * _strFileName, const wchar_t * _strSharedFileName, const char * _romName, unsigned int _maxMSAALevel, unsigned int _maxAnisotropy);
|
||||
EXPORT bool CALL RunConfig(void* parent, const wchar_t * _strFileName, const wchar_t * _strSharedFileName, const char * _romName, unsigned int _maxMSAALevel, unsigned int _maxAnisotropy);
|
||||
EXPORT int CALL RunAbout(const wchar_t * _strFileName);
|
||||
EXPORT void CALL LoadConfig(const wchar_t * _strFileName, const wchar_t * _strSharedFileName);
|
||||
EXPORT void CALL LoadCustomRomSettings(const wchar_t * _strFileName, const wchar_t * _strSharedFileName, const char * _romName);
|
||||
|
||||
@@ -36,9 +36,9 @@ EXPORT m64p_error CALL PluginStartup(
|
||||
}
|
||||
|
||||
#ifdef M64P_GLIDENUI
|
||||
EXPORT m64p_error CALL PluginConfig(void)
|
||||
EXPORT m64p_error CALL PluginConfig(void* parent)
|
||||
{
|
||||
return api().PluginConfig();
|
||||
return api().PluginConfig(parent);
|
||||
}
|
||||
#endif // M64P_GLIDENUI
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ public:
|
||||
|
||||
m64p_error PluginStartup(m64p_dynlib_handle _CoreLibHandle, void * Context, void (*DebugCallback)(void *, int, const char *));
|
||||
#ifdef M64P_GLIDENUI
|
||||
m64p_error PluginConfig();
|
||||
m64p_error PluginConfig(void* parent);
|
||||
#endif // M64P_GLIDENUI
|
||||
m64p_error PluginShutdown();
|
||||
m64p_error PluginGetVersion(
|
||||
|
||||
+2
-2
@@ -115,9 +115,9 @@ m64p_error PluginAPI::PluginStartup(m64p_dynlib_handle _CoreLibHandle, void* Con
|
||||
}
|
||||
|
||||
#ifdef M64P_GLIDENUI
|
||||
m64p_error PluginAPI::PluginConfig()
|
||||
m64p_error PluginAPI::PluginConfig(void* parent)
|
||||
{
|
||||
Config_DoConfig();
|
||||
Config_DoConfig(parent);
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
#endif // M64P_GLIDENUI
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ void PluginAPI::CaptureScreen(char * _Directory)
|
||||
|
||||
void PluginAPI::DllConfig(HWND _hParent)
|
||||
{
|
||||
Config_DoConfig(/*_hParent*/);
|
||||
Config_DoConfig(nullptr);
|
||||
}
|
||||
|
||||
void PluginAPI::GetDllInfo(PLUGIN_INFO * PluginInfo)
|
||||
|
||||
+2
-2
@@ -157,14 +157,14 @@ EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *Plugi
|
||||
|
||||
extern "C"
|
||||
{
|
||||
EXPORT m64p_error CALL PluginConfig(void)
|
||||
EXPORT m64p_error CALL PluginConfig(void* parent)
|
||||
{
|
||||
if (!plugin_initialized)
|
||||
{
|
||||
return M64ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
UserInterface::MainDialog dialog(nullptr);
|
||||
UserInterface::MainDialog dialog((QWidget*)parent);
|
||||
dialog.exec();
|
||||
|
||||
return M64ERR_SUCCESS;
|
||||
|
||||
+3
-2
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "m64p_types.h"
|
||||
#include "m64p_config.h"
|
||||
#include "m64p_plugin.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
@@ -253,14 +254,14 @@ EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *Plugi
|
||||
#ifdef CONFIG_GUI
|
||||
extern "C"
|
||||
{
|
||||
EXPORT m64p_error CALL PluginConfig(void)
|
||||
EXPORT m64p_error CALL PluginConfig(void* parent)
|
||||
{
|
||||
if (!plugin_initialized)
|
||||
{
|
||||
return M64ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
UserInterface::MainDialog dialog(nullptr);
|
||||
UserInterface::MainDialog dialog((QWidget*)parent);
|
||||
dialog.exec();
|
||||
|
||||
return M64ERR_SUCCESS;
|
||||
|
||||
+10
-3
@@ -440,7 +440,9 @@ void vk_process_commands()
|
||||
|
||||
// For synchronous RDP:
|
||||
if (vk_synchronous)
|
||||
processor->signal_timeline();
|
||||
{
|
||||
processor->wait_for_timeline(processor->signal_timeline());
|
||||
}
|
||||
|
||||
*gfx.MI_INTR_REG |= DP_INTERRUPT;
|
||||
*GET_GFX_INFO(DPC_STATUS_REG) &= ~(DP_STATUS_PIPE_BUSY | DP_STATUS_START_GCLK);
|
||||
@@ -464,7 +466,8 @@ void vk_resize()
|
||||
|
||||
void vk_destroy()
|
||||
{
|
||||
wsi->end_frame();
|
||||
if (wsi)
|
||||
wsi->end_frame();
|
||||
|
||||
processor.reset();
|
||||
wsi.reset();
|
||||
@@ -495,7 +498,10 @@ bool vk_init()
|
||||
wsi->set_present_mode(window_vsync ? Vulkan::PresentMode::SyncToVBlank : Vulkan::PresentMode::UnlockedMaybeTear);
|
||||
wsi->set_backbuffer_format(Vulkan::BackbufferFormat::UNORM);
|
||||
if (!wsi->init_simple(1, handles))
|
||||
{
|
||||
vk_destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
uintptr_t aligned_rdram = reinterpret_cast<uintptr_t>(gfx.RDRAM);
|
||||
uintptr_t offset = 0;
|
||||
@@ -507,6 +513,7 @@ bool vk_init()
|
||||
|
||||
if (offset)
|
||||
{
|
||||
vk_destroy();
|
||||
return false;
|
||||
}
|
||||
aligned_rdram -= offset;
|
||||
@@ -539,7 +546,7 @@ bool vk_init()
|
||||
offset, rdram_size, rdram_size / 2, flags));
|
||||
if (!processor->device_is_supported())
|
||||
{
|
||||
processor.reset();
|
||||
vk_destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -175,14 +175,14 @@ EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *Plugi
|
||||
|
||||
/* ----------- Custom Functions ------------ */
|
||||
|
||||
EXPORT m64p_error CALL PluginConfig(void)
|
||||
EXPORT m64p_error CALL PluginConfig(void* parent)
|
||||
{
|
||||
if (!l_PluginInit)
|
||||
{
|
||||
return M64ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
UserInterface::MainDialog dialog(nullptr);
|
||||
UserInterface::MainDialog dialog((QWidget*)parent);
|
||||
dialog.exec();
|
||||
|
||||
// apply volume settings
|
||||
|
||||
@@ -334,7 +334,7 @@ void sdl_push_samples(struct sdl_backend* sdl_backend, const void* src, size_t s
|
||||
|
||||
/* truncate to full samples */
|
||||
if (size & 0x3) {
|
||||
DebugMessage(M64MSG_WARNING, "sdl_push_samples: pushing non full samples: %zu bytes !", size);
|
||||
DebugMessage(M64MSG_VERBOSE, "sdl_push_samples: pushing non full samples: %zu bytes !", size);
|
||||
}
|
||||
size = (size / 4) * 4;
|
||||
|
||||
@@ -372,7 +372,7 @@ void sdl_push_samples(struct sdl_backend* sdl_backend, const void* src, size_t s
|
||||
|
||||
if (size > available)
|
||||
{
|
||||
DebugMessage(M64MSG_WARNING, "sdl_push_samples: pushing %zu bytes, but only %zu available !", size, available);
|
||||
DebugMessage(M64MSG_VERBOSE, "sdl_push_samples: pushing %zu bytes, but only %zu available !", size, available);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -436,6 +436,7 @@ bool CoreUnzip(std::filesystem::path file, std::filesystem::path path)
|
||||
std::string error;
|
||||
std::filesystem::path targetPath;
|
||||
std::filesystem::path fileNamePath;
|
||||
std::error_code errorCode;
|
||||
|
||||
unzFile zipFile;
|
||||
unz_global_info zipInfo;
|
||||
@@ -491,20 +492,14 @@ bool CoreUnzip(std::filesystem::path file, std::filesystem::path path)
|
||||
if (fileNamePath.has_filename() &&
|
||||
fileNamePath.has_parent_path())
|
||||
{ // create parent directories
|
||||
try
|
||||
{
|
||||
if (!std::filesystem::is_directory(targetPath.parent_path()) &&
|
||||
!std::filesystem::create_directories(targetPath.parent_path()))
|
||||
{
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
if (!std::filesystem::is_directory(targetPath.parent_path(), errorCode) &&
|
||||
!std::filesystem::create_directories(targetPath.parent_path(), errorCode))
|
||||
{
|
||||
unzClose(zipFile);
|
||||
error = "CoreUnzip: std::filesystem::create_directory(";
|
||||
error += targetPath.string();
|
||||
error += ") Failed!";
|
||||
error += ") Failed: ";
|
||||
error += errorCode.message();
|
||||
CoreSetError(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -131,6 +131,7 @@ static std::filesystem::path get_user_cheat_file_path(CoreRomHeader romHeader, C
|
||||
{
|
||||
std::filesystem::path oldCheatFilePath;
|
||||
std::filesystem::path cheatFilePath;
|
||||
std::error_code errorCode;
|
||||
|
||||
oldCheatFilePath = CoreGetUserDataDirectory();
|
||||
oldCheatFilePath += CORE_DIR_SEPERATOR_STR;
|
||||
@@ -146,16 +147,9 @@ static std::filesystem::path get_user_cheat_file_path(CoreRomHeader romHeader, C
|
||||
|
||||
// try to make the user cheats directory
|
||||
// if it doesn't exist yet
|
||||
try
|
||||
if (!std::filesystem::is_directory(cheatFilePath.parent_path(), errorCode))
|
||||
{
|
||||
if (!std::filesystem::is_directory(cheatFilePath.parent_path()))
|
||||
{
|
||||
std::filesystem::create_directory(cheatFilePath.parent_path());
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// we'll fail later...
|
||||
std::filesystem::create_directory(cheatFilePath.parent_path(), errorCode);
|
||||
}
|
||||
|
||||
// keep compatability with <v0.4.1
|
||||
|
||||
@@ -14,10 +14,11 @@
|
||||
|
||||
#include "m64p/Api.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#include <shlobj.h>
|
||||
@@ -42,6 +43,8 @@ static std::filesystem::path get_exe_directory(void)
|
||||
static std::filesystem::path directory;
|
||||
#ifdef _WIN32
|
||||
wchar_t buffer[MAX_PATH] = {0};
|
||||
#else
|
||||
std::error_code errorCode;
|
||||
#endif // _WIN32
|
||||
|
||||
if (!directory.empty())
|
||||
@@ -57,13 +60,10 @@ static std::filesystem::path get_exe_directory(void)
|
||||
}
|
||||
directory = std::filesystem::path(buffer).parent_path();
|
||||
#else // _WIN32
|
||||
try
|
||||
directory = std::filesystem::canonical("/proc/self/exe", errorCode).parent_path();
|
||||
if (errorCode)
|
||||
{
|
||||
directory = std::filesystem::canonical("/proc/self/exe").parent_path();
|
||||
}
|
||||
catch (...)
|
||||
{ // fail silently and fallback to current path
|
||||
std::cerr << "get_exe_directory: std::filesystem::canonical(\"/proc/self/exe\") threw an exception!" << std::endl;
|
||||
std::cerr << "get_exe_directory: std::filesystem::canonical(\"/proc/self/exe\") failed: " << errorCode.message() << std::endl;
|
||||
std::terminate();
|
||||
}
|
||||
#endif // _WIN32
|
||||
@@ -133,8 +133,9 @@ static std::filesystem::path get_var_directory(std::string var, std::string appe
|
||||
bool CoreCreateDirectories(void)
|
||||
{
|
||||
std::string error;
|
||||
std::error_code errorCode;
|
||||
|
||||
std::filesystem::path directories[] =
|
||||
const std::filesystem::path directories[] =
|
||||
{
|
||||
#ifdef PORTABLE_INSTALL
|
||||
CoreGetCoreDirectory(),
|
||||
@@ -151,15 +152,13 @@ bool CoreCreateDirectories(void)
|
||||
|
||||
for (const std::filesystem::path& directory : directories)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::filesystem::create_directories(directory);
|
||||
}
|
||||
catch (...)
|
||||
if (!std::filesystem::is_directory(directory) &&
|
||||
!std::filesystem::create_directories(directory, errorCode))
|
||||
{
|
||||
error = "CoreCreateDirectories Failed: cannot create the '";
|
||||
error += directory.string();
|
||||
error += "' directory!";
|
||||
error += "' directory: ";
|
||||
error += errorCode.message();
|
||||
CoreSetError(error);
|
||||
return false;
|
||||
}
|
||||
@@ -171,12 +170,11 @@ bool CoreCreateDirectories(void)
|
||||
bool CoreGetPortableDirectoryMode(void)
|
||||
{
|
||||
#ifdef PORTABLE_INSTALL
|
||||
static bool portable_set = false;
|
||||
static bool is_portable = false;
|
||||
static std::optional<bool> portable;
|
||||
|
||||
if (portable_set)
|
||||
if (portable.has_value())
|
||||
{
|
||||
return is_portable;
|
||||
return portable.value();
|
||||
}
|
||||
|
||||
std::filesystem::path exeDirectory;
|
||||
@@ -189,10 +187,9 @@ bool CoreGetPortableDirectoryMode(void)
|
||||
portableFile = exeDirectory;
|
||||
portableFile += "/portable.txt";
|
||||
|
||||
is_portable = std::filesystem::is_regular_file(portableFile) ||
|
||||
std::filesystem::is_regular_file(configFile);
|
||||
portable_set = true;
|
||||
return is_portable;
|
||||
portable = std::filesystem::is_regular_file(portableFile) ||
|
||||
std::filesystem::is_regular_file(configFile);
|
||||
return portable.value();
|
||||
#else // Linux install
|
||||
return false;
|
||||
#endif // PORTABLE_INSTALL
|
||||
|
||||
@@ -73,8 +73,8 @@ static char* medialoader_get_dd_rom(void*)
|
||||
|
||||
static char* medialoader_get_gb_cart_ram(void*, int index)
|
||||
{
|
||||
std::filesystem::path gameBoyRom;
|
||||
SettingsID settingIds[] =
|
||||
std::filesystem::path gameBoySave;
|
||||
const SettingsID settingIds[] =
|
||||
{
|
||||
SettingsID::Core_Gameboy_P1_Save,
|
||||
SettingsID::Core_Gameboy_P2_Save,
|
||||
@@ -82,26 +82,6 @@ static char* medialoader_get_gb_cart_ram(void*, int index)
|
||||
SettingsID::Core_Gameboy_P4_Save,
|
||||
};
|
||||
|
||||
gameBoyRom = CoreSettingsGetStringValue(settingIds[index]);
|
||||
if (gameBoyRom.empty())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return strdup(gameBoyRom.string().c_str());
|
||||
}
|
||||
|
||||
static char* mediaLoader_get_gb_cart_rom(void*, int index)
|
||||
{
|
||||
std::filesystem::path gameBoySave;
|
||||
SettingsID settingIds[] =
|
||||
{
|
||||
SettingsID::Core_Gameboy_P1_Rom,
|
||||
SettingsID::Core_Gameboy_P2_Rom,
|
||||
SettingsID::Core_Gameboy_P3_Rom,
|
||||
SettingsID::Core_Gameboy_P4_Rom,
|
||||
};
|
||||
|
||||
gameBoySave = CoreSettingsGetStringValue(settingIds[index]);
|
||||
if (gameBoySave.empty())
|
||||
{
|
||||
@@ -111,6 +91,26 @@ static char* mediaLoader_get_gb_cart_rom(void*, int index)
|
||||
return strdup(gameBoySave.string().c_str());
|
||||
}
|
||||
|
||||
static char* mediaLoader_get_gb_cart_rom(void*, int index)
|
||||
{
|
||||
std::filesystem::path gameBoyRom;
|
||||
const SettingsID settingIds[] =
|
||||
{
|
||||
SettingsID::Core_Gameboy_P1_Rom,
|
||||
SettingsID::Core_Gameboy_P2_Rom,
|
||||
SettingsID::Core_Gameboy_P3_Rom,
|
||||
SettingsID::Core_Gameboy_P4_Rom,
|
||||
};
|
||||
|
||||
gameBoyRom = CoreSettingsGetStringValue(settingIds[index]);
|
||||
if (gameBoyRom.empty())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return strdup(gameBoyRom.string().c_str());
|
||||
}
|
||||
|
||||
//
|
||||
// Exported Functions
|
||||
//
|
||||
@@ -146,16 +146,12 @@ bool CoreSetupMediaLoader(void)
|
||||
|
||||
void CoreResetMediaLoader(void)
|
||||
{
|
||||
std::error_code errorCode;
|
||||
|
||||
// attempt to remove extracted disk file
|
||||
if (l_HasExtractedDisk && !l_DdRomFile.empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
std::filesystem::remove(l_DdDiskFile);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
std::filesystem::remove(l_DdDiskFile, errorCode);
|
||||
}
|
||||
|
||||
l_HasExtractedDisk = false;
|
||||
@@ -165,6 +161,7 @@ void CoreResetMediaLoader(void)
|
||||
|
||||
void CoreMediaLoaderSetDiskFile(std::filesystem::path disk)
|
||||
{
|
||||
std::error_code error_code;
|
||||
std::vector<char> buf;
|
||||
std::string file_extension;
|
||||
|
||||
@@ -190,19 +187,14 @@ void CoreMediaLoaderSetDiskFile(std::filesystem::path disk)
|
||||
}
|
||||
|
||||
disk = CoreGetUserCacheDirectory();
|
||||
disk += "/extracted_disks/";
|
||||
disk += CORE_DIR_SEPERATOR_STR;
|
||||
disk += "extracted_disks";
|
||||
disk += CORE_DIR_SEPERATOR_STR;
|
||||
disk += extracted_file.filename();
|
||||
|
||||
// attempt to create extraction directory
|
||||
try
|
||||
{
|
||||
if (!std::filesystem::exists(disk.parent_path()) &&
|
||||
!std::filesystem::create_directory(disk.parent_path()))
|
||||
{
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
if (!std::filesystem::is_directory(disk.parent_path(), error_code) &&
|
||||
!std::filesystem::create_directory(disk.parent_path(), error_code))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
+44
-26
@@ -8,9 +8,11 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#define CORE_INTERNAL
|
||||
#include "CachedRomHeaderAndSettings.hpp"
|
||||
#include "Directories.hpp"
|
||||
#include "RomSettings.hpp"
|
||||
#include "Emulation.hpp"
|
||||
#include "RomHeader.hpp"
|
||||
#include "Callback.hpp"
|
||||
#include "Settings.hpp"
|
||||
#include "Library.hpp"
|
||||
@@ -23,14 +25,21 @@
|
||||
#include <filesystem>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <array>
|
||||
|
||||
//
|
||||
// Local Defines
|
||||
//
|
||||
|
||||
#define NUM_PLUGIN_TYPES 4
|
||||
|
||||
//
|
||||
// Local Variables
|
||||
//
|
||||
|
||||
static m64p::PluginApi l_Plugins[(int)CorePluginType::Input];
|
||||
static std::string l_PluginFiles[(int)CorePluginType::Input];
|
||||
static char l_PluginContext[(int)CorePluginType::Input][20];
|
||||
static m64p::PluginApi l_Plugins[NUM_PLUGIN_TYPES];
|
||||
static std::string l_PluginFiles[NUM_PLUGIN_TYPES];
|
||||
static char l_PluginContext[NUM_PLUGIN_TYPES][20];
|
||||
|
||||
//
|
||||
// Local Functions
|
||||
@@ -58,7 +67,8 @@ static CorePluginType get_plugin_type(m64p::PluginApi* plugin)
|
||||
return CorePluginType::Invalid;
|
||||
}
|
||||
|
||||
if (m64p_type < 1 || m64p_type > 4)
|
||||
if (m64p_type < (int)CorePluginType::Rsp ||
|
||||
m64p_type > (int)CorePluginType::Input)
|
||||
{
|
||||
return CorePluginType::Invalid;
|
||||
}
|
||||
@@ -66,7 +76,7 @@ static CorePluginType get_plugin_type(m64p::PluginApi* plugin)
|
||||
return (CorePluginType)m64p_type;
|
||||
}
|
||||
|
||||
static std::string get_plugin_name(m64p::PluginApi* plugin, std::string filename)
|
||||
static std::string get_plugin_name(m64p::PluginApi* plugin, const std::string& filename)
|
||||
{
|
||||
m64p_error ret;
|
||||
const char* name = nullptr;
|
||||
@@ -102,9 +112,6 @@ static std::string get_plugin_type_name(CorePluginType type)
|
||||
case CorePluginType::Input:
|
||||
name = "Input";
|
||||
break;
|
||||
case CorePluginType::Invalid:
|
||||
name = "Invalid";
|
||||
break;
|
||||
}
|
||||
|
||||
return name + " Plugin";
|
||||
@@ -184,7 +191,7 @@ static std::string get_plugin_path(CorePluginType type, std::string settingsValu
|
||||
return path;
|
||||
}
|
||||
|
||||
static bool apply_plugin_settings(std::string pluginSettings[4])
|
||||
static bool apply_plugin_settings(const std::array<std::string, 4>& pluginSettings)
|
||||
{
|
||||
std::string error;
|
||||
std::string settingValue;
|
||||
@@ -193,7 +200,7 @@ static bool apply_plugin_settings(std::string pluginSettings[4])
|
||||
CoreLibraryHandle handle;
|
||||
m64p_error ret;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int i = 0; i < NUM_PLUGIN_TYPES; i++)
|
||||
{
|
||||
pluginType = (CorePluginType)(i + 1);
|
||||
settingValue = get_plugin_path(pluginType, pluginSettings[i]);
|
||||
@@ -301,13 +308,15 @@ static bool apply_plugin_settings(std::string pluginSettings[4])
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool open_plugin_config(CorePluginType type, bool romConfig)
|
||||
static bool open_plugin_config(CorePluginType type, void* parent, bool romConfig, std::filesystem::path file)
|
||||
{
|
||||
std::string error;
|
||||
m64p_error ret;
|
||||
bool resumeEmulation = false;
|
||||
m64p::PluginApi* plugin;
|
||||
std::string functionName;
|
||||
CoreRomHeader romHeader;
|
||||
CoreRomSettings romSettings;
|
||||
|
||||
if (!romConfig && !CorePluginsHasConfig(type))
|
||||
{
|
||||
@@ -337,6 +346,15 @@ static bool open_plugin_config(CorePluginType type, bool romConfig)
|
||||
resumeEmulation = CorePauseEmulation();
|
||||
}
|
||||
|
||||
if (romConfig && !file.empty())
|
||||
{
|
||||
// try to retrieve cached rom header & settings
|
||||
if (!CoreGetCachedRomHeaderAndSettings(file, nullptr, &romHeader, nullptr, &romSettings))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
plugin = get_plugin(type);
|
||||
if (plugin == nullptr)
|
||||
{
|
||||
@@ -352,18 +370,18 @@ static bool open_plugin_config(CorePluginType type, bool romConfig)
|
||||
// has priority
|
||||
if (plugin->Config2 != nullptr)
|
||||
{
|
||||
ret = plugin->Config2(romConfig ? 1 : 0);
|
||||
ret = plugin->Config2(parent, romConfig ? 1 : 0, &romHeader, &romSettings);
|
||||
functionName = "Config2";
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = plugin->Config();
|
||||
ret = plugin->Config(parent);
|
||||
functionName = "Config";
|
||||
}
|
||||
|
||||
if (ret != M64ERR_SUCCESS)
|
||||
{
|
||||
error = "CorePluginsOpenConfig (";
|
||||
error = "open_plugin_config (";
|
||||
error += get_plugin_type_name(type);
|
||||
error += ")->";
|
||||
error += functionName;
|
||||
@@ -432,7 +450,7 @@ std::vector<CorePlugin> CoreGetAllPlugins(void)
|
||||
|
||||
bool CoreApplyPluginSettings(void)
|
||||
{
|
||||
std::string settings[] =
|
||||
const std::array<std::string, 4> settings =
|
||||
{
|
||||
CoreSettingsGetStringValue(SettingsID::Core_RSP_Plugin),
|
||||
CoreSettingsGetStringValue(SettingsID::Core_GFX_Plugin),
|
||||
@@ -445,14 +463,14 @@ bool CoreApplyPluginSettings(void)
|
||||
|
||||
bool CoreApplyRomPluginSettings(void)
|
||||
{
|
||||
CoreRomSettings romSettings;
|
||||
CoreRomSettings romSettings;
|
||||
|
||||
if (!CoreGetCurrentDefaultRomSettings(romSettings))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string settings[] =
|
||||
const std::array<std::string, 4> settings =
|
||||
{
|
||||
CoreSettingsGetStringValue(SettingsID::Game_RSP_Plugin, romSettings.MD5),
|
||||
CoreSettingsGetStringValue(SettingsID::Game_GFX_Plugin, romSettings.MD5),
|
||||
@@ -467,7 +485,7 @@ bool CoreArePluginsReady(void)
|
||||
{
|
||||
std::string error;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int i = 0; i < NUM_PLUGIN_TYPES; i++)
|
||||
{
|
||||
if (!l_Plugins[i].IsHooked())
|
||||
{
|
||||
@@ -502,9 +520,9 @@ bool CorePluginsHasConfig(CorePluginType type)
|
||||
plugin->Config2 != nullptr;
|
||||
}
|
||||
|
||||
bool CorePluginsOpenConfig(CorePluginType type)
|
||||
bool CorePluginsOpenConfig(CorePluginType type, void* parent)
|
||||
{
|
||||
return open_plugin_config(type, false);
|
||||
return open_plugin_config(type, parent, false, "");
|
||||
}
|
||||
|
||||
bool CorePluginsHasROMConfig(CorePluginType type)
|
||||
@@ -518,16 +536,16 @@ bool CorePluginsHasROMConfig(CorePluginType type)
|
||||
plugin->Config2HasRomConfig() > 0;
|
||||
}
|
||||
|
||||
bool CorePluginsOpenROMConfig(CorePluginType type)
|
||||
bool CorePluginsOpenROMConfig(CorePluginType type, void* parent, std::filesystem::path file)
|
||||
{
|
||||
return open_plugin_config(type, true);
|
||||
return open_plugin_config(type, parent, true, file);
|
||||
}
|
||||
|
||||
bool CoreAttachPlugins(void)
|
||||
{
|
||||
std::string error;
|
||||
m64p_error ret;
|
||||
m64p_plugin_type plugin_types[] =
|
||||
const m64p_plugin_type plugin_types[] =
|
||||
{
|
||||
M64PLUGIN_GFX,
|
||||
M64PLUGIN_AUDIO,
|
||||
@@ -540,7 +558,7 @@ bool CoreAttachPlugins(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int i = 0; i < NUM_PLUGIN_TYPES; i++)
|
||||
{
|
||||
ret = m64p::Core.AttachPlugin(plugin_types[i], get_plugin((CorePluginType)plugin_types[i])->GetHandle());
|
||||
if (ret != M64ERR_SUCCESS)
|
||||
@@ -567,7 +585,7 @@ bool CoreDetachPlugins(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int i = 0; i < NUM_PLUGIN_TYPES; i++)
|
||||
{
|
||||
ret = m64p::Core.DetachPlugin((m64p_plugin_type)(i + 1));
|
||||
if (ret != M64ERR_SUCCESS)
|
||||
@@ -590,7 +608,7 @@ bool CorePluginsShutdown(void)
|
||||
m64p::PluginApi* plugin;
|
||||
m64p_error ret;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int i = 0; i < NUM_PLUGIN_TYPES; i++)
|
||||
{
|
||||
plugin = &l_Plugins[i];
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#ifndef CORE_PLUGINS_HPP
|
||||
#define CORE_PLUGINS_HPP
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -50,7 +51,7 @@ bool CorePluginsHasConfig(CorePluginType type);
|
||||
|
||||
// opens the config GUI for the currently
|
||||
// used plugin of given type
|
||||
bool CorePluginsOpenConfig(CorePluginType type);
|
||||
bool CorePluginsOpenConfig(CorePluginType type, void* parent = nullptr);
|
||||
|
||||
// returns wether the currently used plugin
|
||||
// of the given type has a ROM config GUI
|
||||
@@ -58,7 +59,7 @@ bool CorePluginsHasROMConfig(CorePluginType type);
|
||||
|
||||
// opens the ROM config GUI for the currently
|
||||
// used plugin of given type
|
||||
bool CorePluginsOpenROMConfig(CorePluginType type);
|
||||
bool CorePluginsOpenROMConfig(CorePluginType type, void* parent = nullptr, std::filesystem::path file = "");
|
||||
|
||||
// attaches all used plugins
|
||||
bool CoreAttachPlugins(void);
|
||||
|
||||
+9
-19
@@ -41,6 +41,7 @@ static std::filesystem::path l_RomPath;
|
||||
bool CoreOpenRom(std::filesystem::path file)
|
||||
{
|
||||
std::string error;
|
||||
std::error_code error_code;
|
||||
m64p_error ret;
|
||||
std::vector<char> buf;
|
||||
std::string file_extension;
|
||||
@@ -80,20 +81,14 @@ bool CoreOpenRom(std::filesystem::path file)
|
||||
disk_file += extracted_file.filename();
|
||||
|
||||
// attempt to create extraction directory
|
||||
try
|
||||
{
|
||||
if (!std::filesystem::exists(disk_file.parent_path()) &&
|
||||
!std::filesystem::create_directory(disk_file.parent_path()))
|
||||
{
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
if (!std::filesystem::exists(disk_file.parent_path(), error_code) &&
|
||||
!std::filesystem::create_directory(disk_file.parent_path(), error_code))
|
||||
{
|
||||
error = "CoreOpenRom Failed: ";
|
||||
error += "Failed to create \"";
|
||||
error += disk_file.parent_path().string();
|
||||
error += "\"!";
|
||||
error += "\": ";
|
||||
error += error_code.message();
|
||||
CoreSetError(error);
|
||||
return false;
|
||||
}
|
||||
@@ -204,6 +199,7 @@ bool CoreGetRomPath(std::filesystem::path& path)
|
||||
bool CoreCloseRom(void)
|
||||
{
|
||||
std::string error;
|
||||
std::error_code errorCode;
|
||||
m64p_error ret;
|
||||
|
||||
if (!m64p::Core.IsHooked())
|
||||
@@ -255,18 +251,12 @@ bool CoreCloseRom(void)
|
||||
// attempt to clean temporary extracted disk file
|
||||
if (l_HasExtractedDisk)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!std::filesystem::remove(l_ExtractedDiskPath))
|
||||
{
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
if (!std::filesystem::remove(l_ExtractedDiskPath, errorCode))
|
||||
{
|
||||
error = "CoreCloseRom: Failed to remove \"";
|
||||
error += l_ExtractedDiskPath.string();
|
||||
error += "\"!";
|
||||
error += "\": ";
|
||||
error += errorCode.message();
|
||||
CoreSetError(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ bool CoreGetSaveStatePath(CoreRomHeader header, CoreRomSettings settings, int sl
|
||||
|
||||
// retrieve save state directory
|
||||
saveStatePath = CoreGetSaveStateDirectory();
|
||||
saveStatePath += "/";
|
||||
saveStatePath += CORE_DIR_SEPERATOR_STR;
|
||||
|
||||
// construct extension
|
||||
saveStateExtension = ".st";
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Settings.hpp"
|
||||
|
||||
#include "Directories.hpp"
|
||||
#include "String.hpp"
|
||||
#include "Version.hpp"
|
||||
#include "Error.hpp"
|
||||
|
||||
@@ -807,28 +808,28 @@ static l_Setting get_setting(SettingsID settingId)
|
||||
case SettingsID::Input_CButtonRight_ExtraData:
|
||||
setting = {"", "CButtonRight_ExtraData"};
|
||||
break;
|
||||
case SettingsID::Input_LeftTrigger_InputType:
|
||||
case SettingsID::Input_LeftShoulder_InputType:
|
||||
setting = {"", "LeftTrigger_InputType"};
|
||||
break;
|
||||
case SettingsID::Input_LeftTrigger_Name:
|
||||
case SettingsID::Input_LeftShoulder_Name:
|
||||
setting = {"", "LeftTrigger_Name"};
|
||||
break;
|
||||
case SettingsID::Input_LeftTrigger_Data:
|
||||
case SettingsID::Input_LeftShoulder_Data:
|
||||
setting = {"", "LeftTrigger_Data"};
|
||||
break;
|
||||
case SettingsID::Input_LeftTrigger_ExtraData:
|
||||
case SettingsID::Input_LeftShoulder_ExtraData:
|
||||
setting = {"", "LeftTrigger_ExtraData"};
|
||||
break;
|
||||
case SettingsID::Input_RightTrigger_InputType:
|
||||
case SettingsID::Input_RightShoulder_InputType:
|
||||
setting = {"", "RightTrigger_InputType"};
|
||||
break;
|
||||
case SettingsID::Input_RightTrigger_Name:
|
||||
case SettingsID::Input_RightShoulder_Name:
|
||||
setting = {"", "RightTrigger_Name"};
|
||||
break;
|
||||
case SettingsID::Input_RightTrigger_Data:
|
||||
case SettingsID::Input_RightShoulder_Data:
|
||||
setting = {"", "RightTrigger_Data"};
|
||||
break;
|
||||
case SettingsID::Input_RightTrigger_ExtraData:
|
||||
case SettingsID::Input_RightShoulder_ExtraData:
|
||||
setting = {"", "RightTrigger_ExtraData"};
|
||||
break;
|
||||
case SettingsID::Input_ZTrigger_InputType:
|
||||
@@ -1440,7 +1441,7 @@ static bool config_key_exists(std::string section, std::string key)
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::find(l_keyList.begin(), l_keyList.end(), key) != l_keyList.end();;
|
||||
return std::find(l_keyList.begin(), l_keyList.end(), key) != l_keyList.end();
|
||||
}
|
||||
|
||||
static bool config_option_set(std::string section, std::string key, m64p_type type, void *value)
|
||||
@@ -1578,18 +1579,18 @@ static bool string_to_int_list(std::string string, std::vector<int>& intList)
|
||||
// and append list with each item
|
||||
std::stringstream value_str_stream(string);
|
||||
std::string tmp_str;
|
||||
int num;
|
||||
|
||||
while (std::getline(value_str_stream, tmp_str, ';'))
|
||||
{
|
||||
try
|
||||
if (!CoreStringToInt(tmp_str, num))
|
||||
{
|
||||
intList.emplace_back(std::stoi(tmp_str));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
error = "string_to_int_list: std::stroi threw an exception!";
|
||||
error = "string_to_int_list: failed to parse string into integer!";
|
||||
CoreSetError(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
intList.emplace_back(num);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -276,14 +276,14 @@ enum class SettingsID
|
||||
Input_CButtonRight_Name,
|
||||
Input_CButtonRight_Data,
|
||||
Input_CButtonRight_ExtraData,
|
||||
Input_LeftTrigger_InputType,
|
||||
Input_LeftTrigger_Name,
|
||||
Input_LeftTrigger_Data,
|
||||
Input_LeftTrigger_ExtraData,
|
||||
Input_RightTrigger_InputType,
|
||||
Input_RightTrigger_Name,
|
||||
Input_RightTrigger_Data,
|
||||
Input_RightTrigger_ExtraData,
|
||||
Input_LeftShoulder_InputType,
|
||||
Input_LeftShoulder_Name,
|
||||
Input_LeftShoulder_Data,
|
||||
Input_LeftShoulder_ExtraData,
|
||||
Input_RightShoulder_InputType,
|
||||
Input_RightShoulder_Name,
|
||||
Input_RightShoulder_Data,
|
||||
Input_RightShoulder_ExtraData,
|
||||
Input_ZTrigger_InputType,
|
||||
Input_ZTrigger_Name,
|
||||
Input_ZTrigger_Data,
|
||||
|
||||
@@ -22,9 +22,17 @@ std::string CoreLowerString(std::string str)
|
||||
std::transform(resultString.begin(), resultString.end(), resultString.begin(),
|
||||
[](unsigned char c)
|
||||
{
|
||||
return std::tolower(c);
|
||||
return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c;
|
||||
}
|
||||
);
|
||||
|
||||
return resultString;
|
||||
}
|
||||
|
||||
bool CoreStringToInt(std::string str, int& num)
|
||||
{
|
||||
char* endptr;
|
||||
num = (int)std::strtol(str.c_str(), &endptr, 10);
|
||||
return errno != ERANGE && endptr == (str.c_str() + str.size());
|
||||
}
|
||||
|
||||
|
||||
@@ -15,4 +15,7 @@
|
||||
// returns lowercase string
|
||||
std::string CoreLowerString(std::string str);
|
||||
|
||||
// attempts to parse int32_t from string
|
||||
bool CoreStringToInt(std::string str, int& num);
|
||||
|
||||
#endif // CORE_STRING_HPP
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
#define M64P_CUSTOM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <RMG-Core/RomSettings.hpp>
|
||||
#include <RMG-Core/RomHeader.hpp>
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@@ -16,11 +19,14 @@ extern "C" {
|
||||
* https://github.com/mupen64plus/mupen64plus-core/pull/774
|
||||
*
|
||||
*/
|
||||
typedef m64p_error (*ptr_PluginConfig)(void);
|
||||
typedef m64p_error (*ptr_PluginConfig)(void*);
|
||||
#if defined(M64P_PLUGIN_PROTOTYPES) || defined(M64P_CORE_PROTOTYPES)
|
||||
EXPORT m64p_error CALL PluginConfig(void);
|
||||
EXPORT m64p_error CALL PluginConfig(void*);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus // we need C++ for the RMG-Core types
|
||||
|
||||
|
||||
/* PluginConfig2(int romConfig)
|
||||
*
|
||||
* This optional function opens a configuration GUI for the plugin
|
||||
@@ -28,9 +34,9 @@ EXPORT m64p_error CALL PluginConfig(void);
|
||||
*
|
||||
* romConfig argument determines if it should open the ROM specific config
|
||||
*/
|
||||
typedef m64p_error (*ptr_PluginConfig2)(int);
|
||||
typedef m64p_error (*ptr_PluginConfig2)(void*, int, CoreRomHeader*, CoreRomSettings*);
|
||||
#if defined(M64P_PLUGIN_PROTOTYPES) || defined(M64P_CORE_PROTOTYPES)
|
||||
EXPORT m64p_error CALL PluginConfig2(int);
|
||||
EXPORT m64p_error CALL PluginConfig2(void*, int, CoreRomHeader*, CoreRomSettings*);
|
||||
#endif
|
||||
|
||||
/* PluginConfig2HasRomConfig(void)
|
||||
@@ -44,6 +50,8 @@ typedef int (*ptr_PluginConfig2HasRomConfig)(void);
|
||||
EXPORT int CALL PluginConfig2HasRomConfig(void);
|
||||
#endif
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -20,7 +20,7 @@ Q_DECLARE_METATYPE(SDLDevice);
|
||||
|
||||
using namespace UserInterface;
|
||||
|
||||
MainDialog::MainDialog(QWidget* parent, Thread::SDLThread* sdlThread, bool romConfig) : QDialog(parent)
|
||||
MainDialog::MainDialog(QWidget* parent, Thread::SDLThread* sdlThread, bool romConfig, CoreRomHeader romHeader, CoreRomSettings romSettings) : QDialog(parent)
|
||||
{
|
||||
qRegisterMetaType<SDLDevice>();
|
||||
|
||||
@@ -45,7 +45,7 @@ MainDialog::MainDialog(QWidget* parent, Thread::SDLThread* sdlThread, bool romCo
|
||||
for (int i = 0; i < this->tabWidget->count(); i++)
|
||||
{
|
||||
Widget::ControllerWidget* widget = new Widget::ControllerWidget(this, this->eventFilter);
|
||||
widget->SetOnlyLoadGameProfile(romConfig);
|
||||
widget->SetOnlyLoadGameProfile(romConfig, romHeader, romSettings);
|
||||
widget->SetSettingsSection("Player " + QString::number(i + 1), "Rosalie's Mupen GUI - Input Plugin Profile " + QString::number(i));
|
||||
widget->LoadSettings();
|
||||
this->tabWidget->widget(i)->layout()->addWidget(widget);
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
|
||||
#include "ui_MainDialog.h"
|
||||
|
||||
#include <RMG-Core/RomSettings.hpp>
|
||||
#include <RMG-Core/RomHeader.hpp>
|
||||
|
||||
namespace UserInterface
|
||||
{
|
||||
class MainDialog : public QDialog, private Ui::MainDialog
|
||||
@@ -48,7 +51,7 @@ private:
|
||||
void closeInputDevice();
|
||||
|
||||
public:
|
||||
MainDialog(QWidget *parent, Thread::SDLThread*, bool);
|
||||
MainDialog(QWidget *parent, Thread::SDLThread*, bool, CoreRomHeader, CoreRomSettings);
|
||||
~MainDialog(void);
|
||||
|
||||
public slots:
|
||||
|
||||
@@ -105,9 +105,7 @@ void OptionsDialog::on_controllerPakComboBox_currentIndexChanged(int index)
|
||||
|
||||
void OptionsDialog::on_changeGameboyRomButton_clicked()
|
||||
{
|
||||
QString gameBoyRom;
|
||||
gameBoyRom = QFileDialog::getOpenFileName(this, "", "", "Gameboy ROM (*.gb *.gbc)");
|
||||
|
||||
QString gameBoyRom = QFileDialog::getOpenFileName(this, tr("Open Gameboy ROM"), "", "Gameboy ROM (*.gb *.gbc)");
|
||||
if (!gameBoyRom.isEmpty())
|
||||
{
|
||||
this->gameboyRomLineEdit->setText(QDir::toNativeSeparators(gameBoyRom));
|
||||
@@ -116,9 +114,7 @@ void OptionsDialog::on_changeGameboyRomButton_clicked()
|
||||
|
||||
void OptionsDialog::on_changeGameboySaveButton_clicked()
|
||||
{
|
||||
QString gameBoySave;
|
||||
gameBoySave = QFileDialog::getOpenFileName(this, "", "", "Gameboy save (*.sav *.ram)");
|
||||
|
||||
QString gameBoySave = QFileDialog::getOpenFileName(this, tr("Open Gameboy Save"), "", "Gameboy save (*.sav *.ram)");
|
||||
if (!gameBoySave.isEmpty())
|
||||
{
|
||||
this->gameboySaveLineEdit->setText(QDir::toNativeSeparators(gameBoySave));
|
||||
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -13,8 +13,8 @@
|
||||
<file>Resource/Controller_Pressed_CButtonLeft.svg</file>
|
||||
<file>Resource/Controller_Pressed_CButtonRight.svg</file>
|
||||
<file>Resource/Controller_Pressed_Start.svg</file>
|
||||
<file>Resource/Controller_Pressed_LeftTrigger.svg</file>
|
||||
<file>Resource/Controller_Pressed_RightTrigger.svg</file>
|
||||
<file>Resource/Controller_Pressed_LeftShoulder.svg</file>
|
||||
<file>Resource/Controller_Pressed_RightShoulder.svg</file>
|
||||
<file>Resource/Controller_Pressed_ZTrigger.svg</file>
|
||||
<file>Resource/RMG.png</file>
|
||||
</qresource>
|
||||
|
||||
@@ -132,8 +132,8 @@ void ControllerImageWidget::paintEvent(QPaintEvent *event)
|
||||
{ N64ControllerButton::CButtonDown, ":Resource/Controller_Pressed_CButtonDown.svg" },
|
||||
{ N64ControllerButton::CButtonLeft, ":Resource/Controller_Pressed_CButtonLeft.svg" },
|
||||
{ N64ControllerButton::CButtonRight, ":Resource/Controller_Pressed_CButtonRight.svg" },
|
||||
{ N64ControllerButton::LeftTrigger, ":Resource/Controller_Pressed_LeftTrigger.svg" },
|
||||
{ N64ControllerButton::RightTrigger, ":Resource/Controller_Pressed_RightTrigger.svg" },
|
||||
{ N64ControllerButton::LeftShoulder, ":Resource/Controller_Pressed_LeftShoulder.svg" },
|
||||
{ N64ControllerButton::RightShoulder, ":Resource/Controller_Pressed_RightShoulder.svg" },
|
||||
{ N64ControllerButton::ZTrigger, ":Resource/Controller_Pressed_ZTrigger.svg" }
|
||||
};
|
||||
|
||||
|
||||
@@ -59,8 +59,8 @@ ControllerWidget::ControllerWidget(QWidget* parent, EventFilter* eventFilter) :
|
||||
{ N64ControllerButton::CButtonDown, this->cbuttonDownButton },
|
||||
{ N64ControllerButton::CButtonLeft, this->cbuttonLeftButton },
|
||||
{ N64ControllerButton::CButtonRight, this->cbuttonRightButton },
|
||||
{ N64ControllerButton::LeftTrigger, this->leftTriggerButton },
|
||||
{ N64ControllerButton::RightTrigger, this->rightTriggerButton },
|
||||
{ N64ControllerButton::LeftShoulder, this->leftShoulderButton },
|
||||
{ N64ControllerButton::RightShoulder, this->rightShoulderButton },
|
||||
{ N64ControllerButton::ZTrigger, this->zTriggerButton }
|
||||
});
|
||||
|
||||
@@ -85,8 +85,8 @@ ControllerWidget::ControllerWidget(QWidget* parent, EventFilter* eventFilter) :
|
||||
{ this->cbuttonDownButton, SettingsID::Input_CButtonDown_InputType, SettingsID::Input_CButtonDown_Name, SettingsID::Input_CButtonDown_Data, SettingsID::Input_CButtonDown_ExtraData },
|
||||
{ this->cbuttonLeftButton, SettingsID::Input_CButtonLeft_InputType, SettingsID::Input_CButtonLeft_Name, SettingsID::Input_CButtonLeft_Data, SettingsID::Input_CButtonLeft_ExtraData },
|
||||
{ this->cbuttonRightButton, SettingsID::Input_CButtonRight_InputType, SettingsID::Input_CButtonRight_Name, SettingsID::Input_CButtonRight_Data, SettingsID::Input_CButtonRight_ExtraData },
|
||||
{ this->leftTriggerButton, SettingsID::Input_LeftTrigger_InputType, SettingsID::Input_LeftTrigger_Name, SettingsID::Input_LeftTrigger_Data, SettingsID::Input_LeftTrigger_ExtraData },
|
||||
{ this->rightTriggerButton, SettingsID::Input_RightTrigger_InputType, SettingsID::Input_RightTrigger_Name, SettingsID::Input_RightTrigger_Data, SettingsID::Input_RightTrigger_ExtraData },
|
||||
{ this->leftShoulderButton, SettingsID::Input_LeftShoulder_InputType, SettingsID::Input_LeftShoulder_Name, SettingsID::Input_LeftShoulder_Data, SettingsID::Input_LeftShoulder_ExtraData },
|
||||
{ this->rightShoulderButton, SettingsID::Input_RightShoulder_InputType, SettingsID::Input_RightShoulder_Name, SettingsID::Input_RightShoulder_Data, SettingsID::Input_RightShoulder_ExtraData },
|
||||
{ this->zTriggerButton, SettingsID::Input_ZTrigger_InputType, SettingsID::Input_ZTrigger_Name, SettingsID::Input_ZTrigger_Data, SettingsID::Input_ZTrigger_ExtraData },
|
||||
{ this->analogStickUpButton, SettingsID::Input_AnalogStickUp_InputType, SettingsID::Input_AnalogStickUp_Name, SettingsID::Input_AnalogStickUp_Data, SettingsID::Input_AnalogStickUp_ExtraData },
|
||||
{ this->analogStickDownButton, SettingsID::Input_AnalogStickDown_InputType, SettingsID::Input_AnalogStickDown_Name, SettingsID::Input_AnalogStickDown_Data, SettingsID::Input_AnalogStickDown_ExtraData },
|
||||
@@ -154,8 +154,8 @@ ControllerWidget::ControllerWidget(QWidget* parent, EventFilter* eventFilter) :
|
||||
this->cbuttonLeftButton,
|
||||
this->cbuttonRightButton,
|
||||
// triggers
|
||||
this->leftTriggerButton,
|
||||
this->rightTriggerButton,
|
||||
this->leftShoulderButton,
|
||||
this->rightShoulderButton,
|
||||
this->zTriggerButton,
|
||||
// buttons
|
||||
this->aButton,
|
||||
@@ -203,8 +203,8 @@ void ControllerWidget::initializeMappingButtons()
|
||||
{ this->cbuttonLeftButton, this->cbuttonLeftAddButton, this->cbuttonLeftRemoveButton },
|
||||
{ this->cbuttonRightButton, this->cbuttonRightAddButton, this->cbuttonRightRemoveButton },
|
||||
// triggers
|
||||
{ this->leftTriggerButton, this->leftTriggerAddButton, this->leftTriggerRemoveButton },
|
||||
{ this->rightTriggerButton, this->rightTriggerAddButton, this->rightTriggerRemoveButton },
|
||||
{ this->leftShoulderButton, this->leftShoulderAddButton, this->leftShoulderRemoveButton },
|
||||
{ this->rightShoulderButton, this->rightShoulderAddButton, this->rightShoulderRemoveButton },
|
||||
{ this->zTriggerButton, this->zTriggerAddButton, this->zTriggerRemoveButton },
|
||||
// buttons
|
||||
{ this->aButton, this->aAddButton, this->aRemoveButton },
|
||||
@@ -373,8 +373,8 @@ void ControllerWidget::setPluggedIn(bool value)
|
||||
this->cbuttonRightButton, this->cbuttonRightAddButton, this->cbuttonRightRemoveButton,
|
||||
// triggers
|
||||
this->analogStickGroupBox,
|
||||
this->leftTriggerButton, this->leftTriggerAddButton, this->leftTriggerRemoveButton,
|
||||
this->rightTriggerButton, this->rightTriggerAddButton, this->rightTriggerRemoveButton,
|
||||
this->leftShoulderButton, this->leftShoulderAddButton, this->leftShoulderRemoveButton,
|
||||
this->rightShoulderButton, this->rightShoulderAddButton, this->rightShoulderRemoveButton,
|
||||
this->zTriggerButton, this->zTriggerAddButton, this->zTriggerRemoveButton,
|
||||
// buttons
|
||||
this->buttonsGroupBox,
|
||||
@@ -1454,9 +1454,11 @@ bool ControllerWidget::IsPluggedIn()
|
||||
return this->inputDeviceComboBox->currentData().toInt() != (int)InputDeviceType::None;
|
||||
}
|
||||
|
||||
void ControllerWidget::SetOnlyLoadGameProfile(bool value)
|
||||
void ControllerWidget::SetOnlyLoadGameProfile(bool value, CoreRomHeader romHeader, CoreRomSettings romSettings)
|
||||
{
|
||||
this->onlyLoadGameProfile = value;
|
||||
this->gameRomHeader = romHeader;
|
||||
this->gameRomSettings = romSettings;
|
||||
|
||||
// update UI element
|
||||
this->addProfileButton->setDisabled(value);
|
||||
@@ -1496,10 +1498,11 @@ void ControllerWidget::LoadSettings()
|
||||
// try to retrieve the current rom's settings & header,
|
||||
// if that succeeds, we know we're ingame
|
||||
// and then we'll add a game specific profile to the combobox
|
||||
CoreRomSettings romSettings;
|
||||
CoreRomHeader romHeader;
|
||||
if (CoreGetCurrentRomSettings(romSettings) &&
|
||||
CoreGetCurrentRomHeader(romHeader))
|
||||
CoreRomSettings romSettings = this->gameRomSettings;
|
||||
CoreRomHeader romHeader = this->gameRomHeader;
|
||||
if (this->onlyLoadGameProfile ||
|
||||
(CoreGetCurrentRomSettings(romSettings) &&
|
||||
CoreGetCurrentRomHeader(romHeader)))
|
||||
{
|
||||
this->gameSection = section + " Game " + QString::fromStdString(romSettings.MD5);
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ using namespace UserInterface::Widget;
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include <RMG-Core/RomSettings.hpp>
|
||||
#include <RMG-Core/RomHeader.hpp>
|
||||
#include <RMG-Core/Settings.hpp>
|
||||
|
||||
namespace UserInterface
|
||||
@@ -110,6 +112,8 @@ private:
|
||||
int previousProfileComboBoxIndex = -1;
|
||||
|
||||
bool onlyLoadGameProfile = false;
|
||||
CoreRomHeader gameRomHeader;
|
||||
CoreRomSettings gameRomSettings;
|
||||
|
||||
HotkeysDialog* currentHotkeysDialog = nullptr;
|
||||
|
||||
@@ -128,7 +132,7 @@ public:
|
||||
void GetCurrentInputDevice(SDLDevice& device, bool ignoreDeviceNotFound = false);
|
||||
bool IsPluggedIn();
|
||||
|
||||
void SetOnlyLoadGameProfile(bool value);
|
||||
void SetOnlyLoadGameProfile(bool value, CoreRomHeader romHeader, CoreRomSettings romSettings);
|
||||
|
||||
void SetSettingsSection(QString profile, QString section);
|
||||
void SetInitialized(bool value);
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
<enum>QComboBox::SizeAdjustPolicy::AdjustToContents</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -73,7 +73,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -104,7 +104,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
<enum>QComboBox::SizeAdjustPolicy::AdjustToContents</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -127,7 +127,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -158,10 +158,10 @@
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
<enum>QSlider::TickPosition::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>10</number>
|
||||
@@ -178,7 +178,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -193,7 +193,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -625,10 +625,10 @@
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
<enum>QSlider::TickPosition::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>15</number>
|
||||
@@ -641,7 +641,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -663,7 +663,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -678,26 +678,26 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>L-Trigger: </string>
|
||||
<string>L-Shoulder: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MappingButton" name="leftTriggerButton">
|
||||
<widget class="MappingButton" name="leftShoulderButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="AddMappingButton" name="leftTriggerAddButton">
|
||||
<widget class="AddMappingButton" name="leftShoulderAddButton">
|
||||
<property name="text">
|
||||
<string>+</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="RemoveMappingButton" name="leftTriggerRemoveButton">
|
||||
<widget class="RemoveMappingButton" name="leftShoulderRemoveButton">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
@@ -706,7 +706,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -718,31 +718,44 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>R-Trigger: </string>
|
||||
<string>R-Shoulder: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MappingButton" name="rightTriggerButton">
|
||||
<widget class="MappingButton" name="rightShoulderButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="AddMappingButton" name="rightTriggerAddButton">
|
||||
<widget class="AddMappingButton" name="rightShoulderAddButton">
|
||||
<property name="text">
|
||||
<string>+</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="RemoveMappingButton" name="rightTriggerRemoveButton">
|
||||
<widget class="RemoveMappingButton" name="rightShoulderRemoveButton">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
@@ -753,7 +766,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -786,7 +799,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_10">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -834,7 +847,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -882,7 +895,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_11">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -901,7 +914,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -1230,7 +1243,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -1266,7 +1279,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
||||
@@ -189,5 +189,5 @@ void InputDevice::on_SDLThread_DeviceSearchFinished(void)
|
||||
}
|
||||
|
||||
this->isOpeningDevice = false;
|
||||
this->hasOpenDevice = this->joystick != nullptr || this->gameController == nullptr;
|
||||
this->hasOpenDevice = this->joystick != nullptr || this->gameController != nullptr;
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ static bool setup_vosk_model(void)
|
||||
{
|
||||
std::filesystem::path fullFilePath;
|
||||
fullFilePath = CoreGetUserDataDirectory();
|
||||
fullFilePath += "/";
|
||||
fullFilePath += CORE_DIR_SEPERATOR_STR;
|
||||
fullFilePath += file;
|
||||
|
||||
if (!std::filesystem::exists(fullFilePath))
|
||||
|
||||
@@ -27,8 +27,8 @@ enum class N64ControllerButton
|
||||
CButtonDown,
|
||||
CButtonLeft,
|
||||
CButtonRight,
|
||||
LeftTrigger,
|
||||
RightTrigger,
|
||||
LeftShoulder,
|
||||
RightShoulder,
|
||||
ZTrigger,
|
||||
Invalid
|
||||
};
|
||||
|
||||
+12
-10
@@ -111,8 +111,8 @@ struct InputProfile
|
||||
InputMapping Button_CButtonDown;
|
||||
InputMapping Button_CButtonLeft;
|
||||
InputMapping Button_CButtonRight;
|
||||
InputMapping Button_LeftTrigger;
|
||||
InputMapping Button_RightTrigger;
|
||||
InputMapping Button_LeftShoulder;
|
||||
InputMapping Button_RightShoulder;
|
||||
InputMapping Button_ZTrigger;
|
||||
|
||||
// analog stick
|
||||
@@ -342,8 +342,8 @@ static void load_settings(void)
|
||||
LOAD_INPUT_MAPPING(Button_CButtonDown, Input_CButtonDown);
|
||||
LOAD_INPUT_MAPPING(Button_CButtonLeft, Input_CButtonLeft);
|
||||
LOAD_INPUT_MAPPING(Button_CButtonRight, Input_CButtonRight);
|
||||
LOAD_INPUT_MAPPING(Button_LeftTrigger, Input_LeftTrigger);
|
||||
LOAD_INPUT_MAPPING(Button_RightTrigger, Input_RightTrigger);
|
||||
LOAD_INPUT_MAPPING(Button_LeftShoulder, Input_LeftShoulder);
|
||||
LOAD_INPUT_MAPPING(Button_RightShoulder, Input_RightShoulder);
|
||||
LOAD_INPUT_MAPPING(Button_ZTrigger, Input_ZTrigger);
|
||||
LOAD_INPUT_MAPPING(AnalogStick_Up, Input_AnalogStickUp);
|
||||
LOAD_INPUT_MAPPING(AnalogStick_Down, Input_AnalogStickDown);
|
||||
@@ -706,7 +706,7 @@ static double get_axis_state(InputProfile* profile, const InputMapping* inputMap
|
||||
{
|
||||
case InputType::GamepadButton:
|
||||
{
|
||||
button_state |= SDL_GameControllerGetButton(profile->InputDevice.GetGameControllerHandle(), (SDL_GameControllerButton)data);;
|
||||
button_state |= SDL_GameControllerGetButton(profile->InputDevice.GetGameControllerHandle(), (SDL_GameControllerButton)data);
|
||||
} break;
|
||||
case InputType::GamepadAxis:
|
||||
{
|
||||
@@ -721,7 +721,7 @@ static double get_axis_state(InputProfile* profile, const InputMapping* inputMap
|
||||
} break;
|
||||
case InputType::JoystickButton:
|
||||
{
|
||||
button_state |= SDL_JoystickGetButton(profile->InputDevice.GetJoystickHandle(), data);;
|
||||
button_state |= SDL_JoystickGetButton(profile->InputDevice.GetJoystickHandle(), data);
|
||||
} break;
|
||||
case InputType::JoystickHat:
|
||||
{
|
||||
@@ -1086,7 +1086,7 @@ void PluginDebugMessage(int level, std::string message)
|
||||
// Custom Plugin Functions
|
||||
//
|
||||
|
||||
EXPORT m64p_error CALL PluginConfig2(int romConfig)
|
||||
EXPORT m64p_error CALL PluginConfig2(void* parent, int romConfig, CoreRomHeader* romHeader, CoreRomSettings* romSettings)
|
||||
{
|
||||
if (l_SDLThread == nullptr)
|
||||
{
|
||||
@@ -1100,7 +1100,7 @@ EXPORT m64p_error CALL PluginConfig2(int romConfig)
|
||||
|
||||
l_SDLThread->SetAction(SDLThreadAction::SDLPumpEvents);
|
||||
|
||||
UserInterface::MainDialog dialog(nullptr, l_SDLThread, romConfig);
|
||||
UserInterface::MainDialog dialog((QWidget*)parent, l_SDLThread, romConfig, *romHeader, *romSettings);
|
||||
dialog.exec();
|
||||
|
||||
// when PluginShutdown() is called during PluginConfig2(),
|
||||
@@ -1232,6 +1232,7 @@ EXPORT void CALL GetKeys(int Control, BUTTONS* Keys)
|
||||
}
|
||||
#endif // VRU
|
||||
|
||||
#if 0 // TODO: fix hotplug support
|
||||
// check if device has been disconnected,
|
||||
// if it has, try to open it again,
|
||||
// only do this every 2 seconds to prevent lag
|
||||
@@ -1254,6 +1255,7 @@ EXPORT void CALL GetKeys(int Control, BUTTONS* Keys)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// when we've matched a hotkey,
|
||||
// we don't need to check anything
|
||||
@@ -1274,8 +1276,8 @@ EXPORT void CALL GetKeys(int Control, BUTTONS* Keys)
|
||||
Keys->D_CBUTTON = get_button_state(profile, &profile->Button_CButtonDown);
|
||||
Keys->L_CBUTTON = get_button_state(profile, &profile->Button_CButtonLeft);
|
||||
Keys->R_CBUTTON = get_button_state(profile, &profile->Button_CButtonRight);
|
||||
Keys->L_TRIG = get_button_state(profile, &profile->Button_LeftTrigger);
|
||||
Keys->R_TRIG = get_button_state(profile, &profile->Button_RightTrigger);
|
||||
Keys->L_TRIG = get_button_state(profile, &profile->Button_LeftShoulder);
|
||||
Keys->R_TRIG = get_button_state(profile, &profile->Button_RightShoulder);
|
||||
Keys->Z_TRIG = get_button_state(profile, &profile->Button_ZTrigger);
|
||||
|
||||
double inputX = 0, inputY = 0;
|
||||
|
||||
@@ -7,6 +7,10 @@ set(CMAKE_AUTOUIC ON)
|
||||
|
||||
find_package(Qt6 COMPONENTS Gui Widgets Core REQUIRED)
|
||||
|
||||
if (NOT WIN32)
|
||||
find_package(Qt6 REQUIRED COMPONENTS DBus)
|
||||
endif(NOT WIN32)
|
||||
|
||||
if (PORTABLE_INSTALL)
|
||||
add_definitions(-DPORTABLE_INSTALL)
|
||||
endif(PORTABLE_INSTALL)
|
||||
@@ -144,6 +148,10 @@ target_include_directories(RMG PRIVATE
|
||||
|
||||
target_link_libraries(RMG Qt6::Gui Qt6::Widgets)
|
||||
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(RMG Qt6::DBus)
|
||||
endif(NOT WIN32)
|
||||
|
||||
if (UPDATER)
|
||||
target_link_libraries(RMG Qt6::Network)
|
||||
endif(UPDATER)
|
||||
|
||||
@@ -8,9 +8,17 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "EmulationThread.hpp"
|
||||
|
||||
#include <RMG-Core/Emulation.hpp>
|
||||
#include <RMG-Core/Error.hpp>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else // Linux
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusReply>
|
||||
#endif
|
||||
|
||||
using namespace Thread;
|
||||
|
||||
EmulationThread::EmulationThread(QObject *parent) : QThread(parent)
|
||||
@@ -48,26 +56,64 @@ void EmulationThread::SetNetplay(QString address, int port, int player)
|
||||
|
||||
void EmulationThread::run(void)
|
||||
{
|
||||
this->inhibitScreensaver();
|
||||
|
||||
emit this->on_Emulation_Started();
|
||||
|
||||
bool ret = CoreStartEmulation(this->rom.toStdU32String(), this->disk.toStdU32String(),
|
||||
this->address.toStdString(), this->port, this->player);
|
||||
if (!ret)
|
||||
{
|
||||
this->errorMessage = QString::fromStdString(CoreGetError());
|
||||
}
|
||||
|
||||
// reset state
|
||||
emit this->on_Emulation_Finished(ret, QString::fromStdString(CoreGetError()));
|
||||
|
||||
this->resetState();
|
||||
this->uninhibitScreensaver();
|
||||
}
|
||||
|
||||
void EmulationThread::resetState(void)
|
||||
{
|
||||
this->rom.clear();
|
||||
this->disk.clear();
|
||||
this->address.clear();
|
||||
this->port = -1;
|
||||
this->port = -1;
|
||||
this->player = -1;
|
||||
|
||||
emit this->on_Emulation_Finished(ret);
|
||||
}
|
||||
|
||||
QString EmulationThread::GetLastError(void)
|
||||
void EmulationThread::inhibitScreensaver(void)
|
||||
{
|
||||
return this->errorMessage;
|
||||
#ifdef _WIN32
|
||||
SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
|
||||
#else
|
||||
this->dbusCookieId = 0;
|
||||
this->dbusInterface = new QDBusInterface("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver", "org.freedesktop.ScreenSaver", QDBusConnection::sessionBus());
|
||||
if (!this->dbusInterface->isValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QDBusReply<uint32_t> dbusReply = this->dbusInterface->call("Inhibit", "RMG", "game");
|
||||
if (dbusReply.isValid())
|
||||
{
|
||||
this->dbusCookieId = dbusReply.value();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void EmulationThread::uninhibitScreensaver(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SetThreadExecutionState(ES_CONTINUOUS);
|
||||
#else
|
||||
if (this->dbusInterface == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->dbusCookieId != 0)
|
||||
{
|
||||
this->dbusInterface->call("UnInhibit", this->dbusCookieId);
|
||||
}
|
||||
|
||||
this->dbusInterface->deleteLater();
|
||||
this->dbusInterface = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -10,8 +10,11 @@
|
||||
#ifndef EMULATIONTHREAD_HPP
|
||||
#define EMULATIONTHREAD_HPP
|
||||
|
||||
#include <QString>
|
||||
#ifndef _WIN32
|
||||
#include <QDBusInterface>
|
||||
#endif
|
||||
#include <QSurfaceFormat>
|
||||
#include <QString>
|
||||
#include <QThread>
|
||||
|
||||
enum class VidExtRenderMode
|
||||
@@ -37,19 +40,24 @@ class EmulationThread : public QThread
|
||||
|
||||
void run(void) override;
|
||||
|
||||
QString GetLastError(void);
|
||||
|
||||
private:
|
||||
QString rom;
|
||||
QString disk;
|
||||
QString address;
|
||||
int port = -1;
|
||||
int player = -1;
|
||||
QString errorMessage;
|
||||
#ifndef _WIN32
|
||||
uint32_t dbusCookieId = 0;
|
||||
QDBusInterface* dbusInterface = nullptr;
|
||||
#endif
|
||||
|
||||
void resetState(void);
|
||||
void inhibitScreensaver(void);
|
||||
void uninhibitScreensaver(void);
|
||||
|
||||
signals:
|
||||
void on_Emulation_Started(void);
|
||||
void on_Emulation_Finished(bool);
|
||||
void on_Emulation_Finished(bool ret, QString error);
|
||||
|
||||
void on_VidExt_SetupOGL(QSurfaceFormat, QThread *);
|
||||
void on_VidExt_ResizeWindow(int, int);
|
||||
|
||||
@@ -21,11 +21,19 @@ LogDialog::LogDialog(QWidget *parent) : QDialog(parent)
|
||||
this->setWindowIcon(QIcon(":Resource/RMG.png"));
|
||||
this->setWindowFlags(this->windowFlags() | Qt::WindowMinimizeButtonHint);
|
||||
|
||||
QFont font("monospace");
|
||||
try
|
||||
{ // for some reason on Windows 10 for some users,
|
||||
// ->setFont() will crash in DwriteCreateFactory,
|
||||
// so catch the exception and do nothing
|
||||
QFont font("monospace");
|
||||
#ifdef _WIN32
|
||||
font.setStyleHint(QFont::TypeWriter);
|
||||
font.setStyleHint(QFont::TypeWriter);
|
||||
#endif
|
||||
this->plainTextEdit->setFont(font);
|
||||
this->plainTextEdit->setFont(font);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
LogDialog::~LogDialog(void)
|
||||
|
||||
@@ -300,7 +300,7 @@ void SettingsDialog::loadCoreSettings(void)
|
||||
randomizeInterrupt = CoreSettingsGetBoolValue(SettingsID::CoreOverlay_RandomizeInterrupt);
|
||||
usePIFROM = CoreSettingsGetBoolValue(SettingsID::Core_PIF_Use);
|
||||
ntscPifROM = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::Core_PIF_NTSC));
|
||||
palPifRom = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::Core_PIF_PAL));;
|
||||
palPifRom = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::Core_PIF_PAL));
|
||||
overrideGameSettings = CoreSettingsGetBoolValue(SettingsID::Core_OverrideGameSpecificSettings);
|
||||
|
||||
this->coreCpuEmulatorComboBox->setCurrentIndex(cpuEmulator);
|
||||
@@ -475,7 +475,9 @@ void SettingsDialog::loadInterfaceGeneralSettings(void)
|
||||
// find stylesheets and add them to the UI
|
||||
QString directory;
|
||||
directory = QString::fromStdString(CoreGetSharedDataDirectory().string());
|
||||
directory += "/Styles/";
|
||||
directory += CORE_DIR_SEPERATOR_STR;
|
||||
directory += "Styles";
|
||||
directory += CORE_DIR_SEPERATOR_STR;
|
||||
|
||||
QStringList filter;
|
||||
filter << "*.qss";
|
||||
@@ -579,7 +581,7 @@ void SettingsDialog::loadDefaultCoreSettings(void)
|
||||
randomizeInterrupt = CoreSettingsGetDefaultBoolValue(SettingsID::CoreOverlay_RandomizeInterrupt);
|
||||
usePIFROM = CoreSettingsGetDefaultBoolValue(SettingsID::Core_PIF_Use);
|
||||
ntscPifROM = QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::Core_PIF_NTSC));
|
||||
palPifRom = QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::Core_PIF_PAL));;
|
||||
palPifRom = QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::Core_PIF_PAL));
|
||||
overrideGameSettings = CoreSettingsGetDefaultBoolValue(SettingsID::Core_OverrideGameSpecificSettings);
|
||||
|
||||
this->coreCpuEmulatorComboBox->setCurrentIndex(cpuEmulator);
|
||||
@@ -1250,11 +1252,9 @@ void SettingsDialog::hideEmulationInfoText(void)
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::chooseDirectory(QLineEdit *lineEdit)
|
||||
void SettingsDialog::chooseDirectory(QLineEdit *lineEdit, QString caption)
|
||||
{
|
||||
QString dir;
|
||||
|
||||
dir = QFileDialog::getExistingDirectory(this);
|
||||
QString dir = QFileDialog::getExistingDirectory(this, caption);
|
||||
if (dir.isEmpty())
|
||||
{
|
||||
return;
|
||||
@@ -1263,11 +1263,9 @@ void SettingsDialog::chooseDirectory(QLineEdit *lineEdit)
|
||||
lineEdit->setText(QDir::toNativeSeparators(dir));
|
||||
}
|
||||
|
||||
void SettingsDialog::chooseFile(QLineEdit *lineEdit, QString filter, QString md5)
|
||||
void SettingsDialog::chooseFile(QLineEdit *lineEdit, QString caption, QString filter, QString md5)
|
||||
{
|
||||
QString file;
|
||||
|
||||
file = QFileDialog::getOpenFileName(this, "", "", filter);
|
||||
QString file = QFileDialog::getOpenFileName(this, caption, "", filter);
|
||||
if (file.isEmpty())
|
||||
{
|
||||
return;
|
||||
@@ -1404,42 +1402,42 @@ void SettingsDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
|
||||
void SettingsDialog::on_changeScreenShotDirButton_clicked(void)
|
||||
{
|
||||
this->chooseDirectory(this->screenshotDirLineEdit);
|
||||
this->chooseDirectory(this->screenshotDirLineEdit, tr("Select Screenshot Directory"));
|
||||
}
|
||||
|
||||
void SettingsDialog::on_changeSaveStateDirButton_clicked(void)
|
||||
{
|
||||
this->chooseDirectory(this->saveStateDirLineEdit);
|
||||
this->chooseDirectory(this->saveStateDirLineEdit, tr("Select Save (State) Directory"));
|
||||
}
|
||||
|
||||
void SettingsDialog::on_changeSaveSramDirButton_clicked(void)
|
||||
{
|
||||
this->chooseDirectory(this->saveSramDirLineEdit);
|
||||
this->chooseDirectory(this->saveSramDirLineEdit, tr("Select Save (SRAM) Directory"));
|
||||
}
|
||||
|
||||
void SettingsDialog::on_changeUserDataDirButton_clicked(void)
|
||||
{
|
||||
this->chooseDirectory(this->userDataDirLineEdit);
|
||||
this->chooseDirectory(this->userDataDirLineEdit, tr("Select User Data Directory"));
|
||||
}
|
||||
|
||||
void SettingsDialog::on_changeUserCacheDirButton_clicked(void)
|
||||
{
|
||||
this->chooseDirectory(this->userCacheDirLineEdit);
|
||||
this->chooseDirectory(this->userCacheDirLineEdit, tr("Select User Cache Directory"));
|
||||
}
|
||||
|
||||
void SettingsDialog::on_changeJapaneseIPLRomPathButton_clicked(void)
|
||||
{
|
||||
this->chooseFile(this->japaneseIPLRomLineEdit, "IPL ROMs (*.n64 *.v64 *.z64)");
|
||||
this->chooseFile(this->japaneseIPLRomLineEdit, tr("Open Japanese Retail 64DD IPL"), "IPL ROMs (*.n64)");
|
||||
}
|
||||
|
||||
void SettingsDialog::on_changeAmericanIPLRomPathButton_clicked(void)
|
||||
{
|
||||
this->chooseFile(this->americanIPLRomLineEdit, "IPL ROMs (*.n64 *.v64 *.z64)");
|
||||
this->chooseFile(this->americanIPLRomLineEdit, tr("Open American Retail 64DD IPL"), "IPL ROMs (*.n64)");
|
||||
}
|
||||
|
||||
void SettingsDialog::on_changeDevelopmentIPLRomPathButton_clicked(void)
|
||||
{
|
||||
this->chooseFile(this->developmentIPLRomLineEdit, "IPL ROMs (*.n64 *.v64 *.z64)");
|
||||
this->chooseFile(this->developmentIPLRomLineEdit, tr("Open Japanese Development 64DD IPL"), "IPL ROMs (*.n64)");
|
||||
}
|
||||
|
||||
void SettingsDialog::on_changeBackgroundColorButton_clicked(void)
|
||||
@@ -1600,10 +1598,10 @@ void SettingsDialog::on_coreCpuEmulatorComboBox_currentIndexChanged(int index)
|
||||
|
||||
void SettingsDialog::on_changeNTSCPifRomButton_clicked(void)
|
||||
{
|
||||
this->chooseFile(this->ntscPifRomLineEdit, "PIF ROMs (*.rom)", "5c124e7948ada85da603a522782940d0");
|
||||
this->chooseFile(this->ntscPifRomLineEdit, tr("Open NTSC PIF ROM"), "PIF ROMs (*.rom)", "5c124e7948ada85da603a522782940d0");
|
||||
}
|
||||
|
||||
void SettingsDialog::on_changePALPifRomButton_clicked(void)
|
||||
{
|
||||
this->chooseFile(this->palPifRomLineEdit, "PIF ROMs (*.rom)", "d4232dc935cad0650ac2664d52281f3a");
|
||||
this->chooseFile(this->palPifRomLineEdit, tr("Open PAL PIF ROM"), "PIF ROMs (*.rom)", "d4232dc935cad0650ac2664d52281f3a");
|
||||
}
|
||||
|
||||
@@ -126,8 +126,8 @@ class SettingsDialog : public QDialog, private Ui::SettingsDialog
|
||||
void setIconsForEmulationInfoText(void);
|
||||
void hideEmulationInfoText(void);
|
||||
|
||||
void chooseDirectory(QLineEdit *);
|
||||
void chooseFile(QLineEdit *, QString filter = "", QString md5 = "");
|
||||
void chooseDirectory(QLineEdit *, QString caption);
|
||||
void chooseFile(QLineEdit *, QString caption, QString filter = "", QString md5 = "");
|
||||
void chooseColor(QPushButton *, QColor *, bool skipChoice = false);
|
||||
|
||||
bool applyPluginSettings(void);
|
||||
|
||||
@@ -254,11 +254,8 @@ void MainWindow::configureUI(QApplication* app, bool showUI)
|
||||
{
|
||||
this->setCentralWidget(this->ui_Widgets);
|
||||
|
||||
QString geometry;
|
||||
bool maximized;
|
||||
|
||||
geometry = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::RomBrowser_Geometry));
|
||||
maximized = CoreSettingsGetBoolValue(SettingsID::RomBrowser_Maximized);
|
||||
QString geometry = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::RomBrowser_Geometry));
|
||||
bool maximized = CoreSettingsGetBoolValue(SettingsID::RomBrowser_Maximized);
|
||||
if (maximized)
|
||||
{
|
||||
this->showMaximized();
|
||||
@@ -378,7 +375,9 @@ void MainWindow::configureTheme(QApplication* app)
|
||||
{
|
||||
QString themePath;
|
||||
themePath = QString::fromStdString(CoreGetSharedDataDirectory().string());
|
||||
themePath += "/Styles/";
|
||||
themePath += CORE_DIR_SEPERATOR_STR;
|
||||
themePath += "Styles";
|
||||
themePath += CORE_DIR_SEPERATOR_STR;
|
||||
themePath += theme;
|
||||
|
||||
// use Fusion as a base for the stylesheet
|
||||
@@ -1392,7 +1391,7 @@ void MainWindow::on_EventFilter_FileDropped(QDropEvent *event)
|
||||
|
||||
bool inEmulation = (this->ui_Widgets->currentIndex() != 0);
|
||||
bool confirmDragDrop = CoreSettingsGetBoolValue(SettingsID::GUI_ConfirmDragDrop);
|
||||
bool refreshRomList = false;
|
||||
bool refreshRomList = false;
|
||||
QString file;
|
||||
|
||||
if (inEmulation && confirmDragDrop)
|
||||
@@ -1526,10 +1525,7 @@ void MainWindow::on_Action_System_OpenRom(void)
|
||||
this->on_Action_System_Pause();
|
||||
}
|
||||
|
||||
QString romFile;
|
||||
|
||||
romFile = QFileDialog::getOpenFileName(this, "", "", "N64 ROMs & Disks (*.n64 *.z64 *.v64 *.ndd *.d64 *.zip *.7z)");
|
||||
|
||||
QString romFile = QFileDialog::getOpenFileName(this, tr("Open N64 ROM or 64DD Disk"), "", "N64 ROMs & Disks (*.n64 *.z64 *.v64 *.ndd *.d64 *.zip *.7z)");
|
||||
if (romFile.isEmpty())
|
||||
{
|
||||
if (isRunning && !isPaused)
|
||||
@@ -1557,10 +1553,7 @@ void MainWindow::on_Action_System_OpenCombo(void)
|
||||
this->on_Action_System_Pause();
|
||||
}
|
||||
|
||||
QString cartRom, diskRom;
|
||||
|
||||
cartRom = QFileDialog::getOpenFileName(this, "", "", "N64 ROMs (*.n64 *.z64 *.v64 *.zip *.7z)");
|
||||
|
||||
QString cartRom = QFileDialog::getOpenFileName(this, tr("Open N64 ROM"), "", "N64 ROMs (*.n64 *.z64 *.v64 *.zip *.7z)");
|
||||
if (cartRom.isEmpty())
|
||||
{
|
||||
if (isRunning && !isPaused)
|
||||
@@ -1571,8 +1564,7 @@ void MainWindow::on_Action_System_OpenCombo(void)
|
||||
}
|
||||
|
||||
|
||||
diskRom = QFileDialog::getOpenFileName(this, "", "", "N64DD Disk Image (*.ndd *.d64)");
|
||||
|
||||
QString diskRom = QFileDialog::getOpenFileName(this, tr("Open 64DD Disk"), "", "N64DD Disk Image (*.ndd *.d64 *.zip *.7z)");
|
||||
if (diskRom.isEmpty())
|
||||
{
|
||||
if (isRunning && !isPaused)
|
||||
@@ -1670,13 +1662,9 @@ void MainWindow::on_Action_System_Screenshot(void)
|
||||
|
||||
void MainWindow::on_Action_System_LimitFPS(void)
|
||||
{
|
||||
bool enabled, ret;
|
||||
bool enabled = this->action_System_LimitFPS->isChecked();
|
||||
|
||||
enabled = this->action_System_LimitFPS->isChecked();
|
||||
|
||||
ret = CoreSetSpeedLimiterState(enabled);
|
||||
|
||||
if (!ret)
|
||||
if (!CoreSetSpeedLimiterState(enabled))
|
||||
{
|
||||
this->showErrorMessage("CoreSetSpeedLimiterState() Failed", QString::fromStdString(CoreGetError()));
|
||||
}
|
||||
@@ -1716,7 +1704,6 @@ void MainWindow::on_Action_System_SaveAs(void)
|
||||
}
|
||||
|
||||
QString fileName = QFileDialog::getSaveFileName(this, tr("Save State"), "", tr("Save State (*.state);;Project64 Save State (*.pj);;All Files (*)"));
|
||||
|
||||
if (!fileName.isEmpty())
|
||||
{
|
||||
this->ui_ManuallySavedState = true;
|
||||
@@ -1836,22 +1823,22 @@ void MainWindow::on_Action_System_GSButton(void)
|
||||
|
||||
void MainWindow::on_Action_Settings_Graphics(void)
|
||||
{
|
||||
CorePluginsOpenConfig(CorePluginType::Gfx);
|
||||
CorePluginsOpenConfig(CorePluginType::Gfx, (void*)this);
|
||||
}
|
||||
|
||||
void MainWindow::on_Action_Settings_Audio(void)
|
||||
{
|
||||
CorePluginsOpenConfig(CorePluginType::Audio);
|
||||
CorePluginsOpenConfig(CorePluginType::Audio, (void*)this);
|
||||
}
|
||||
|
||||
void MainWindow::on_Action_Settings_Rsp(void)
|
||||
{
|
||||
CorePluginsOpenConfig(CorePluginType::Rsp);
|
||||
CorePluginsOpenConfig(CorePluginType::Rsp, (void*)this);
|
||||
}
|
||||
|
||||
void MainWindow::on_Action_Settings_Input(void)
|
||||
{
|
||||
CorePluginsOpenConfig(CorePluginType::Input);
|
||||
CorePluginsOpenConfig(CorePluginType::Input, (void*)this);
|
||||
}
|
||||
|
||||
void MainWindow::on_Action_Settings_Settings(void)
|
||||
@@ -2045,7 +2032,7 @@ void MainWindow::on_Emulation_Started(void)
|
||||
this->ui_DebugCallbackErrors.clear();
|
||||
}
|
||||
|
||||
void MainWindow::on_Emulation_Finished(bool ret)
|
||||
void MainWindow::on_Emulation_Finished(bool ret, QString error)
|
||||
{
|
||||
if (!ret)
|
||||
{
|
||||
@@ -2095,7 +2082,7 @@ void MainWindow::on_Emulation_Finished(bool ret)
|
||||
// after switching back to the ROM browser
|
||||
if (!ret)
|
||||
{
|
||||
this->showErrorMessage("EmulationThread::run Failed", this->emulationThread->GetLastError());
|
||||
this->showErrorMessage("EmulationThread::run Failed", error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2112,11 +2099,11 @@ void MainWindow::on_RomBrowser_PlayGameWith(CoreRomType type, QString file)
|
||||
if (type == CoreRomType::Cartridge)
|
||||
{ // cartridge
|
||||
mainRom = file;
|
||||
otherRom = QFileDialog::getOpenFileName(this, "", "", "N64DD Disk Image (*.ndd *.d64 *.zip *.7z)");
|
||||
otherRom = QFileDialog::getOpenFileName(this, tr("Open 64DD Disk"), "", "N64DD Disk Image (*.ndd *.d64 *.zip *.7z)");
|
||||
}
|
||||
else
|
||||
{ // disk
|
||||
mainRom = QFileDialog::getOpenFileName(this, "", "", "N64 ROMs (*.n64 *.z64 *.v64 *.zip *.7z)");
|
||||
mainRom = QFileDialog::getOpenFileName(this, tr("Open N64 ROM"), "", "N64 ROMs (*.n64 *.z64 *.v64 *.zip *.7z)");
|
||||
otherRom = file;
|
||||
}
|
||||
|
||||
@@ -2140,10 +2127,7 @@ void MainWindow::on_RomBrowser_PlayGameWithSlot(QString file, int slot)
|
||||
|
||||
void MainWindow::on_RomBrowser_ChangeRomDirectory(void)
|
||||
{
|
||||
QString dir;
|
||||
|
||||
dir = QFileDialog::getExistingDirectory(this);
|
||||
|
||||
QString dir = QFileDialog::getExistingDirectory(this, tr("Select ROM Directory"));
|
||||
if (!dir.isEmpty())
|
||||
{
|
||||
CoreSettingsSetValue(SettingsID::RomBrowser_Directory, dir.toStdString());
|
||||
@@ -2154,7 +2138,6 @@ void MainWindow::on_RomBrowser_ChangeRomDirectory(void)
|
||||
void MainWindow::on_RomBrowser_RomInformation(QString file)
|
||||
{
|
||||
bool isRefreshingRomList = this->ui_Widget_RomBrowser->IsRefreshingRomList();
|
||||
|
||||
if (isRefreshingRomList)
|
||||
{
|
||||
this->ui_Widget_RomBrowser->StopRefreshRomList();
|
||||
@@ -2207,17 +2190,9 @@ void MainWindow::on_RomBrowser_EditGameInputSettings(QString file)
|
||||
this->ui_Widget_RomBrowser->StopRefreshRomList();
|
||||
}
|
||||
|
||||
if (!CoreOpenRom(file.toStdU32String()))
|
||||
if (!CorePluginsOpenROMConfig(CorePluginType::Input, (void*)this, file.toStdU32String()))
|
||||
{
|
||||
this->showErrorMessage("CoreOpenRom() Failed", QString::fromStdString(CoreGetError()));
|
||||
return;
|
||||
}
|
||||
|
||||
CorePluginsOpenROMConfig(CorePluginType::Input);
|
||||
|
||||
if (!CoreCloseRom())
|
||||
{
|
||||
this->showErrorMessage("CoreCloseRom() Failed", QString::fromStdString(CoreGetError()));
|
||||
this->showErrorMessage("CorePluginsOpenROMConfig() Failed", QString::fromStdString(CoreGetError()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -224,7 +224,7 @@ class MainWindow : public QMainWindow, private Ui::MainWindow
|
||||
void on_Action_Audio_ToggleVolumeMute(void);
|
||||
|
||||
void on_Emulation_Started(void);
|
||||
void on_Emulation_Finished(bool ret);
|
||||
void on_Emulation_Finished(bool ret, QString error);
|
||||
|
||||
void on_RomBrowser_PlayGame(QString file);
|
||||
void on_RomBrowser_PlayGameWith(CoreRomType type, QString file);
|
||||
|
||||
@@ -177,8 +177,8 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent)
|
||||
this->contextMenu = new QMenu(this);
|
||||
this->action_PlayGame = new QAction(this);
|
||||
this->action_PlayGameWith = new QAction(this);
|
||||
this->menu_PlayGameWithDisk = new QMenu(this);
|
||||
this->menu_PlayGameWithSlot = new QMenu(this);
|
||||
this->menu_PlayGameWithDisk = new QMenu(this->contextMenu);
|
||||
this->menu_PlayGameWithSlot = new QMenu(this->contextMenu);
|
||||
this->action_RefreshRomList = new QAction(this);
|
||||
this->action_OpenRomDirectory = new QAction(this);
|
||||
this->action_ChangeRomDirectory = new QAction(this);
|
||||
@@ -191,7 +191,7 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent)
|
||||
this->action_RemoveCoverImage = new QAction(this);
|
||||
|
||||
// define columns menu and its contents
|
||||
this->menu_Columns = new QMenu(this);
|
||||
this->menu_Columns = new QMenu(this->contextMenu);
|
||||
this->action_ColumnsMenuEntry = new QAction(this);
|
||||
|
||||
// configure context menu contents
|
||||
@@ -270,7 +270,8 @@ void RomBrowserWidget::RefreshRomList(void)
|
||||
this->menu_PlayGameWithDisk->clear();
|
||||
|
||||
this->coversDirectory = QString::fromStdString(CoreGetUserDataDirectory().string());
|
||||
this->coversDirectory += "/Covers";
|
||||
this->coversDirectory += CORE_DIR_SEPERATOR_STR;
|
||||
this->coversDirectory += "Covers";
|
||||
|
||||
this->listViewSortSection = CoreSettingsGetIntValue(SettingsID::RomBrowser_ListViewSortSection);
|
||||
this->listViewSortOrder = CoreSettingsGetIntValue(SettingsID::RomBrowser_ListViewSortOrder);
|
||||
@@ -583,7 +584,7 @@ QIcon RomBrowserWidget::getCurrentCover(QString file, CoreRomHeader header, Core
|
||||
for (QString ext : { ".png", ".jpg", ".jpeg" })
|
||||
{
|
||||
QString coverPath = this->coversDirectory;
|
||||
coverPath += "/";
|
||||
coverPath += CORE_DIR_SEPERATOR_STR;
|
||||
coverPath += fixedName;
|
||||
coverPath += ext;
|
||||
|
||||
@@ -1159,7 +1160,7 @@ void RomBrowserWidget::on_Action_SetCoverImage(void)
|
||||
|
||||
// construct new file name (for the cover)
|
||||
QString newFileName = this->coversDirectory;
|
||||
newFileName += "/";
|
||||
newFileName += CORE_DIR_SEPERATOR_STR;
|
||||
newFileName += QString::fromStdString(data.settings.MD5);
|
||||
newFileName += ".";
|
||||
newFileName += sourceFileInfo.suffix();
|
||||
|
||||
+15
-4
@@ -55,7 +55,14 @@ static bool VidExt_OglSetup(void)
|
||||
|
||||
if (!(*l_OGLWidget)->GetContext()->isValid())
|
||||
{
|
||||
CoreAddCallbackMessage(CoreDebugMessageType::Error, "Failed to retrieve valid OpenGL context");
|
||||
if (QSurfaceFormat::defaultFormat().renderableType() == QSurfaceFormat::OpenGLES)
|
||||
{
|
||||
CoreAddCallbackMessage(CoreDebugMessageType::Error, "Failed to retrieve valid OpenGL ES context");
|
||||
}
|
||||
else
|
||||
{
|
||||
CoreAddCallbackMessage(CoreDebugMessageType::Error, "Failed to retrieve valid OpenGL context");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -445,14 +452,18 @@ static m64p_error VidExt_VK_GetInstanceExtensions(const char** Extensions[], uin
|
||||
l_VulkanExtensions = l_VulkanInstance.supportedExtensions();
|
||||
l_VulkanExtensionList.clear();
|
||||
|
||||
// add every extension to the string list
|
||||
// only add surface extensions
|
||||
for (int i = 0; i < l_VulkanExtensions.size(); i++)
|
||||
{
|
||||
l_VulkanExtensionList.append(l_VulkanExtensions[i].name.data());
|
||||
if (l_VulkanExtensions[i].name.startsWith("VK_KHR_") &&
|
||||
l_VulkanExtensions[i].name.endsWith("surface"))
|
||||
{
|
||||
l_VulkanExtensionList.append(l_VulkanExtensions[i].name.data());
|
||||
}
|
||||
}
|
||||
|
||||
*Extensions = l_VulkanExtensionList.data();
|
||||
*NumExtensions = l_VulkanExtensions.size();
|
||||
*NumExtensions = l_VulkanExtensionList.size();
|
||||
return M64ERR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ do
|
||||
copyForOBJ "$file"
|
||||
done
|
||||
|
||||
windeployqt-qt6 --exclude-plugins qpdf,qwebp,qgif,qjpeg,qtga,qtuiotouchplugin,qglib,qtiff,qmng,qwbmp,qjp2 \
|
||||
windeployqt-qt6 --exclude-plugins qpdf,qwebp,qgif,qtga,qtuiotouchplugin,qglib,qtiff,qmng,qwbmp \
|
||||
--no-translations "$exe"
|
||||
|
||||
# needed by Qt at runtime
|
||||
|
||||
Reference in New Issue
Block a user