Commit 79be6f23 authored by Tim Allen's avatar Tim Allen

Update to v106r70 release.

byuu says:

Changelog:

  - Interface::displays() -> vector<Display> → Interface::display() -> Display
  - <Platform::videoRefresh(display>, ...) → <Platform::videoFrame>(...)
  - <Platform::audioSample>(...) → <Platform::audioFrame>(...)
  - higan, icarus: use AboutDialog class instead of ad-hoc
    implementations
      - about dialog is now modal, but now has a clickable website URL
  - icarus: reverted if constexpr for now
  - MSX: implemented basic CPU, VDP support

I took out the multiple displays support thing because it was never
really implemented fully (Emulator::Video and the GUIs both ignored it)
or used anyway. If it ends up necessary in the future, I'll worry about
it then.

There's enough MSX emulation now to run Mr. Do! without sound or input.
I'm shipping higan with C-BIOS 0.29a, although it likely won't be good
enough in the future (eg it can't do BASIC, floppy disk, or cassette
loading.) I have keyboard and (not working) AY-3-8910 support in a
different branch, so that won't take too long to implement. Main problem
is naming all the darned keyboard keys. I think I need to change
settings.bml's input mapping lines so that the key names are values
instead of node names, so that any characters can appear inside of them.

It turns out my MSX set uses .rom for the file extensions ... gods. So,
icarus can't really import them like this. I may have to re-design
icarus' importer to stop caring about the file extension and instead ask
you what kind of games you are importing. There's no way icarus can
heuristically guess what systems the images belong to, because many
systems don't have any standardized magic bytes.

