Compare commits

...

10 commits

Author SHA1 Message Date
DerKoun
0bb7b8645e
Merge pull request #134 from warmenhoven/warmenhoven/pr/osx
Fix osx build
2024-10-21 22:26:17 +02:00
Eric Warmenhoven
4723fd00ca Fix osx build 2024-10-10 09:07:50 -04:00
DerKoun
f46b6d6368
Merge pull request #124 from heitbaum/patch-1
Fix build with gcc-13
2023-04-27 00:15:39 +02:00
Rudi Heitbaum
587e496f66
Fix build with gcc-13
Error was:
In file included from ../nall/arithmetic.hpp:69:
../nall/arithmetic/natural.hpp: In function 'void nall::div(const uint4096_t&, const uint4096_t&, uint4096_t&, uint4096_t&)':
../nall/arithmetic/natural.hpp:239:23: error: 'runtime_error' is not a member of 'std'
  239 |   if(!rhs) throw std::runtime_error("division by zero");
      |                       ^~~~~~~~~~~~~
../nall/arithmetic/natural.hpp:239:23: note: 'std::runtime_error' is defined in header '<stdexcept>'; did you forget to '#include <stdexcept>'?
2023-04-27 02:24:24 +10:00
DerKoun
04821703ae
Adding Linux ARM libretro build (thx @hunterk) 2022-06-29 22:53:50 +02:00
DerKoun
65f24e56c3 Update Super Metroid widescreen patch to v0.3.01 (by ocesse) 2021-10-16 20:48:29 +02:00
DerKoun
03cd4e11f1 Merge branch 'pr/87' 2021-06-25 23:19:34 +02:00
Ryunam
711a1e5b9c [Libretro] Upgrade Core Options to v1.3 2021-06-19 20:53:58 +02:00
DerKoun
0fd18e0f57
Added SMW WS likn to readme (until I package it with the next release) 2021-06-18 22:14:43 +02:00
DerKoun
de27b9ea85 beta 10.6 2021-06-17 23:03:05 +02:00
28 changed files with 2444 additions and 579 deletions

View file

@ -57,7 +57,7 @@ jobs:
- name: Setup
run: |
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
run: make -j $(nproc) -C bsnes
- name: Prepare artifacts
@ -85,7 +85,7 @@ jobs:
- name: Setup
run: |
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
run: make -j $(nproc) -C bsnes target=libretro
- name: Prepare artifacts
@ -101,6 +101,49 @@ jobs:
path: bsnes/out/pack
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:
runs-on: macos-latest
steps:

View file

@ -143,7 +143,7 @@ libretro-build-osx-arm64:
- .libretro-osx-arm64-make-default
- .core-defs-osx
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 #################################
# Android ARMv7a

View file

@ -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
- [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
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 demo](https://www.youtube.com/watch?v=IW7VOQKxtUQ) by *Emulators & Gameplay HD* (youtube)
### Widescreen
@ -194,17 +196,21 @@ The file must contain alternating letters and numbers, each pair overriding a se
#### Settings
| Description | Letter | Values |
| ----------------------------------- | ------- | ----------------------------------------------- |
| ----------------------------------- | ------- | ------------------------------------------------ |
| widescreen mode | w | 0:off 1:on(always) 2:on(mode7) |
| widescreen sprites | s | 0:safe 1:unsafe(widescreen) 2:clip |
| 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 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*) |
| scale factor | f | 0:off 1-10:factor |
| disable sprite limit | l | 0:off 1:on |
| ignore window | i | 0:none 1:outside 2:outside&always 3:all |
| 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

View file

