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:
Tim Allen 2016-03-02 22:19:33 +11:00
parent 570eb9c5f5
commit b0d2f5033e
26 changed files with 214 additions and 83 deletions

View File

@ -6,7 +6,7 @@ using namespace nall;
namespace Emulator {
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 License = "GPLv3";
static const string Website = "http://byuu.org/";

View File

@ -410,8 +410,8 @@ auto R65816::disassemble_opcode(char* output, uint32 addr, bool e, bool m, bool
strcat(s, t);
strcat(s, " ");
sprintf(t, "A:%.4x X:%.4x Y:%.4x S:%.4x D:%.4x DB:%.2x ",
regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d.w, regs.db);
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, (uint8_t)regs.db);
strcat(s, t);
if(regs.e) {

View File

@ -3,7 +3,7 @@ processors += r65816 spc700 arm gsu hg51b upd96050
objects += sfc-interface sfc-system sfc-scheduler sfc-controller
objects += sfc-cartridge sfc-cheat
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-sa1 sfc-superfx
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-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-icd2.o: sfc/coprocessor/icd2/icd2.cpp $(call rwildcard,sfc/coprocessor/icd2/)

View File

@ -1,2 +1,3 @@
#include <sfc/expansion/eboot/eboot.hpp>
#include <sfc/expansion/satellaview/satellaview.hpp>
#include <sfc/expansion/superdisc/superdisc.hpp>
#include <sfc/expansion/eboot/eboot.hpp>

View File

@ -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);
}
}

View File

@ -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;

View File

@ -117,7 +117,11 @@ Interface::Interface() {
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);
}

View File

@ -19,6 +19,7 @@ struct Device {
//expansion port devices
Satellaview,
SuperDisc,
eBoot,
};

View File

