mirror of
https://github.com/DerKoun/bsnes-hd.git
synced 2025-04-02 10:52:49 -04:00
Compare commits
10 commits
Author | SHA1 | Date | |
---|---|---|---|
|
0bb7b8645e | ||
|
4723fd00ca | ||
|
f46b6d6368 | ||
|
587e496f66 | ||
|
04821703ae | ||
|
65f24e56c3 | ||
|
03cd4e11f1 | ||
|
711a1e5b9c | ||
|
0fd18e0f57 | ||
|
de27b9ea85 |
28 changed files with 2444 additions and 579 deletions
47
.github/workflows/CI.yml
vendored
47
.github/workflows/CI.yml
vendored
|
@ -57,7 +57,7 @@ jobs:
|
||||||
- name: Setup
|
- name: Setup
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get -y install build-essential libgtk2.0-dev libpulse-dev mesa-common-dev libgtksourceview2.0-dev libcairo2-dev libsdl2-dev libxv-dev libao-dev libopenal-dev libudev-dev
|
sudo apt-get -y install build-essential libgtk2.0-dev libpulse-dev mesa-common-dev libcairo2-dev libsdl2-dev libxv-dev libao-dev libopenal-dev libudev-dev
|
||||||
- name: Build
|
- name: Build
|
||||||
run: make -j $(nproc) -C bsnes
|
run: make -j $(nproc) -C bsnes
|
||||||
- name: Prepare artifacts
|
- name: Prepare artifacts
|
||||||
|
@ -85,7 +85,7 @@ jobs:
|
||||||
- name: Setup
|
- name: Setup
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get -y install build-essential libgtk2.0-dev libpulse-dev mesa-common-dev libgtksourceview2.0-dev libcairo2-dev libsdl2-dev libxv-dev libao-dev libopenal-dev libudev-dev
|
sudo apt-get -y install build-essential libgtk2.0-dev libpulse-dev mesa-common-dev libcairo2-dev libsdl2-dev libxv-dev libao-dev libopenal-dev libudev-dev
|
||||||
- name: Build
|
- name: Build
|
||||||
run: make -j $(nproc) -C bsnes target=libretro
|
run: make -j $(nproc) -C bsnes target=libretro
|
||||||
- name: Prepare artifacts
|
- name: Prepare artifacts
|
||||||
|
@ -101,6 +101,49 @@ jobs:
|
||||||
path: bsnes/out/pack
|
path: bsnes/out/pack
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
|
Linux-ARM-libretro:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: add foreign arch
|
||||||
|
run: |
|
||||||
|
sudo dpkg --add-architecture arm64
|
||||||
|
sudo rm -rf /etc/apt/sources.list
|
||||||
|
echo "deb [arch=amd64] http://us.archive.ubuntu.com/ubuntu focal main restricted" | sudo tee -a /etc/apt/sources.list
|
||||||
|
echo "deb [arch=amd64] http://us.archive.ubuntu.com/ubuntu focal-updates main restricted" | sudo tee -a /etc/apt/sources.list
|
||||||
|
echo "deb [arch=amd64] http://us.archive.ubuntu.com/ubuntu focal universe" | sudo tee -a /etc/apt/sources.list
|
||||||
|
echo "deb [arch=amd64] http://us.archive.ubuntu.com/ubuntu focal-updates universe" | sudo tee -a /etc/apt/sources.list
|
||||||
|
echo "deb [arch=amd64] http://us.archive.ubuntu.com/ubuntu focal multiverse" | sudo tee -a /etc/apt/sources.list
|
||||||
|
echo "deb [arch=amd64] http://us.archive.ubuntu.com/ubuntu focal-updates multiverse" | sudo tee -a /etc/apt/sources.list
|
||||||
|
echo "deb [arch=amd64] http://us.archive.ubuntu.com/ubuntu focal-backports main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list
|
||||||
|
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports focal main restricted" | sudo tee -a /etc/apt/sources.list
|
||||||
|
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports focal-updates main restricted" | sudo tee -a /etc/apt/sources.list
|
||||||
|
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports focal universe" | sudo tee -a /etc/apt/sources.list
|
||||||
|
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports focal-updates universe" | sudo tee -a /etc/apt/sources.list
|
||||||
|
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports focal multiverse" | sudo tee -a /etc/apt/sources.list
|
||||||
|
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports focal-updates multiverse" | sudo tee -a /etc/apt/sources.list
|
||||||
|
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports focal-backports main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list
|
||||||
|
- name: Install needed packages
|
||||||
|
run: sudo apt update && sudo apt install wget:amd64 git:amd64 build-essential:amd64 gcc:amd64 make:amd64 g++-aarch64-linux-gnu:amd64 gcc-aarch64-linux-gnu:amd64 binutils-aarch64-linux-gnu:amd64 libx11-dev:arm64 libxext-dev:arm64
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
make -j $(nproc) -C bsnes target=libretro compiler=/usr/bin/aarch64-linux-gnu-g++
|
||||||
|
wget https://raw.githubusercontent.com/libretro/libretro-super/master/retrolink.sh && chmod +x retrolink.sh && ./retrolink.sh bsnes/out/bsnes_hd_beta_libretro.so
|
||||||
|
- name: Prepare artifacts
|
||||||
|
run: |
|
||||||
|
mkdir bsnes/out/pack
|
||||||
|
cp README.md bsnes/out/pack
|
||||||
|
cp LICENSE bsnes/out/pack
|
||||||
|
cp -R bsnes/out/*bsnes* bsnes/out/pack
|
||||||
|
- name: Upload artifacts
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: bsnes_hd_beta_X_linux_arm_libretro
|
||||||
|
path: bsnes/out/pack
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
macOS:
|
macOS:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
|
|
|
@ -143,7 +143,7 @@ libretro-build-osx-arm64:
|
||||||
- .libretro-osx-arm64-make-default
|
- .libretro-osx-arm64-make-default
|
||||||
- .core-defs-osx
|
- .core-defs-osx
|
||||||
script:
|
script:
|
||||||
- make -C ${MAKEFILE_PATH} -f ${MAKEFILE} -j$NUMPROC platform=macos target=libretro binary=library local=false openmp=false compiler="c++ -std=c++17 -stdlib=libc++ -target arm64-apple-macos10.15 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"
|
- make -C ${MAKEFILE_PATH} -f ${MAKEFILE} -j$NUMPROC platform=macos target=libretro binary=library local=false openmp=false compiler="c++ -std=c++17 -stdlib=libc++ -target ${LIBRETRO_APPLE_PLATFORM} -isysroot $(xcodebuild -version -sdk macosx Path)"
|
||||||
|
|
||||||
################################### CELLULAR #################################
|
################################### CELLULAR #################################
|
||||||
# Android ARMv7a
|
# Android ARMv7a
|
||||||
|
|
34
README.md
34
README.md
|
@ -1,4 +1,6 @@
|
||||||
# bsnes-hd *beta 10.5*
|
2021-06-18: Vitor's Super Mario World widescreen patch is available: https://github.com/VitorVilela7/wide-snes#download
|
||||||
|
|
||||||
|
# bsnes-hd *beta 10.6*
|
||||||
|
|
||||||
- [downloads](https://github.com/DerKoun/bsnes-hd/releases) for the latest betas (there are only beta) / also on the libretro auto-updater
|
- [downloads](https://github.com/DerKoun/bsnes-hd/releases) for the latest betas (there are only beta) / also on the libretro auto-updater
|
||||||
- [GitHub project](https://github.com/DerKoun/bsnes-hd) for source code, issues, feature requests, ...
|
- [GitHub project](https://github.com/DerKoun/bsnes-hd) for source code, issues, feature requests, ...
|
||||||
|
@ -19,8 +21,8 @@ bsnes-hd (called "*HD Mode 7 mod, for bsnes*" in early betas) is a fork of bsnes
|
||||||
### HD Mode 7
|
### HD Mode 7
|
||||||
|
|
||||||
Rendering the rotated, scaled or pseudo perspective backgrounds at higher resolutions. This does not involve new custom imagery or upscaling algorithms. It is a higher resolution version of the process the SNES uses.
|
Rendering the rotated, scaled or pseudo perspective backgrounds at higher resolutions. This does not involve new custom imagery or upscaling algorithms. It is a higher resolution version of the process the SNES uses.
|
||||||
- [image comparison](http://www.framecompare.com/image-compare/screenshotcomparison/EB9MNNNU) (framecompare)
|
|
||||||
- [video comparison](https://www.youtube.com/watch?v=6VrzJ6Y1kjQ) by *reznoire* (youtube)
|
- [video comparison](https://www.youtube.com/watch?v=6VrzJ6Y1kjQ) by *reznoire* (youtube)
|
||||||
|
- [video demo](https://www.youtube.com/watch?v=IW7VOQKxtUQ) by *Emulators & Gameplay HD* (youtube)
|
||||||
|
|
||||||
### Widescreen
|
### Widescreen
|
||||||
|
|
||||||
|
@ -193,18 +195,22 @@ The file must contain alternating letters and numbers, each pair overriding a se
|
||||||
|
|
||||||
#### Settings
|
#### Settings
|
||||||
|
|
||||||
| Description | Letter | Values |
|
| Description | Letter | Values |
|
||||||
| ----------------------------------- | ------- | ----------------------------------------------- |
|
| ----------------------------------- | ------- | ------------------------------------------------ |
|
||||||
| widescreen mode | w | 0:off 1:on(always) 2:on(mode7) |
|
| widescreen mode | w | 0:off 1:on(always) 2:on(mode7) |
|
||||||
| widescreen sprites | s | 0:safe 1:unsafe(widescreen) 2:clip |
|
| widescreen sprites | s | 0:safe 1:unsafe(widescreen) 2:clip |
|
||||||
| widescreen aspect ratio | W | 0-200:widescreen-extension 201+:AR(*see below*) |
|
| widescreen aspect ratio | W | 0-200:widescreen-extension 201+:AR (*see below*) |
|
||||||
| widescreen background 1/2/3/4 | b/B/c/C | 0+:WS 10+:crop 20:disab 1000+:line(*see below*) |
|
| widescreen background 1/2/3/4 | b/B/c/C | 0+:WS 10+:crop 20:disab 1000+:line (*see below*) |
|
||||||
| widescreen marker | m | 0:off 1+:line 11+:darken (*see below*) |
|
| widescreen marker | m | 0:off 1+:line 11+:darken (*see below*) |
|
||||||
| mode 7 perspective correction | P | 0:off 1-3:auto 4-6+:on (*see below*) |
|
| mode 7 perspective correction | P | 0:off 1-3:auto 4-6+:on (*see below*) |
|
||||||
| ignore window | i | 0:none 1:outside 2:outside&always 3:all |
|
| scale factor | f | 0:off 1-10:factor |
|
||||||
| ignore window fallback x-coordinate | I | 0-255:x-coordinate |
|
| disable sprite limit | l | 0:off 1:on |
|
||||||
| overclock CPU | O | 100+:percentage(100 is normal) |
|
| ignore window | i | 0:none 1:outside 2:outside&always 3:all |
|
||||||
| stretch windowing | S | (*for widescreen patches only*, *see below*) |
|
| ignore window fallback x-coordinate | I | 0-255:x-coordinate |
|
||||||
|
| overclock CPU | O | 100+:percentage(100 is normal) |
|
||||||
|
| stretch windowing | S | (*for widescreen patches only*, *see below*) |
|
||||||
|
| pixel aspect ratio correction | p | 0:off 1:on (*libretro only*) |
|
||||||
|
| overscan | o | 0:off(216 / 5th HD) 1:on(224) (*libretro only*) |
|
||||||
|
|
||||||
#### Widescreen Aspect Ratio values
|
#### Widescreen Aspect Ratio values
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "bsnes-hd beta";
|
static const string Name = "bsnes-hd beta";
|
||||||
static const string Version = "10.5";//bsnes/target-bsnes/presentation/presentation.cpp:create:about:setVersion
|
static const string Version = "10.6";//bsnes/target-bsnes/presentation/presentation.cpp:create:about:setVersion
|
||||||
static const string Author = "DerKoun(Near)";
|
static const string Author = "DerKoun(Near)";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "https://github.com/DerKoun/bsnes-hd";
|
static const string Website = "https://github.com/DerKoun/bsnes-hd";
|
||||||
|
|
|
@ -433,13 +433,7 @@ auto SuperFamicom::serial() const -> string {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFamicom::romSize() const -> uint {
|
auto SuperFamicom::romSize() const -> uint {
|
||||||
//subtract appended firmware size, if firmware is present
|
return size() - firmwareRomSize();
|
||||||
if((size() & 0x7fff) == 0x100) return size() - 0x100;
|
|
||||||
if((size() & 0x7fff) == 0xc00) return size() - 0xc00;
|
|
||||||
if((size() & 0x7fff) == 0x2000) return size() - 0x2000;
|
|
||||||
if((size() & 0xffff) == 0xd000) return size() - 0xd000;
|
|
||||||
if((size() & 0x3ffff) == 0x28000) return size() - 0x28000;
|
|
||||||
return size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFamicom::programRomSize() const -> uint {
|
auto SuperFamicom::programRomSize() const -> uint {
|
||||||
|
@ -459,8 +453,38 @@ auto SuperFamicom::expansionRomSize() const -> uint {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//detect if any firmware is appended to the ROM image, and return its size if so
|
||||||
auto SuperFamicom::firmwareRomSize() const -> uint {
|
auto SuperFamicom::firmwareRomSize() const -> uint {
|
||||||
return size() - romSize();
|
auto cartridgeTypeLo = data[headerAddress + 0x26] & 15;
|
||||||
|
auto cartridgeTypeHi = data[headerAddress + 0x26] >> 4;
|
||||||
|
auto cartridgeSubType = data[headerAddress + 0x0f];
|
||||||
|
|
||||||
|
if(serial() == "042J" || (cartridgeTypeLo == 0x3 && cartridgeTypeHi == 0xe)) {
|
||||||
|
//Game Boy
|
||||||
|
if((size() & 0x7fff) == 0x100) return 0x100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cartridgeTypeLo >= 0x3 && cartridgeTypeHi == 0xf && cartridgeSubType == 0x10) {
|
||||||
|
//Hitachi HG51BS169
|
||||||
|
if((size() & 0x7fff) == 0xc00) return 0xc00;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cartridgeTypeLo >= 0x3 && cartridgeTypeHi == 0x0) {
|
||||||
|
//NEC uPD7725
|
||||||
|
if((size() & 0x7fff) == 0x2000) return 0x2000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cartridgeTypeLo >= 0x3 && cartridgeTypeHi == 0xf && cartridgeSubType == 0x01) {
|
||||||
|
//NEC uPD96050
|
||||||
|
if((size() & 0xffff) == 0xd000) return 0xd000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cartridgeTypeLo >= 0x3 && cartridgeTypeHi == 0xf && cartridgeSubType == 0x02) {
|
||||||
|
//ARM6
|
||||||
|
if((size() & 0x3ffff) == 0x28000) return 0x28000;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFamicom::ramSize() const -> uint {
|
auto SuperFamicom::ramSize() const -> uint {
|
||||||
|
|
|
@ -43,6 +43,7 @@ auto Configuration::process(Markup::Node document, bool load) -> void {
|
||||||
bind(natural, "Hacks/PPU/Mode7/Igwin", hacks.ppu.mode7.igwin);
|
bind(natural, "Hacks/PPU/Mode7/Igwin", hacks.ppu.mode7.igwin);
|
||||||
bind(natural, "Hacks/PPU/Mode7/Igwinx", hacks.ppu.mode7.igwinx);
|
bind(natural, "Hacks/PPU/Mode7/Igwinx", hacks.ppu.mode7.igwinx);
|
||||||
bind(boolean, "Hacks/PPU/Mode7/Strwin", hacks.ppu.mode7.strwin);
|
bind(boolean, "Hacks/PPU/Mode7/Strwin", hacks.ppu.mode7.strwin);
|
||||||
|
bind(natural, "Hacks/PPU/Mode7/VramExt", hacks.ppu.mode7.vramExt);
|
||||||
bind(natural, "Hacks/PPU/Mode7/BgGrad", hacks.ppu.mode7.bgGrad);
|
bind(natural, "Hacks/PPU/Mode7/BgGrad", hacks.ppu.mode7.bgGrad);
|
||||||
bind(natural, "Hacks/PPU/Mode7/WindRad", hacks.ppu.mode7.windRad);
|
bind(natural, "Hacks/PPU/Mode7/WindRad", hacks.ppu.mode7.windRad);
|
||||||
bind(natural, "Hacks/PPU/Mode7/WsMode", hacks.ppu.mode7.wsMode);
|
bind(natural, "Hacks/PPU/Mode7/WsMode", hacks.ppu.mode7.wsMode);
|
||||||
|
|
|
@ -58,6 +58,7 @@ struct Configuration {
|
||||||
uint igwin = 1;
|
uint igwin = 1;
|
||||||
uint igwinx = 128;
|
uint igwinx = 128;
|
||||||
bool strwin = false;
|
bool strwin = false;
|
||||||
|
uint vramExt = 0x7fff;
|
||||||
uint bgGrad = 4;
|
uint bgGrad = 4;
|
||||||
uint windRad = 0;
|
uint windRad = 0;
|
||||||
uint wsMode = 1;
|
uint wsMode = 1;
|
||||||
|
|
|
@ -115,7 +115,7 @@ auto PPU::Line::renderBackground(PPU::IO::Background& self, uint8 source) -> voi
|
||||||
tileNumber = (tileNumber & 0x03ff) + tiledataIndex & tileMask;
|
tileNumber = (tileNumber & 0x03ff) + tiledataIndex & tileMask;
|
||||||
|
|
||||||
uint16 address;
|
uint16 address;
|
||||||
address = (tileNumber << colorShift) + (voffset & 7 ^ mirrorY) & 0x7fff;
|
address = ppu.vramExt((tileNumber << colorShift) + (voffset & 7 ^ mirrorY)) /*& 0x7fff*/;
|
||||||
|
|
||||||
uint64 data;
|
uint64 data;
|
||||||
data = (uint64)ppu.vram[address + 0] << 0;
|
data = (uint64)ppu.vram[address + 0] << 0;
|
||||||
|
@ -196,5 +196,5 @@ auto PPU::Line::getTile(PPU::IO::Background& self, uint hoffset, uint voffset) -
|
||||||
uint offset = (tileY & 0x1f) << 5 | (tileX & 0x1f);
|
uint offset = (tileY & 0x1f) << 5 | (tileX & 0x1f);
|
||||||
if(tileX & 0x20) offset += screenX;
|
if(tileX & 0x20) offset += screenX;
|
||||||
if(tileY & 0x20) offset += screenY;
|
if(tileY & 0x20) offset += screenY;
|
||||||
return ppu.vram[self.screenAddress + offset & 0x7fff];
|
return ppu.vram[ppu.vramExt(self.screenAddress + offset) /*& 0x7fff*/];
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,10 @@ auto PPU::latchCounters() -> void {
|
||||||
auto PPU::vramAddress() const -> uint {
|
auto PPU::vramAddress() const -> uint {
|
||||||
uint address = io.vramAddress;
|
uint address = io.vramAddress;
|
||||||
switch(io.vramMapping) {
|
switch(io.vramMapping) {
|
||||||
case 0: return address & 0x7fff;
|
case 0: return ppu.vramExt(address & 0xffff /*0x7fff*/);
|
||||||
case 1: return address & 0x7f00 | address << 3 & 0x00f8 | address >> 5 & 7;
|
case 1: return ppu.vramExt(address & 0xff00 /*0x7f00*/| address << 3 & 0x00f8 | address >> 5 & 7);
|
||||||
case 2: return address & 0x7e00 | address << 3 & 0x01f8 | address >> 6 & 7;
|
case 2: return ppu.vramExt(address & 0xfe00 /*0x7e00*/| address << 3 & 0x01f8 | address >> 6 & 7);
|
||||||
case 3: return address & 0x7c00 | address << 3 & 0x03f8 | address >> 7 & 7;
|
case 3: return ppu.vramExt(address & 0xfc00 /*0x7c00*/| address << 3 & 0x03f8 | address >> 7 & 7);
|
||||||
}
|
}
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
@ -263,37 +263,37 @@ auto PPU::writeIO(uint address, uint8 data) -> void {
|
||||||
|
|
||||||
case 0x2107: { //BG1SC
|
case 0x2107: { //BG1SC
|
||||||
io.bg1.screenSize = data >> 0 & 3;
|
io.bg1.screenSize = data >> 0 & 3;
|
||||||
io.bg1.screenAddress = data << 8 & 0x7c00;
|
io.bg1.screenAddress = ppu.vramExt(data << 8 & 0xfc00) /*0x7c00*/;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x2108: { //BG2SC
|
case 0x2108: { //BG2SC
|
||||||
io.bg2.screenSize = data >> 0 & 3;
|
io.bg2.screenSize = data >> 0 & 3;
|
||||||
io.bg2.screenAddress = data << 8 & 0x7c00;
|
io.bg2.screenAddress = ppu.vramExt(data << 8 & 0xfc00) /*0x7c00*/;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x2109: { //BG3SC
|
case 0x2109: { //BG3SC
|
||||||
io.bg3.screenSize = data >> 0 & 3;
|
io.bg3.screenSize = data >> 0 & 3;
|
||||||
io.bg3.screenAddress = data << 8 & 0x7c00;
|
io.bg3.screenAddress = ppu.vramExt(data << 8 & 0xfc00) /*0x7c00*/;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x210a: { //BG4SC
|
case 0x210a: { //BG4SC
|
||||||
io.bg4.screenSize = data >> 0 & 3;
|
io.bg4.screenSize = data >> 0 & 3;
|
||||||
io.bg4.screenAddress = data << 8 & 0x7c00;
|
io.bg4.screenAddress = ppu.vramExt(data << 8 & 0xfc00) /*0x7c00*/;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x210b: { //BG12NBA
|
case 0x210b: { //BG12NBA
|
||||||
io.bg1.tiledataAddress = data << 12 & 0x7000;
|
io.bg1.tiledataAddress = ppu.vramExt(data << 12 & 0xf000) /*0x7000*/;
|
||||||
io.bg2.tiledataAddress = data << 8 & 0x7000;
|
io.bg2.tiledataAddress = ppu.vramExt(data << 8 & 0xf000) /*0x7000*/;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x210c: { //BG34NBA
|
case 0x210c: { //BG34NBA
|
||||||
io.bg3.tiledataAddress = data << 12 & 0x7000;
|
io.bg3.tiledataAddress = ppu.vramExt(data << 12 & 0xf000) /*0x7000*/;
|
||||||
io.bg4.tiledataAddress = data << 8 & 0x7000;
|
io.bg4.tiledataAddress = ppu.vramExt(data << 8 & 0xf000) /*0x7000*/;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ auto PPU::Line::renderObject(PPU::IO::Object& self) -> void {
|
||||||
|
|
||||||
uint mirrorX = !object.hflip ? tileX : tileWidth - 1 - tileX;
|
uint mirrorX = !object.hflip ? tileX : tileWidth - 1 - tileX;
|
||||||
uint address = tiledataAddress + ((characterY + (characterX + mirrorX & 15)) << 4);
|
uint address = tiledataAddress + ((characterY + (characterX + mirrorX & 15)) << 4);
|
||||||
address = (address & 0x7ff0) + (y & 7);
|
address = ppu.vramExt((address & 0xfff0 /*0x7ff0*/) + (y & 7));
|
||||||
tile.data = ppu.vram[address + 0] << 0;
|
tile.data = ppu.vram[address + 0] << 0;
|
||||||
tile.data |= ppu.vram[address + 8] << 16;
|
tile.data |= ppu.vram[address + 8] << 16;
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ auto PPU::winXadHd(uint x, bool bel) const -> uint {
|
||||||
|| configuration.hacks.ppu.mode7.igwin >= 1 && ((bel ? io.col.window.belowMask : io.col.window.aboveMask) == 2)))
|
|| configuration.hacks.ppu.mode7.igwin >= 1 && ((bel ? io.col.window.belowMask : io.col.window.aboveMask) == 2)))
|
||||||
? configuration.hacks.ppu.mode7.igwinx * PPU::hdScale() : x; }
|
? configuration.hacks.ppu.mode7.igwinx * PPU::hdScale() : x; }
|
||||||
auto PPU::strwin() const -> bool { return configuration.hacks.ppu.mode7.strwin; }
|
auto PPU::strwin() const -> bool { return configuration.hacks.ppu.mode7.strwin; }
|
||||||
|
auto PPU::vramExt(uint addr) const -> uint { return addr & configuration.hacks.ppu.mode7.vramExt; }
|
||||||
auto PPU::bgGrad() const -> uint { return !hd() ? 0 : configuration.hacks.ppu.mode7.bgGrad; }
|
auto PPU::bgGrad() const -> uint { return !hd() ? 0 : configuration.hacks.ppu.mode7.bgGrad; }
|
||||||
auto PPU::windRad() const -> uint { return !hd() ? 0 : configuration.hacks.ppu.mode7.windRad; }
|
auto PPU::windRad() const -> uint { return !hd() ? 0 : configuration.hacks.ppu.mode7.windRad; }
|
||||||
auto PPU::wsOverrideCandidate() const -> bool { return configuration.hacks.ppu.mode7.wsMode == 1; }
|
auto PPU::wsOverrideCandidate() const -> bool { return configuration.hacks.ppu.mode7.wsMode == 1; }
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
//limitations:
|
//limitations:
|
||||||
//* mid-scanline effects not support
|
//* mid-scanline effects not support
|
||||||
//* vertical mosaic coordinates are not exact
|
//* vertical mosaic coordinates are not exact
|
||||||
//* (hardware-mod) 128KB VRAM mode not supported
|
|
||||||
|
|
||||||
#define PPU PPUfast
|
#define PPU PPUfast
|
||||||
|
|
||||||
|
@ -25,6 +24,7 @@ struct PPU : PPUcounter {
|
||||||
alwaysinline auto winXad(uint x, bool bel) const -> uint;
|
alwaysinline auto winXad(uint x, bool bel) const -> uint;
|
||||||
alwaysinline auto winXadHd(uint x, bool bel) const -> uint;
|
alwaysinline auto winXadHd(uint x, bool bel) const -> uint;
|
||||||
alwaysinline auto strwin() const -> bool;
|
alwaysinline auto strwin() const -> bool;
|
||||||
|
alwaysinline auto vramExt(uint addr) const -> uint;
|
||||||
alwaysinline auto bgGrad() const -> uint;
|
alwaysinline auto bgGrad() const -> uint;
|
||||||
alwaysinline auto windRad() const -> uint;
|
alwaysinline auto windRad() const -> uint;
|
||||||
alwaysinline auto wsOverrideCandidate() const -> bool;
|
alwaysinline auto wsOverrideCandidate() const -> bool;
|
||||||
|
@ -287,7 +287,7 @@ public:
|
||||||
Latch latch;
|
Latch latch;
|
||||||
IO io;
|
IO io;
|
||||||
|
|
||||||
uint16 vram[32 * 1024] = {};
|
uint16 vram[32 * 1024 * 2] = {}; //0-ffff
|
||||||
uint16 cgram[256] = {};
|
uint16 cgram[256] = {};
|
||||||
Object objects[128] = {};
|
Object objects[128] = {};
|
||||||
|
|
||||||
|
|
|
@ -123,8 +123,23 @@ auto Program::loadSuperFamicom(string location) -> bool {
|
||||||
rom.resize(rom.size() - 512);
|
rom.resize(rom.size() - 512);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!superFamicom.patched) superFamicom.patched = applyPatchIPS(rom, location);
|
if (!superFamicom.patched) {
|
||||||
if(!superFamicom.patched) superFamicom.patched = applyPatchBPS(rom, location);
|
bool p = applyPatchBPS(rom, location, "") || applyPatchIPS(rom, location, "");
|
||||||
|
superFamicom.patched = p;
|
||||||
|
if (p) {
|
||||||
|
p = applyPatchBPS(rom, location, "1") || applyPatchIPS(rom, location, "1");
|
||||||
|
if (p) {
|
||||||
|
p = applyPatchBPS(rom, location, "2") || applyPatchIPS(rom, location, "2");
|
||||||
|
if (p) {
|
||||||
|
p = applyPatchBPS(rom, location, "3") || applyPatchIPS(rom, location, "3");
|
||||||
|
if (p) {
|
||||||
|
p = applyPatchBPS(rom, location, "4") || applyPatchIPS(rom, location, "4");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto heuristics = Heuristics::SuperFamicom(rom, location);
|
auto heuristics = Heuristics::SuperFamicom(rom, location);
|
||||||
auto sha256 = Hash::SHA256(rom).digest();
|
auto sha256 = Hash::SHA256(rom).digest();
|
||||||
superFamicom.title = heuristics.title();
|
superFamicom.title = heuristics.title();
|
||||||
|
@ -199,7 +214,7 @@ auto Program::loadGameBoy(string location) -> bool {
|
||||||
}
|
}
|
||||||
if(rom.size() < 0x4000) return false;
|
if(rom.size() < 0x4000) return false;
|
||||||
|
|
||||||
gameBoy.patched = applyPatchIPS(rom, location) || applyPatchBPS(rom, location);
|
gameBoy.patched = applyPatchIPS(rom, location, "") || applyPatchBPS(rom, location, "");
|
||||||
auto heuristics = Heuristics::GameBoy(rom, location);
|
auto heuristics = Heuristics::GameBoy(rom, location);
|
||||||
auto sha256 = Hash::SHA256(rom).digest();
|
auto sha256 = Hash::SHA256(rom).digest();
|
||||||
if(auto document = BML::unserialize(string::read(locate("Database/Game Boy.bml")))) {
|
if(auto document = BML::unserialize(string::read(locate("Database/Game Boy.bml")))) {
|
||||||
|
@ -236,7 +251,7 @@ auto Program::loadBSMemory(string location) -> bool {
|
||||||
}
|
}
|
||||||
if(rom.size() < 0x8000) return false;
|
if(rom.size() < 0x8000) return false;
|
||||||
|
|
||||||
bsMemory.patched = applyPatchIPS(rom, location) || applyPatchBPS(rom, location);
|
bsMemory.patched = applyPatchIPS(rom, location, "") || applyPatchBPS(rom, location, "");
|
||||||
auto heuristics = Heuristics::BSMemory(rom, location);
|
auto heuristics = Heuristics::BSMemory(rom, location);
|
||||||
auto sha256 = Hash::SHA256(rom).digest();
|
auto sha256 = Hash::SHA256(rom).digest();
|
||||||
if(auto document = BML::unserialize(string::read(locate("Database/BS Memory.bml")))) {
|
if(auto document = BML::unserialize(string::read(locate("Database/BS Memory.bml")))) {
|
||||||
|
@ -266,7 +281,7 @@ auto Program::loadSufamiTurboA(string location) -> bool {
|
||||||
}
|
}
|
||||||
if(rom.size() < 0x20000) return false;
|
if(rom.size() < 0x20000) return false;
|
||||||
|
|
||||||
sufamiTurboA.patched = applyPatchIPS(rom, location) || applyPatchBPS(rom, location);
|
sufamiTurboA.patched = applyPatchIPS(rom, location, "") || applyPatchBPS(rom, location, "");
|
||||||
auto heuristics = Heuristics::SufamiTurbo(rom, location);
|
auto heuristics = Heuristics::SufamiTurbo(rom, location);
|
||||||
auto sha256 = Hash::SHA256(rom).digest();
|
auto sha256 = Hash::SHA256(rom).digest();
|
||||||
if(auto document = BML::unserialize(string::read(locate("Database/Sufami Turbo.bml")))) {
|
if(auto document = BML::unserialize(string::read(locate("Database/Sufami Turbo.bml")))) {
|
||||||
|
@ -296,7 +311,7 @@ auto Program::loadSufamiTurboB(string location) -> bool {
|
||||||
}
|
}
|
||||||
if(rom.size() < 0x20000) return false;
|
if(rom.size() < 0x20000) return false;
|
||||||
|
|
||||||
sufamiTurboB.patched = applyPatchIPS(rom, location) || applyPatchBPS(rom, location);
|
sufamiTurboB.patched = applyPatchIPS(rom, location, "") || applyPatchBPS(rom, location, "");
|
||||||
auto heuristics = Heuristics::SufamiTurbo(rom, location);
|
auto heuristics = Heuristics::SufamiTurbo(rom, location);
|
||||||
auto sha256 = Hash::SHA256(rom).digest();
|
auto sha256 = Hash::SHA256(rom).digest();
|
||||||
if(auto document = BML::unserialize(string::read(locate("Database/Sufami Turbo.bml")))) {
|
if(auto document = BML::unserialize(string::read(locate("Database/Sufami Turbo.bml")))) {
|
||||||
|
|
|
@ -82,6 +82,7 @@ auto Program::hackCompatibility() -> void {
|
||||||
emulator->configure("Hacks/PPU/Mode7/Igwin", settings.emulator.hack.ppu.mode7.igwin);
|
emulator->configure("Hacks/PPU/Mode7/Igwin", settings.emulator.hack.ppu.mode7.igwin);
|
||||||
emulator->configure("Hacks/PPU/Mode7/Igwinx", settings.emulator.hack.ppu.mode7.igwinx);
|
emulator->configure("Hacks/PPU/Mode7/Igwinx", settings.emulator.hack.ppu.mode7.igwinx);
|
||||||
emulator->configure("Hacks/PPU/Mode7/Strwin", false);
|
emulator->configure("Hacks/PPU/Mode7/Strwin", false);
|
||||||
|
emulator->configure("Hacks/PPU/Mode7/VramExt", 0x7fff);
|
||||||
emulator->configure("Hacks/PPU/Mode7/BgGrad", settings.emulator.hack.ppu.mode7.bgGrad);
|
emulator->configure("Hacks/PPU/Mode7/BgGrad", settings.emulator.hack.ppu.mode7.bgGrad);
|
||||||
emulator->configure("Hacks/PPU/Mode7/WindRad", settings.emulator.hack.ppu.mode7.windRad);
|
emulator->configure("Hacks/PPU/Mode7/WindRad", settings.emulator.hack.ppu.mode7.windRad);
|
||||||
emulator->configure("Hacks/PPU/Mode7/WsMode", settings.emulator.hack.ppu.mode7.wsMode);
|
emulator->configure("Hacks/PPU/Mode7/WsMode", settings.emulator.hack.ppu.mode7.wsMode);
|
||||||
|
@ -114,12 +115,12 @@ auto Program::hackCompatibility() -> void {
|
||||||
n = (n * 10) + (v - '0');
|
n = (n * 10) + (v - '0');
|
||||||
if (i == rso.size() || rso[i] < '0' || rso[i] > '9') {
|
if (i == rso.size() || rso[i] < '0' || rso[i] > '9') {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
// case 'p': //pixelAspectCorrect 0:off 1:on
|
// case 'p': //pixelAspectCorrect 0:off 1:on [libretro exclusive]
|
||||||
// emulator->configure("Video/AspectCorrection", n == 1);
|
// aspectcorrection = n == 1;
|
||||||
// break;
|
// break;
|
||||||
// case 'o': //overscan 0:216 1:224 (2:240 3:240f)
|
// case 'o': //overscan 0:216 1:224 (2:240 3:240f) [libretro exclusive]
|
||||||
// emulator->configure("Video/Overscan", n == 1);
|
// overscan = n == 1;
|
||||||
// break;
|
// break;
|
||||||
case 'w': //widescreenMode 0:none 1:on 2:mode7
|
case 'w': //widescreenMode 0:none 1:on 2:mode7
|
||||||
emulator->configure("Hacks/PPU/Mode7/WsMode", n == 1 ? 2 : (n == 2 ? 1 : 0));
|
emulator->configure("Hacks/PPU/Mode7/WsMode", n == 1 ? 2 : (n == 2 ? 1 : 0));
|
||||||
break;
|
break;
|
||||||
|
@ -196,6 +197,15 @@ auto Program::hackCompatibility() -> void {
|
||||||
case 'S': //Stretch Window [for widescreen patches only]
|
case 'S': //Stretch Window [for widescreen patches only]
|
||||||
emulator->configure("Hacks/PPU/Mode7/Strwin", n == 2 );
|
emulator->configure("Hacks/PPU/Mode7/Strwin", n == 2 );
|
||||||
break;
|
break;
|
||||||
|
case 'v': //VRAM extension
|
||||||
|
emulator->configure("Hacks/PPU/Mode7/VramExt", n > 0 ? 0xffff : 0x7fff );
|
||||||
|
break;
|
||||||
|
case 'f': //Scale factor 0:disable 1-10:scale
|
||||||
|
emulator->configure("Hacks/PPU/Mode7/Scale", n >= 0 && n <= 10 ? n : 2);
|
||||||
|
break;
|
||||||
|
case 'l': //Disable sprite limit
|
||||||
|
emulator->configure("Hacks/PPU/NoSpriteLimit", n == 1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
c = -1;
|
c = -1;
|
||||||
n = 0;
|
n = 0;
|
||||||
|
|
|
@ -8,29 +8,29 @@ auto Program::appliedPatch() const -> bool {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Program::applyPatchIPS(vector<uint8_t>& data, string location) -> bool {
|
auto Program::applyPatchIPS(vector<uint8_t>& data, string location, string suffix) -> bool {
|
||||||
vector<uint8_t> patch;
|
vector<uint8_t> patch;
|
||||||
|
|
||||||
if(location.endsWith("/")) {
|
if(location.endsWith("/")) {
|
||||||
patch = file::read({location, "patch.ips"});
|
patch = file::read({location, "patch.ips", suffix});
|
||||||
} else if(location.iendsWith(".zip")) {
|
} else if(location.iendsWith(".zip")) {
|
||||||
Decode::ZIP archive;
|
Decode::ZIP archive;
|
||||||
if(archive.open(location)) {
|
if(archive.open(location)) {
|
||||||
for(auto& file : archive.file) {
|
for(auto& file : archive.file) {
|
||||||
if(file.name.iendsWith(".ips")) {
|
if(file.name.iendsWith({".ips", suffix})) {
|
||||||
patch = archive.extract(file);
|
patch = archive.extract(file);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!patch) patch = file::read(path("Patches", location, ".ips"));
|
if(!patch) patch = file::read(path("Patches", location, {".ips", suffix}));
|
||||||
} else {
|
} else {
|
||||||
patch = file::read(path("Patches", location, ".ips"));
|
patch = file::read(path("Patches", location, {".ips", suffix}));
|
||||||
}
|
}
|
||||||
if(!patch) return false;
|
if(!patch) return false;
|
||||||
|
|
||||||
bool headered = false;
|
bool headered = false;
|
||||||
if(MessageDialog().setAlignment(*presentation).setTitle({Location::prefix(location), ".ips"}).setText({
|
if(MessageDialog().setAlignment(*presentation).setTitle({Location::prefix(location), ".ips", suffix}).setText({
|
||||||
"(You're seeing this prompt because IPS is a terrible patch file format,\n"
|
"(You're seeing this prompt because IPS is a terrible patch file format,\n"
|
||||||
" and nobody can agree on whether SNES ROMs should be headered or not.\n"
|
" and nobody can agree on whether SNES ROMs should be headered or not.\n"
|
||||||
" Please consider asking the patch author to use BPS patches instead.)\n\n"
|
" Please consider asking the patch author to use BPS patches instead.)\n\n"
|
||||||
|
@ -103,24 +103,24 @@ auto Program::applyPatchIPS(vector<uint8_t>& data, string location) -> bool {
|
||||||
|
|
||||||
#include <nall/beat/single/apply.hpp>
|
#include <nall/beat/single/apply.hpp>
|
||||||
|
|
||||||
auto Program::applyPatchBPS(vector<uint8_t>& input, string location) -> bool {
|
auto Program::applyPatchBPS(vector<uint8_t>& input, string location, string suffix) -> bool {
|
||||||
vector<uint8_t> patch;
|
vector<uint8_t> patch;
|
||||||
|
|
||||||
if(location.endsWith("/")) {
|
if(location.endsWith("/")) {
|
||||||
patch = file::read({location, "patch.bps"});
|
patch = file::read({location, "patch.bps", suffix});
|
||||||
} else if(location.iendsWith(".zip")) {
|
} else if(location.iendsWith(".zip")) {
|
||||||
Decode::ZIP archive;
|
Decode::ZIP archive;
|
||||||
if(archive.open(location)) {
|
if(archive.open(location)) {
|
||||||
for(auto& file : archive.file) {
|
for(auto& file : archive.file) {
|
||||||
if(file.name.iendsWith(".bps")) {
|
if(file.name.iendsWith({".bps", suffix})) {
|
||||||
patch = archive.extract(file);
|
patch = archive.extract(file);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!patch) patch = file::read(path("Patches", location, ".bps"));
|
if(!patch) patch = file::read(path("Patches", location, {".bps", suffix}));
|
||||||
} else {
|
} else {
|
||||||
patch = file::read(path("Patches", location, ".bps"));
|
patch = file::read(path("Patches", location, {".bps", suffix}));
|
||||||
}
|
}
|
||||||
if(!patch) return false;
|
if(!patch) return false;
|
||||||
|
|
||||||
|
|
|
@ -124,8 +124,8 @@ struct Program : Lock, Emulator::Platform {
|
||||||
|
|
||||||
//patch.cpp
|
//patch.cpp
|
||||||
auto appliedPatch() const -> bool;
|
auto appliedPatch() const -> bool;
|
||||||
auto applyPatchIPS(vector<uint8_t>& data, string location) -> bool;
|
auto applyPatchIPS(vector<uint8_t>& data, string location, string suffix) -> bool;
|
||||||
auto applyPatchBPS(vector<uint8_t>& data, string location) -> bool;
|
auto applyPatchBPS(vector<uint8_t>& data, string location, string suffix) -> bool;
|
||||||
|
|
||||||
//hacks.cpp
|
//hacks.cpp
|
||||||
auto hackCompatibility() -> void;
|
auto hackCompatibility() -> void;
|
||||||
|
|
39
bsnes/target-libretro/libretro-common/include/retro_inline.h
Normal file
39
bsnes/target-libretro/libretro-common/include/retro_inline.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (retro_inline.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge,
|
||||||
|
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBRETRO_SDK_INLINE_H
|
||||||
|
#define __LIBRETRO_SDK_INLINE_H
|
||||||
|
|
||||||
|
#ifndef INLINE
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(__INTEL_COMPILER)
|
||||||
|
#define INLINE __inline
|
||||||
|
#elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L
|
||||||
|
#define INLINE inline
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#define INLINE __inline__
|
||||||
|
#else
|
||||||
|
#define INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this libretro API header (libretro.h).
|
* The following license statement only applies to this libretro API header (libretro.h).
|
||||||
|
@ -69,7 +69,7 @@ extern "C" {
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
# else
|
# else
|
||||||
# if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__CELLOS_LV2__)
|
# if defined(__GNUC__) && __GNUC__ >= 4
|
||||||
# define RETRO_API RETRO_CALLCONV __attribute__((__visibility__("default")))
|
# define RETRO_API RETRO_CALLCONV __attribute__((__visibility__("default")))
|
||||||
# else
|
# else
|
||||||
# define RETRO_API RETRO_CALLCONV
|
# define RETRO_API RETRO_CALLCONV
|
||||||
|
@ -278,6 +278,11 @@ enum retro_language
|
||||||
RETRO_LANGUAGE_ARABIC = 16,
|
RETRO_LANGUAGE_ARABIC = 16,
|
||||||
RETRO_LANGUAGE_GREEK = 17,
|
RETRO_LANGUAGE_GREEK = 17,
|
||||||
RETRO_LANGUAGE_TURKISH = 18,
|
RETRO_LANGUAGE_TURKISH = 18,
|
||||||
|
RETRO_LANGUAGE_SLOVAK = 19,
|
||||||
|
RETRO_LANGUAGE_PERSIAN = 20,
|
||||||
|
RETRO_LANGUAGE_HEBREW = 21,
|
||||||
|
RETRO_LANGUAGE_ASTURIAN = 22,
|
||||||
|
RETRO_LANGUAGE_FINNISH = 23,
|
||||||
RETRO_LANGUAGE_LAST,
|
RETRO_LANGUAGE_LAST,
|
||||||
|
|
||||||
/* Ensure sizeof(enum) == sizeof(int) */
|
/* Ensure sizeof(enum) == sizeof(int) */
|
||||||
|
@ -708,6 +713,9 @@ enum retro_mod
|
||||||
* state of rumble motors in controllers.
|
* state of rumble motors in controllers.
|
||||||
* A strong and weak motor is supported, and they can be
|
* A strong and weak motor is supported, and they can be
|
||||||
* controlled indepedently.
|
* controlled indepedently.
|
||||||
|
* Should be called from either retro_init() or retro_load_game().
|
||||||
|
* Should not be called from retro_set_environment().
|
||||||
|
* Returns false if rumble functionality is unavailable.
|
||||||
*/
|
*/
|
||||||
#define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24
|
#define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24
|
||||||
/* uint64_t * --
|
/* uint64_t * --
|
||||||
|
@ -1087,10 +1095,10 @@ enum retro_mod
|
||||||
|
|
||||||
#define RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE (50 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
#define RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE (50 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||||
/* float * --
|
/* float * --
|
||||||
* Float value that lets us know what target refresh rate
|
* Float value that lets us know what target refresh rate
|
||||||
* is curently in use by the frontend.
|
* is curently in use by the frontend.
|
||||||
*
|
*
|
||||||
* The core can use the returned value to set an ideal
|
* The core can use the returned value to set an ideal
|
||||||
* refresh rate/framerate.
|
* refresh rate/framerate.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1098,7 +1106,7 @@ enum retro_mod
|
||||||
/* bool * --
|
/* bool * --
|
||||||
* Boolean value that indicates whether or not the frontend supports
|
* Boolean value that indicates whether or not the frontend supports
|
||||||
* input bitmasks being returned by retro_input_state_t. The advantage
|
* input bitmasks being returned by retro_input_state_t. The advantage
|
||||||
* of this is that retro_input_state_t has to be only called once to
|
* of this is that retro_input_state_t has to be only called once to
|
||||||
* grab all button states instead of multiple times.
|
* grab all button states instead of multiple times.
|
||||||
*
|
*
|
||||||
* If it returns true, you can pass RETRO_DEVICE_ID_JOYPAD_MASK as 'id'
|
* If it returns true, you can pass RETRO_DEVICE_ID_JOYPAD_MASK as 'id'
|
||||||
|
@ -1117,7 +1125,7 @@ enum retro_mod
|
||||||
* This may be still be done regardless of the core options
|
* This may be still be done regardless of the core options
|
||||||
* interface version.
|
* interface version.
|
||||||
*
|
*
|
||||||
* If version is 1 however, core options may instead be set by
|
* If version is >= 1 however, core options may instead be set by
|
||||||
* passing an array of retro_core_option_definition structs to
|
* passing an array of retro_core_option_definition structs to
|
||||||
* RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of
|
* RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of
|
||||||
* retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL.
|
* retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL.
|
||||||
|
@ -1132,8 +1140,8 @@ enum retro_mod
|
||||||
* GET_VARIABLE.
|
* GET_VARIABLE.
|
||||||
* This allows the frontend to present these variables to
|
* This allows the frontend to present these variables to
|
||||||
* a user dynamically.
|
* a user dynamically.
|
||||||
* This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
|
* This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION
|
||||||
* returns an API version of 1.
|
* returns an API version of >= 1.
|
||||||
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
|
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
|
||||||
* This should be called the first time as early as
|
* This should be called the first time as early as
|
||||||
* possible (ideally in retro_set_environment).
|
* possible (ideally in retro_set_environment).
|
||||||
|
@ -1194,8 +1202,8 @@ enum retro_mod
|
||||||
* GET_VARIABLE.
|
* GET_VARIABLE.
|
||||||
* This allows the frontend to present these variables to
|
* This allows the frontend to present these variables to
|
||||||
* a user dynamically.
|
* a user dynamically.
|
||||||
* This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
|
* This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION
|
||||||
* returns an API version of 1.
|
* returns an API version of >= 1.
|
||||||
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
|
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
|
||||||
* This should be called the first time as early as
|
* This should be called the first time as early as
|
||||||
* possible (ideally in retro_set_environment).
|
* possible (ideally in retro_set_environment).
|
||||||
|
@ -1246,6 +1254,140 @@ enum retro_mod
|
||||||
* default when calling SET_VARIABLES/SET_CORE_OPTIONS.
|
* default when calling SET_VARIABLES/SET_CORE_OPTIONS.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER 56
|
||||||
|
/* unsigned * --
|
||||||
|
*
|
||||||
|
* Allows an implementation to ask frontend preferred hardware
|
||||||
|
* context to use. Core should use this information to deal
|
||||||
|
* with what specific context to request with SET_HW_RENDER.
|
||||||
|
*
|
||||||
|
* 'data' points to an unsigned variable
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION 57
|
||||||
|
/* unsigned * --
|
||||||
|
* Unsigned value is the API version number of the disk control
|
||||||
|
* interface supported by the frontend. If callback return false,
|
||||||
|
* API version is assumed to be 0.
|
||||||
|
*
|
||||||
|
* In legacy code, the disk control interface is defined by passing
|
||||||
|
* a struct of type retro_disk_control_callback to
|
||||||
|
* RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE.
|
||||||
|
* This may be still be done regardless of the disk control
|
||||||
|
* interface version.
|
||||||
|
*
|
||||||
|
* If version is >= 1 however, the disk control interface may
|
||||||
|
* instead be defined by passing a struct of type
|
||||||
|
* retro_disk_control_ext_callback to
|
||||||
|
* RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE.
|
||||||
|
* This allows the core to provide additional information about
|
||||||
|
* disk images to the frontend and/or enables extra
|
||||||
|
* disk control functionality by the frontend.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE 58
|
||||||
|
/* const struct retro_disk_control_ext_callback * --
|
||||||
|
* Sets an interface which frontend can use to eject and insert
|
||||||
|
* disk images, and also obtain information about individual
|
||||||
|
* disk image files registered by the core.
|
||||||
|
* This is used for games which consist of multiple images and
|
||||||
|
* must be manually swapped out by the user (e.g. PSX, floppy disk
|
||||||
|
* based systems).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION 59
|
||||||
|
/* unsigned * --
|
||||||
|
* Unsigned value is the API version number of the message
|
||||||
|
* interface supported by the frontend. If callback returns
|
||||||
|
* false, API version is assumed to be 0.
|
||||||
|
*
|
||||||
|
* In legacy code, messages may be displayed in an
|
||||||
|
* implementation-specific manner by passing a struct
|
||||||
|
* of type retro_message to RETRO_ENVIRONMENT_SET_MESSAGE.
|
||||||
|
* This may be still be done regardless of the message
|
||||||
|
* interface version.
|
||||||
|
*
|
||||||
|
* If version is >= 1 however, messages may instead be
|
||||||
|
* displayed by passing a struct of type retro_message_ext
|
||||||
|
* to RETRO_ENVIRONMENT_SET_MESSAGE_EXT. This allows the
|
||||||
|
* core to specify message logging level, priority and
|
||||||
|
* destination (OSD, logging interface or both).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_SET_MESSAGE_EXT 60
|
||||||
|
/* const struct retro_message_ext * --
|
||||||
|
* Sets a message to be displayed in an implementation-specific
|
||||||
|
* manner for a certain amount of 'frames'. Additionally allows
|
||||||
|
* the core to specify message logging level, priority and
|
||||||
|
* destination (OSD, logging interface or both).
|
||||||
|
* Should not be used for trivial messages, which should simply be
|
||||||
|
* logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a
|
||||||
|
* fallback, stderr).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_GET_INPUT_MAX_USERS 61
|
||||||
|
/* unsigned * --
|
||||||
|
* Unsigned value is the number of active input devices
|
||||||
|
* provided by the frontend. This may change between
|
||||||
|
* frames, but will remain constant for the duration
|
||||||
|
* of each frame.
|
||||||
|
* If callback returns true, a core need not poll any
|
||||||
|
* input device with an index greater than or equal to
|
||||||
|
* the number of active devices.
|
||||||
|
* If callback returns false, the number of active input
|
||||||
|
* devices is unknown. In this case, all input devices
|
||||||
|
* should be considered active.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK 62
|
||||||
|
/* const struct retro_audio_buffer_status_callback * --
|
||||||
|
* Lets the core know the occupancy level of the frontend
|
||||||
|
* audio buffer. Can be used by a core to attempt frame
|
||||||
|
* skipping in order to avoid buffer under-runs.
|
||||||
|
* A core may pass NULL to disable buffer status reporting
|
||||||
|
* in the frontend.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY 63
|
||||||
|
/* const unsigned * --
|
||||||
|
* Sets minimum frontend audio latency in milliseconds.
|
||||||
|
* Resultant audio latency may be larger than set value,
|
||||||
|
* or smaller if a hardware limit is encountered. A frontend
|
||||||
|
* is expected to honour requests up to 512 ms.
|
||||||
|
*
|
||||||
|
* - If value is less than current frontend
|
||||||
|
* audio latency, callback has no effect
|
||||||
|
* - If value is zero, default frontend audio
|
||||||
|
* latency is set
|
||||||
|
*
|
||||||
|
* May be used by a core to increase audio latency and
|
||||||
|
* therefore decrease the probability of buffer under-runs
|
||||||
|
* (crackling) when performing 'intensive' operations.
|
||||||
|
* A core utilising RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK
|
||||||
|
* to implement audio-buffer-based frame skipping may achieve
|
||||||
|
* optimal results by setting the audio latency to a 'high'
|
||||||
|
* (typically 6x or 8x) integer multiple of the expected
|
||||||
|
* frame time.
|
||||||
|
*
|
||||||
|
* WARNING: This can only be called from within retro_run().
|
||||||
|
* Calling this can require a full reinitialization of audio
|
||||||
|
* drivers in the frontend, so it is important to call it very
|
||||||
|
* sparingly, and usually only with the users explicit consent.
|
||||||
|
* An eventual driver reinitialize will happen so that audio
|
||||||
|
* callbacks happening after this call within the same retro_run()
|
||||||
|
* call will target the newly initialized driver.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE 64
|
||||||
|
/* const struct retro_fastforwarding_override * --
|
||||||
|
* Used by a libretro core to override the current
|
||||||
|
* fastforwarding mode of the frontend.
|
||||||
|
* If NULL is passed to this function, the frontend
|
||||||
|
* will return true if fastforwarding override
|
||||||
|
* functionality is supported (no change in
|
||||||
|
* fastforwarding state will occur in this case).
|
||||||
|
*/
|
||||||
|
|
||||||
/* VFS functionality */
|
/* VFS functionality */
|
||||||
|
|
||||||
/* File paths:
|
/* File paths:
|
||||||
|
@ -1922,6 +2064,10 @@ enum retro_sensor_action
|
||||||
{
|
{
|
||||||
RETRO_SENSOR_ACCELEROMETER_ENABLE = 0,
|
RETRO_SENSOR_ACCELEROMETER_ENABLE = 0,
|
||||||
RETRO_SENSOR_ACCELEROMETER_DISABLE,
|
RETRO_SENSOR_ACCELEROMETER_DISABLE,
|
||||||
|
RETRO_SENSOR_GYROSCOPE_ENABLE,
|
||||||
|
RETRO_SENSOR_GYROSCOPE_DISABLE,
|
||||||
|
RETRO_SENSOR_ILLUMINANCE_ENABLE,
|
||||||
|
RETRO_SENSOR_ILLUMINANCE_DISABLE,
|
||||||
|
|
||||||
RETRO_SENSOR_DUMMY = INT_MAX
|
RETRO_SENSOR_DUMMY = INT_MAX
|
||||||
};
|
};
|
||||||
|
@ -1930,6 +2076,10 @@ enum retro_sensor_action
|
||||||
#define RETRO_SENSOR_ACCELEROMETER_X 0
|
#define RETRO_SENSOR_ACCELEROMETER_X 0
|
||||||
#define RETRO_SENSOR_ACCELEROMETER_Y 1
|
#define RETRO_SENSOR_ACCELEROMETER_Y 1
|
||||||
#define RETRO_SENSOR_ACCELEROMETER_Z 2
|
#define RETRO_SENSOR_ACCELEROMETER_Z 2
|
||||||
|
#define RETRO_SENSOR_GYROSCOPE_X 3
|
||||||
|
#define RETRO_SENSOR_GYROSCOPE_Y 4
|
||||||
|
#define RETRO_SENSOR_GYROSCOPE_Z 5
|
||||||
|
#define RETRO_SENSOR_ILLUMINANCE 6
|
||||||
|
|
||||||
typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port,
|
typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port,
|
||||||
enum retro_sensor_action action, unsigned rate);
|
enum retro_sensor_action action, unsigned rate);
|
||||||
|
@ -2127,6 +2277,30 @@ struct retro_frame_time_callback
|
||||||
retro_usec_t reference;
|
retro_usec_t reference;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Notifies a libretro core of the current occupancy
|
||||||
|
* level of the frontend audio buffer.
|
||||||
|
*
|
||||||
|
* - active: 'true' if audio buffer is currently
|
||||||
|
* in use. Will be 'false' if audio is
|
||||||
|
* disabled in the frontend
|
||||||
|
*
|
||||||
|
* - occupancy: Given as a value in the range [0,100],
|
||||||
|
* corresponding to the occupancy percentage
|
||||||
|
* of the audio buffer
|
||||||
|
*
|
||||||
|
* - underrun_likely: 'true' if the frontend expects an
|
||||||
|
* audio buffer underrun during the
|
||||||
|
* next frame (indicates that a core
|
||||||
|
* should attempt frame skipping)
|
||||||
|
*
|
||||||
|
* It will be called right before retro_run() every frame. */
|
||||||
|
typedef void (RETRO_CALLCONV *retro_audio_buffer_status_callback_t)(
|
||||||
|
bool active, unsigned occupancy, bool underrun_likely);
|
||||||
|
struct retro_audio_buffer_status_callback
|
||||||
|
{
|
||||||
|
retro_audio_buffer_status_callback_t callback;
|
||||||
|
};
|
||||||
|
|
||||||
/* Pass this to retro_video_refresh_t if rendering to hardware.
|
/* Pass this to retro_video_refresh_t if rendering to hardware.
|
||||||
* Passing NULL to retro_video_refresh_t is still a frame dupe as normal.
|
* Passing NULL to retro_video_refresh_t is still a frame dupe as normal.
|
||||||
* */
|
* */
|
||||||
|
@ -2287,7 +2461,8 @@ struct retro_keyboard_callback
|
||||||
retro_keyboard_event_t callback;
|
retro_keyboard_event_t callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE.
|
/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE &
|
||||||
|
* RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE.
|
||||||
* Should be set for implementations which can swap out multiple disk
|
* Should be set for implementations which can swap out multiple disk
|
||||||
* images in runtime.
|
* images in runtime.
|
||||||
*
|
*
|
||||||
|
@ -2345,6 +2520,53 @@ typedef bool (RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index,
|
||||||
* with replace_image_index. */
|
* with replace_image_index. */
|
||||||
typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void);
|
typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void);
|
||||||
|
|
||||||
|
/* Sets initial image to insert in drive when calling
|
||||||
|
* core_load_game().
|
||||||
|
* Since we cannot pass the initial index when loading
|
||||||
|
* content (this would require a major API change), this
|
||||||
|
* is set by the frontend *before* calling the core's
|
||||||
|
* retro_load_game()/retro_load_game_special() implementation.
|
||||||
|
* A core should therefore cache the index/path values and handle
|
||||||
|
* them inside retro_load_game()/retro_load_game_special().
|
||||||
|
* - If 'index' is invalid (index >= get_num_images()), the
|
||||||
|
* core should ignore the set value and instead use 0
|
||||||
|
* - 'path' is used purely for error checking - i.e. when
|
||||||
|
* content is loaded, the core should verify that the
|
||||||
|
* disk specified by 'index' has the specified file path.
|
||||||
|
* This is to guard against auto selecting the wrong image
|
||||||
|
* if (for example) the user should modify an existing M3U
|
||||||
|
* playlist. We have to let the core handle this because
|
||||||
|
* set_initial_image() must be called before loading content,
|
||||||
|
* i.e. the frontend cannot access image paths in advance
|
||||||
|
* and thus cannot perform the error check itself.
|
||||||
|
* If set path and content path do not match, the core should
|
||||||
|
* ignore the set 'index' value and instead use 0
|
||||||
|
* Returns 'false' if index or 'path' are invalid, or core
|
||||||
|
* does not support this functionality
|
||||||
|
*/
|
||||||
|
typedef bool (RETRO_CALLCONV *retro_set_initial_image_t)(unsigned index, const char *path);
|
||||||
|
|
||||||
|
/* Fetches the path of the specified disk image file.
|
||||||
|
* Returns 'false' if index is invalid (index >= get_num_images())
|
||||||
|
* or path is otherwise unavailable.
|
||||||
|
*/
|
||||||
|
typedef bool (RETRO_CALLCONV *retro_get_image_path_t)(unsigned index, char *path, size_t len);
|
||||||
|
|
||||||
|
/* Fetches a core-provided 'label' for the specified disk
|
||||||
|
* image file. In the simplest case this may be a file name
|
||||||
|
* (without extension), but for cores with more complex
|
||||||
|
* content requirements information may be provided to
|
||||||
|
* facilitate user disk swapping - for example, a core
|
||||||
|
* running floppy-disk-based content may uniquely label
|
||||||
|
* save disks, data disks, level disks, etc. with names
|
||||||
|
* corresponding to in-game disk change prompts (so the
|
||||||
|
* frontend can provide better user guidance than a 'dumb'
|
||||||
|
* disk index value).
|
||||||
|
* Returns 'false' if index is invalid (index >= get_num_images())
|
||||||
|
* or label is otherwise unavailable.
|
||||||
|
*/
|
||||||
|
typedef bool (RETRO_CALLCONV *retro_get_image_label_t)(unsigned index, char *label, size_t len);
|
||||||
|
|
||||||
struct retro_disk_control_callback
|
struct retro_disk_control_callback
|
||||||
{
|
{
|
||||||
retro_set_eject_state_t set_eject_state;
|
retro_set_eject_state_t set_eject_state;
|
||||||
|
@ -2358,6 +2580,27 @@ struct retro_disk_control_callback
|
||||||
retro_add_image_index_t add_image_index;
|
retro_add_image_index_t add_image_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct retro_disk_control_ext_callback
|
||||||
|
{
|
||||||
|
retro_set_eject_state_t set_eject_state;
|
||||||
|
retro_get_eject_state_t get_eject_state;
|
||||||
|
|
||||||
|
retro_get_image_index_t get_image_index;
|
||||||
|
retro_set_image_index_t set_image_index;
|
||||||
|
retro_get_num_images_t get_num_images;
|
||||||
|
|
||||||
|
retro_replace_image_index_t replace_image_index;
|
||||||
|
retro_add_image_index_t add_image_index;
|
||||||
|
|
||||||
|
/* NOTE: Frontend will only attempt to record/restore
|
||||||
|
* last used disk index if both set_initial_image()
|
||||||
|
* and get_image_path() are implemented */
|
||||||
|
retro_set_initial_image_t set_initial_image; /* Optional - may be NULL */
|
||||||
|
|
||||||
|
retro_get_image_path_t get_image_path; /* Optional - may be NULL */
|
||||||
|
retro_get_image_label_t get_image_label; /* Optional - may be NULL */
|
||||||
|
};
|
||||||
|
|
||||||
enum retro_pixel_format
|
enum retro_pixel_format
|
||||||
{
|
{
|
||||||
/* 0RGB1555, native endian.
|
/* 0RGB1555, native endian.
|
||||||
|
@ -2388,6 +2631,104 @@ struct retro_message
|
||||||
unsigned frames; /* Duration in frames of message. */
|
unsigned frames; /* Duration in frames of message. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum retro_message_target
|
||||||
|
{
|
||||||
|
RETRO_MESSAGE_TARGET_ALL = 0,
|
||||||
|
RETRO_MESSAGE_TARGET_OSD,
|
||||||
|
RETRO_MESSAGE_TARGET_LOG
|
||||||
|
};
|
||||||
|
|
||||||
|
enum retro_message_type
|
||||||
|
{
|
||||||
|
RETRO_MESSAGE_TYPE_NOTIFICATION = 0,
|
||||||
|
RETRO_MESSAGE_TYPE_NOTIFICATION_ALT,
|
||||||
|
RETRO_MESSAGE_TYPE_STATUS,
|
||||||
|
RETRO_MESSAGE_TYPE_PROGRESS
|
||||||
|
};
|
||||||
|
|
||||||
|
struct retro_message_ext
|
||||||
|
{
|
||||||
|
/* Message string to be displayed/logged */
|
||||||
|
const char *msg;
|
||||||
|
/* Duration (in ms) of message when targeting the OSD */
|
||||||
|
unsigned duration;
|
||||||
|
/* Message priority when targeting the OSD
|
||||||
|
* > When multiple concurrent messages are sent to
|
||||||
|
* the frontend and the frontend does not have the
|
||||||
|
* capacity to display them all, messages with the
|
||||||
|
* *highest* priority value should be shown
|
||||||
|
* > There is no upper limit to a message priority
|
||||||
|
* value (within the bounds of the unsigned data type)
|
||||||
|
* > In the reference frontend (RetroArch), the same
|
||||||
|
* priority values are used for frontend-generated
|
||||||
|
* notifications, which are typically assigned values
|
||||||
|
* between 0 and 3 depending upon importance */
|
||||||
|
unsigned priority;
|
||||||
|
/* Message logging level (info, warn, error, etc.) */
|
||||||
|
enum retro_log_level level;
|
||||||
|
/* Message destination: OSD, logging interface or both */
|
||||||
|
enum retro_message_target target;
|
||||||
|
/* Message 'type' when targeting the OSD
|
||||||
|
* > RETRO_MESSAGE_TYPE_NOTIFICATION: Specifies that a
|
||||||
|
* message should be handled in identical fashion to
|
||||||
|
* a standard frontend-generated notification
|
||||||
|
* > RETRO_MESSAGE_TYPE_NOTIFICATION_ALT: Specifies that
|
||||||
|
* message is a notification that requires user attention
|
||||||
|
* or action, but that it should be displayed in a manner
|
||||||
|
* that differs from standard frontend-generated notifications.
|
||||||
|
* This would typically correspond to messages that should be
|
||||||
|
* displayed immediately (independently from any internal
|
||||||
|
* frontend message queue), and/or which should be visually
|
||||||
|
* distinguishable from frontend-generated notifications.
|
||||||
|
* For example, a core may wish to inform the user of
|
||||||
|
* information related to a disk-change event. It is
|
||||||
|
* expected that the frontend itself may provide a
|
||||||
|
* notification in this case; if the core sends a
|
||||||
|
* message of type RETRO_MESSAGE_TYPE_NOTIFICATION, an
|
||||||
|
* uncomfortable 'double-notification' may occur. A message
|
||||||
|
* of RETRO_MESSAGE_TYPE_NOTIFICATION_ALT should therefore
|
||||||
|
* be presented such that visual conflict with regular
|
||||||
|
* notifications does not occur
|
||||||
|
* > RETRO_MESSAGE_TYPE_STATUS: Indicates that message
|
||||||
|
* is not a standard notification. This typically
|
||||||
|
* corresponds to 'status' indicators, such as a core's
|
||||||
|
* internal FPS, which are intended to be displayed
|
||||||
|
* either permanently while a core is running, or in
|
||||||
|
* a manner that does not suggest user attention or action
|
||||||
|
* is required. 'Status' type messages should therefore be
|
||||||
|
* displayed in a different on-screen location and in a manner
|
||||||
|
* easily distinguishable from both standard frontend-generated
|
||||||
|
* notifications and messages of type RETRO_MESSAGE_TYPE_NOTIFICATION_ALT
|
||||||
|
* > RETRO_MESSAGE_TYPE_PROGRESS: Indicates that message reports
|
||||||
|
* the progress of an internal core task. For example, in cases
|
||||||
|
* where a core itself handles the loading of content from a file,
|
||||||
|
* this may correspond to the percentage of the file that has been
|
||||||
|
* read. Alternatively, an audio/video playback core may use a
|
||||||
|
* message of type RETRO_MESSAGE_TYPE_PROGRESS to display the current
|
||||||
|
* playback position as a percentage of the runtime. 'Progress' type
|
||||||
|
* messages should therefore be displayed as a literal progress bar,
|
||||||
|
* where:
|
||||||
|
* - 'retro_message_ext.msg' is the progress bar title/label
|
||||||
|
* - 'retro_message_ext.progress' determines the length of
|
||||||
|
* the progress bar
|
||||||
|
* NOTE: Message type is a *hint*, and may be ignored
|
||||||
|
* by the frontend. If a frontend lacks support for
|
||||||
|
* displaying messages via alternate means than standard
|
||||||
|
* frontend-generated notifications, it will treat *all*
|
||||||
|
* messages as having the type RETRO_MESSAGE_TYPE_NOTIFICATION */
|
||||||
|
enum retro_message_type type;
|
||||||
|
/* Task progress when targeting the OSD and message is
|
||||||
|
* of type RETRO_MESSAGE_TYPE_PROGRESS
|
||||||
|
* > -1: Unmetered/indeterminate
|
||||||
|
* > 0-100: Current progress percentage
|
||||||
|
* NOTE: Since message type is a hint, a frontend may ignore
|
||||||
|
* progress values. Where relevant, a core should therefore
|
||||||
|
* include progress percentage within the message string,
|
||||||
|
* such that the message intent remains clear when displayed
|
||||||
|
* as a standard frontend-generated notification */
|
||||||
|
int8_t progress;
|
||||||
|
};
|
||||||
|
|
||||||
/* Describes how the libretro implementation maps a libretro input bind
|
/* Describes how the libretro implementation maps a libretro input bind
|
||||||
* to its internal input system through a human readable string.
|
* to its internal input system through a human readable string.
|
||||||
* This string can be used to better let a user configure input. */
|
* This string can be used to better let a user configure input. */
|
||||||
|
@ -2408,7 +2749,7 @@ struct retro_input_descriptor
|
||||||
struct retro_system_info
|
struct retro_system_info
|
||||||
{
|
{
|
||||||
/* All pointers are owned by libretro implementation, and pointers must
|
/* All pointers are owned by libretro implementation, and pointers must
|
||||||
* remain valid until retro_deinit() is called. */
|
* remain valid until it is unloaded. */
|
||||||
|
|
||||||
const char *library_name; /* Descriptive name of library. Should not
|
const char *library_name; /* Descriptive name of library. Should not
|
||||||
* contain any version numbers, etc. */
|
* contain any version numbers, etc. */
|
||||||
|
@ -2501,7 +2842,21 @@ struct retro_core_option_display
|
||||||
bool visible;
|
bool visible;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Maximum number of values permitted for a core option */
|
/* Maximum number of values permitted for a core option
|
||||||
|
* > Note: We have to set a maximum value due the limitations
|
||||||
|
* of the C language - i.e. it is not possible to create an
|
||||||
|
* array of structs each containing a variable sized array,
|
||||||
|
* so the retro_core_option_definition values array must
|
||||||
|
* have a fixed size. The size limit of 128 is a balancing
|
||||||
|
* act - it needs to be large enough to support all 'sane'
|
||||||
|
* core options, but setting it too large may impact low memory
|
||||||
|
* platforms. In practise, if a core option has more than
|
||||||
|
* 128 values then the implementation is likely flawed.
|
||||||
|
* To quote the above API reference:
|
||||||
|
* "The number of possible options should be very limited
|
||||||
|
* i.e. it should be feasible to cycle through options
|
||||||
|
* without a keyboard."
|
||||||
|
*/
|
||||||
#define RETRO_NUM_CORE_OPTION_VALUES_MAX 128
|
#define RETRO_NUM_CORE_OPTION_VALUES_MAX 128
|
||||||
|
|
||||||
struct retro_core_option_value
|
struct retro_core_option_value
|
||||||
|
@ -2593,6 +2948,47 @@ struct retro_framebuffer
|
||||||
Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */
|
Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Used by a libretro core to override the current
|
||||||
|
* fastforwarding mode of the frontend */
|
||||||
|
struct retro_fastforwarding_override
|
||||||
|
{
|
||||||
|
/* Specifies the runtime speed multiplier that
|
||||||
|
* will be applied when 'fastforward' is true.
|
||||||
|
* For example, a value of 5.0 when running 60 FPS
|
||||||
|
* content will cap the fast-forward rate at 300 FPS.
|
||||||
|
* Note that the target multiplier may not be achieved
|
||||||
|
* if the host hardware has insufficient processing
|
||||||
|
* power.
|
||||||
|
* Setting a value of 0.0 (or greater than 0.0 but
|
||||||
|
* less than 1.0) will result in an uncapped
|
||||||
|
* fast-forward rate (limited only by hardware
|
||||||
|
* capacity).
|
||||||
|
* If the value is negative, it will be ignored
|
||||||
|
* (i.e. the frontend will use a runtime speed
|
||||||
|
* multiplier of its own choosing) */
|
||||||
|
float ratio;
|
||||||
|
|
||||||
|
/* If true, fastforwarding mode will be enabled.
|
||||||
|
* If false, fastforwarding mode will be disabled. */
|
||||||
|
bool fastforward;
|
||||||
|
|
||||||
|
/* If true, and if supported by the frontend, an
|
||||||
|
* on-screen notification will be displayed while
|
||||||
|
* 'fastforward' is true.
|
||||||
|
* If false, and if supported by the frontend, any
|
||||||
|
* on-screen fast-forward notifications will be
|
||||||
|
* suppressed */
|
||||||
|
bool notification;
|
||||||
|
|
||||||
|
/* If true, the core will have sole control over
|
||||||
|
* when fastforwarding mode is enabled/disabled;
|
||||||
|
* the frontend will not be able to change the
|
||||||
|
* state set by 'fastforward' until either
|
||||||
|
* 'inhibit_toggle' is set to false, or the core
|
||||||
|
* is unloaded */
|
||||||
|
bool inhibit_toggle;
|
||||||
|
};
|
||||||
|
|
||||||
/* Callbacks */
|
/* Callbacks */
|
||||||
|
|
||||||
/* Environment callback. Gives implementations a way of performing
|
/* Environment callback. Gives implementations a way of performing
|
||||||
|
|
1032
bsnes/target-libretro/libretro_core_options.h
Normal file
1032
bsnes/target-libretro/libretro_core_options.h
Normal file
File diff suppressed because it is too large
Load diff
90
bsnes/target-libretro/libretro_core_options_intl.h
Normal file
90
bsnes/target-libretro/libretro_core_options_intl.h
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
#ifndef LIBRETRO_CORE_OPTIONS_INTL_H__
|
||||||
|
#define LIBRETRO_CORE_OPTIONS_INTL_H__
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1500 && _MSC_VER < 1900)
|
||||||
|
/* https://support.microsoft.com/en-us/kb/980263 */
|
||||||
|
#pragma execution_character_set("utf-8")
|
||||||
|
#pragma warning(disable:4566)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "libretro.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
********************************
|
||||||
|
* VERSION: 1.3
|
||||||
|
********************************
|
||||||
|
*
|
||||||
|
* - 1.3: Move translations to libretro_core_options_intl.h
|
||||||
|
* - libretro_core_options_intl.h includes BOM and utf-8
|
||||||
|
* fix for MSVC 2010-2013
|
||||||
|
* - Added HAVE_NO_LANGEXTRA flag to disable translations
|
||||||
|
* on platforms/compilers without BOM support
|
||||||
|
* - 1.2: Use core options v1 interface when
|
||||||
|
* RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION is >= 1
|
||||||
|
* (previously required RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION == 1)
|
||||||
|
* - 1.1: Support generation of core options v0 retro_core_option_value
|
||||||
|
* arrays containing options with a single value
|
||||||
|
* - 1.0: First commit
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
********************************
|
||||||
|
* Core Option Definitions
|
||||||
|
********************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_JAPANESE */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_FRENCH */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_SPANISH */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_GERMAN */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_ITALIAN */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_DUTCH */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_RUSSIAN */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_KOREAN */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_CHINESE_TRADITIONAL */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_ESPERANTO */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_POLISH */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_VIETNAMESE */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_ARABIC */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_GREEK */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_TURKISH */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_SLOVAK */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_PERSIAN */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_HEBREW */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_ASTURIAN */
|
||||||
|
|
||||||
|
/* RETRO_LANGUAGE_FINNISH */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -48,7 +48,9 @@ struct Program : Emulator::Platform
|
||||||
|
|
||||||
auto hackPatchMemory(vector<uint8_t>& data) -> void;
|
auto hackPatchMemory(vector<uint8_t>& data) -> void;
|
||||||
|
|
||||||
auto applyPatchBPS(vector<uint8_t>& data, string location) -> bool;
|
auto applyPatchBPS(vector<uint8_t>& data, string location, string suffix) -> bool;
|
||||||
|
auto applyPatchIPS(vector<uint8_t>& data, string location, string suffix) -> bool;
|
||||||
|
auto applySettingOverrides() -> void;
|
||||||
vector<uint8_t> rso;
|
vector<uint8_t> rso;
|
||||||
|
|
||||||
string base_name;
|
string base_name;
|
||||||
|
@ -57,7 +59,7 @@ struct Program : Emulator::Platform
|
||||||
bool aspectcorrection = false;
|
bool aspectcorrection = false;
|
||||||
uint ws = 0;
|
uint ws = 0;
|
||||||
uint scale = 1;
|
uint scale = 1;
|
||||||
|
bool ipsHeadered = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Game {
|
struct Game {
|
||||||
|
@ -229,6 +231,12 @@ auto Program::load() -> void {
|
||||||
if (title == "ニチブツ・アーケード・クラシックス") emulator->configure("Hacks/Entropy", "None");
|
if (title == "ニチブツ・アーケード・クラシックス") emulator->configure("Hacks/Entropy", "None");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Program::applySettingOverrides();
|
||||||
|
|
||||||
|
emulator->power();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Program::applySettingOverrides() -> void {
|
||||||
// setting override processing (copied from standalone target)
|
// setting override processing (copied from standalone target)
|
||||||
if(rso) {
|
if(rso) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -250,12 +258,12 @@ auto Program::load() -> void {
|
||||||
n = (n * 10) + (v - '0');
|
n = (n * 10) + (v - '0');
|
||||||
if (i == rso.size() || rso[i] < '0' || rso[i] > '9') {
|
if (i == rso.size() || rso[i] < '0' || rso[i] > '9') {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
// case 'p': //pixelAspectCorrect 0:off 1:on
|
case 'p': //pixelAspectCorrect 0:off 1:on [libretro exclusive]
|
||||||
// emulator->configure("Video/AspectCorrection", n == 1);
|
aspectcorrection = n == 1;
|
||||||
// break;
|
break;
|
||||||
// case 'o': //overscan 0:216 1:224 (2:240 3:240f)
|
case 'o': //overscan 0:216 1:224 (2:240 3:240f) [libretro exclusive]
|
||||||
// emulator->configure("Video/Overscan", n == 1);
|
overscan = n == 1;
|
||||||
// break;
|
break;
|
||||||
case 'w': //widescreenMode 0:none 1:on 2:mode7
|
case 'w': //widescreenMode 0:none 1:on 2:mode7
|
||||||
emulator->configure("Hacks/PPU/Mode7/WsMode", n == 1 ? 2 : (n == 2 ? 1 : 0));
|
emulator->configure("Hacks/PPU/Mode7/WsMode", n == 1 ? 2 : (n == 2 ? 1 : 0));
|
||||||
break;
|
break;
|
||||||
|
@ -332,6 +340,15 @@ auto Program::load() -> void {
|
||||||
case 'S': //Stretch Window [for widescreen patches only]
|
case 'S': //Stretch Window [for widescreen patches only]
|
||||||
emulator->configure("Hacks/PPU/Mode7/Strwin", n == 2 );
|
emulator->configure("Hacks/PPU/Mode7/Strwin", n == 2 );
|
||||||
break;
|
break;
|
||||||
|
case 'v': //VRAM extension
|
||||||
|
emulator->configure("Hacks/PPU/Mode7/VramExt", n > 0 ? 0xffff : 0x7fff );
|
||||||
|
break;
|
||||||
|
case 'f': //Scale factor 0:disable 1-10:scale
|
||||||
|
emulator->configure("Hacks/PPU/Mode7/Scale", n >= 0 && n <= 10 ? n : 2);
|
||||||
|
break;
|
||||||
|
case 'l': //Disable sprite limit
|
||||||
|
emulator->configure("Hacks/PPU/NoSpriteLimit", n == 1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
c = -1;
|
c = -1;
|
||||||
n = 0;
|
n = 0;
|
||||||
|
@ -340,8 +357,6 @@ auto Program::load() -> void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// END OF setting override processing (copied from standalone target)
|
// END OF setting override processing (copied from standalone target)
|
||||||
|
|
||||||
emulator->power();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Program::load(uint id, string name, string type, vector<string> options) -> Emulator::Platform::Load {
|
auto Program::load(uint id, string name, string type, vector<string> options) -> Emulator::Platform::Load {
|
||||||
|
@ -611,7 +626,22 @@ auto Program::loadSuperFamicom(string location) -> bool
|
||||||
// soft patching (copied from standalone target)
|
// soft patching (copied from standalone target)
|
||||||
// note: soft patching should be done via the libretro frontend
|
// note: soft patching should be done via the libretro frontend
|
||||||
// so this is only a workaround until that is possible
|
// so this is only a workaround until that is possible
|
||||||
if(!superFamicom.patched) superFamicom.patched = applyPatchBPS(rom, location);
|
if (!superFamicom.patched) {
|
||||||
|
bool p = applyPatchBPS(rom, location, "") || applyPatchIPS(rom, location, "");
|
||||||
|
superFamicom.patched = p;
|
||||||
|
if (p) {
|
||||||
|
p = applyPatchBPS(rom, location, "1") || applyPatchIPS(rom, location, "1");
|
||||||
|
if (p) {
|
||||||
|
p = applyPatchBPS(rom, location, "2") || applyPatchIPS(rom, location, "2");
|
||||||
|
if (p) {
|
||||||
|
p = applyPatchBPS(rom, location, "3") || applyPatchIPS(rom, location, "3");
|
||||||
|
if (p) {
|
||||||
|
p = applyPatchBPS(rom, location, "4") || applyPatchIPS(rom, location, "4");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// END OF soft patching (copied from standalone target)
|
// END OF soft patching (copied from standalone target)
|
||||||
|
|
||||||
// setting override loading (copied from standalone target)
|
// setting override loading (copied from standalone target)
|
||||||
|
@ -896,26 +926,26 @@ auto decodeGB(string& code) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// soft patching (copied from standalone target), note: soft patching should be done via the libretro frontend, so this is only a workaround until that is possible
|
// soft patching (copied from standalone target), note: soft patching should be done via the libretro frontend, so this is only a workaround until that is possible
|
||||||
auto Program::applyPatchBPS(vector<uint8_t>& input, string location) -> bool {
|
auto Program::applyPatchBPS(vector<uint8_t>& input, string location, string suffix) -> bool {
|
||||||
vector<uint8_t> patch;
|
vector<uint8_t> patch;
|
||||||
|
|
||||||
if(location.endsWith("/")) {
|
if(location.endsWith("/")) {
|
||||||
patch = file::read({location, "patch.bps"});
|
patch = file::read({location, "patch.bps", suffix});
|
||||||
} else if(location.iendsWith(".zip")) {
|
} else if(location.iendsWith(".zip")) {
|
||||||
Decode::ZIP archive;
|
Decode::ZIP archive;
|
||||||
if(archive.open(location)) {
|
if(archive.open(location)) {
|
||||||
for(auto& file : archive.file) {
|
for(auto& file : archive.file) {
|
||||||
if(file.name.iendsWith(".bps")) {
|
if(file.name.iendsWith({".bps", suffix})) {
|
||||||
patch = archive.extract(file);
|
patch = archive.extract(file);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!patch) patch = file::read({Location::path(location),
|
if(!patch) patch = file::read({Location::path(location),
|
||||||
Location::prefix(Location::file(location)), ".bps"});
|
Location::prefix(Location::file(location)), ".bps", suffix});
|
||||||
} else {
|
} else {
|
||||||
patch = file::read({Location::path(location),
|
patch = file::read({Location::path(location),
|
||||||
Location::prefix(Location::file(location)), ".bps"});
|
Location::prefix(Location::file(location)), ".bps", suffix});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!patch) return false;
|
if(!patch) return false;
|
||||||
|
@ -931,4 +961,91 @@ auto Program::applyPatchBPS(vector<uint8_t>& input, string location) -> bool {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Program::applyPatchIPS(vector<uint8_t>& data, string location, string suffix) -> bool {
|
||||||
|
vector<uint8_t> patch;
|
||||||
|
|
||||||
|
if(location.endsWith("/")) {
|
||||||
|
patch = file::read({location, "patch.ips", suffix});
|
||||||
|
} else if(location.iendsWith(".zip")) {
|
||||||
|
Decode::ZIP archive;
|
||||||
|
if(archive.open(location)) {
|
||||||
|
for(auto& file : archive.file) {
|
||||||
|
if(file.name.iendsWith({".ips", suffix})) {
|
||||||
|
patch = archive.extract(file);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!patch) patch = file::read({Location::path(location),
|
||||||
|
Location::prefix(Location::file(location)), ".ips", suffix});
|
||||||
|
} else {
|
||||||
|
patch = file::read({Location::path(location),
|
||||||
|
Location::prefix(Location::file(location)), ".ips", suffix});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!patch) return false;
|
||||||
|
|
||||||
|
//sanity checks
|
||||||
|
if(patch.size() < 8) return false;
|
||||||
|
if(patch[0] != 'P') return false;
|
||||||
|
if(patch[1] != 'A') return false;
|
||||||
|
if(patch[2] != 'T') return false;
|
||||||
|
if(patch[3] != 'C') return false;
|
||||||
|
if(patch[4] != 'H') return false;
|
||||||
|
|
||||||
|
for(uint index = 5;;) {
|
||||||
|
if(index == patch.size() - 6) {
|
||||||
|
if(patch[index + 0] == 'E' && patch[index + 1] == 'O' && patch[index + 2] == 'F') {
|
||||||
|
uint32_t truncate = 0;
|
||||||
|
truncate |= patch[index + 3] << 16;
|
||||||
|
truncate |= patch[index + 4] << 8;
|
||||||
|
truncate |= patch[index + 5] << 0;
|
||||||
|
data.resize(truncate);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(index == patch.size() - 3) {
|
||||||
|
if(patch[index + 0] == 'E' && patch[index + 1] == 'O' && patch[index + 2] == 'F') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(index >= patch.size()) break;
|
||||||
|
|
||||||
|
int32_t offset = 0;
|
||||||
|
offset |= patch(index++, 0) << 16;
|
||||||
|
offset |= patch(index++, 0) << 8;
|
||||||
|
offset |= patch(index++, 0) << 0;
|
||||||
|
if(ipsHeadered) offset -= 512;
|
||||||
|
|
||||||
|
uint16_t length = 0;
|
||||||
|
length |= patch(index++, 0) << 8;
|
||||||
|
length |= patch(index++, 0) << 0;
|
||||||
|
|
||||||
|
if(length == 0) {
|
||||||
|
uint16_t repeat = 0;
|
||||||
|
repeat |= patch(index++, 0) << 8;
|
||||||
|
repeat |= patch(index++, 0) << 0;
|
||||||
|
|
||||||
|
uint8_t fill = patch(index++, 0);
|
||||||
|
|
||||||
|
while(repeat--) {
|
||||||
|
if(offset >= 0) data(offset) = fill;
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while(length--) {
|
||||||
|
if(offset >= 0) data(offset) = patch(index, 0);
|
||||||
|
offset++;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//"EOF" marker not found in correct place
|
||||||
|
//technically should return false, but be permissive (data was already modified)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// END OF soft patching (copied from standalone target)
|
// END OF soft patching (copied from standalone target)
|
|
@ -9,13 +9,13 @@ ifeq ($(platform),windows)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(hiro),gtk2)
|
ifeq ($(hiro),gtk2)
|
||||||
hiro.flags = $(flags.cpp) -DHIRO_GTK=2 $(shell pkg-config --cflags gtk+-2.0 gtksourceview-2.0)
|
hiro.flags = $(flags.cpp) -DHIRO_GTK=2 $(shell pkg-config --cflags gtk+-2.0)
|
||||||
hiro.options = $(shell pkg-config --libs gtk+-2.0 gtksourceview-2.0)
|
hiro.options = $(shell pkg-config --libs gtk+-2.0)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(hiro),gtk3)
|
ifeq ($(hiro),gtk3)
|
||||||
hiro.flags = $(flags.cpp) -DHIRO_GTK=3 $(shell pkg-config --cflags gtk+-3.0 gtksourceview-3.0) -Wno-deprecated-declarations
|
hiro.flags = $(flags.cpp) -DHIRO_GTK=3 $(shell pkg-config --cflags gtk+-3.0) -Wno-deprecated-declarations
|
||||||
hiro.options = $(shell pkg-config --libs gtk+-3.0 gtksourceview-3.0)
|
hiro.options = $(shell pkg-config --libs gtk+-3.0)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -36,13 +36,13 @@ ifneq ($(filter $(platform),linux bsd),)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(hiro),gtk2)
|
ifeq ($(hiro),gtk2)
|
||||||
hiro.flags = $(flags.cpp) -DHIRO_GTK=2 $(shell pkg-config --cflags gtk+-2.0 gtksourceview-2.0)
|
hiro.flags = $(flags.cpp) -DHIRO_GTK=2 $(shell pkg-config --cflags gtk+-2.0)
|
||||||
hiro.options = -L/usr/local/lib -lX11 $(shell pkg-config --libs gtk+-2.0 gtksourceview-2.0)
|
hiro.options = -L/usr/local/lib -lX11 $(shell pkg-config --libs gtk+-2.0)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(hiro),gtk3)
|
ifeq ($(hiro),gtk3)
|
||||||
hiro.flags = $(flags.cpp) -DHIRO_GTK=3 $(shell pkg-config --cflags gtk+-3.0 gtksourceview-3.0) -Wno-deprecated-declarations
|
hiro.flags = $(flags.cpp) -DHIRO_GTK=3 $(shell pkg-config --cflags gtk+-3.0) -Wno-deprecated-declarations
|
||||||
hiro.options = -L/usr/local/lib -lX11 $(shell pkg-config --libs gtk+-3.0 gtksourceview-3.0)
|
hiro.options = -L/usr/local/lib -lX11 $(shell pkg-config --libs gtk+-3.0)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(hiro),qt4)
|
ifeq ($(hiro),qt4)
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
#define Hiro_ProgressBar
|
#define Hiro_ProgressBar
|
||||||
#define Hiro_RadioButton
|
#define Hiro_RadioButton
|
||||||
#define Hiro_RadioLabel
|
#define Hiro_RadioLabel
|
||||||
#define Hiro_SourceEdit
|
//define Hiro_SourceEdit
|
||||||
#define Hiro_TabFrame
|
#define Hiro_TabFrame
|
||||||
#define Hiro_TableView
|
#define Hiro_TableView
|
||||||
#define Hiro_TextEdit
|
#define Hiro_TextEdit
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#define ConcatenateType(Size) uint##Size##_t
|
#define ConcatenateType(Size) uint##Size##_t
|
||||||
#define DeclareType(Size) ConcatenateType(Size)
|
#define DeclareType(Size) ConcatenateType(Size)
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -1,14 +1,17 @@
|
||||||
% SUPER METROID %
|
% SUPER METROID %
|
||||||
% ! with widescreen patch by ocesse ! %
|
% ! with widescreen patch by ocesse ! %
|
||||||
w : 1 % enabled widescreen permanently %
|
w : 1 % Widescreen : all %
|
||||||
W : 1609 % aspect ratio 16:9 %
|
W : 1609 % Aspect ratio : 16:9 %
|
||||||
P : 0 % disable pixel aspect ratio correction %
|
s : 1 % Widescreen sprites/objects : unsafe %
|
||||||
s : 1 % widescreen sprites/objects %
|
b : 2 % Background layer 1 : autoHor&Ver %
|
||||||
b : 2 % background layer 1 auto widescreen %
|
B : 1 % Background layer 2 : on %
|
||||||
B : 1 % background layer 2 on %
|
c : 2032 % Background layer 3 : widescreen below line 32 %
|
||||||
c : 2032 % background layer 3 widescreen below line 32 %
|
C : 2 % Background layer 4 : autoHor&Ver %
|
||||||
C : 2 % background layer 4 auto widescreen %
|
i : 0 % Ignore window : None %
|
||||||
i : 0 % disable ignore window %
|
m : 0 % Widescreen markers : off %
|
||||||
m : 0 % disable widescreen markers %
|
O : 200 % Overclock CPU : 200 percent %
|
||||||
O : 200 % overclock CPU to 200 percent %
|
S : 2 % Stretch windowing effects : on %
|
||||||
S : 2 % stretch windowing effects %
|
o : 0 % Show Overscan Area : off (affects RetroArch only) %
|
||||||
|
p : 0 % Pixel Aspect Ratio Correction : off (affects RetroArch only) %
|
||||||
|
l : 1 % PPU No sprite limit : on %
|
||||||
|
f : 1 % HD Mode 7 Scale : 1x (this is only an optimization) %
|
|
@ -1,11 +1,28 @@
|
||||||
|
|
||||||
Super Metroid widescreen patch
|
September 27, 2021
|
||||||
|
|
||||||
2021-23-05, by ocesse
|
Super Metroid (JU) [!] (UH) - Widescreen Patch v0.3.01 by ocesse
|
||||||
|
|
||||||
This folder contains a patch and a setting overrides file for Super Metroid (US+JP version).
|
This folder contains a patch and a setting overrides file for Super Metroid (JU) [!] (UH).
|
||||||
To use those, copy both to the same folder as the ROM and rename them to the same name as the ROM (except for the extensions ".bps" and ".bso").
|
|
||||||
(Since bsnes-hd 10.5 these instructions apply to the libretro core as well, so RetroArch users no longer have to manually patch the ROM or adjust the settings.)
|
Get the lastest bsnes-hd
|
||||||
|
https://github.com/DerKoun/bsnes-hd/releases
|
||||||
|
|
||||||
|
Instructions
|
||||||
|
1.- You need Super Metroid (JU) [!] (UH).smc (CRC32: D63ED5F8)
|
||||||
|
|
||||||
|
Be sure that your game, the Widescreen bps patch and the bso override configuration file have the same name, for example:
|
||||||
|
Super Metroid (JU) [!] (UH) - WS.smc (CRC32: D63ED5F8)
|
||||||
|
Super Metroid (JU) [!] (UH) - WS.bps
|
||||||
|
Super Metroid (JU) [!] (UH) - WS.bso
|
||||||
|
Put the three files in the same folder and open your smc game with bsnes_hd.exe
|
||||||
|
|
||||||
|
Or apply the Widescreen bps patch to Super Metroid (JU) [!] (UH).smc with a bps patcher like beat and rename it the same as the bso override file, for example:
|
||||||
|
Super Metroid (JU) [!] (UH) - WS Patched.smc (CRC32: E76A23D2)
|
||||||
|
Super Metroid (JU) [!] (UH) - WS Patched.bso
|
||||||
|
Put only the two files in the same folder, no bps patch here, and open your smc game with bsnes_hd.exe
|
||||||
|
|
||||||
|
The RetroArch core bsnes-hd now support softpatch and the bso override file.
|
||||||
|
|
||||||
The patch has been developed by ocesse. If you want to report issues, share ideas or just talk about widescreen patches join us on our Discord:
|
The patch has been developed by ocesse. If you want to report issues, share ideas or just talk about widescreen patches join us on our Discord:
|
||||||
https://discord.gg/7ahAzCV
|
https://discord.gg/7ahAzCV
|
||||||
|
@ -28,6 +45,7 @@ Lioran: Elevator speed change
|
||||||
http://metroidconstruction.com/resource.php?id=104
|
http://metroidconstruction.com/resource.php?id=104
|
||||||
|
|
||||||
snaphat: Overclocking fix for Super Metroid
|
snaphat: Overclocking fix for Super Metroid
|
||||||
|
Discord user: snaphat#7786
|
||||||
|
|
||||||
Near: bsnes developer
|
Near: bsnes developer
|
||||||
https://bsnes.dev/
|
https://bsnes.dev/
|
||||||
|
|
Loading…
Add table
Reference in a new issue