@ -31,7 +31,7 @@ using namespace nall;
namespace Emulator {
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 License = "GPLv3";
static const string Website = "https://github.com/DerKoun/bsnes-hd";

View file

@ -433,13 +433,7 @@ auto SuperFamicom::serial() const -> string {
}
auto SuperFamicom::romSize() const -> uint {
//subtract appended firmware size, if firmware is present
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();
return size() - firmwareRomSize();
}
auto SuperFamicom::programRomSize() const -> uint {
@ -459,8 +453,38 @@ auto SuperFamicom::expansionRomSize() const -> uint {
return 0;
}
//detect if any firmware is appended to the ROM image, and return its size if so
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 {

View file

@ -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/Igwinx", hacks.ppu.mode7.igwinx);
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/WindRad", hacks.ppu.mode7.windRad);
bind(natural, "Hacks/PPU/Mode7/WsMode", hacks.ppu.mode7.wsMode);

View file

@ -58,6 +58,7 @@ struct Configuration {
uint igwin = 1;
uint igwinx = 128;
bool strwin = false;
uint vramExt = 0x7fff;
uint bgGrad = 4;
uint windRad = 0;
uint wsMode = 1;

View file

@ -115,7 +115,7 @@ auto PPU::Line::renderBackground(PPU::IO::Background& self, uint8 source) -> voi
tileNumber = (tileNumber & 0x03ff) + tiledataIndex & tileMask;
uint16 address;
address = (tileNumber << colorShift) + (voffset & 7 ^ mirrorY) & 0x7fff;
address = ppu.vramExt((tileNumber << colorShift) + (voffset & 7 ^ mirrorY)) /*& 0x7fff*/;
uint64 data;
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);
if(tileX & 0x20) offset += screenX;
if(tileY & 0x20) offset += screenY;
return ppu.vram[self.screenAddress + offset & 0x7fff];
return ppu.vram[ppu.vramExt(self.screenAddress + offset) /*& 0x7fff*/];
}

View file

@ -13,10 +13,10 @@ auto PPU::latchCounters() -> void {
auto PPU::vramAddress() const -> uint {
uint address = io.vramAddress;
switch(io.vramMapping) {
case 0: return address & 0x7fff;
case 1: return address & 0x7f00 | address << 3 & 0x00f8 | address >> 5 & 7;
case 2: return address & 0x7e00 | address << 3 & 0x01f8 | address >> 6 & 7;
case 3: return address & 0x7c00 | address << 3 & 0x03f8 | address >> 7 & 7;
case 0: return ppu.vramExt(address & 0xffff /*0x7fff*/);
case 1: return ppu.vramExt(address & 0xff00 /*0x7f00*/| address << 3 & 0x00f8 | address >> 5 & 7);
case 2: return ppu.vramExt(address & 0xfe00 /*0x7e00*/| address << 3 & 0x01f8 | address >> 6 & 7);
case 3: return ppu.vramExt(address & 0xfc00 /*0x7c00*/| address << 3 & 0x03f8 | address >> 7 & 7);
}
unreachable;
}
@ -263,37 +263,37 @@ auto PPU::writeIO(uint address, uint8 data) -> void {
case 0x2107: { //BG1SC
io.bg1.screenSize = data >> 0 & 3;
io.bg1.screenAddress = data << 8 & 0x7c00;
io.bg1.screenAddress = ppu.vramExt(data << 8 & 0xfc00) /*0x7c00*/;
return;
}
case 0x2108: { //BG2SC
io.bg2.screenSize = data >> 0 & 3;
io.bg2.screenAddress = data << 8 & 0x7c00;
io.bg2.screenAddress = ppu.vramExt(data << 8 & 0xfc00) /*0x7c00*/;
return;
}
case 0x2109: { //BG3SC
io.bg3.screenSize = data >> 0 & 3;
io.bg3.screenAddress = data << 8 & 0x7c00;
io.bg3.screenAddress = ppu.vramExt(data << 8 & 0xfc00) /*0x7c00*/;
return;
}
case 0x210a: { //BG4SC
io.bg4.screenSize = data >> 0 & 3;
io.bg4.screenAddress = data << 8 & 0x7c00;
io.bg4.screenAddress = ppu.vramExt(data << 8 & 0xfc00) /*0x7c00*/;
return;
}
case 0x210b: { //BG12NBA
io.bg1.tiledataAddress = data << 12 & 0x7000;
io.bg2.tiledataAddress = data << 8 & 0x7000;
io.bg1.tiledataAddress = ppu.vramExt(data << 12 & 0xf000) /*0x7000*/;
io.bg2.tiledataAddress = ppu.vramExt(data << 8 & 0xf000) /*0x7000*/;
return;
}
case 0x210c: { //BG34NBA
io.bg3.tiledataAddress = data << 12 & 0x7000;
io.bg4.tiledataAddress = data << 8 & 0x7000;
io.bg3.tiledataAddress = ppu.vramExt(data << 12 & 0xf000) /*0x7000*/;
io.bg4.tiledataAddress = ppu.vramExt(data << 8 & 0xf000) /*0x7000*/;
return;
}

View file

@ -88,7 +88,7 @@ auto PPU::Line::renderObject(PPU::IO::Object& self) -> void {
uint mirrorX = !object.hflip ? tileX : tileWidth - 1 - tileX;
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 + 8] << 16;

View file

@ -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.igwinx * PPU::hdScale() : x; }
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::windRad() const -> uint { return !hd() ? 0 : configuration.hacks.ppu.mode7.windRad; }
auto PPU::wsOverrideCandidate() const -> bool { return configuration.hacks.ppu.mode7.wsMode == 1; }

View file

@ -3,7 +3,6 @@
//limitations:
//* mid-scanline effects not support
//* vertical mosaic coordinates are not exact
//* (hardware-mod) 128KB VRAM mode not supported
#define PPU PPUfast
@ -25,6 +24,7 @@ struct PPU : PPUcounter {
alwaysinline auto winXad(uint x, bool bel) const -> uint;
alwaysinline auto winXadHd(uint x, bool bel) const -> uint;
alwaysinline auto strwin() const -> bool;
alwaysinline auto vramExt(uint addr) const -> uint;
alwaysinline auto bgGrad() const -> uint;
alwaysinline auto windRad() const -> uint;
alwaysinline auto wsOverrideCandidate() const -> bool;
@ -287,7 +287,7 @@ public:
Latch latch;
IO io;
uint16 vram[32 * 1024] = {};
uint16 vram[32 * 1024 * 2] = {}; //0-ffff
uint16 cgram[256] = {};
Object objects[128] = {};

View file

@ -123,8 +123,23 @@ auto Program::loadSuperFamicom(string location) -> bool {
rom.resize(rom.size() - 512);
}
if(!superFamicom.patched) superFamicom.patched = applyPatchIPS(rom, location);
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");
}
}
}
}
}
auto heuristics = Heuristics::SuperFamicom(rom, location);
auto sha256 = Hash::SHA256(rom).digest();
superFamicom.title = heuristics.title();
@ -199,7 +214,7 @@ auto Program::loadGameBoy(string location) -> bool {
}
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 sha256 = Hash::SHA256(rom).digest();
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;
bsMemory.patched = applyPatchIPS(rom, location) || applyPatchBPS(rom, location);
bsMemory.patched = applyPatchIPS(rom, location, "") || applyPatchBPS(rom, location, "");
auto heuristics = Heuristics::BSMemory(rom, location);
auto sha256 = Hash::SHA256(rom).digest();
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;
sufamiTurboA.patched = applyPatchIPS(rom, location) || applyPatchBPS(rom, location);
sufamiTurboA.patched = applyPatchIPS(rom, location, "") || applyPatchBPS(rom, location, "");
auto heuristics = Heuristics::SufamiTurbo(rom, location);
auto sha256 = Hash::SHA256(rom).digest();
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;
sufamiTurboB.patched = applyPatchIPS(rom, location) || applyPatchBPS(rom, location);
sufamiTurboB.patched = applyPatchIPS(rom, location, "") || applyPatchBPS(rom, location, "");
auto heuristics = Heuristics::SufamiTurbo(rom, location);
auto sha256 = Hash::SHA256(rom).digest();
if(auto document = BML::unserialize(string::read(locate("Database/Sufami Turbo.bml")))) {

View file

@ -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/Igwinx", settings.emulator.hack.ppu.mode7.igwinx);
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/WindRad", settings.emulator.hack.ppu.mode7.windRad);
emulator->configure("Hacks/PPU/Mode7/WsMode", settings.emulator.hack.ppu.mode7.wsMode);
@ -114,11 +115,11 @@ auto Program::hackCompatibility() -> void {
n = (n * 10) + (v - '0');
if (i == rso.size() || rso[i] < '0' || rso[i] > '9') {
switch (c) {
// case 'p': //pixelAspectCorrect 0:off 1:on
// emulator->configure("Video/AspectCorrection", n == 1);
// case 'p': //pixelAspectCorrect 0:off 1:on [libretro exclusive]
// aspectcorrection = n == 1;
// break;
// case 'o': //overscan 0:216 1:224 (2:240 3:240f)
// emulator->configure("Video/Overscan", n == 1);
// case 'o': //overscan 0:216 1:224 (2:240 3:240f) [libretro exclusive]
// overscan = n == 1;
// break;
case 'w': //widescreenMode 0:none 1:on 2:mode7
emulator->configure("Hacks/PPU/Mode7/WsMode", n == 1 ? 2 : (n == 2 ? 1 : 0));
@ -196,6 +197,15 @@ auto Program::hackCompatibility() -> void {
case 'S': //Stretch Window [for widescreen patches only]
emulator->configure("Hacks/PPU/Mode7/Strwin", n == 2 );
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;
n = 0;

View file

@ -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;
if(location.endsWith("/")) {
patch = file::read({location, "patch.ips"});
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")) {
if(file.name.iendsWith({".ips", suffix})) {
patch = archive.extract(file);
break;
}
}
}
if(!patch) patch = file::read(path("Patches", location, ".ips"));
if(!patch) patch = file::read(path("Patches", location, {".ips", suffix}));
} else {
patch = file::read(path("Patches", location, ".ips"));
patch = file::read(path("Patches", location, {".ips", suffix}));
}
if(!patch) return 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"
" 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"
@ -103,24 +103,24 @@ auto Program::applyPatchIPS(vector<uint8_t>& data, string location) -> bool {
#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;
if(location.endsWith("/")) {
patch = file::read({location, "patch.bps"});
patch = file::read({location, "patch.bps", suffix});
} else if(location.iendsWith(".zip")) {
Decode::ZIP archive;
if(archive.open(location)) {
for(auto& file : archive.file) {
if(file.name.iendsWith(".bps")) {
if(file.name.iendsWith({".bps", suffix})) {
patch = archive.extract(file);
break;
}
}
}
if(!patch) patch = file::read(path("Patches", location, ".bps"));
if(!patch) patch = file::read(path("Patches", location, {".bps", suffix}));
} else {
patch = file::read(path("Patches", location, ".bps"));
patch = file::read(path("Patches", location, {".bps", suffix}));
}
if(!patch) return false;

View file

@ -124,8 +124,8 @@ struct Program : Lock, Emulator::Platform {
//patch.cpp
auto appliedPatch() const -> bool;
auto applyPatchIPS(vector<uint8_t>& data, string location) -> bool;
auto applyPatchBPS(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, string suffix) -> bool;
//hacks.cpp
auto hackCompatibility() -> void;

View 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

View file

@ -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).
@ -69,7 +69,7 @@ extern "C" {
# endif
# endif
# else
# if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__CELLOS_LV2__)
# if defined(__GNUC__) && __GNUC__ >= 4
# define RETRO_API RETRO_CALLCONV __attribute__((__visibility__("default")))
# else
# define RETRO_API RETRO_CALLCONV
@ -278,6 +278,11 @@ enum retro_language
RETRO_LANGUAGE_ARABIC = 16,
RETRO_LANGUAGE_GREEK = 17,
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,
/* Ensure sizeof(enum) == sizeof(int) */
@ -708,6 +713,9 @@ enum retro_mod
* state of rumble motors in controllers.
* A strong and weak motor is supported, and they can be
* 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
/* uint64_t * --
@ -1117,7 +1125,7 @@ enum retro_mod
* This may be still be done regardless of the core options
* 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
* RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of
* retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL.
@ -1132,8 +1140,8 @@ enum retro_mod
* GET_VARIABLE.
* This allows the frontend to present these variables to
* a user dynamically.
* This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
* returns an API version of 1.
* This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION
* returns an API version of >= 1.
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
* This should be called the first time as early as
* possible (ideally in retro_set_environment).
@ -1194,8 +1202,8 @@ enum retro_mod
* GET_VARIABLE.
* This allows the frontend to present these variables to
* a user dynamically.
* This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
* returns an API version of 1.
* This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION
* returns an API version of >= 1.
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
* This should be called the first time as early as
* possible (ideally in retro_set_environment).
@ -1246,6 +1254,140 @@ enum retro_mod
* 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 */
/* File paths:
@ -1922,6 +2064,10 @@ enum retro_sensor_action
{
RETRO_SENSOR_ACCELEROMETER_ENABLE = 0,
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
};
@ -1930,6 +2076,10 @@ enum retro_sensor_action
#define RETRO_SENSOR_ACCELEROMETER_X 0
#define RETRO_SENSOR_ACCELEROMETER_Y 1
#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,
enum retro_sensor_action action, unsigned rate);
@ -2127,6 +2277,30 @@ struct retro_frame_time_callback
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.
* 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;
};
/* 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
* images in runtime.
*
@ -2345,6 +2520,53 @@ typedef bool (RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index,
* with replace_image_index. */
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
{
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;
};
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
{
/* 0RGB1555, native endian.
@ -2388,6 +2631,104 @@ struct retro_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
* to its internal input system through a human readable string.
* This string can be used to better let a user configure input. */
@ -2408,7 +2749,7 @@ struct retro_input_descriptor
struct retro_system_info
{
/* 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
* contain any version numbers, etc. */
@ -2501,7 +2842,21 @@ struct retro_core_option_display
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
struct retro_core_option_value
@ -2593,6 +2948,47 @@ struct retro_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 */
/* Environment callback. Gives implementations a way of performing

File diff suppressed because it is too large Load diff

View 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

View file

@ -48,7 +48,9 @@ struct Program : Emulator::Platform
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;
string base_name;
@ -57,7 +59,7 @@ struct Program : Emulator::Platform
bool aspectcorrection = false;
uint ws = 0;
uint scale = 1;
bool ipsHeadered = false;
public:
struct Game {
@ -229,6 +231,12 @@ auto Program::load() -> void {
if (title == "ニチブツ・アーケード・クラシックス") emulator->configure("Hacks/Entropy", "None");
}
Program::applySettingOverrides();
emulator->power();
}
auto Program::applySettingOverrides() -> void {
// setting override processing (copied from standalone target)
if(rso) {
int i = 0;
@ -250,12 +258,12 @@ auto Program::load() -> void {
n = (n * 10) + (v - '0');
if (i == rso.size() || rso[i] < '0' || rso[i] > '9') {
switch (c) {
// case 'p': //pixelAspectCorrect 0:off 1:on
// emulator->configure("Video/AspectCorrection", n == 1);
// break;
// case 'o': //overscan 0:216 1:224 (2:240 3:240f)
// emulator->configure("Video/Overscan", n == 1);
// break;
case 'p': //pixelAspectCorrect 0:off 1:on [libretro exclusive]
aspectcorrection = n == 1;
break;
case 'o': //overscan 0:216 1:224 (2:240 3:240f) [libretro exclusive]
overscan = n == 1;
break;
case 'w': //widescreenMode 0:none 1:on 2:mode7
emulator->configure("Hacks/PPU/Mode7/WsMode", n == 1 ? 2 : (n == 2 ? 1 : 0));
break;
@ -332,6 +340,15 @@ auto Program::load() -> void {
case 'S': //Stretch Window [for widescreen patches only]
emulator->configure("Hacks/PPU/Mode7/Strwin", n == 2 );
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;
n = 0;
@ -340,8 +357,6 @@ auto Program::load() -> void {
}
}
// 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 {
@ -611,7 +626,22 @@ auto Program::loadSuperFamicom(string location) -> 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
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)
// 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
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;
if(location.endsWith("/")) {
patch = file::read({location, "patch.bps"});
patch = file::read({location, "patch.bps", suffix});
} else if(location.iendsWith(".zip")) {
Decode::ZIP archive;
if(archive.open(location)) {
for(auto& file : archive.file) {
if(file.name.iendsWith(".bps")) {
if(file.name.iendsWith({".bps", suffix})) {
patch = archive.extract(file);
break;
}
}
}
if(!patch) patch = file::read({Location::path(location),
Location::prefix(Location::file(location)), ".bps"});
Location::prefix(Location::file(location)), ".bps", suffix});
} else {
patch = file::read({Location::path(location),
Location::prefix(Location::file(location)), ".bps"});
Location::prefix(Location::file(location)), ".bps", suffix});
}
if(!patch) return false;
@ -931,4 +961,91 @@ auto Program::applyPatchBPS(vector<uint8_t>& input, string location) -> bool {
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)

View file

@ -9,13 +9,13 @@ ifeq ($(platform),windows)
endif
ifeq ($(hiro),gtk2)
hiro.flags = $(flags.cpp) -DHIRO_GTK=2 $(shell pkg-config --cflags gtk+-2.0 gtksourceview-2.0)
hiro.options = $(shell pkg-config --libs 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)
endif
ifeq ($(hiro),gtk3)
hiro.flags = $(flags.cpp) -DHIRO_GTK=3 $(shell pkg-config --cflags gtk+-3.0 gtksourceview-3.0) -Wno-deprecated-declarations
hiro.options = $(shell pkg-config --libs gtk+-3.0 gtksourceview-3.0)
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)
endif
endif
@ -36,13 +36,13 @@ ifneq ($(filter $(platform),linux bsd),)
endif
ifeq ($(hiro),gtk2)
hiro.flags = $(flags.cpp) -DHIRO_GTK=2 $(shell pkg-config --cflags gtk+-2.0 gtksourceview-2.0)
hiro.options = -L/usr/local/lib -lX11 $(shell pkg-config --libs 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)
endif
ifeq ($(hiro),gtk3)
hiro.flags = $(flags.cpp) -DHIRO_GTK=3 $(shell pkg-config --cflags gtk+-3.0 gtksourceview-3.0) -Wno-deprecated-declarations
hiro.options = -L/usr/local/lib -lX11 $(shell pkg-config --libs gtk+-3.0 gtksourceview-3.0)
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)
endif
ifeq ($(hiro),qt4)

View file

@ -66,7 +66,7 @@
#define Hiro_ProgressBar
#define Hiro_RadioButton
#define Hiro_RadioLabel
#define Hiro_SourceEdit
//define Hiro_SourceEdit
#define Hiro_TabFrame
#define Hiro_TableView
#define Hiro_TextEdit

View file

@ -1,3 +1,5 @@
#include <stdexcept>
#define ConcatenateType(Size) uint##Size##_t
#define DeclareType(Size) ConcatenateType(Size)

View file

@ -1,14 +1,17 @@
% SUPER METROID %
% ! with widescreen patch by ocesse ! %
w : 1 % enabled widescreen permanently %
W : 1609 % aspect ratio 16:9 %
P : 0 % disable pixel aspect ratio correction %
s : 1 % widescreen sprites/objects %
b : 2 % background layer 1 auto widescreen %
B : 1 % background layer 2 on %
c : 2032 % background layer 3 widescreen below line 32 %
C : 2 % background layer 4 auto widescreen %
i : 0 % disable ignore window %
m : 0 % disable widescreen markers %
O : 200 % overclock CPU to 200 percent %
S : 2 % stretch windowing effects %
w : 1 % Widescreen : all %
W : 1609 % Aspect ratio : 16:9 %
s : 1 % Widescreen sprites/objects : unsafe %
b : 2 % Background layer 1 : autoHor&Ver %
B : 1 % Background layer 2 : on %
c : 2032 % Background layer 3 : widescreen below line 32 %
C : 2 % Background layer 4 : autoHor&Ver %
i : 0 % Ignore window : None %
m : 0 % Widescreen markers : off %
O : 200 % Overclock CPU : 200 percent %
S : 2 % Stretch windowing effects : on %
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) %

View file

@ -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).
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.)
This folder contains a patch and a setting overrides file for Super Metroid (JU) [!] (UH).
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:
https://discord.gg/7ahAzCV
@ -28,6 +45,7 @@ Lioran: Elevator speed change
http://metroidconstruction.com/resource.php?id=104
snaphat: Overclocking fix for Super Metroid
Discord user: snaphat#7786
Near: bsnes developer
https://bsnes.dev/