@ -32,6 +32,7 @@ auto System::init() -> void {
assert(interface != nullptr);
satellaview.init();
superdisc.init();
eboot.init();
icd2.init();
@ -81,6 +82,7 @@ auto System::load() -> void {
ppu.enable();
if(expansionPort() == Device::ID::Satellaview) satellaview.load();
if(expansionPort() == Device::ID::SuperDisc) superdisc.load();
if(expansionPort() == Device::ID::eBoot) eboot.load();
if(cartridge.hasICD2()) icd2.load();
@ -109,6 +111,7 @@ auto System::load() -> void {
auto System::unload() -> void {
if(!loaded()) return;
if(expansionPort() == Device::ID::Satellaview) satellaview.unload();
if(expansionPort() == Device::ID::SuperDisc) superdisc.unload();
if(expansionPort() == Device::ID::eBoot) eboot.unload();
if(cartridge.hasICD2()) icd2.unload();
@ -143,6 +146,7 @@ auto System::power() -> void {
ppu.power();
if(expansionPort() == Device::ID::Satellaview) satellaview.power();
if(expansionPort() == Device::ID::SuperDisc) superdisc.power();
if(expansionPort() == Device::ID::eBoot) eboot.power();
if(cartridge.hasICD2()) icd2.power();
@ -173,6 +177,7 @@ auto System::reset() -> void {
ppu.reset();
if(expansionPort() == Device::ID::Satellaview) satellaview.reset();
if(expansionPort() == Device::ID::SuperDisc) superdisc.reset();
if(expansionPort() == Device::ID::eBoot) eboot.reset();
if(cartridge.hasICD2()) icd2.reset();

View File

@ -41,6 +41,7 @@ auto Program::loadRequest(uint id, string filename, bool required) -> void {
auto Program::saveRequest(uint id, string filename) -> void {
string pathname = mediaPaths(emulator->group(id));
string location = {pathname, filename};
if(!pathname) return; //should never occur
filestream stream{location, file::mode::write};
return emulator->save(id, stream);

View File

@ -23,18 +23,20 @@ auto Cartridge::load() -> void {
}
if(auto node = document["board/ram"]) {
ram.name = node["name"].text();
ram.size = node["size"].natural();
ram.mask = bit::round(ram.size) - 1;
if(ram.size) ram.data = new uint8[ram.mask + 1]();
if(ram.name) interface->loadRequest(ID::RAM, ram.name, false);
}
if(node["type"].text() == "sram") {
ram.name = node["name"].text();
ram.size = node["size"].natural();
ram.mask = bit::round(ram.size) - 1;
if(ram.size) ram.data = new uint8[ram.mask + 1]();
if(ram.name) interface->loadRequest(ID::RAM, ram.name, false);
}
if(auto node = document["board/eeprom"]) {
eeprom.setName(node["name"].text());
eeprom.setSize(node["size"].natural() / sizeof(uint16));
eeprom.erase();
if(eeprom.name()) interface->loadRequest(ID::EEPROM, eeprom.name(), false);
if(node["type"].text() == "eeprom") {
eeprom.setName(node["name"].text());
eeprom.setSize(node["size"].natural() / sizeof(uint16));
eeprom.erase();
if(eeprom.name()) interface->loadRequest(ID::EEPROM, eeprom.name(), false);
}
}
information.title = document["information/title"].text();

View File

@ -3,11 +3,11 @@ struct Cartridge : IO {
auto unload() -> void;
auto power() -> void;
auto romRead(uint addr) -> uint8;
auto romWrite(uint addr, uint8 data) -> void;
auto romRead(uint20 addr) -> uint8;
auto romWrite(uint20 addr, uint8 data) -> void;
auto ramRead(uint addr) -> uint8;
auto ramWrite(uint addr, uint8 data) -> void;
auto ramRead(uint20 addr) -> uint8;
auto ramWrite(uint20 addr, uint8 data) -> void;
auto portRead(uint16 addr) -> uint8 override;
auto portWrite(uint16 addr, uint8 data) -> void override;

View File

@ -1,26 +1,27 @@
//20000-fffff
auto Cartridge::romRead(uint 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
}
auto Cartridge::romRead(uint20 addr) -> uint8 {
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
auto Cartridge::ramRead(uint addr) -> uint8 {
addr = r.bank_sram << 16 | (uint16)addr;
auto Cartridge::ramRead(uint20 addr) -> uint8 {
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 {
addr = r.bank_sram << 16 | (uint16)addr;
auto Cartridge::ramWrite(uint20 addr, uint8 data) -> void {
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;
}

View File

@ -53,6 +53,7 @@ auto CPU::power() -> void {
iomap[0x00b0] = this;
iomap[0x00b2] = this;
iomap[0x00b4] = this;
iomap[0x00b5] = this;
iomap[0x00b6] = this;
if(WSC() || SC()) {

View File

@ -27,6 +27,7 @@ struct CPU : Processor::V30MZ, Thread, IO {
auto ramWrite(uint16 addr, uint8 data) -> void;
//io.cpp
auto keypadRead() -> uint4;
auto portRead(uint16 addr) -> uint8 override;
auto portWrite(uint16 addr, uint8 data) -> void override;
@ -49,8 +50,8 @@ struct CPU : Processor::V30MZ, Thread, IO {
uint16 dmaLength;
//$0048 DMA_CTRL
bool dmaEnable;
bool dmaMode; //0 = increment; 1 = decrement
uint1 dmaEnable;
uint1 dmaMode; //0 = increment; 1 = decrement
//$00b0 INT_BASE
uint8 interruptBase;
@ -60,6 +61,11 @@ struct CPU : Processor::V30MZ, Thread, IO {
//$00b4 INT_STATUS
uint8 interruptStatus;
//$00b5 KEYPAD
uint1 ypadEnable;
uint1 xpadEnable;
uint1 buttonEnable;
} r;
};

View File

@ -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 {
//DMA_SRC
if(addr == 0x0040) return r.dmaSource.byte(0);
@ -42,6 +69,14 @@ auto CPU::portRead(uint16 addr) -> uint8 {
//INT_STATUS
if(addr == 0x00b4) return r.interruptStatus;
//KEYPAD
if(addr == 0x00b5) return (
keypadRead() << 0
| r.ypadEnable << 4
| r.xpadEnable << 5
| r.buttonEnable << 6
);
return 0x00;
}
@ -91,6 +126,14 @@ auto CPU::portWrite(uint16 addr, uint8 data) -> void {
return;
}
//KEYPAD
if(addr == 0x00b5) {
r.ypadEnable = data.bit(4);
r.xpadEnable = data.bit(5);
r.buttonEnable = data.bit(6);
return;
}
//INT_ACK
if(addr == 0x00b6) {
r.interruptStatus &= ~data;

View File

@ -23,14 +23,14 @@ Interface::Interface() {
media.append({ID::WonderSwanColor, "WonderSwan Color", "wsc", true});
{ Device device{0, ID::DeviceHorizontal, "Controller"};
device.input.append({ 0, 0, "X1"});
device.input.append({ 1, 0, "X2"});
device.input.append({ 2, 0, "X3"});
device.input.append({ 3, 0, "X4"});
device.input.append({ 4, 0, "Y1"});
device.input.append({ 5, 0, "Y2"});
device.input.append({ 6, 0, "Y3"});
device.input.append({ 7, 0, "Y4"});
device.input.append({ 0, 0, "Y1"});
device.input.append({ 1, 0, "Y2"});
device.input.append({ 2, 0, "Y3"});
device.input.append({ 3, 0, "Y4"});
device.input.append({ 4, 0, "X1"});
device.input.append({ 5, 0, "X2"});
device.input.append({ 6, 0, "X3"});
device.input.append({ 7, 0, "X4"});
device.input.append({ 8, 0, "B"});
device.input.append({ 9, 0, "A"});
device.input.append({10, 0, "Start"});
@ -39,14 +39,14 @@ Interface::Interface() {
}
{ Device device{1, ID::DeviceVertical, "Controller"};
device.input.append({ 0, 0, "X1"});
device.input.append({ 1, 0, "X2"});
device.input.append({ 2, 0, "X3"});
device.input.append({ 3, 0, "X4"});
device.input.append({ 4, 0, "Y1"});
device.input.append({ 5, 0, "Y2"});
device.input.append({ 6, 0, "Y3"});
device.input.append({ 7, 0, "Y4"});
device.input.append({ 0, 0, "Y1"});
device.input.append({ 1, 0, "Y2"});
device.input.append({ 2, 0, "Y3"});
device.input.append({ 3, 0, "Y4"});
device.input.append({ 4, 0, "X1"});
device.input.append({ 5, 0, "X2"});
device.input.append({ 6, 0, "X3"});
device.input.append({ 7, 0, "X4"});
device.input.append({ 8, 0, "B"});
device.input.append({ 9, 0, "A"});
device.input.append({10, 0, "Start"});

View File

@ -2,8 +2,8 @@
namespace WonderSwan {
uint8 iram[64 * 1024] = {0};
IO* iomap[64 * 1024] = {0};
uint8 iram[64 * 1024];
IO* iomap[64 * 1024] = {nullptr};
Bus bus;
auto IO::power() -> void {
@ -21,15 +21,16 @@ auto IO::portWrite(uint16 addr, uint8 data) -> void {
}
auto Bus::read(uint20 addr) -> uint8 {
if(addr < 0x10000) return cpu.ramRead(addr);
if(addr < 0x20000) return cartridge.ramRead(addr);
return cartridge.romRead(addr);
if(addr.bits(16,19) == 0) return cpu.ramRead(addr);
if(addr.bits(16,19) == 1) return cartridge.ramRead(addr);
if(addr.bits(16,19) >= 2) return cartridge.romRead(addr);
unreachable;
}
auto Bus::write(uint20 addr, uint8 data) -> void {
if(addr < 0x10000) return cpu.ramWrite(addr, data);
if(addr < 0x20000) return cartridge.ramWrite(addr, data);
return cartridge.romWrite(addr, data);
if(addr.bits(16,19) == 0) return cpu.ramWrite(addr, data);
if(addr.bits(16,19) == 1) return cartridge.ramWrite(addr, data);
if(addr.bits(16,19) >= 2) return cartridge.romWrite(addr, data);
}
}

View File

@ -14,7 +14,7 @@ auto PPU::Enter() -> void {
auto PPU::main() -> void {
if(status.vclk < 144) {
for(uint x = 0; x < 224; x++) {
pixel = {Pixel::Source::None, 0xfff};
renderBack();
renderScreenOne();
renderScreenTwo();
renderSprite();

View File

@ -13,6 +13,7 @@ struct PPU : Thread, IO {
auto portWrite(uint16 addr, uint8 data) -> void override;
//render.cpp
auto renderBack() -> void;
auto renderScreenOne() -> void;
auto renderScreenTwo() -> void;
auto renderSprite() -> void;
@ -26,7 +27,7 @@ struct PPU : Thread, IO {
} status;
struct Pixel {
enum class Source : uint { None, ScreenOne, ScreenTwo, Sprite };
enum class Source : uint { Back, ScreenOne, ScreenTwo, Sprite };
Source source;
uint12 color;
} pixel;

View File

@ -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 {
if(!r.screenOneEnable) return;
@ -81,7 +86,7 @@ auto PPU::renderSprite() -> void {
uint14 spriteBase = r.spriteBase << 9;
uint7 spriteIndex = r.spriteFirst;
uint8 spriteCount = max(128, (uint)r.spriteCount);
uint8 spriteCount = min(128, (uint)r.spriteCount);
while(spriteCount--) {
uint32 sprite;
sprite.byte(0) = iram[spriteBase + (spriteIndex << 2) + 0];
@ -91,7 +96,6 @@ auto PPU::renderSprite() -> void {
spriteIndex++;
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 spriteX = sprite.bits(24,31);
@ -112,6 +116,7 @@ auto PPU::renderSprite() -> void {
uint2 tileColor = (d0 & tileMask ? 1 : 0) | (d1 & tileMask ? 2 : 0);
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];
uint4 poolColor = 15 - r.pool[paletteColor];

View File

@ -1,3 +1,9 @@
enum class Keypad : uint {
Y1, Y2, Y3, Y4,
X1, X2, X3, X4,
B, A, Start,
};
struct System : IO {
enum class Revision : uint {
WonderSwan, //SW-001 (ASWAN)

View File

@ -18,7 +18,7 @@ auto Icarus::wonderSwanColorManifest(vector<uint8_t>& buffer, string location) -
}
if(settings["icarus/UseHeuristics"].boolean() && !manifest) {
WonderSwanColorCartridge cartridge{buffer.data(), buffer.size()};
WonderSwanCartridge cartridge{buffer.data(), buffer.size()};
if(manifest = cartridge.manifest) {
manifest.append("\n");
manifest.append("information\n");

View File

@ -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");
}

View File

@ -5,12 +5,34 @@ struct WonderSwanCartridge {
//private:
struct Information {
bool color;
string ramType;
uint ramSize;
} information;
};
WonderSwanCartridge::WonderSwanCartridge(uint8_t* data, uint size) {
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(" 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");
}

View File

@ -23,7 +23,6 @@ Settings settings;
#include "heuristics/game-boy.cpp"
#include "heuristics/game-boy-advance.cpp"
#include "heuristics/wonderswan.cpp"
#include "heuristics/wonderswan-color.cpp"
#include "heuristics/bs-memory.cpp"
#include "heuristics/sufami-turbo.cpp"