I'm struggling with where to put SG-1000, SC-3000, ColecoVision, Coleco
Adam stuff. I think they need to be split to two separate higan
subfolders (sg and cv, most likely ...) The MS/GG share a very
customized and extended VDP that the other systems don't have. The Sega
and Coleco older hardware share the same TMS9918 as the MSX, yet have
very different memory maps and peripherals that I don't want to mix
together. Especially if we start getting into the computer-variants
more.
parent cac3858f
Pipeline #41986729 passed with stage
in 12 minutes and 57 seconds
......@@ -64,7 +64,7 @@ auto Audio::process() -> void {
if(balance > 0.0) samples[0] *= 1.0 - balance;
}
platform->audioSample(samples, channels);
platform->audioFrame(samples, channels);
}
}
......
......@@ -30,7 +30,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "106.69";
static const string Version = "106.70";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "https://byuu.org/";
......
......@@ -54,7 +54,7 @@ struct Interface {
//information
virtual auto information() -> Information { return {}; }
virtual auto displays() -> vector<Display> { return {}; }
virtual auto display() -> Display { return {}; }
virtual auto color(uint32 color) -> uint64 { return 0; }
//game interface
......
......@@ -16,8 +16,8 @@ struct Platform {
virtual auto path(uint id) -> string { return ""; }
virtual auto open(uint id, string name, vfs::file::mode mode, bool required = false) -> vfs::shared::file { return {}; }
virtual auto load(uint id, string name, string type, vector<string> options = {}) -> Load { return {}; }
virtual auto videoRefresh(uint display, const uint32* data, uint pitch, uint width, uint height) -> void {}
virtual auto audioSample(const double* samples, uint channels) -> void {}
virtual auto videoFrame(const uint32* data, uint pitch, uint width, uint height) -> void {}
virtual auto audioFrame(const double* samples, uint channels) -> void {}
virtual auto inputPoll(uint port, uint device, uint input) -> int16 { return 0; }
virtual auto inputRumble(uint port, uint device, uint input, bool enable) -> void {}
virtual auto dipSettings(Markup::Node node) -> uint { return 0; }
......
......@@ -28,7 +28,7 @@ auto Video::setPalette() -> void {
if(!interface) return;
delete palette;
colors = interface->displays()[0].colors;
colors = interface->display().colors;
palette = new uint32[colors];
for(auto index : range(colors)) {
uint64 color = interface->color(index);
......@@ -185,7 +185,7 @@ auto Video::refresh(uint32* input, uint pitch, uint width, uint height) -> void
}
}
platform->videoRefresh(0, output, width * sizeof(uint32), width, height);
platform->videoFrame(output, width * sizeof(uint32), width, height);
}
}
......@@ -13,7 +13,7 @@ auto Interface::information() -> Information {
return information;
}
auto Interface::displays() -> vector<Display> {
auto Interface::display() -> Display {
Display display;
display.type = Display::Type::CRT;
display.colors = 1 << 9;
......@@ -23,7 +23,7 @@ auto Interface::displays() -> vector<Display> {
display.internalHeight = 240;
display.aspectCorrection = 8.0 / 7.0;
display.refreshRate = system.frequency() / (ppu.vlines() * ppu.rate() * 341.0);
return {display};
return display;
}
auto Interface::color(uint32 n) -> uint64 {
......
......@@ -23,7 +23,7 @@ struct ID {
struct Interface : Emulator::Interface {
auto information() -> Information override;
auto displays() -> vector<Display> override;
auto display() -> Display override;
auto color(uint32 color) -> uint64 override;
auto loaded() -> bool override;
......
......@@ -7,7 +7,7 @@ Settings settings;
#include "game-boy.cpp"
#include "game-boy-color.cpp"
auto Interface::displays() -> vector<Display> {
auto Interface::display() -> Display {
Display display;
display.type = Display::Type::LCD;
display.colors = Model::GameBoyColor() ? 1 << 15 : 1 << 2;
......@@ -17,7 +17,7 @@ auto Interface::displays() -> vector<Display> {
display.internalHeight = 144;
display.aspectCorrection = 1.0;
display.refreshRate = (4.0 * 1024.0 * 1024.0) / (154.0 * 456.0);
return {display};
return display;
}
auto Interface::loaded() -> bool {
......
......@@ -23,7 +23,7 @@ struct ID {
};
struct Interface : Emulator::Interface {
auto displays() -> vector<Display> override;
auto display() -> Display override;
auto loaded() -> bool override;
auto hashes() -> vector<string> override;
......
......@@ -12,7 +12,7 @@ auto Interface::information() -> Information {
return information;
}
auto Interface::displays() -> vector<Display> {
auto Interface::display() -> Display {
Display display;
display.type = Display::Type::LCD;
display.colors = 1 << 15;
......@@ -26,7 +26,7 @@ auto Interface::displays() -> vector<Display> {
swap(display.width, display.height);
swap(display.internalWidth, display.internalHeight);
}
return {display};
return display;
}
auto Interface::color(uint32 color) -> uint64 {
......
......@@ -20,7 +20,7 @@ struct ID {
struct Interface : Emulator::Interface {
auto information() -> Information override;
auto displays() -> vector<Display> override;
auto display() -> Display override;
auto color(uint32 color) -> uint64 override;
auto loaded() -> bool override;
......
......@@ -13,7 +13,7 @@ auto Interface::information() -> Information {
return information;
}
auto Interface::displays() -> vector<Display> {
auto Interface::display() -> Display {
Display display;
display.type = Display::Type::CRT;
display.colors = 3 * (1 << 9);
......@@ -23,7 +23,7 @@ auto Interface::displays() -> vector<Display> {
display.internalHeight = 480;
display.aspectCorrection = 1.0;
display.refreshRate = (system.frequency() / 2.0) / (vdp.frameHeight() * 1710.0);
return {display};
return display;
}
auto Interface::color(uint32 color) -> uint64 {
......
......@@ -24,7 +24,7 @@ struct ID {
struct Interface : Emulator::Interface {
auto information() -> Information override;
auto displays() -> vector<Display> override;
auto display() -> Display override;
auto color(uint32 color) -> uint64 override;
auto loaded() -> bool override;
......
......@@ -6,7 +6,7 @@ auto ColecoVisionInterface::information() -> Information {
return information;
}
auto ColecoVisionInterface::displays() -> vector<Display> {
auto ColecoVisionInterface::display() -> Display {
Display display;
display.type = Display::Type::CRT;
display.colors = 1 << 4;
......@@ -17,7 +17,7 @@ auto ColecoVisionInterface::displays() -> vector<Display> {
display.aspectCorrection = 1.0;
if(Region::NTSC()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0);
if(Region::PAL()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (312.0 * 684.0);
return {display};
return display;
}
auto ColecoVisionInterface::color(uint32 color) -> uint64 {
......
......@@ -6,7 +6,7 @@ auto GameGearInterface::information() -> Information {
return information;
}
auto GameGearInterface::displays() -> vector<Display> {
auto GameGearInterface::display() -> Display {
Display display;
display.type = Display::Type::LCD;
display.colors = 1 << 12;
......@@ -16,7 +16,7 @@ auto GameGearInterface::displays() -> vector<Display> {
display.internalHeight = 144;
display.aspectCorrection = 1.0;
display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0);
return {display};
return display;
}
auto GameGearInterface::color(uint32 color) -> uint64 {
......
......@@ -53,7 +53,7 @@ struct Interface : Emulator::Interface {
struct ColecoVisionInterface : Interface {
auto information() -> Information override;
auto displays() -> vector<Display> override;
auto display() -> Display override;
auto color(uint32 color) -> uint64 override;
auto ports() -> vector<Port> override;
......@@ -69,7 +69,7 @@ struct ColecoVisionInterface : Interface {
struct SG1000Interface : Interface {
auto information() -> Information override;
auto displays() -> vector<Display> override;
auto display() -> Display override;
auto color(uint32 color) -> uint64 override;
auto ports() -> vector<Port> override;
......@@ -85,7 +85,7 @@ struct SG1000Interface : Interface {
struct SC3000Interface : Interface {
auto information() -> Information override;
auto displays() -> vector<Display> override;
auto display() -> Display override;
auto color(uint32 color) -> uint64 override;
auto ports() -> vector<Port> override;
......@@ -101,7 +101,7 @@ struct SC3000Interface : Interface {
struct MasterSystemInterface : Interface {
auto information() -> Information override;
auto displays() -> vector<Display> override;
auto display() -> Display override;
auto color(uint32 color) -> uint64 override;
auto ports() -> vector<Port> override;
......@@ -117,7 +117,7 @@ struct MasterSystemInterface : Interface {
struct GameGearInterface : Interface {
auto information() -> Information override;
auto displays() -> vector<Display> override;
auto display() -> Display override;
auto color(uint32 color) -> uint64 override;
auto ports() -> vector<Port> override;
......
......@@ -6,7 +6,7 @@ auto MasterSystemInterface::information() -> Information {
return information;
}
auto MasterSystemInterface::displays() -> vector<Display> {
auto MasterSystemInterface::display() -> Display {
Display display;
display.type = Display::Type::CRT;
display.colors = 1 << 6;
......@@ -17,7 +17,7 @@ auto MasterSystemInterface::displays() -> vector<Display> {
display.aspectCorrection = 8.0 / 7.0;
if(Region::NTSC()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0);
if(Region::PAL()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (312.0 * 684.0);
return {display};
return display;
}
auto MasterSystemInterface::color(uint32 color) -> uint64 {
......
......@@ -6,7 +6,7 @@ auto SC3000Interface::information() -> Information {
return information;
}
auto SC3000Interface::displays() -> vector<Display> {
auto SC3000Interface::display() -> Display {
Display display;
display.type = Display::Type::CRT;
display.colors = 1 << 4;
......@@ -17,7 +17,7 @@ auto SC3000Interface::displays() -> vector<Display> {
display.aspectCorrection = 1.0;
if(Region::NTSC()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0);
if(Region::PAL()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (312.0 * 684.0);
return {display};
return display;
}
auto SC3000Interface::color(uint32 color) -> uint64 {
......
......@@ -6,7 +6,7 @@ auto SG1000Interface::information() -> Information {
return information;
}
auto SG1000Interface::displays() -> vector<Display> {
auto SG1000Interface::display() -> Display {
Display display;
display.type = Display::Type::CRT;
display.colors = 1 << 4;
......@@ -17,7 +17,7 @@ auto SG1000Interface::displays() -> vector<Display> {
display.aspectCorrection = 1.0;
if(Region::NTSC()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0);
if(Region::PAL()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (312.0 * 684.0);
return {display};
return display;
}
auto SG1000Interface::color(uint32 color) -> uint64 {
......
......@@ -57,13 +57,8 @@ auto VDP::Background::graphics2(uint8 hoffset, uint9 voffset) -> void {
patternAddress.bits(3,10) = pattern;
if(voffset >= 64 && voffset <= 127) patternAddress.bit(11) = vdp.io.patternTableAddress.bit(0);
if(voffset >= 128 && voffset <= 191) patternAddress.bit(12) = vdp.io.patternTableAddress.bit(1);
uint14 colorAddress = patternAddress;
patternAddress.bit(13) = vdp.io.patternTableAddress.bit(2);
uint14 colorAddress;
colorAddress.bits(0, 2) = voffset.bits(0,2);
colorAddress.bits(3,10) = pattern;
if(voffset >= 64 && voffset <= 127) colorAddress.bit(11) = vdp.io.patternTableAddress.bit(0);
if(voffset >= 128 && voffset <= 191) colorAddress.bit(12) = vdp.io.patternTableAddress.bit(1);
colorAddress.bit(13) = vdp.io.colorTableAddress.bit(7);
uint8 colorMask = vdp.io.colorTableAddress.bits(0,6) << 1 | 1;
......
......@@ -58,4 +58,11 @@ auto Cartridge::unload() -> void {
auto Cartridge::power() -> void {
}
auto Cartridge::read(uint16 address) -> uint8 {
return rom.read(address);
}
auto Cartridge::write(uint16 address, uint8 data) -> void {
}
}
......@@ -12,6 +12,9 @@ struct Cartridge {
auto power() -> void;
auto read(uint16 address) -> uint8;
auto write(uint16 address, uint8 data) -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
......
......@@ -11,11 +11,14 @@ auto CPU::Enter() -> void {
}
auto CPU::main() -> void {
if(io.irqLine) irq(1, 0x0038, 0xff);
instruction();
}
auto CPU::step(uint clocks) -> void {
Thread::step(clocks);
synchronize(vdp);
synchronize(psg);
}
auto CPU::synchronizing() const -> bool {
......@@ -23,6 +26,19 @@ auto CPU::synchronizing() const -> bool {
}
auto CPU::power() -> void {
Z80::bus = this;
Z80::power();
create(CPU::Enter, system.colorburst());
r.pc = 0x0000; //reset vector address
ram.allocate(0x10000);
io = {};
}
auto CPU::setIRQ(bool line) -> void {
io.irqLine = line;
}
}
......@@ -6,6 +6,7 @@ struct CPU : Processor::Z80, Processor::Z80::Bus, Thread {
auto synchronizing() const -> bool override;
auto power() -> void;
auto setIRQ(bool) -> void;
//memory.cpp
auto read(uint16 address) -> uint8 override;
......@@ -16,6 +17,14 @@ struct CPU : Processor::Z80, Processor::Z80::Bus, Thread {
//serialization.cpp
auto serialize(serializer&) -> void;
private:
Emulator::Memory::Writable<uint8> ram;
struct IO {
uint1 irqLine;
uint2 slot[4];
} io;
};
extern CPU cpu;
auto CPU::read(uint16 address) -> uint8 {
uint2 slot = io.slot[address.bits(14,15)];
if(slot == 0) {
if(!address.bit(15)) return system.bios.read(address);
return 0xff;
}
if(slot == 1) {
return cartridge.read(address);
}
if(slot == 2) {
return ram.read(address);
}
if(slot == 3) {
}
return 0xff;
}
auto CPU::write(uint16 address, uint8 data) -> void {
uint2 slot = io.slot[address.bits(14,15)];
if(slot == 0) {
return;
}
if(slot == 1) {
return cartridge.write(address, data);
}
if(slot == 2) {
return ram.write(address, data);
}
if(slot == 3) {
return;
}
}
auto CPU::in(uint8 address) -> uint8 {
switch(address) {
case 0x98: return vdp.data();
case 0x99: return vdp.status();
case 0xa8: return io.slot[0] << 0
| io.slot[1] << 2
| io.slot[2] << 4
| io.slot[3] << 6;
}
return 0xff;
}
auto CPU::out(uint8 address, uint8 data) -> void {
switch(address) {
case 0x98: return vdp.data(data);
case 0x99: return vdp.control(data);
case 0xa8: io.slot[0] = data.bits(0,1);
io.slot[1] = data.bits(2,3);
io.slot[2] = data.bits(4,5);
io.slot[3] = data.bits(6,7);
break;
}
}
......@@ -6,11 +6,11 @@ auto Interface::information() -> Information {
Information information;
information.manufacturer = "";
information.name = "MSX";
information.extension = ".msx";
information.extension = "msx";
return information;
}
auto Interface::displays() -> vector<Display> {
auto Interface::display() -> Display {
Display display;
display.type = Display::Type::CRT;
display.colors = 1 << 4;
......@@ -20,40 +20,58 @@ auto Interface::displays() -> vector<Display> {
display.internalHeight = 192;
display.aspectCorrection = 1.0;
display.refreshRate = 60.0; //todo: PAL
return {display};
return display;
}
auto Interface::color(uint32 color) -> uint64 {
switch(color.bits(0,3)) {
case 0: return 0x0000'0000'0000ull; //transparent
case 1: return 0x0000'0000'0000ull; //black
case 2: return 0x2121'c8c8'4242ull; //medium green
case 3: return 0x5e5e'dcdc'7878ull; //light green
case 4: return 0x5454'5555'ededull; //dark blue
case 5: return 0x7d7d'7676'fcfcull; //light blue
case 6: return 0xd4d4'5252'4d4dull; //dark red
case 7: return 0x4242'ebeb'f5f5ull; //cyan
case 8: return 0xfcfc'5555'5454ull; //medium red
case 9: return 0xffff'7979'7878ull; //light red
case 10: return 0xd4d4'c1c1'5454ull; //dark yellow
case 11: return 0xe6e6'cece'8080ull; //light yellow
case 12: return 0x2121'b0b0'3b3bull; //dark green
case 13: return 0xc9c9'5b5b'babaull; //magenta
case 14: return 0xcccc'cccc'ccccull; //gray
case 15: return 0xffff'ffff'ffffull; //white
}
return 0;
}
auto Interface::loaded() -> bool {
return false;
return system.loaded();
}
auto Interface::hashes() -> vector<string> {
return {};
return {cartridge.hash()};
}
auto Interface::manifests() -> vector<string> {
return {};
return {cartridge.manifest()};
}
auto Interface::titles() -> vector<string> {
return {};
return {cartridge.title()};
}
auto Interface::load() -> bool {
return false;
return system.load(this, System::Model::MSX);
}
auto Interface::save() -> void {
system.save();
}
auto Interface::unload() -> void {
save();
system.unload();
}
auto Interface::ports() -> vector<Port> { return {
......@@ -91,17 +109,20 @@ auto Interface::inputs(uint device) -> vector<Input> {
}
auto Interface::power() -> void {
system.power();
}
auto Interface::run() -> void {
system.run();
}
auto Interface::serialize() -> serializer {
return {};
system.runToSave();
return system.serialize();
}
auto Interface::unserialize(serializer& s) -> bool {
return false;
return system.unserialize(s);
}
}
......@@ -25,7 +25,7 @@ struct ID {
struct Interface : Emulator::Interface {
auto information() -> Information override;
auto displays() -> vector<Display> override;
auto display() -> Display override;
auto color(uint32 color