mirror of https://github.com/bsnes-emu/bsnes.git
Update to v097r21 release.
byuu says: Changelog: - icarus: WS/C detects RAM type/size heuristically now - icarus: WS/C uses ram type=$type instead of $type - WS: use back color instead of white for backdrop - WS: fixed sprite count limit; removes all the garbled sprites from GunPey - WS: hopefully fixed sprite priority with screen 2 - WS: implemented keypad polling; GunPey is now fully playable - SNES: added Super Disc expansion port device (doesn't do anything, just for testing) Note: WS is hard-coded to vertical orientation right now. But there's basic code in there for all the horizontal stuff.
This commit is contained in:
parent
570eb9c5f5
commit
b0d2f5033e
|
@ -6,7 +6,7 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "higan";
|
static const string Name = "higan";
|
||||||
static const string Version = "097.20";
|
static const string Version = "097.21";
|
||||||
static const string Author = "byuu";
|
static const string Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "http://byuu.org/";
|
static const string Website = "http://byuu.org/";
|
||||||
|
|
|
@ -410,8 +410,8 @@ auto R65816::disassemble_opcode(char* output, uint32 addr, bool e, bool m, bool
|
||||||
strcat(s, t);
|
strcat(s, t);
|
||||||
strcat(s, " ");
|
strcat(s, " ");
|
||||||
|
|
||||||
sprintf(t, "A:%.4x X:%.4x Y:%.4x S:%.4x D:%.4x DB:%.2x ",
|
sprintf(t, "A:%.4x X:%.4x Y:%.4x S:%.4x D:%.4x B:%.2x ",
|
||||||
regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d.w, regs.db);
|
regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d.w, (uint8_t)regs.db);
|
||||||
strcat(s, t);
|
strcat(s, t);
|
||||||
|
|
||||||
if(regs.e) {
|
if(regs.e) {
|
||||||
|
|
|
@ -3,7 +3,7 @@ processors += r65816 spc700 arm gsu hg51b upd96050
|
||||||
objects += sfc-interface sfc-system sfc-scheduler sfc-controller
|
objects += sfc-interface sfc-system sfc-scheduler sfc-controller
|
||||||
objects += sfc-cartridge sfc-cheat
|
objects += sfc-cartridge sfc-cheat
|
||||||
objects += sfc-memory sfc-cpu sfc-smp sfc-dsp sfc-ppu
|
objects += sfc-memory sfc-cpu sfc-smp sfc-dsp sfc-ppu
|
||||||
objects += sfc-satellaview sfc-eboot
|
objects += sfc-satellaview sfc-superdisc sfc-eboot
|
||||||
objects += sfc-icd2 sfc-mcc sfc-nss sfc-event
|
objects += sfc-icd2 sfc-mcc sfc-nss sfc-event
|
||||||
objects += sfc-sa1 sfc-superfx
|
objects += sfc-sa1 sfc-superfx
|
||||||
objects += sfc-armdsp sfc-hitachidsp sfc-necdsp
|
objects += sfc-armdsp sfc-hitachidsp sfc-necdsp
|
||||||
|
@ -47,6 +47,7 @@ obj/sfc-dsp.o: sfc/$(sfcdsp)/dsp.cpp $(call rwildcard,sfc/$(sfcdsp)/)
|
||||||
obj/sfc-ppu.o: sfc/$(sfcppu)/ppu.cpp $(call rwildcard,sfc/$(sfcppu)/)
|
obj/sfc-ppu.o: sfc/$(sfcppu)/ppu.cpp $(call rwildcard,sfc/$(sfcppu)/)
|
||||||
|
|
||||||
obj/sfc-satellaview.o: sfc/expansion/satellaview/satellaview.cpp $(call rwildcard,sfc/expansion/satellaview/)
|
obj/sfc-satellaview.o: sfc/expansion/satellaview/satellaview.cpp $(call rwildcard,sfc/expansion/satellaview/)
|
||||||
|
obj/sfc-superdisc.o: sfc/expansion/superdisc/superdisc.cpp $(call rwildcard,sfc/expansion/superdisc/)
|
||||||
obj/sfc-eboot.o: sfc/expansion/eboot/eboot.cpp $(call rwildcard,sfc/expansion/eboot/)
|
obj/sfc-eboot.o: sfc/expansion/eboot/eboot.cpp $(call rwildcard,sfc/expansion/eboot/)
|
||||||
|
|
||||||
obj/sfc-icd2.o: sfc/coprocessor/icd2/icd2.cpp $(call rwildcard,sfc/coprocessor/icd2/)
|
obj/sfc-icd2.o: sfc/coprocessor/icd2/icd2.cpp $(call rwildcard,sfc/coprocessor/icd2/)
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
#include <sfc/expansion/eboot/eboot.hpp>
|
|
||||||
#include <sfc/expansion/satellaview/satellaview.hpp>
|
#include <sfc/expansion/satellaview/satellaview.hpp>
|
||||||
|
#include <sfc/expansion/superdisc/superdisc.hpp>
|
||||||
|
#include <sfc/expansion/eboot/eboot.hpp>
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
#include <sfc/sfc.hpp>
|
||||||
|
|
||||||
|
namespace SuperFamicom {
|
||||||
|
|
||||||
|
SuperDisc superdisc;
|
||||||
|
|
||||||
|
auto SuperDisc::init() -> void {
|
||||||
|
}
|
||||||
|
|
||||||
|
auto SuperDisc::load() -> void {
|
||||||
|
bus.map({&SuperDisc::read, &superdisc}, {&SuperDisc::write, &superdisc}, 0x00, 0x3f, 0x21e0, 0x21e5);
|
||||||
|
bus.map({&SuperDisc::read, &superdisc}, {&SuperDisc::write, &superdisc}, 0x80, 0xbf, 0x21e0, 0x21e5);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto SuperDisc::unload() -> void {
|
||||||
|
}
|
||||||
|
|
||||||
|
auto SuperDisc::power() -> void {
|
||||||
|
}
|
||||||
|
|
||||||
|
auto SuperDisc::reset() -> void {
|
||||||
|
}
|
||||||
|
|
||||||
|
auto SuperDisc::read(uint24 addr, uint8 data) -> uint8 {
|
||||||
|
addr = 0x21e0 | (addr & 7);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto SuperDisc::write(uint24 addr, uint8 data) -> void {
|
||||||
|
addr = 0x21e0 | (addr & 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
struct SuperDisc : Memory {
|
||||||
|
auto init() -> void;
|
||||||
|
auto load() -> void;
|
||||||
|
auto unload() -> void;
|
||||||
|
auto power() -> void;
|
||||||
|
auto reset() -> void;
|
||||||
|
|
||||||
|
auto read(uint24 addr, uint8 data) -> uint8;
|
||||||
|
auto write(uint24 addr, uint8 data) -> void;
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
extern SuperDisc superdisc;
|
|
@ -117,7 +117,11 @@ Interface::Interface() {
|
||||||
this->device.append(device);
|
this->device.append(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
{ Device device{9, ID::ExpansionPort, "eBoot"};
|
{ Device device{9, ID::ExpansionPort, "Super Disc"};
|
||||||
|
this->device.append(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ Device device{10, ID::ExpansionPort, "eBoot"};
|
||||||
this->device.append(device);
|
this->device.append(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ struct Device {
|
||||||
|
|
||||||
//expansion port devices
|
//expansion port devices
|
||||||
Satellaview,
|
Satellaview,
|
||||||
|
SuperDisc,
|
||||||
eBoot,
|
eBoot,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ auto System::init() -> void {
|
||||||
assert(interface != nullptr);
|
assert(interface != nullptr);
|
||||||
|
|
||||||
satellaview.init();
|
satellaview.init();
|
||||||
|
superdisc.init();
|
||||||
eboot.init();
|
eboot.init();
|
||||||
|
|
||||||
icd2.init();
|
icd2.init();
|
||||||
|
@ -81,6 +82,7 @@ auto System::load() -> void {
|
||||||
ppu.enable();
|
ppu.enable();
|
||||||
|
|
||||||
if(expansionPort() == Device::ID::Satellaview) satellaview.load();
|
if(expansionPort() == Device::ID::Satellaview) satellaview.load();
|
||||||
|
if(expansionPort() == Device::ID::SuperDisc) superdisc.load();
|
||||||
if(expansionPort() == Device::ID::eBoot) eboot.load();
|
if(expansionPort() == Device::ID::eBoot) eboot.load();
|
||||||
|
|
||||||
if(cartridge.hasICD2()) icd2.load();
|
if(cartridge.hasICD2()) icd2.load();
|
||||||
|
@ -109,6 +111,7 @@ auto System::load() -> void {
|
||||||
auto System::unload() -> void {
|
auto System::unload() -> void {
|
||||||
if(!loaded()) return;
|
if(!loaded()) return;
|
||||||
if(expansionPort() == Device::ID::Satellaview) satellaview.unload();
|
if(expansionPort() == Device::ID::Satellaview) satellaview.unload();
|
||||||
|
if(expansionPort() == Device::ID::SuperDisc) superdisc.unload();
|
||||||
if(expansionPort() == Device::ID::eBoot) eboot.unload();
|
if(expansionPort() == Device::ID::eBoot) eboot.unload();
|
||||||
|
|
||||||
if(cartridge.hasICD2()) icd2.unload();
|
if(cartridge.hasICD2()) icd2.unload();
|
||||||
|
@ -143,6 +146,7 @@ auto System::power() -> void {
|
||||||
ppu.power();
|
ppu.power();
|
||||||
|
|
||||||
if(expansionPort() == Device::ID::Satellaview) satellaview.power();
|
if(expansionPort() == Device::ID::Satellaview) satellaview.power();
|
||||||
|
if(expansionPort() == Device::ID::SuperDisc) superdisc.power();
|
||||||
if(expansionPort() == Device::ID::eBoot) eboot.power();
|
if(expansionPort() == Device::ID::eBoot) eboot.power();
|
||||||
|
|
||||||
if(cartridge.hasICD2()) icd2.power();
|
if(cartridge.hasICD2()) icd2.power();
|
||||||
|
@ -173,6 +177,7 @@ auto System::reset() -> void {
|
||||||
ppu.reset();
|
ppu.reset();
|
||||||
|
|
||||||
if(expansionPort() == Device::ID::Satellaview) satellaview.reset();
|
if(expansionPort() == Device::ID::Satellaview) satellaview.reset();
|
||||||
|
if(expansionPort() == Device::ID::SuperDisc) superdisc.reset();
|
||||||
if(expansionPort() == Device::ID::eBoot) eboot.reset();
|
if(expansionPort() == Device::ID::eBoot) eboot.reset();
|
||||||
|
|
||||||
if(cartridge.hasICD2()) icd2.reset();
|
if(cartridge.hasICD2()) icd2.reset();
|
||||||
|
|
|
@ -41,6 +41,7 @@ auto Program::loadRequest(uint id, string filename, bool required) -> void {
|
||||||
auto Program::saveRequest(uint id, string filename) -> void {
|
auto Program::saveRequest(uint id, string filename) -> void {
|
||||||
string pathname = mediaPaths(emulator->group(id));
|
string pathname = mediaPaths(emulator->group(id));
|
||||||
string location = {pathname, filename};
|
string location = {pathname, filename};
|
||||||
|
if(!pathname) return; //should never occur
|
||||||
|
|
||||||
filestream stream{location, file::mode::write};
|
filestream stream{location, file::mode::write};
|
||||||
return emulator->save(id, stream);
|
return emulator->save(id, stream);
|
||||||
|
|
|
@ -23,6 +23,7 @@ auto Cartridge::load() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(auto node = document["board/ram"]) {
|
if(auto node = document["board/ram"]) {
|
||||||
|
if(node["type"].text() == "sram") {
|
||||||
ram.name = node["name"].text();
|
ram.name = node["name"].text();
|
||||||
ram.size = node["size"].natural();
|
ram.size = node["size"].natural();
|
||||||
ram.mask = bit::round(ram.size) - 1;
|
ram.mask = bit::round(ram.size) - 1;
|
||||||
|
@ -30,12 +31,13 @@ auto Cartridge::load() -> void {
|
||||||
if(ram.name) interface->loadRequest(ID::RAM, ram.name, false);
|
if(ram.name) interface->loadRequest(ID::RAM, ram.name, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(auto node = document["board/eeprom"]) {
|
if(node["type"].text() == "eeprom") {
|
||||||
eeprom.setName(node["name"].text());
|
eeprom.setName(node["name"].text());
|
||||||
eeprom.setSize(node["size"].natural() / sizeof(uint16));
|
eeprom.setSize(node["size"].natural() / sizeof(uint16));
|
||||||
eeprom.erase();
|
eeprom.erase();
|
||||||
if(eeprom.name()) interface->loadRequest(ID::EEPROM, eeprom.name(), false);
|
if(eeprom.name()) interface->loadRequest(ID::EEPROM, eeprom.name(), false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
information.title = document["information/title"].text();
|
information.title = document["information/title"].text();
|
||||||
information.sha256 = Hash::SHA256(rom.data, rom.size).digest();
|
information.sha256 = Hash::SHA256(rom.data, rom.size).digest();
|
||||||
|
|
|
@ -3,11 +3,11 @@ struct Cartridge : IO {
|
||||||
auto unload() -> void;
|
auto unload() -> void;
|
||||||
auto power() -> void;
|
auto power() -> void;
|
||||||
|
|
||||||
auto romRead(uint addr) -> uint8;
|
auto romRead(uint20 addr) -> uint8;
|
||||||
auto romWrite(uint addr, uint8 data) -> void;
|
auto romWrite(uint20 addr, uint8 data) -> void;
|
||||||
|
|
||||||
auto ramRead(uint addr) -> uint8;
|
auto ramRead(uint20 addr) -> uint8;
|
||||||
auto ramWrite(uint addr, uint8 data) -> void;
|
auto ramWrite(uint20 addr, uint8 data) -> void;
|
||||||
|
|
||||||
auto portRead(uint16 addr) -> uint8 override;
|
auto portRead(uint16 addr) -> uint8 override;
|
||||||
auto portWrite(uint16 addr, uint8 data) -> void override;
|
auto portWrite(uint16 addr, uint8 data) -> void override;
|
||||||
|
|
|
@ -1,26 +1,27 @@
|
||||||
//20000-fffff
|
//20000-fffff
|
||||||
auto Cartridge::romRead(uint addr) -> uint8 {
|
auto Cartridge::romRead(uint20 addr) -> uint8 {
|
||||||
switch((uint4)(addr >> 16)) {
|
|
||||||
case 2: addr = r.bank_rom0 << 16 | (uint16)addr; break; //20000-2ffff
|
|
||||||
case 3: addr = r.bank_rom1 << 16 | (uint16)addr; break; //30000-3ffff
|
|
||||||
default: addr = r.bank_rom2 << 20 | (uint20)addr; break; //40000-fffff
|
|
||||||
}
|
|
||||||
if(!rom.data) return 0x00;
|
if(!rom.data) return 0x00;
|
||||||
return rom.data[addr & rom.mask];
|
uint28 offset;
|
||||||
|
switch(addr.byte(2)) {
|
||||||
|
case 2: offset = r.bank_rom0 << 16 | addr.bits(0,15); break; //20000-2ffff
|
||||||
|
case 3: offset = r.bank_rom1 << 16 | addr.bits(0,15); break; //30000-3ffff
|
||||||
|
default: offset = r.bank_rom2 << 20 | addr.bits(0,19); break; //40000-fffff
|
||||||
|
}
|
||||||
|
return rom.data[offset & rom.mask];
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::romWrite(uint addr, uint8 data) -> void {
|
auto Cartridge::romWrite(uint20 addr, uint8 data) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
//10000-1ffff
|
//10000-1ffff
|
||||||
auto Cartridge::ramRead(uint addr) -> uint8 {
|
auto Cartridge::ramRead(uint20 addr) -> uint8 {
|
||||||
addr = r.bank_sram << 16 | (uint16)addr;
|
|
||||||
if(!ram.data) return 0x00;
|
if(!ram.data) return 0x00;
|
||||||
return ram.data[addr & ram.mask];
|
uint24 offset = r.bank_sram << 16 | addr.bits(0,15);
|
||||||
|
return ram.data[offset & ram.mask];
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::ramWrite(uint addr, uint8 data) -> void {
|
auto Cartridge::ramWrite(uint20 addr, uint8 data) -> void {
|
||||||
addr = r.bank_sram << 16 | (uint16)addr;
|
|
||||||
if(!ram.data) return;
|
if(!ram.data) return;
|
||||||
ram.data[addr & ram.mask] = data;
|
uint24 offset = r.bank_sram << 16 | addr.bits(0,15);
|
||||||
|
ram.data[offset & ram.mask] = data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ auto CPU::power() -> void {
|
||||||
iomap[0x00b0] = this;
|
iomap[0x00b0] = this;
|
||||||
iomap[0x00b2] = this;
|
iomap[0x00b2] = this;
|
||||||
iomap[0x00b4] = this;
|
iomap[0x00b4] = this;
|
||||||
|
iomap[0x00b5] = this;
|
||||||
iomap[0x00b6] = this;
|
iomap[0x00b6] = this;
|
||||||
|
|
||||||
if(WSC() || SC()) {
|
if(WSC() || SC()) {
|
||||||
|
|
|
@ -27,6 +27,7 @@ struct CPU : Processor::V30MZ, Thread, IO {
|
||||||
auto ramWrite(uint16 addr, uint8 data) -> void;
|
auto ramWrite(uint16 addr, uint8 data) -> void;
|
||||||
|
|
||||||
//io.cpp
|
//io.cpp
|
||||||
|
auto keypadRead() -> uint4;
|
||||||
auto portRead(uint16 addr) -> uint8 override;
|
auto portRead(uint16 addr) -> uint8 override;
|
||||||
auto portWrite(uint16 addr, uint8 data) -> void override;
|
auto portWrite(uint16 addr, uint8 data) -> void override;
|
||||||
|
|
||||||
|
@ -49,8 +50,8 @@ struct CPU : Processor::V30MZ, Thread, IO {
|
||||||
uint16 dmaLength;
|
uint16 dmaLength;
|
||||||
|
|
||||||
//$0048 DMA_CTRL
|
//$0048 DMA_CTRL
|
||||||
bool dmaEnable;
|
uint1 dmaEnable;
|
||||||
bool dmaMode; //0 = increment; 1 = decrement
|
uint1 dmaMode; //0 = increment; 1 = decrement
|
||||||
|
|
||||||
//$00b0 INT_BASE
|
//$00b0 INT_BASE
|
||||||
uint8 interruptBase;
|
uint8 interruptBase;
|
||||||
|
@ -60,6 +61,11 @@ struct CPU : Processor::V30MZ, Thread, IO {
|
||||||
|
|
||||||
//$00b4 INT_STATUS
|
//$00b4 INT_STATUS
|
||||||
uint8 interruptStatus;
|
uint8 interruptStatus;
|
||||||
|
|
||||||
|
//$00b5 KEYPAD
|
||||||
|
uint1 ypadEnable;
|
||||||
|
uint1 xpadEnable;
|
||||||
|
uint1 buttonEnable;
|
||||||
} r;
|
} r;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,30 @@
|
||||||
|
auto CPU::keypadRead() -> uint4 {
|
||||||
|
uint1 orientation = 1;
|
||||||
|
uint4 data = 0;
|
||||||
|
|
||||||
|
if(r.ypadEnable) {
|
||||||
|
data |= interface->inputPoll(orientation, 0, (uint)Keypad::Y1) << 0;
|
||||||
|
data |= interface->inputPoll(orientation, 0, (uint)Keypad::Y2) << 1;
|
||||||
|
data |= interface->inputPoll(orientation, 0, (uint)Keypad::Y3) << 2;
|
||||||
|
data |= interface->inputPoll(orientation, 0, (uint)Keypad::Y4) << 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(r.xpadEnable) {
|
||||||
|
data |= interface->inputPoll(orientation, 0, (uint)Keypad::X1) << 0;
|
||||||
|
data |= interface->inputPoll(orientation, 0, (uint)Keypad::X2) << 1;
|
||||||
|
data |= interface->inputPoll(orientation, 0, (uint)Keypad::X3) << 2;
|
||||||
|
data |= interface->inputPoll(orientation, 0, (uint)Keypad::X4) << 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(r.buttonEnable) {
|
||||||
|
data |= interface->inputPoll(orientation, 0, (uint)Keypad::Start) << 1;
|
||||||
|
data |= interface->inputPoll(orientation, 0, (uint)Keypad::A) << 2;
|
||||||
|
data |= interface->inputPoll(orientation, 0, (uint)Keypad::B) << 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
auto CPU::portRead(uint16 addr) -> uint8 {
|
auto CPU::portRead(uint16 addr) -> uint8 {
|
||||||
//DMA_SRC
|
//DMA_SRC
|
||||||
if(addr == 0x0040) return r.dmaSource.byte(0);
|
if(addr == 0x0040) return r.dmaSource.byte(0);
|
||||||
|
@ -42,6 +69,14 @@ auto CPU::portRead(uint16 addr) -> uint8 {
|
||||||
//INT_STATUS
|
//INT_STATUS
|
||||||
if(addr == 0x00b4) return r.interruptStatus;
|
if(addr == 0x00b4) return r.interruptStatus;
|
||||||
|
|
||||||
|
//KEYPAD
|
||||||
|
if(addr == 0x00b5) return (
|
||||||
|
keypadRead() << 0
|
||||||
|
| r.ypadEnable << 4
|
||||||
|
| r.xpadEnable << 5
|
||||||
|
| r.buttonEnable << 6
|
||||||
|
);
|
||||||
|
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +126,14 @@ auto CPU::portWrite(uint16 addr, uint8 data) -> void {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//KEYPAD
|
||||||
|
if(addr == 0x00b5) {
|
||||||
|
r.ypadEnable = data.bit(4);
|
||||||
|
r.xpadEnable = data.bit(5);
|
||||||
|
r.buttonEnable = data.bit(6);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//INT_ACK
|
//INT_ACK
|
||||||
if(addr == 0x00b6) {
|
if(addr == 0x00b6) {
|
||||||
r.interruptStatus &= ~data;
|
r.interruptStatus &= ~data;
|
||||||
|
|
|
@ -23,14 +23,14 @@ Interface::Interface() {
|
||||||
media.append({ID::WonderSwanColor, "WonderSwan Color", "wsc", true});
|
media.append({ID::WonderSwanColor, "WonderSwan Color", "wsc", true});
|
||||||
|
|
||||||
{ Device device{0, ID::DeviceHorizontal, "Controller"};
|
{ Device device{0, ID::DeviceHorizontal, "Controller"};
|
||||||
device.input.append({ 0, 0, "X1"});
|
device.input.append({ 0, 0, "Y1"});
|
||||||
device.input.append({ 1, 0, "X2"});
|
device.input.append({ 1, 0, "Y2"});
|
||||||
device.input.append({ 2, 0, "X3"});
|
device.input.append({ 2, 0, "Y3"});
|
||||||
device.input.append({ 3, 0, "X4"});
|
device.input.append({ 3, 0, "Y4"});
|
||||||
device.input.append({ 4, 0, "Y1"});
|
device.input.append({ 4, 0, "X1"});
|
||||||
device.input.append({ 5, 0, "Y2"});
|
device.input.append({ 5, 0, "X2"});
|
||||||
device.input.append({ 6, 0, "Y3"});
|
device.input.append({ 6, 0, "X3"});
|
||||||
device.input.append({ 7, 0, "Y4"});
|
device.input.append({ 7, 0, "X4"});
|
||||||
device.input.append({ 8, 0, "B"});
|
device.input.append({ 8, 0, "B"});
|
||||||
device.input.append({ 9, 0, "A"});
|
device.input.append({ 9, 0, "A"});
|
||||||
device.input.append({10, 0, "Start"});
|
device.input.append({10, 0, "Start"});
|
||||||
|
@ -39,14 +39,14 @@ Interface::Interface() {
|
||||||
}
|
}
|
||||||
|
|
||||||
{ Device device{1, ID::DeviceVertical, "Controller"};
|
{ Device device{1, ID::DeviceVertical, "Controller"};
|
||||||
device.input.append({ 0, 0, "X1"});
|
device.input.append({ 0, 0, "Y1"});
|
||||||
device.input.append({ 1, 0, "X2"});
|
device.input.append({ 1, 0, "Y2"});
|
||||||
device.input.append({ 2, 0, "X3"});
|
device.input.append({ 2, 0, "Y3"});
|
||||||
device.input.append({ 3, 0, "X4"});
|
device.input.append({ 3, 0, "Y4"});
|
||||||
device.input.append({ 4, 0, "Y1"});
|
device.input.append({ 4, 0, "X1"});
|
||||||
device.input.append({ 5, 0, "Y2"});
|
device.input.append({ 5, 0, "X2"});
|
||||||
device.input.append({ 6, 0, "Y3"});
|
device.input.append({ 6, 0, "X3"});
|
||||||
device.input.append({ 7, 0, "Y4"});
|
device.input.append({ 7, 0, "X4"});
|
||||||
device.input.append({ 8, 0, "B"});
|
device.input.append({ 8, 0, "B"});
|
||||||
device.input.append({ 9, 0, "A"});
|
device.input.append({ 9, 0, "A"});
|
||||||
device.input.append({10, 0, "Start"});
|
device.input.append({10, 0, "Start"});
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
namespace WonderSwan {
|
namespace WonderSwan {
|
||||||
|
|
||||||
uint8 iram[64 * 1024] = {0};
|
uint8 iram[64 * 1024];
|
||||||
IO* iomap[64 * 1024] = {0};
|
IO* iomap[64 * 1024] = {nullptr};
|
||||||
Bus bus;
|
Bus bus;
|
||||||
|
|
||||||
auto IO::power() -> void {
|
auto IO::power() -> void {
|
||||||
|
@ -21,15 +21,16 @@ auto IO::portWrite(uint16 addr, uint8 data) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Bus::read(uint20 addr) -> uint8 {
|
auto Bus::read(uint20 addr) -> uint8 {
|
||||||
if(addr < 0x10000) return cpu.ramRead(addr);
|
if(addr.bits(16,19) == 0) return cpu.ramRead(addr);
|
||||||
if(addr < 0x20000) return cartridge.ramRead(addr);
|
if(addr.bits(16,19) == 1) return cartridge.ramRead(addr);
|
||||||
return cartridge.romRead(addr);
|
if(addr.bits(16,19) >= 2) return cartridge.romRead(addr);
|
||||||
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Bus::write(uint20 addr, uint8 data) -> void {
|
auto Bus::write(uint20 addr, uint8 data) -> void {
|
||||||
if(addr < 0x10000) return cpu.ramWrite(addr, data);
|
if(addr.bits(16,19) == 0) return cpu.ramWrite(addr, data);
|
||||||
if(addr < 0x20000) return cartridge.ramWrite(addr, data);
|
if(addr.bits(16,19) == 1) return cartridge.ramWrite(addr, data);
|
||||||
return cartridge.romWrite(addr, data);
|
if(addr.bits(16,19) >= 2) return cartridge.romWrite(addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ auto PPU::Enter() -> void {
|
||||||
auto PPU::main() -> void {
|
auto PPU::main() -> void {
|
||||||
if(status.vclk < 144) {
|
if(status.vclk < 144) {
|
||||||
for(uint x = 0; x < 224; x++) {
|
for(uint x = 0; x < 224; x++) {
|
||||||
pixel = {Pixel::Source::None, 0xfff};
|
renderBack();
|
||||||
renderScreenOne();
|
renderScreenOne();
|
||||||
renderScreenTwo();
|
renderScreenTwo();
|
||||||
renderSprite();
|
renderSprite();
|
||||||
|
|
|
@ -13,6 +13,7 @@ struct PPU : Thread, IO {
|
||||||
auto portWrite(uint16 addr, uint8 data) -> void override;
|
auto portWrite(uint16 addr, uint8 data) -> void override;
|
||||||
|
|
||||||
//render.cpp
|
//render.cpp
|
||||||
|
auto renderBack() -> void;
|
||||||
auto renderScreenOne() -> void;
|
auto renderScreenOne() -> void;
|
||||||
auto renderScreenTwo() -> void;
|
auto renderScreenTwo() -> void;
|
||||||
auto renderSprite() -> void;
|
auto renderSprite() -> void;
|
||||||
|
@ -26,7 +27,7 @@ struct PPU : Thread, IO {
|
||||||
} status;
|
} status;
|
||||||
|
|
||||||
struct Pixel {
|
struct Pixel {
|
||||||
enum class Source : uint { None, ScreenOne, ScreenTwo, Sprite };
|
enum class Source : uint { Back, ScreenOne, ScreenTwo, Sprite };
|
||||||
Source source;
|
Source source;
|
||||||
uint12 color;
|
uint12 color;
|
||||||
} pixel;
|
} pixel;
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
auto PPU::renderBack() -> void {
|
||||||
|
uint4 poolColor = 15 - r.pool[r.backColorIndex];
|
||||||
|
pixel = {Pixel::Source::Back, poolColor << 0 | poolColor << 4 | poolColor << 8};
|
||||||
|
}
|
||||||
|
|
||||||
auto PPU::renderScreenOne() -> void {
|
auto PPU::renderScreenOne() -> void {
|
||||||
if(!r.screenOneEnable) return;
|
if(!r.screenOneEnable) return;
|
||||||
|
|
||||||
|
@ -81,7 +86,7 @@ auto PPU::renderSprite() -> void {
|
||||||
uint14 spriteBase = r.spriteBase << 9;
|
uint14 spriteBase = r.spriteBase << 9;
|
||||||
|
|
||||||
uint7 spriteIndex = r.spriteFirst;
|
uint7 spriteIndex = r.spriteFirst;
|
||||||
uint8 spriteCount = max(128, (uint)r.spriteCount);
|
uint8 spriteCount = min(128, (uint)r.spriteCount);
|
||||||
while(spriteCount--) {
|
while(spriteCount--) {
|
||||||
uint32 sprite;
|
uint32 sprite;
|
||||||
sprite.byte(0) = iram[spriteBase + (spriteIndex << 2) + 0];
|
sprite.byte(0) = iram[spriteBase + (spriteIndex << 2) + 0];
|
||||||
|
@ -91,7 +96,6 @@ auto PPU::renderSprite() -> void {
|
||||||
spriteIndex++;
|
spriteIndex++;
|
||||||
|
|
||||||
if(r.spriteWindowEnable && sprite.bit(12) && !windowInside) continue;
|
if(r.spriteWindowEnable && sprite.bit(12) && !windowInside) continue;
|
||||||
if(pixel.source == Pixel::Source::ScreenTwo && !sprite.bit(13)) continue;
|
|
||||||
|
|
||||||
uint8 spriteY = sprite.bits(16,23);
|
uint8 spriteY = sprite.bits(16,23);
|
||||||
uint8 spriteX = sprite.bits(24,31);
|
uint8 spriteX = sprite.bits(24,31);
|
||||||
|
@ -112,6 +116,7 @@ auto PPU::renderSprite() -> void {
|
||||||
uint2 tileColor = (d0 & tileMask ? 1 : 0) | (d1 & tileMask ? 2 : 0);
|
uint2 tileColor = (d0 & tileMask ? 1 : 0) | (d1 & tileMask ? 2 : 0);
|
||||||
|
|
||||||
if(sprite.bit(11) && tileColor == 0) continue;
|
if(sprite.bit(11) && tileColor == 0) continue;
|
||||||
|
if(!sprite.bit(13) && pixel.source == Pixel::Source::ScreenTwo) continue;
|
||||||
uint3 paletteColor = r.palette[8 + sprite.bits(9,11)].color[tileColor];
|
uint3 paletteColor = r.palette[8 + sprite.bits(9,11)].color[tileColor];
|
||||||
uint4 poolColor = 15 - r.pool[paletteColor];
|
uint4 poolColor = 15 - r.pool[paletteColor];
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
enum class Keypad : uint {
|
||||||
|
Y1, Y2, Y3, Y4,
|
||||||
|
X1, X2, X3, X4,
|
||||||
|
B, A, Start,
|
||||||
|
};
|
||||||
|
|
||||||
struct System : IO {
|
struct System : IO {
|
||||||
enum class Revision : uint {
|
enum class Revision : uint {
|
||||||
WonderSwan, //SW-001 (ASWAN)
|
WonderSwan, //SW-001 (ASWAN)
|
||||||
|
|
|
@ -18,7 +18,7 @@ auto Icarus::wonderSwanColorManifest(vector<uint8_t>& buffer, string location) -
|
||||||
}
|
}
|
||||||
|
|
||||||
if(settings["icarus/UseHeuristics"].boolean() && !manifest) {
|
if(settings["icarus/UseHeuristics"].boolean() && !manifest) {
|
||||||
WonderSwanColorCartridge cartridge{buffer.data(), buffer.size()};
|
WonderSwanCartridge cartridge{buffer.data(), buffer.size()};
|
||||||
if(manifest = cartridge.manifest) {
|
if(manifest = cartridge.manifest) {
|
||||||
manifest.append("\n");
|
manifest.append("\n");
|
||||||
manifest.append("information\n");
|
manifest.append("information\n");
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
struct WonderSwanColorCartridge {
|
|
||||||
WonderSwanColorCartridge(uint8_t* data, uint size);
|
|
||||||
|
|
||||||
string manifest;
|
|
||||||
|
|
||||||
//private:
|
|
||||||
struct Information {
|
|
||||||
} information;
|
|
||||||
};
|
|
||||||
|
|
||||||
WonderSwanColorCartridge::WonderSwanColorCartridge(uint8_t* data, uint size) {
|
|
||||||
if(size < 0x10000) return;
|
|
||||||
|
|
||||||
manifest.append("board\n");
|
|
||||||
manifest.append(" rom name=program.rom size=0x", hex(size), "\n");
|
|
||||||
}
|
|
|
@ -5,12 +5,34 @@ struct WonderSwanCartridge {
|
||||||
|
|
||||||
//private:
|
//private:
|
||||||
struct Information {
|
struct Information {
|
||||||
|
bool color;
|
||||||
|
|
||||||
|
string ramType;
|
||||||
|
uint ramSize;
|
||||||
} information;
|
} information;
|
||||||
};
|
};
|
||||||
|
|
||||||
WonderSwanCartridge::WonderSwanCartridge(uint8_t* data, uint size) {
|
WonderSwanCartridge::WonderSwanCartridge(uint8_t* data, uint size) {
|
||||||
if(size < 0x10000) return;
|
if(size < 0x10000) return;
|
||||||
|
|
||||||
|
auto metadata = data + size - 16;
|
||||||
|
|
||||||
|
information.color = metadata[7];
|
||||||
|
|
||||||
|
switch(metadata[11]) {
|
||||||
|
default: information.ramType = ""; information.ramSize = 0; break;
|
||||||
|
case 0x01: information.ramType = "sram"; information.ramSize = 8 * 1024; break;
|
||||||
|
case 0x02: information.ramType = "sram"; information.ramSize = 32 * 1024; break;
|
||||||
|
case 0x03: information.ramType = "sram"; information.ramSize = 128 * 1024; break;
|
||||||
|
case 0x04: information.ramType = "sram"; information.ramSize = 256 * 1024; break;
|
||||||
|
case 0x05: information.ramType = "sram"; information.ramSize = 512 * 1024; break;
|
||||||
|
case 0x10: information.ramType = "eeprom"; information.ramSize = 128; break;
|
||||||
|
case 0x20: information.ramType = "eeprom"; information.ramSize = 2048; break;
|
||||||
|
case 0x50: information.ramType = "eeprom"; information.ramSize = 1024; break;
|
||||||
|
}
|
||||||
|
|
||||||
manifest.append("board\n");
|
manifest.append("board\n");
|
||||||
manifest.append(" rom name=program.rom size=0x", hex(size), "\n");
|
manifest.append(" rom name=program.rom size=0x", hex(size), "\n");
|
||||||
|
if(information.ramType && information.ramSize)
|
||||||
|
manifest.append(" ram name=save.ram type=", information.ramType, " size=0x", hex(information.ramSize), "\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ Settings settings;
|
||||||
#include "heuristics/game-boy.cpp"
|
#include "heuristics/game-boy.cpp"
|
||||||
#include "heuristics/game-boy-advance.cpp"
|
#include "heuristics/game-boy-advance.cpp"
|
||||||
#include "heuristics/wonderswan.cpp"
|
#include "heuristics/wonderswan.cpp"
|
||||||
#include "heuristics/wonderswan-color.cpp"
|
|
||||||
#include "heuristics/bs-memory.cpp"
|
#include "heuristics/bs-memory.cpp"
|
||||||
#include "heuristics/sufami-turbo.cpp"
|
#include "heuristics/sufami-turbo.cpp"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue