diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index e3c29ab8..43f58cb8 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,7 +12,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "101.07"; + static const string Version = "101.08"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/md/cpu/cpu.cpp b/higan/md/cpu/cpu.cpp index 765e48b3..f3a67267 100644 --- a/higan/md/cpu/cpu.cpp +++ b/higan/md/cpu/cpu.cpp @@ -23,15 +23,17 @@ auto CPU::main() -> void { if(state.interruptPending) { if(state.interruptPending.bit((uint)Interrupt::HorizontalBlank)) { - state.interruptPending.bit((uint)Interrupt::HorizontalBlank) = 0; - r.i = 4; - return exception(Exception::Interrupt, Vector::HorizontalBlank); + if(4 > r.i) { + state.interruptPending.bit((uint)Interrupt::HorizontalBlank) = 0; + return exception(Exception::Interrupt, Vector::HorizontalBlank, 4); + } } if(state.interruptPending.bit((uint)Interrupt::VerticalBlank)) { - state.interruptPending.bit((uint)Interrupt::VerticalBlank) = 0; - r.i = 6; - return exception(Exception::Interrupt, Vector::VerticalBlank); + if(6 > r.i) { + state.interruptPending.bit((uint)Interrupt::VerticalBlank) = 0; + return exception(Exception::Interrupt, Vector::VerticalBlank, 6); + } } } @@ -64,6 +66,7 @@ auto CPU::raise(Interrupt interrupt) -> void { auto CPU::lower(Interrupt interrupt) -> void { state.interruptLine.bit((uint)interrupt) = 0; + state.interruptPending.bit((uint)interrupt) = 0; } auto CPU::power() -> void { @@ -81,14 +84,16 @@ auto CPU::reset() -> void { auto CPU::readByte(uint24 addr) -> uint8 { if(addr < 0x400000) return cartridge.readByte(addr); - if(addr < 0xc00000) return 0x00; + if(addr < 0xa00000) return 0x00; + if(addr < 0xc00000) return rand(); if(addr < 0xe00000) return vdp.readByte(addr); return ram[addr & 0xffff]; } auto CPU::readWord(uint24 addr) -> uint16 { if(addr < 0x400000) return cartridge.readWord(addr); - if(addr < 0xc00000) return 0x0000; + if(addr < 0xa00000) return 0x0000; + if(addr < 0xc00000) return rand(); if(addr < 0xe00000) return vdp.readWord(addr); uint16 data = ram[addr + 0 & 65535] << 8; return data | ram[addr + 1 & 65535] << 0; diff --git a/higan/md/vdp/dma.cpp b/higan/md/vdp/dma.cpp index 1e01b1d7..5f478aa3 100644 --- a/higan/md/vdp/dma.cpp +++ b/higan/md/vdp/dma.cpp @@ -23,11 +23,11 @@ auto VDP::dmaLoad() -> void { auto VDP::dmaFill() -> void { if(io.dmaFillWait) return; - auto data = io.dmaFillWord; - writeDataPort(data); + auto data = io.dmaFillByte; + writeDataPort(data << 8 | data << 0); - io.dmaSource.bits(0,15) += 2; - if(--io.dmaLength == 0 || --io.dmaLength == 0) { + io.dmaSource.bits(0,15)++; + if(--io.dmaLength == 0) { io.command.bit(5) = 0; } } diff --git a/higan/md/vdp/io.cpp b/higan/md/vdp/io.cpp index 2cf5c945..e638afdf 100644 --- a/higan/md/vdp/io.cpp +++ b/higan/md/vdp/io.cpp @@ -73,8 +73,7 @@ auto VDP::writeDataPort(uint16 data) -> void { //DMA VRAM fill if(io.dmaFillWait.lower()) { - io.dmaFillWord = data; - return; + io.dmaFillByte = data >> 8; } //VRAM write @@ -82,6 +81,9 @@ auto VDP::writeDataPort(uint16 data) -> void { auto address = io.address.bits(1,15); if(io.address.bit(0)) data = data >> 8 | data << 8; vram[address] = data; + if(address >= sprite.io.attributeAddress && address < sprite.io.attributeAddress + 320) { + sprite.write(address, data); + } io.address += io.dataIncrement; return; } diff --git a/higan/md/vdp/render.cpp b/higan/md/vdp/render.cpp index 08867c6e..3a893d6e 100644 --- a/higan/md/vdp/render.cpp +++ b/higan/md/vdp/render.cpp @@ -1,11 +1,6 @@ auto VDP::scanline() -> void { state.x = 0; if(++state.y >= 262) state.y = 0; - if(state.y == 0) scheduler.exit(Scheduler::Event::Frame); - - if(state.y == 0) { - sprite.frame(); - } if(state.y < 240) { planeA.scanline(state.y); @@ -14,6 +9,8 @@ auto VDP::scanline() -> void { sprite.scanline(state.y); } + if(state.y == 240) scheduler.exit(Scheduler::Event::Frame); + state.output = buffer + (state.y * 2 + 0) * 1280; } diff --git a/higan/md/vdp/sprite.cpp b/higan/md/vdp/sprite.cpp index 667084c5..8a53927b 100644 --- a/higan/md/vdp/sprite.cpp +++ b/higan/md/vdp/sprite.cpp @@ -1,40 +1,54 @@ -auto VDP::Sprite::frame() -> void { - uint15 address = io.attributeAddress; - uint7 link = 0; +auto VDP::Sprite::write(uint9 address, uint16 data) -> void { + if(address > 320) return; - oam.reset(); - while(oam.size() < 80) { - uint64 attributes; - attributes |= (uint64)vdp.vram[address + (link << 2) + 0] << 48; - attributes |= (uint64)vdp.vram[address + (link << 2) + 1] << 32; - attributes |= (uint64)vdp.vram[address + (link << 2) + 2] << 16; - attributes |= (uint64)vdp.vram[address + (link << 2) + 3] << 0; + auto& object = oam[address >> 2]; + switch(address.bits(0,1)) { - auto& object = oam.append(); - object.x = attributes.bits( 0, 9) - 128; - object.address = attributes.bits(16,26) << 4; - object.horizontalFlip = attributes.bit (27); - object.verticalFlip = attributes.bit (28); - object.palette = attributes.bits(29,30); - object.priority = attributes.bit (31); - object.height = attributes.bits(40,41) << 3; - object.width = attributes.bits(42,43) << 3; - object.y = attributes.bits(48,57) - 128; + case 0: { + object.y = data.bits(0,9) - 128; + break; + } + + case 1: { + object.link = data.bits(0,6); + object.height = data.bits(8,9) << 3; + object.width = data.bits(10,11) << 3; + break; + } + + case 2: { + object.address = data.bits(0,10) << 4; + object.horizontalFlip = data.bit(11); + object.verticalFlip = data.bit(12); + object.palette = data.bits(13,14); + object.priority = data.bit(15); + break; + } + + case 3: { + object.x = data.bits(0,9) - 128; + break; + } - link = attributes.bits(32,38); - if(!link) break; } } auto VDP::Sprite::scanline(uint y) -> void { object.reset(); - for(auto& o : oam) { + + uint7 link = 0; + while(link) { + auto& o = oam[link]; + if((uint9)(o.y + o.height - 1) < y) continue; if((uint9)(y + o.height - 1) < o.y) continue; if(o.x == 0) break; object.append(o); - if(object.size() >= object.capacity()) break; + if(object.size() >= 20) break; + + link = o.link; + if(!link || link >= 80) break; } } diff --git a/higan/md/vdp/vdp.hpp b/higan/md/vdp/vdp.hpp index 14e2c9ba..09f991d4 100644 --- a/higan/md/vdp/vdp.hpp +++ b/higan/md/vdp/vdp.hpp @@ -58,7 +58,7 @@ struct VDP : Thread { //sprite.cpp struct Sprite { - auto frame() -> void; + auto write(uint9 addr, uint16 data) -> void; auto scanline(uint y) -> void; auto run(uint x, uint y) -> void; @@ -80,6 +80,7 @@ struct VDP : Thread { uint2 palette; uint1 priority; uint15 address; + uint7 link; }; struct Output { @@ -101,7 +102,7 @@ private: struct IO { //internal state boolean dmaFillWait; - uint8 dmaFillWord; + uint8 dmaFillByte; //command uint6 command; diff --git a/higan/ms/GNUmakefile b/higan/ms/GNUmakefile new file mode 100644 index 00000000..21a36e0f --- /dev/null +++ b/higan/ms/GNUmakefile @@ -0,0 +1,12 @@ +processors += z80 + +objects += ms-interface +objects += ms-cpu ms-vdp ms-psg +objects += ms-system ms-cartridge + +obj/ms-interface.o: ms/interface/interface.cpp $(call rwildcard,ms/interface) +obj/ms-cpu.o: ms/cpu/cpu.cpp $(call rwildcard,ms/cpu) +obj/ms-vdp.o: ms/vdp/vdp.cpp $(call rwildcard,ms/vdp) +obj/ms-psg.o: ms/psg/psg.cpp $(call rwildcard,ms/psg) +obj/ms-system.o: ms/system/system.cpp $(call rwildcard,ms/system) +obj/ms-cartridge.o: ms/cartridge/cartridge.cpp $(call rwildcard,ms/cartridge) diff --git a/higan/ms/cartridge/cartridge.cpp b/higan/ms/cartridge/cartridge.cpp new file mode 100644 index 00000000..15b1cb2a --- /dev/null +++ b/higan/ms/cartridge/cartridge.cpp @@ -0,0 +1,7 @@ +#include + +namespace MasterSystem { + +Cartridge cartridge; + +} diff --git a/higan/ms/cartridge/cartridge.hpp b/higan/ms/cartridge/cartridge.hpp new file mode 100644 index 00000000..26579aec --- /dev/null +++ b/higan/ms/cartridge/cartridge.hpp @@ -0,0 +1,4 @@ +struct Cartridge { +}; + +extern Cartridge cartridge; diff --git a/higan/ms/cpu/cpu.cpp b/higan/ms/cpu/cpu.cpp new file mode 100644 index 00000000..ffca5083 --- /dev/null +++ b/higan/ms/cpu/cpu.cpp @@ -0,0 +1,18 @@ +#include + +namespace MasterSystem { + +CPU cpu; + +auto CPU::Enter() -> void { + while(true) scheduler.synchronize(), cpu.main(); +} + +auto CPU::main() -> void { +} + +auto CPU::step(uint clocks) -> void { + Thread::step(clocks); +} + +} diff --git a/higan/ms/cpu/cpu.hpp b/higan/ms/cpu/cpu.hpp new file mode 100644 index 00000000..92eb165e --- /dev/null +++ b/higan/ms/cpu/cpu.hpp @@ -0,0 +1,9 @@ +//Zilog Z80 + +struct CPU : Processor::Z80, Thread { + static auto Enter() -> void; + auto main() -> void; + auto step(uint clocks) -> void; +}; + +extern CPU cpu; diff --git a/higan/ms/interface/interface.cpp b/higan/ms/interface/interface.cpp new file mode 100644 index 00000000..845b2213 --- /dev/null +++ b/higan/ms/interface/interface.cpp @@ -0,0 +1,115 @@ +#include + +namespace MasterSystem { + +Interface* interface = nullptr; +Settings settings; + +Interface::Interface() { + interface = this; + + information.manufacturer = "Sega"; + information.name = "Master System"; + information.overscan = true; + information.resettable = true; + + information.capability.states = false; + information.capability.cheats = false; + + media.append({ID::MasterSystem, "Master System", "ms"}); + media.append({ID::GameGear, "Game Gear", "gg"}); + + Port controllerPort1{ID::Port::Controller1, "Controller Port 1"}; + Port controllerPort2{ID::Port::Controller2, "Controller Port 2"}; + + { Device device{ID::Device::Gamepad, "Gamepad"}; + device.inputs.append({0, "Up"}); + device.inputs.append({0, "Down"}); + device.inputs.append({0, "Left"}); + device.inputs.append({0, "Right"}); + device.inputs.append({0, "1"}); + device.inputs.append({0, "2"}); + controllerPort1.devices.append(device); + controllerPort2.devices.append(device); + } +} + +auto Interface::manifest() -> string { + return ""; +} + +auto Interface::title() -> string { + return ""; +} + +auto Interface::videoSize() -> VideoSize { + return {256, 192}; +} + +auto Interface::videoSize(uint width, uint height, bool arc) -> VideoSize { + uint w = 256; + uint h = 192; + uint m = min(width / w, height / h); + return {w * m, h * m}; +} + +auto Interface::videoFrequency() -> double { + return 60.0; +} + +auto Interface::videoColors() -> uint32 { + return 1 << 6; +} + +auto Interface::videoColor(uint32 color) -> uint64 { + return 0; +} + +auto Interface::audioFrequency() -> double { + return 44'100.0; +} + +auto Interface::loaded() -> bool { + return false; +} + +auto Interface::load(uint id) -> bool { + return false; +} + +auto Interface::save() -> void { +} + +auto Interface::unload() -> void { +} + +auto Interface::power() -> void { +} + +auto Interface::reset() -> void { +} + +auto Interface::run() -> void { +} + +auto Interface::serialize() -> serializer { + return {}; +} + +auto Interface::unserialize(serializer& s) -> bool { + return false; +} + +auto Interface::cap(const string& name) -> bool { + return false; +} + +auto Interface::get(const string& name) -> any { + return {}; +} + +auto Interface::set(const string& name, const any& value) -> bool { + return false; +} + +} diff --git a/higan/ms/interface/interface.hpp b/higan/ms/interface/interface.hpp new file mode 100644 index 00000000..076e5753 --- /dev/null +++ b/higan/ms/interface/interface.hpp @@ -0,0 +1,59 @@ +namespace MasterSystem { + +struct ID { + enum : uint { + System, + MasterSystem, + GameGear, + }; + + struct Port { enum : uint { + Controller1, + Controller2, + };}; + + struct Device { enum : uint { + Gamepad, + };}; +}; + +struct Interface : Emulator::Interface { + using Emulator::Interface::load; + + Interface(); + + auto manifest() -> string override; + auto title() -> string override; + + auto videoSize() -> VideoSize override; + auto videoSize(uint width, uint height, bool arc) -> VideoSize override; + auto videoFrequency() -> double override; + auto videoColors() -> uint32 override; + auto videoColor(uint32 color) -> uint64 override; + + auto audioFrequency() -> double override; + + auto loaded() -> bool override; + auto load(uint id) -> bool override; + auto save() -> void override; + auto unload() -> void override; + + auto power() -> void override; + auto reset() -> void override; + auto run() -> void override; + + auto serialize() -> serializer override; + auto unserialize(serializer&) -> bool override; + + auto cap(const string& name) -> bool override; + auto get(const string& name) -> any override; + auto set(const string& name, const any& value) -> bool override; +}; + +struct Settings { +}; + +extern Interface* interface; +extern Settings settings; + +} diff --git a/higan/ms/ms.hpp b/higan/ms/ms.hpp new file mode 100644 index 00000000..b688f6ea --- /dev/null +++ b/higan/ms/ms.hpp @@ -0,0 +1,36 @@ +#pragma once + +//license: GPLv3 +//started: 2016-08-17 + +#include +#include +#include + +#include + +namespace MasterSystem { + using File = Emulator::File; + using Scheduler = Emulator::Scheduler; + extern Scheduler scheduler; + + struct Thread : Emulator::Thread { + auto create(auto (*entrypoint)() -> void, double frequency) -> void { + Emulator::Thread::create(entrypoint, frequency); + scheduler.append(*this); + } + + inline auto synchronize(Thread& thread) -> void { + if(clock() >= thread.clock()) scheduler.resume(thread); + } + }; + + #include + #include + #include + + #include + #include +} + +#include diff --git a/higan/ms/psg/psg.cpp b/higan/ms/psg/psg.cpp new file mode 100644 index 00000000..60d64bf4 --- /dev/null +++ b/higan/ms/psg/psg.cpp @@ -0,0 +1,18 @@ +#include + +namespace MasterSystem { + +PSG psg; + +auto PSG::Enter() -> void { + while(true) scheduler.synchronize(), psg.main(); +} + +auto PSG::main() -> void { +} + +auto PSG::step(uint clocks) -> void { + Thread::step(clocks); +} + +} diff --git a/higan/ms/psg/psg.hpp b/higan/ms/psg/psg.hpp new file mode 100644 index 00000000..0e30f7cc --- /dev/null +++ b/higan/ms/psg/psg.hpp @@ -0,0 +1,9 @@ +//TI SN76489 + +struct PSG : Thread { + static auto Enter() -> void; + auto main() -> void; + auto step(uint clocks) -> void; +}; + +extern PSG psg; diff --git a/higan/ms/system/system.cpp b/higan/ms/system/system.cpp new file mode 100644 index 00000000..3376bb10 --- /dev/null +++ b/higan/ms/system/system.cpp @@ -0,0 +1,27 @@ +#include + +namespace MasterSystem { + +System system; +Scheduler scheduler; + +auto System::run() -> void { +} + +auto System::load() -> bool { + return false; +} + +auto System::save() -> void { +} + +auto System::unload() -> void { +} + +auto System::power() -> void { +} + +auto System::reset() -> void { +} + +} diff --git a/higan/ms/system/system.hpp b/higan/ms/system/system.hpp new file mode 100644 index 00000000..e5ea4571 --- /dev/null +++ b/higan/ms/system/system.hpp @@ -0,0 +1,15 @@ +struct System { + auto loaded() const -> bool { return false; } + auto colorburst() const -> double { return 0.0; } + + auto run() -> void; + + auto load() -> bool; + auto save() -> void; + auto unload() -> void; + + auto power() -> void; + auto reset() -> void; +}; + +extern System system; diff --git a/higan/ms/vdp/vdp.cpp b/higan/ms/vdp/vdp.cpp new file mode 100644 index 00000000..196b5c46 --- /dev/null +++ b/higan/ms/vdp/vdp.cpp @@ -0,0 +1,18 @@ +#include + +namespace MasterSystem { + +VDP vdp; + +auto VDP::Enter() -> void { + while(true) scheduler.synchronize(), vdp.main(); +} + +auto VDP::main() -> void { +} + +auto VDP::step(uint clocks) -> void { + Thread::step(clocks); +} + +} diff --git a/higan/ms/vdp/vdp.hpp b/higan/ms/vdp/vdp.hpp new file mode 100644 index 00000000..c913b45f --- /dev/null +++ b/higan/ms/vdp/vdp.hpp @@ -0,0 +1,9 @@ +//... + +struct VDP : Thread { + static auto Enter() -> void; + auto main() -> void; + auto step(uint clocks) -> void; +}; + +extern VDP vdp; diff --git a/higan/processor/m68k/disassembler.cpp b/higan/processor/m68k/disassembler.cpp index 005705e8..073ae657 100644 --- a/higan/processor/m68k/disassembler.cpp +++ b/higan/processor/m68k/disassembler.cpp @@ -130,8 +130,8 @@ template auto M68K::disassembleADDQ(uint4 immediate, EffectiveAddress return {"addq", _suffix(), " #", immediate, ",", _effectiveAddress(modify)}; } -template auto M68K::disassembleADDX(EffectiveAddress target, EffectiveAddress source) -> string { - return {"addx", _suffix(), " ", _effectiveAddress(target), ",", _effectiveAddress(source)}; +template auto M68K::disassembleADDX(EffectiveAddress with, EffectiveAddress from) -> string { + return {"addx", _suffix(), " ", _effectiveAddress(from), ",", _effectiveAddress(with)}; } template auto M68K::disassembleAND(EffectiveAddress from, DataRegister with) -> string { @@ -544,11 +544,11 @@ template auto M68K::disassembleSUBI(EffectiveAddress with) -> string } template auto M68K::disassembleSUBQ(uint4 immediate, EffectiveAddress ea) -> string { - return {"subq", _suffix(), " #", immediate, _effectiveAddress(ea)}; + return {"subq", _suffix(), " #", immediate, ",", _effectiveAddress(ea)}; } template auto M68K::disassembleSUBX(EffectiveAddress with, EffectiveAddress from) -> string { - return {"subx", _suffix(), " ", _effectiveAddress(with), ",", _effectiveAddress(from)}; + return {"subx", _suffix(), " ", _effectiveAddress(from), ",", _effectiveAddress(with)}; } auto M68K::disassembleSWAP(DataRegister with) -> string { diff --git a/higan/processor/m68k/effective-address.cpp b/higan/processor/m68k/effective-address.cpp index e080b1e2..bb301a42 100644 --- a/higan/processor/m68k/effective-address.cpp +++ b/higan/processor/m68k/effective-address.cpp @@ -68,7 +68,7 @@ template auto M68K::fetch(EffectiveAddress& ea) -> uint32 { return 0; } -template auto M68K::read(EffectiveAddress& ea) -> uint32 { +template auto M68K::read(EffectiveAddress& ea) -> uint32 { ea.address = fetch(ea); switch(ea.mode) { @@ -78,7 +78,7 @@ template auto M68K::read(EffectiveAddress& ea) -> uint32 } case AddressRegisterDirect: { - return clip(ea.address); + return sign(ea.address); } case AddressRegisterIndirect: { @@ -87,13 +87,13 @@ template auto M68K::read(EffectiveAddress& ea) -> uint32 case AddressRegisterIndirectWithPostIncrement: { auto data = read(ea.address); - if(Update) write(AddressRegister{ea.reg}, ea.address += bytes()); + if(!Hold) write(AddressRegister{ea.reg}, ea.address += bytes()); return data; } case AddressRegisterIndirectWithPreDecrement: { auto data = read(ea.address - bytes()); - if(Update) write(AddressRegister{ea.reg}, ea.address -= bytes()); + if(!Hold) write(AddressRegister{ea.reg}, ea.address -= bytes()); return data; } @@ -130,7 +130,7 @@ template auto M68K::read(EffectiveAddress& ea) -> uint32 return 0; } -template auto M68K::write(EffectiveAddress& ea, uint32 data) -> void { +template auto M68K::write(EffectiveAddress& ea, uint32 data) -> void { ea.address = fetch(ea); switch(ea.mode) { @@ -149,13 +149,13 @@ template auto M68K::write(EffectiveAddress& ea, uint32 d case AddressRegisterIndirectWithPostIncrement: { write(ea.address, data); - if(Update) write(AddressRegister{ea.reg}, ea.address += bytes()); + if(!Hold) write(AddressRegister{ea.reg}, ea.address += bytes()); return; } case AddressRegisterIndirectWithPreDecrement: { write(ea.address - bytes(), data); - if(Update) write(AddressRegister{ea.reg}, ea.address -= bytes()); + if(!Hold) write(AddressRegister{ea.reg}, ea.address -= bytes()); return; } diff --git a/higan/processor/m68k/instruction.cpp b/higan/processor/m68k/instruction.cpp index dc8b7165..fd19db71 100644 --- a/higan/processor/m68k/instruction.cpp +++ b/higan/processor/m68k/instruction.cpp @@ -115,21 +115,21 @@ M68K::M68K() { } //ADDX - for(uint3 treg : range(8)) - for(uint3 sreg : range(8)) { - auto opcode = pattern("1101 ---1 ++00 ----") | treg << 9 | sreg << 0; + for(uint3 xreg : range(8)) + for(uint3 yreg : range(8)) { + auto opcode = pattern("1101 ---1 ++00 ----") | xreg << 9 | yreg << 0; - EffectiveAddress dataTarget{DataRegisterDirect, treg}; - EffectiveAddress dataSource{DataRegisterDirect, sreg}; - bind(opcode | 0 << 6 | 0 << 3, ADDX, dataTarget, dataSource); - bind(opcode | 1 << 6 | 0 << 3, ADDX, dataTarget, dataSource); - bind(opcode | 2 << 6 | 0 << 3, ADDX, dataTarget, dataSource); + EffectiveAddress dataWith{DataRegisterDirect, xreg}; + EffectiveAddress dataFrom{DataRegisterDirect, yreg}; + bind(opcode | 0 << 6 | 0 << 3, ADDX, dataWith, dataFrom); + bind(opcode | 1 << 6 | 0 << 3, ADDX, dataWith, dataFrom); + bind(opcode | 2 << 6 | 0 << 3, ADDX, dataWith, dataFrom); - EffectiveAddress addressTarget{AddressRegisterIndirectWithPreDecrement, treg}; - EffectiveAddress addressSource{AddressRegisterIndirectWithPreDecrement, sreg}; - bind(opcode | 0 << 6 | 1 << 3, ADDX, addressTarget, addressSource); - bind(opcode | 1 << 6 | 1 << 3, ADDX, addressTarget, addressSource); - bind(opcode | 2 << 6 | 1 << 3, ADDX, addressTarget, addressSource); + EffectiveAddress addressWith{AddressRegisterIndirectWithPreDecrement, xreg}; + EffectiveAddress addressFrom{AddressRegisterIndirectWithPreDecrement, yreg}; + bind(opcode | 0 << 6 | 1 << 3, ADDX, addressWith, addressFrom); + bind(opcode | 1 << 6 | 1 << 3, ADDX, addressWith, addressFrom); + bind(opcode | 2 << 6 | 1 << 3, ADDX, addressWith, addressFrom); } //AND @@ -166,10 +166,10 @@ M68K::M68K() { auto opcode = pattern("0000 0010 ++-- ----") | mode << 3 | reg << 0; if(mode == 1 || (mode == 7 && reg >= 2)) continue; - EffectiveAddress ea{mode, reg}; - bind(opcode | 0 << 6, ANDI, ea); - bind(opcode | 1 << 6, ANDI, ea); - bind(opcode | 2 << 6, ANDI, ea); + EffectiveAddress with{mode, reg}; + bind(opcode | 0 << 6, ANDI, with); + bind(opcode | 1 << 6, ANDI, with); + bind(opcode | 2 << 6, ANDI, with); } //ANDI_TO_CCR diff --git a/higan/processor/m68k/instructions.cpp b/higan/processor/m68k/instructions.cpp index e774599a..91dee2d5 100644 --- a/higan/processor/m68k/instructions.cpp +++ b/higan/processor/m68k/instructions.cpp @@ -52,7 +52,7 @@ template<> auto M68K::sign(uint32 data) -> int32 { return (int32)data; } auto M68K::instructionABCD(EffectiveAddress with, EffectiveAddress from) -> void { auto source = read(from); - auto target = read(with); + auto target = read(with); auto result = source + target + r.x; bool v = false; @@ -72,19 +72,18 @@ auto M68K::instructionABCD(EffectiveAddress with, EffectiveAddress from) -> void r.c = sign(result >> 1) < 0; r.v = v; - r.z = clip(result) == 0 ? 0 : r.z; + r.z = clip(result) ? 0 : r.z; r.n = sign(result) < 0; r.x = r.c; } template auto M68K::ADD(uint32 source, uint32 target) -> uint32 { - uint64 result = (uint64)source + (uint64)target; + auto result = (uint64)source + target; if(Extend) result += r.x; r.c = sign(result >> 1) < 0; r.v = sign(~(target ^ source) & (target ^ result)) < 0; - if(Extend == 0) r.z = clip(result) == 0; - if(Extend == 1) if(clip(result)) r.z = 0; + r.z = clip(result) ? 0 : (Extend ? r.z : 1); r.n = sign(result) < 0; r.x = r.c; @@ -100,7 +99,7 @@ template auto M68K::instructionADD(EffectiveAddress from, DataRegiste template auto M68K::instructionADD(DataRegister from, EffectiveAddress with) -> void { auto source = read(from); - auto target = read(with); + auto target = read(with); auto result = ADD(source, target); write(with, result); } @@ -113,23 +112,23 @@ template auto M68K::instructionADDA(AddressRegister ar, EffectiveAddr template auto M68K::instructionADDI(EffectiveAddress modify) -> void { auto source = readPC(); - auto target = read(modify); + auto target = read(modify); auto result = ADD(source, target); write(modify, result); } template auto M68K::instructionADDQ(uint4 immediate, EffectiveAddress modify) -> void { - auto source = read(modify); + auto source = read(modify); auto target = immediate; auto result = ADD(source, target); write(modify, result); } -template auto M68K::instructionADDX(EffectiveAddress target_, EffectiveAddress source_) -> void { - auto source = read(source_); - auto target = read(target_); +template auto M68K::instructionADDX(EffectiveAddress with, EffectiveAddress from) -> void { + auto source = read(from); + auto target = read(with); auto result = ADD(source, target); - write(target, result); + write(with, result); } template auto M68K::AND(uint32 source, uint32 target) -> uint32 { @@ -152,16 +151,16 @@ template auto M68K::instructionAND(EffectiveAddress from, DataRegiste template auto M68K::instructionAND(DataRegister from, EffectiveAddress with) -> void { auto source = read(from); - auto target = read(with); + auto target = read(with); auto result = AND(source, target); write(with, result); } -template auto M68K::instructionANDI(EffectiveAddress ea) -> void { +template auto M68K::instructionANDI(EffectiveAddress with) -> void { auto source = readPC(); - auto target = read(ea); + auto target = read(with); auto result = AND(source, target); - write(ea, result); + write(with, result); } auto M68K::instructionANDI_TO_CCR() -> void { @@ -207,7 +206,7 @@ template auto M68K::instructionASL(DataRegister shift, DataRegister m } auto M68K::instructionASL(EffectiveAddress modify) -> void { - auto result = ASL(read(modify), 1); + auto result = ASL(read(modify), 1); write(modify, result); } @@ -242,7 +241,7 @@ template auto M68K::instructionASR(DataRegister shift, DataRegister m } auto M68K::instructionASR(EffectiveAddress modify) -> void { - auto result = ASR(read(modify), 1); + auto result = ASR(read(modify), 1); write(modify, result); } @@ -256,7 +255,7 @@ auto M68K::instructionBCC(uint4 condition, uint8 displacement) -> void { template auto M68K::instructionBCHG(DataRegister bit, EffectiveAddress with) -> void { auto index = read(bit) & bits() - 1; - auto test = read(with); + auto test = read(with); r.z = test.bit(index) == 0; test.bit(index) ^= 1; write(with, test); @@ -264,7 +263,7 @@ template auto M68K::instructionBCHG(DataRegister bit, EffectiveAddres template auto M68K::instructionBCHG(EffectiveAddress with) -> void { auto index = readPC() & bits() - 1; - auto test = read(with); + auto test = read(with); r.z = test.bit(index) == 0; test.bit(index) ^= 1; write(with, test); @@ -272,7 +271,7 @@ template auto M68K::instructionBCHG(EffectiveAddress with) -> void { template auto M68K::instructionBCLR(DataRegister bit, EffectiveAddress with) -> void { auto index = read(bit) & bits() - 1; - auto test = read(with); + auto test = read(with); r.z = test.bit(index) == 0; test.bit(index) = 0; write(with, test); @@ -280,7 +279,7 @@ template auto M68K::instructionBCLR(DataRegister bit, EffectiveAddres template auto M68K::instructionBCLR(EffectiveAddress with) -> void { auto index = readPC() & bits() - 1; - auto test = read(with); + auto test = read(with); r.z = test.bit(index) == 0; test.bit(index) = 0; write(with, test); @@ -288,7 +287,7 @@ template auto M68K::instructionBCLR(EffectiveAddress with) -> void { template auto M68K::instructionBSET(DataRegister bit, EffectiveAddress with) -> void { auto index = read(bit) & bits() - 1; - auto test = read(with); + auto test = read(with); r.z = test.bit(index) == 0; test.bit(index) = 1; write(with, test); @@ -296,7 +295,7 @@ template auto M68K::instructionBSET(DataRegister bit, EffectiveAddres template auto M68K::instructionBSET(EffectiveAddress with) -> void { auto index = readPC() & bits() - 1; - auto test = read(with); + auto test = read(with); r.z = test.bit(index) == 0; test.bit(index) = 1; write(with, test); @@ -322,7 +321,7 @@ auto M68K::instructionCHK(DataRegister compare, EffectiveAddress maximum) -> voi r.n = sign(target) < 0; if(r.n) return exception(Exception::BoundsCheck, Vector::BoundsCheck); - auto result = target - source; + auto result = (uint64)target - source; r.c = sign(result >> 1) < 0; r.v = sign((target ^ source) & (target ^ result)) < 0; r.z = clip(result) == 0; @@ -331,7 +330,7 @@ auto M68K::instructionCHK(DataRegister compare, EffectiveAddress maximum) -> voi } template auto M68K::instructionCLR(EffectiveAddress ea) -> void { - read(ea); + read(ea); write(ea, 0); r.c = 0; @@ -341,7 +340,7 @@ template auto M68K::instructionCLR(EffectiveAddress ea) -> void { } template auto M68K::CMP(uint32 source, uint32 target) -> uint32 { - uint64 result = (uint64)target - (uint64)source; + auto result = (uint64)target - source; r.c = sign(result >> 1) < 0; r.v = sign((target ^ source) & (target ^ result)) < 0; @@ -358,7 +357,7 @@ template auto M68K::instructionCMP(DataRegister dr, EffectiveAddress } template auto M68K::instructionCMPA(AddressRegister ar, EffectiveAddress ea) -> void { - auto source = read(ea); + auto source = sign(read(ea)); auto target = read(ar); CMP(source, target); } @@ -452,14 +451,14 @@ template auto M68K::EOR(uint32 source, uint32 target) -> uint32 { template auto M68K::instructionEOR(DataRegister from, EffectiveAddress with) -> void { auto source = read(from); - auto target = read(with); + auto target = read(with); auto result = EOR(source, target); write(with, result); } template auto M68K::instructionEORI(EffectiveAddress with) -> void { auto source = readPC(); - auto target = read(with); + auto target = read(with); auto result = EOR(source, target); write(with, result); } @@ -570,7 +569,7 @@ template auto M68K::instructionLSL(DataRegister sr, DataRegister dr) } auto M68K::instructionLSL(EffectiveAddress ea) -> void { - auto result = LSL(read(ea), 1); + auto result = LSL(read(ea), 1); write(ea, result); } @@ -602,7 +601,7 @@ template auto M68K::instructionLSR(DataRegister shift, DataRegister d } auto M68K::instructionLSR(EffectiveAddress ea) -> void { - auto result = LSR(read(ea), 1); + auto result = LSR(read(ea), 1); write(ea, result); } @@ -745,8 +744,8 @@ auto M68K::instructionMULU(DataRegister with, EffectiveAddress from) -> void { auto M68K::instructionNBCD(EffectiveAddress with) -> void { auto source = 0u; - auto target = read(with); - auto result = source - target - r.x; + auto target = read(with); + auto result = (uint64)target - source - r.x; bool v = false; const bool adjustLo = (target ^ source ^ result) & 0x10; @@ -768,18 +767,18 @@ auto M68K::instructionNBCD(EffectiveAddress with) -> void { r.c = sign(result >> 1) < 0; r.v = v; - r.z = clip(result) == 0 ? 0 : r.z; + r.z = clip(result) ? 0 : r.z; r.n = sign(result) < 0; } template auto M68K::instructionNEG(EffectiveAddress with) -> void { - auto source = read(with); + auto source = read(with); auto result = SUB(0, source); write(with, result); } template auto M68K::instructionNEGX(EffectiveAddress with) -> void { - auto source = read(with); + auto source = read(with); auto result = SUB(0, source); write(with, result); } @@ -788,7 +787,7 @@ auto M68K::instructionNOP() -> void { } template auto M68K::instructionNOT(EffectiveAddress with) -> void { - auto result = ~read(with); + auto result = ~read(with); write(with, result); r.c = 0; @@ -817,14 +816,14 @@ template auto M68K::instructionOR(EffectiveAddress from, DataRegister template auto M68K::instructionOR(DataRegister from, EffectiveAddress with) -> void { auto source = read(from); - auto target = read(with); + auto target = read(with); auto result = OR(source, target); write(with, result); } template auto M68K::instructionORI(EffectiveAddress with) -> void { auto source = readPC(); - auto target = read(with); + auto target = read(with); auto result = OR(source, target); write(with, result); } @@ -879,7 +878,7 @@ template auto M68K::instructionROL(DataRegister shift, DataRegister m } auto M68K::instructionROL(EffectiveAddress modify) -> void { - auto result = ROL(read(modify), 1); + auto result = ROL(read(modify), 1); write(modify, result); } @@ -911,7 +910,7 @@ template auto M68K::instructionROR(DataRegister shift, DataRegister m } auto M68K::instructionROR(EffectiveAddress modify) -> void { - auto result = ROR(read(modify), 1); + auto result = ROR(read(modify), 1); write(modify, result); } @@ -944,7 +943,7 @@ template auto M68K::instructionROXL(DataRegister shift, DataRegister } auto M68K::instructionROXL(EffectiveAddress modify) -> void { - auto result = ROXL(read(modify), 1); + auto result = ROXL(read(modify), 1); write(modify, result); } @@ -978,7 +977,7 @@ template auto M68K::instructionROXR(DataRegister shift, DataRegister } auto M68K::instructionROXR(EffectiveAddress modify) -> void { - auto result = ROXR(read(modify), 1); + auto result = ROXR(read(modify), 1); write(modify, result); } @@ -1001,8 +1000,8 @@ auto M68K::instructionRTS() -> void { auto M68K::instructionSBCD(EffectiveAddress with, EffectiveAddress from) -> void { auto source = read(from); - auto target = read(with); - auto result = target - source - r.x; + auto target = read(with); + auto result = (uint64)target - source - r.x; bool v = false; const bool adjustLo = (target ^ source ^ result) & 0x10; @@ -1024,7 +1023,7 @@ auto M68K::instructionSBCD(EffectiveAddress with, EffectiveAddress from) -> void r.c = sign(result >> 1) < 0; r.v = v; - r.z = clip(result) == 0 ? 0 : r.z; + r.z = clip(result) ? 0 : r.z; r.n = sign(result) < 0; } @@ -1042,13 +1041,12 @@ auto M68K::instructionSTOP() -> void { } template auto M68K::SUB(uint32 source, uint32 target) -> uint32 { - uint64 result = source - target; + auto result = (uint64)target - source; if(Extend) result -= r.x; r.c = sign(result >> 1) < 0; r.v = sign((target ^ source) & (target ^ result)) < 0; - if(Extend == 0) r.z = clip(result == 0); - if(Extend == 1) if(clip(result)) r.z = 0; + r.z = clip(result) ? 0 : (Extend ? r.z : 1); r.n = sign(result) < 0; r.x = r.c; @@ -1064,34 +1062,34 @@ template auto M68K::instructionSUB(EffectiveAddress source_, DataRegi template auto M68K::instructionSUB(DataRegister source_, EffectiveAddress target_) -> void { auto source = read(source_); - auto target = read(target_); + auto target = read(target_); auto result = SUB(source, target); write(target_, result); } template auto M68K::instructionSUBA(AddressRegister to, EffectiveAddress from) -> void { - auto source = read(from); + auto source = sign(read(from)); auto target = read(to); write(to, target - source); } template auto M68K::instructionSUBI(EffectiveAddress with) -> void { auto source = readPC(); - auto target = read(with); + auto target = read(with); auto result = SUB(source, target); write(with, result); } template auto M68K::instructionSUBQ(uint4 immediate, EffectiveAddress ea) -> void { auto source = immediate; - auto target = read(ea); + auto target = read(ea); auto result = SUB(source, target); write(ea, result); } template auto M68K::instructionSUBX(EffectiveAddress with, EffectiveAddress from) -> void { auto source = read(from); - auto target = read(with); + auto target = read(with); auto result = SUB(source, target); write(with, result); } @@ -1108,7 +1106,7 @@ auto M68K::instructionSWAP(DataRegister with) -> void { } auto M68K::instructionTAS(EffectiveAddress with) -> void { - auto data = read(with); + auto data = read(with); write(with, data | 0x80); r.c = 0; diff --git a/higan/processor/m68k/m68k.cpp b/higan/processor/m68k/m68k.cpp index 90d712e5..41c3874a 100644 --- a/higan/processor/m68k/m68k.cpp +++ b/higan/processor/m68k/m68k.cpp @@ -45,10 +45,11 @@ auto M68K::supervisor() -> bool { return false; } -auto M68K::exception(uint exception, uint vector) -> void { +auto M68K::exception(uint exception, uint vector, uint priority) -> void { auto pc = r.pc; auto sr = readSR(); + r.i = priority; r.s = 1; r.t = 0; diff --git a/higan/processor/m68k/m68k.hpp b/higan/processor/m68k/m68k.hpp index 7b26e5b1..0595ba03 100644 --- a/higan/processor/m68k/m68k.hpp +++ b/higan/processor/m68k/m68k.hpp @@ -7,7 +7,7 @@ namespace Processor { struct M68K { enum : bool { User, Supervisor }; enum : uint { Byte, Word, Long }; - enum : bool { NoUpdate = 0, Reverse = 1, Extend = 1 }; + enum : bool { Reverse = 1, Extend = 1, Hold = 1 }; enum : uint { DataRegisterDirect, @@ -58,7 +58,7 @@ struct M68K { auto power() -> void; auto reset() -> void; auto supervisor() -> bool; - auto exception(uint exception, uint vector) -> void; + auto exception(uint exception, uint vector, uint priority = 7) -> void; //registers.cpp struct DataRegister { @@ -101,8 +101,8 @@ struct M68K { }; template auto fetch(EffectiveAddress& ea) -> uint32; - template auto read(EffectiveAddress& ea) -> uint32; - template auto write(EffectiveAddress& ea, uint32 data) -> void; + template auto read(EffectiveAddress& ea) -> uint32; + template auto write(EffectiveAddress& ea, uint32 data) -> void; template auto flush(EffectiveAddress& ea, uint32 data) -> void; //instruction.cpp @@ -126,11 +126,11 @@ struct M68K { template auto instructionADDA(AddressRegister ar, EffectiveAddress ea) -> void; template auto instructionADDI(EffectiveAddress modify) -> void; template auto instructionADDQ(uint4 immediate, EffectiveAddress modify) -> void; - template auto instructionADDX(EffectiveAddress target, EffectiveAddress source) -> void; + template auto instructionADDX(EffectiveAddress with, EffectiveAddress from) -> void; template auto AND(uint32 source, uint32 target) -> uint32; template auto instructionAND(EffectiveAddress from, DataRegister with) -> void; template auto instructionAND(DataRegister from, EffectiveAddress with) -> void; - template auto instructionANDI(EffectiveAddress ea) -> void; + template auto instructionANDI(EffectiveAddress with) -> void; auto instructionANDI_TO_CCR() -> void; auto instructionANDI_TO_SR() -> void; template auto ASL(uint32 result, uint shift) -> uint32; @@ -282,10 +282,10 @@ private: template auto disassembleADDA(AddressRegister ar, EffectiveAddress ea) -> string; template auto disassembleADDI(EffectiveAddress modify) -> string; template auto disassembleADDQ(uint4 immediate, EffectiveAddress modify) -> string; - template auto disassembleADDX(EffectiveAddress target, EffectiveAddress source) -> string; + template auto disassembleADDX(EffectiveAddress with, EffectiveAddress from) -> string; template auto disassembleAND(EffectiveAddress from, DataRegister with) -> string; template auto disassembleAND(DataRegister from, EffectiveAddress with) -> string; - template auto disassembleANDI(EffectiveAddress ea) -> string; + template auto disassembleANDI(EffectiveAddress with) -> string; auto disassembleANDI_TO_CCR() -> string; auto disassembleANDI_TO_SR() -> string; template auto disassembleASL(uint4 shift, DataRegister modify) -> string; diff --git a/higan/systems/Game Gear.sys/manifest.bml b/higan/systems/Game Gear.sys/manifest.bml new file mode 100644 index 00000000..41f40dcb --- /dev/null +++ b/higan/systems/Game Gear.sys/manifest.bml @@ -0,0 +1 @@ +system name:Game Gear diff --git a/higan/systems/Master System.sys/manifest.bml b/higan/systems/Master System.sys/manifest.bml new file mode 100644 index 00000000..770db3fb --- /dev/null +++ b/higan/systems/Master System.sys/manifest.bml @@ -0,0 +1 @@ +system name:Master System diff --git a/higan/target-tomoko/GNUmakefile b/higan/target-tomoko/GNUmakefile index 5195ed72..5569af92 100644 --- a/higan/target-tomoko/GNUmakefile +++ b/higan/target-tomoko/GNUmakefile @@ -3,6 +3,7 @@ flags += -DSFC_SUPERGAMEBOY include fc/GNUmakefile include sfc/GNUmakefile +include ms/GNUmakefile include md/GNUmakefile include gb/GNUmakefile include gba/GNUmakefile diff --git a/higan/target-tomoko/program/program.cpp b/higan/target-tomoko/program/program.cpp index 5cbba905..06aa549f 100644 --- a/higan/target-tomoko/program/program.cpp +++ b/higan/target-tomoko/program/program.cpp @@ -1,6 +1,7 @@ #include "../tomoko.hpp" #include #include +#include #include #include #include @@ -17,6 +18,7 @@ Program::Program(string_vector args) { emulators.append(new Famicom::Interface); emulators.append(new SuperFamicom::Interface); + emulators.append(new MasterSystem::Interface); emulators.append(new MegaDrive::Interface); emulators.append(new GameBoy::Interface); emulators.append(new GameBoyAdvance::Interface); diff --git a/nall/primitives.hpp b/nall/primitives.hpp index 57aacd5e..b933801c 100644 --- a/nall/primitives.hpp +++ b/nall/primitives.hpp @@ -86,8 +86,8 @@ template struct Natural { inline auto& operator *=(const type value) { return set(get() * value); } inline auto& operator /=(const type value) { return set(get() / value); } inline auto& operator %=(const type value) { return set(get() % value); } - inline auto& operator++(int) { auto value = get(); set(value + 1); return value; } - inline auto& operator--(int) { auto value = get(); set(value - 1); return value; } + inline auto operator++(int) { auto value = get(); set(value + 1); return value; } + inline auto operator--(int) { auto value = get(); set(value - 1); return value; } inline auto& operator++() { return set(get() + 1); } inline auto& operator--() { return set(get() - 1); } @@ -190,8 +190,8 @@ template struct Integer { inline auto& operator *=(const utype value) { return set(get() * value); } inline auto& operator /=(const utype value) { return set(get() / value); } inline auto& operator %=(const utype value) { return set(get() % value); } - inline auto& operator++(int) { auto value = get(); set(value + 1); return value; } - inline auto& operator--(int) { auto value = get(); set(value - 1); return value; } + inline auto operator++(int) { auto value = get(); set(value + 1); return value; } + inline auto operator--(int) { auto value = get(); set(value - 1); return value; } inline auto& operator++() { return set(get() + 1); } inline auto& operator--() { return set(get() - 1); }