mirror of
https://github.com/DerKoun/bsnes-hd.git
synced 2024-05-16 11:10:51 -04:00
beta 10.6
This commit is contained in:
parent
d2d7815c25
commit
de27b9ea85
4
.github/workflows/CI.yml
vendored
4
.github/workflows/CI.yml
vendored
|
@ -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
|
||||
|
|
32
README.md
32
README.md
|
@ -1,4 +1,4 @@
|
|||
# bsnes-hd *beta 10.5*
|
||||
# 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 +19,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
|
||||
|
||||
|
@ -193,18 +193,22 @@ 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*) |
|
||||
| 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*) |
|
||||
| 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
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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*/];
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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] = {};
|
||||
|
||||
|
|
|
@ -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")))) {
|
||||
|
|
|
@ -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,12 +115,12 @@ 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);
|
||||
// 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;
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -504,6 +504,15 @@ static bool flush_variables() // returns whether video dimensions have changed (
|
|||
emulator->configure("Hacks/PPU/Mode7/WindRad", val);
|
||||
}
|
||||
|
||||
variable = { "bsnes_mode7_strWin", nullptr };
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &variable) && variable.value)
|
||||
{
|
||||
if (strcmp(variable.value, "ON") == 0)
|
||||
emulator->configure("Hacks/PPU/Mode7/Strwin", true);
|
||||
else if (strcmp(variable.value, "OFF") == 0)
|
||||
emulator->configure("Hacks/PPU/Mode7/StrwinE", false);
|
||||
}
|
||||
|
||||
bool aspectcorrection = program->aspectcorrection;
|
||||
variable = { "bsnes_video_aspectcorrection", nullptr };
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &variable) && variable.value)
|
||||
|
@ -536,6 +545,18 @@ static bool flush_variables() // returns whether video dimensions have changed (
|
|||
emulator->configure("Video/Gamma", val);
|
||||
}
|
||||
|
||||
variable = { "bsnes_ips_headered", nullptr };
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &variable) && variable.value)
|
||||
{
|
||||
if (strcmp(variable.value, "ON") == 0)
|
||||
program->ipsHeadered = true;
|
||||
else if (strcmp(variable.value, "OFF") == 0)
|
||||
program->ipsHeadered = false;
|
||||
}
|
||||
|
||||
//override with setting overrides (BSO) if any
|
||||
program->applySettingOverrides();
|
||||
|
||||
bool vc = program->overscan != overscan; // overscan changed
|
||||
program->overscan = overscan;
|
||||
vc = vc | program->aspectcorrection != aspectcorrection; // aspectcorrection changed
|
||||
|
@ -758,6 +779,8 @@ static void set_environment_info(retro_environment_t cb)
|
|||
{ "bsnes_video_luminance", "Luminance; 100|90|80|70|60|50|40|30|20|10|0" },
|
||||
{ "bsnes_video_saturation", "Saturation; 100|90|80|70|60|50|40|30|20|10|0|200|190|180|170|160|150|140|130|120|110" },
|
||||
{ "bsnes_video_gamma", "Gamma; 100|110|120|130|140|150|160|170|180|190|200" },
|
||||
{ "bsnes_mode7_strWin", "Stretch Window (For WideScreen Hacks Only!); OFF|ON" },
|
||||
{ "bsnes_ips_headered", "IPS Patches expect headered ROMs; OFF|ON" },
|
||||
{ nullptr },
|
||||
};
|
||||
cb(RETRO_ENVIRONMENT_SET_VARIABLES, const_cast<retro_variable *>(vars));
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue