Update to v101r08 release.

byuu says:

Changelog:

  - 68K: fixed read-modify-write instructions
  - 68K: fixed ADDX bug (using wrong target)
  - 68K: fixed major bug with SUB using wrong argument ordering
  - 68K: fixed sign extension when reading address registers from
    effective addressing
  - 68K: fixed sign extension on CMPA, SUBA instructions
  - VDP: improved OAM sprite attribute table caching behavior
  - VDP: improved DMA fill operation behavior
  - added Master System / Game Gear stubs (needed for developing the Z80
    core)
This commit is contained in:
Tim Allen 2016-08-17 22:31:22 +10:00
parent ffd150735b
commit 043f6a8b33
32 changed files with 522 additions and 143 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

12
higan/ms/GNUmakefile Normal file
View File

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

View File

@ -0,0 +1,7 @@
#include <ms/ms.hpp>
namespace MasterSystem {
Cartridge cartridge;
}

View File

@ -0,0 +1,4 @@
struct Cartridge {
};
extern Cartridge cartridge;

18
higan/ms/cpu/cpu.cpp Normal file
View File

@ -0,0 +1,18 @@
#include <ms/ms.hpp>
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);
}
}

9
higan/ms/cpu/cpu.hpp Normal file
View File

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

View File

@ -0,0 +1,115 @@
#include <ms/ms.hpp>
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;
}
}

View File

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

36
higan/ms/ms.hpp Normal file
View File

@ -0,0 +1,36 @@
#pragma once
//license: GPLv3
//started: 2016-08-17
#include <emulator/emulator.hpp>
#include <emulator/thread.hpp>
#include <emulator/scheduler.hpp>
#include <processor/z80/z80.hpp>
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 <ms/cpu/cpu.hpp>
#include <ms/vdp/vdp.hpp>
#include <ms/psg/psg.hpp>
#include <ms/system/system.hpp>
#include <ms/cartridge/cartridge.hpp>
}
#include <ms/interface/interface.hpp>

18
higan/ms/psg/psg.cpp Normal file
View File

@ -0,0 +1,18 @@
#include <ms/ms.hpp>
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);
}
}

9
higan/ms/psg/psg.hpp Normal file
View File

@ -0,0 +1,9 @@
//TI SN76489
struct PSG : Thread {
static auto Enter() -> void;
auto main() -> void;
auto step(uint clocks) -> void;
};
extern PSG psg;

View File

@ -0,0 +1,27 @@
#include <ms/ms.hpp>
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 {
}
}

View File

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

18
higan/ms/vdp/vdp.cpp Normal file
View File

@ -0,0 +1,18 @@
#include <ms/ms.hpp>
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);
}
}

9
higan/ms/vdp/vdp.hpp Normal file
View File

@ -0,0 +1,9 @@
//...
struct VDP : Thread {
static auto Enter() -> void;
auto main() -> void;
auto step(uint clocks) -> void;
};
extern VDP vdp;

View File

@ -130,8 +130,8 @@ template<uint Size> auto M68K::disassembleADDQ(uint4 immediate, EffectiveAddress
return {"addq", _suffix<Size>(), " #", immediate, ",", _effectiveAddress<Size>(modify)};
}
template<uint Size> auto M68K::disassembleADDX(EffectiveAddress target, EffectiveAddress source) -> string {
return {"addx", _suffix<Size>(), " ", _effectiveAddress<Size>(target), ",", _effectiveAddress<Size>(source)};
template<uint Size> auto M68K::disassembleADDX(EffectiveAddress with, EffectiveAddress from) -> string {
return {"addx", _suffix<Size>(), " ", _effectiveAddress<Size>(from), ",", _effectiveAddress<Size>(with)};
}
template<uint Size> auto M68K::disassembleAND(EffectiveAddress from, DataRegister with) -> string {
@ -544,11 +544,11 @@ template<uint Size> auto M68K::disassembleSUBI(EffectiveAddress with) -> string
}
template<uint Size> auto M68K::disassembleSUBQ(uint4 immediate, EffectiveAddress ea) -> string {
return {"subq", _suffix<Size>(), " #", immediate, _effectiveAddress<Size>(ea)};
return {"subq", _suffix<Size>(), " #", immediate, ",", _effectiveAddress<Size>(ea)};
}
template<uint Size> auto M68K::disassembleSUBX(EffectiveAddress with, EffectiveAddress from) -> string {
return {"subx", _suffix<Size>(), " ", _effectiveAddress<Size>(with), ",", _effectiveAddress<Size>(from)};
return {"subx", _suffix<Size>(), " ", _effectiveAddress<Size>(from), ",", _effectiveAddress<Size>(with)};
}
auto M68K::disassembleSWAP(DataRegister with) -> string {

View File

@ -68,7 +68,7 @@ template<uint Size> auto M68K::fetch(EffectiveAddress& ea) -> uint32 {
return 0;
}
template<uint Size, bool Update> auto M68K::read(EffectiveAddress& ea) -> uint32 {
template<uint Size, bool Hold> auto M68K::read(EffectiveAddress& ea) -> uint32 {
ea.address = fetch<Size>(ea);
switch(ea.mode) {
@ -78,7 +78,7 @@ template<uint Size, bool Update> auto M68K::read(EffectiveAddress& ea) -> uint32
}
case AddressRegisterDirect: {
return clip<Size>(ea.address);
return sign<Size>(ea.address);
}
case AddressRegisterIndirect: {
@ -87,13 +87,13 @@ template<uint Size, bool Update> auto M68K::read(EffectiveAddress& ea) -> uint32
case AddressRegisterIndirectWithPostIncrement: {
auto data = read<Size>(ea.address);
if(Update) write(AddressRegister{ea.reg}, ea.address += bytes<Size>());
if(!Hold) write(AddressRegister{ea.reg}, ea.address += bytes<Size>());
return data;
}
case AddressRegisterIndirectWithPreDecrement: {
auto data = read<Size>(ea.address - bytes<Size>());
if(Update) write(AddressRegister{ea.reg}, ea.address -= bytes<Size>());
if(!Hold) write(AddressRegister{ea.reg}, ea.address -= bytes<Size>());
return data;
}
@ -130,7 +130,7 @@ template<uint Size, bool Update> auto M68K::read(EffectiveAddress& ea) -> uint32
return 0;
}
template<uint Size, bool Update> auto M68K::write(EffectiveAddress& ea, uint32 data) -> void {
template<uint Size, bool Hold> auto M68K::write(EffectiveAddress& ea, uint32 data) -> void {
ea.address = fetch<Size>(ea);
switch(ea.mode) {
@ -149,13 +149,13 @@ template<uint Size, bool Update> auto M68K::write(EffectiveAddress& ea, uint32 d
case AddressRegisterIndirectWithPostIncrement: {
write<Size>(ea.address, data);
if(Update) write(AddressRegister{ea.reg}, ea.address += bytes<Size>());
if(!Hold) write(AddressRegister{ea.reg}, ea.address += bytes<Size>());
return;
}
case AddressRegisterIndirectWithPreDecrement: {
write<Size, Reverse>(ea.address - bytes<Size>(), data);
if(Update) write(AddressRegister{ea.reg}, ea.address -= bytes<Size>());
if(!Hold) write(AddressRegister{ea.reg}, ea.address -= bytes<Size>());
return;
}

View File

@ -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<Byte>, dataTarget, dataSource);
bind(opcode | 1 << 6 | 0 << 3, ADDX<Word>, dataTarget, dataSource);
bind(opcode | 2 << 6 | 0 << 3, ADDX<Long>, dataTarget, dataSource);
EffectiveAddress dataWith{DataRegisterDirect, xreg};
EffectiveAddress dataFrom{DataRegisterDirect, yreg};
bind(opcode | 0 << 6 | 0 << 3, ADDX<Byte>, dataWith, dataFrom);
bind(opcode | 1 << 6 | 0 << 3, ADDX<Word>, dataWith, dataFrom);
bind(opcode | 2 << 6 | 0 << 3, ADDX<Long>, dataWith, dataFrom);
EffectiveAddress addressTarget{AddressRegisterIndirectWithPreDecrement, treg};
EffectiveAddress addressSource{AddressRegisterIndirectWithPreDecrement, sreg};
bind(opcode | 0 << 6 | 1 << 3, ADDX<Byte>, addressTarget, addressSource);
bind(opcode | 1 << 6 | 1 << 3, ADDX<Word>, addressTarget, addressSource);
bind(opcode | 2 << 6 | 1 << 3, ADDX<Long>, addressTarget, addressSource);
EffectiveAddress addressWith{AddressRegisterIndirectWithPreDecrement, xreg};
EffectiveAddress addressFrom{AddressRegisterIndirectWithPreDecrement, yreg};
bind(opcode | 0 << 6 | 1 << 3, ADDX<Byte>, addressWith, addressFrom);
bind(opcode | 1 << 6 | 1 << 3, ADDX<Word>, addressWith, addressFrom);
bind(opcode | 2 << 6 | 1 << 3, ADDX<Long>, 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<Byte>, ea);
bind(opcode | 1 << 6, ANDI<Word>, ea);
bind(opcode | 2 << 6, ANDI<Long>, ea);
EffectiveAddress with{mode, reg};
bind(opcode | 0 << 6, ANDI<Byte>, with);
bind(opcode | 1 << 6, ANDI<Word>, with);
bind(opcode | 2 << 6, ANDI<Long>, with);
}
//ANDI_TO_CCR

View File

@ -52,7 +52,7 @@ template<> auto M68K::sign<Long>(uint32 data) -> int32 { return (int32)data; }
auto M68K::instructionABCD(EffectiveAddress with, EffectiveAddress from) -> void {
auto source = read<Byte>(from);
auto target = read<Byte, NoUpdate>(with);
auto target = read<Byte, Hold>(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<Byte>(result >> 1) < 0;
r.v = v;
r.z = clip<Byte>(result) == 0 ? 0 : r.z;
r.z = clip<Byte>(result) ? 0 : r.z;
r.n = sign<Byte>(result) < 0;
r.x = r.c;
}
template<uint Size, bool Extend> 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<Size>(result >> 1) < 0;
r.v = sign<Size>(~(target ^ source) & (target ^ result)) < 0;
if(Extend == 0) r.z = clip<Size>(result) == 0;
if(Extend == 1) if(clip<Size>(result)) r.z = 0;
r.z = clip<Size>(result) ? 0 : (Extend ? r.z : 1);
r.n = sign<Size>(result) < 0;
r.x = r.c;
@ -100,7 +99,7 @@ template<uint Size> auto M68K::instructionADD(EffectiveAddress from, DataRegiste
template<uint Size> auto M68K::instructionADD(DataRegister from, EffectiveAddress with) -> void {
auto source = read<Size>(from);
auto target = read<Size>(with);
auto target = read<Size, Hold>(with);
auto result = ADD<Size>(source, target);
write<Size>(with, result);
}
@ -113,23 +112,23 @@ template<uint Size> auto M68K::instructionADDA(AddressRegister ar, EffectiveAddr
template<uint Size> auto M68K::instructionADDI(EffectiveAddress modify) -> void {
auto source = readPC<Size>();
auto target = read<Size>(modify);
auto target = read<Size, Hold>(modify);
auto result = ADD<Size>(source, target);
write<Size>(modify, result);
}
template<uint Size> auto M68K::instructionADDQ(uint4 immediate, EffectiveAddress modify) -> void {
auto source = read<Size>(modify);
auto source = read<Size, Hold>(modify);
auto target = immediate;
auto result = ADD<Size>(source, target);
write<Size>(modify, result);
}
template<uint Size> auto M68K::instructionADDX(EffectiveAddress target_, EffectiveAddress source_) -> void {
auto source = read<Size>(source_);
auto target = read<Size>(target_);
template<uint Size> auto M68K::instructionADDX(EffectiveAddress with, EffectiveAddress from) -> void {
auto source = read<Size>(from);
auto target = read<Size, Hold>(with);
auto result = ADD<Size, Extend>(source, target);
write<Size>(target, result);
write<Size>(with, result);
}
template<uint Size> auto M68K::AND(uint32 source, uint32 target) -> uint32 {
@ -152,16 +151,16 @@ template<uint Size> auto M68K::instructionAND(EffectiveAddress from, DataRegiste
template<uint Size> auto M68K::instructionAND(DataRegister from, EffectiveAddress with) -> void {
auto source = read<Size>(from);
auto target = read<Size>(with);
auto target = read<Size, Hold>(with);
auto result = AND<Size>(source, target);
write<Size>(with, result);
}
template<uint Size> auto M68K::instructionANDI(EffectiveAddress ea) -> void {
template<uint Size> auto M68K::instructionANDI(EffectiveAddress with) -> void {
auto source = readPC<Size>();
auto target = read<Size, NoUpdate>(ea);
auto target = read<Size, Hold>(with);
auto result = AND<Size>(source, target);
write<Size>(ea, result);
write<Size>(with, result);
}
auto M68K::instructionANDI_TO_CCR() -> void {
@ -207,7 +206,7 @@ template<uint Size> auto M68K::instructionASL(DataRegister shift, DataRegister m
}
auto M68K::instructionASL(EffectiveAddress modify) -> void {
auto result = ASL<Word>(read<Word, NoUpdate>(modify), 1);
auto result = ASL<Word>(read<Word, Hold>(modify), 1);
write<Word>(modify, result);
}
@ -242,7 +241,7 @@ template<uint Size> auto M68K::instructionASR(DataRegister shift, DataRegister m
}
auto M68K::instructionASR(EffectiveAddress modify) -> void {
auto result = ASR<Word>(read<Word, NoUpdate>(modify), 1);
auto result = ASR<Word>(read<Word, Hold>(modify), 1);
write<Word>(modify, result);
}
@ -256,7 +255,7 @@ auto M68K::instructionBCC(uint4 condition, uint8 displacement) -> void {
template<uint Size> auto M68K::instructionBCHG(DataRegister bit, EffectiveAddress with) -> void {
auto index = read<Size>(bit) & bits<Size>() - 1;
auto test = read<Size>(with);
auto test = read<Size, Hold>(with);
r.z = test.bit(index) == 0;
test.bit(index) ^= 1;
write<Size>(with, test);
@ -264,7 +263,7 @@ template<uint Size> auto M68K::instructionBCHG(DataRegister bit, EffectiveAddres
template<uint Size> auto M68K::instructionBCHG(EffectiveAddress with) -> void {
auto index = readPC<Word>() & bits<Size>() - 1;
auto test = read<Size>(with);
auto test = read<Size, Hold>(with);
r.z = test.bit(index) == 0;
test.bit(index) ^= 1;
write<Size>(with, test);
@ -272,7 +271,7 @@ template<uint Size> auto M68K::instructionBCHG(EffectiveAddress with) -> void {
template<uint Size> auto M68K::instructionBCLR(DataRegister bit, EffectiveAddress with) -> void {
auto index = read<Size>(bit) & bits<Size>() - 1;
auto test = read<Size>(with);
auto test = read<Size, Hold>(with);
r.z = test.bit(index) == 0;
test.bit(index) = 0;
write<Size>(with, test);
@ -280,7 +279,7 @@ template<uint Size> auto M68K::instructionBCLR(DataRegister bit, EffectiveAddres
template<uint Size> auto M68K::instructionBCLR(EffectiveAddress with) -> void {
auto index = readPC<Word>() & bits<Size>() - 1;
auto test = read<Size>(with);
auto test = read<Size, Hold>(with);
r.z = test.bit(index) == 0;
test.bit(index) = 0;
write<Size>(with, test);
@ -288,7 +287,7 @@ template<uint Size> auto M68K::instructionBCLR(EffectiveAddress with) -> void {
template<uint Size> auto M68K::instructionBSET(DataRegister bit, EffectiveAddress with) -> void {
auto index = read<Size>(bit) & bits<Size>() - 1;
auto test = read<Size>(with);
auto test = read<Size, Hold>(with);
r.z = test.bit(index) == 0;
test.bit(index) = 1;
write<Size>(with, test);
@ -296,7 +295,7 @@ template<uint Size> auto M68K::instructionBSET(DataRegister bit, EffectiveAddres
template<uint Size> auto M68K::instructionBSET(EffectiveAddress with) -> void {
auto index = readPC<Word>() & bits<Size>() - 1;
auto test = read<Size>(with);
auto test = read<Size, Hold>(with);
r.z = test.bit(index) == 0;
test.bit(index) = 1;
write<Size>(with, test);
@ -322,7 +321,7 @@ auto M68K::instructionCHK(DataRegister compare, EffectiveAddress maximum) -> voi
r.n = sign<Word>(target) < 0;
if(r.n) return exception(Exception::BoundsCheck, Vector::BoundsCheck);
auto result = target - source;
auto result = (uint64)target - source;
r.c = sign<Word>(result >> 1) < 0;
r.v = sign<Word>((target ^ source) & (target ^ result)) < 0;
r.z = clip<Word>(result) == 0;
@ -331,7 +330,7 @@ auto M68K::instructionCHK(DataRegister compare, EffectiveAddress maximum) -> voi
}
template<uint Size> auto M68K::instructionCLR(EffectiveAddress ea) -> void {
read<Size>(ea);
read<Size, Hold>(ea);
write<Size>(ea, 0);
r.c = 0;
@ -341,7 +340,7 @@ template<uint Size> auto M68K::instructionCLR(EffectiveAddress ea) -> void {
}
template<uint Size> auto M68K::CMP(uint32 source, uint32 target) -> uint32 {
uint64 result = (uint64)target - (uint64)source;
auto result = (uint64)target - source;
r.c = sign<Size>(result >> 1) < 0;
r.v = sign<Size>((target ^ source) & (target ^ result)) < 0;
@ -358,7 +357,7 @@ template<uint Size> auto M68K::instructionCMP(DataRegister dr, EffectiveAddress
}
template<uint Size> auto M68K::instructionCMPA(AddressRegister ar, EffectiveAddress ea) -> void {
auto source = read<Size>(ea);
auto source = sign<Size>(read<Size>(ea));
auto target = read<Size>(ar);
CMP<Size>(source, target);
}
@ -452,14 +451,14 @@ template<uint Size> auto M68K::EOR(uint32 source, uint32 target) -> uint32 {
template<uint Size> auto M68K::instructionEOR(DataRegister from, EffectiveAddress with) -> void {
auto source = read<Size>(from);
auto target = read<Size>(with);
auto target = read<Size, Hold>(with);
auto result = EOR<Size>(source, target);
write<Size>(with, result);
}
template<uint Size> auto M68K::instructionEORI(EffectiveAddress with) -> void {
auto source = readPC<Size>();
auto target = read<Size, NoUpdate>(with);
auto target = read<Size, Hold>(with);
auto result = EOR<Size>(source, target);
write<Size>(with, result);
}
@ -570,7 +569,7 @@ template<uint Size> auto M68K::instructionLSL(DataRegister sr, DataRegister dr)
}
auto M68K::instructionLSL(EffectiveAddress ea) -> void {
auto result = LSL<Word>(read<Word, NoUpdate>(ea), 1);
auto result = LSL<Word>(read<Word, Hold>(ea), 1);
write<Word>(ea, result);
}
@ -602,7 +601,7 @@ template<uint Size> auto M68K::instructionLSR(DataRegister shift, DataRegister d
}
auto M68K::instructionLSR(EffectiveAddress ea) -> void {
auto result = LSR<Word>(read<Word, NoUpdate>(ea), 1);
auto result = LSR<Word>(read<Word, Hold>(ea), 1);
write<Word>(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<Byte, NoUpdate>(with);
auto result = source - target - r.x;
auto target = read<Byte, Hold>(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<Byte>(result >> 1) < 0;
r.v = v;
r.z = clip<Byte>(result) == 0 ? 0 : r.z;
r.z = clip<Byte>(result) ? 0 : r.z;
r.n = sign<Byte>(result) < 0;
}
template<uint Size> auto M68K::instructionNEG(EffectiveAddress with) -> void {
auto source = read<Size>(with);
auto source = read<Size, Hold>(with);
auto result = SUB<Size>(0, source);
write<Size>(with, result);
}
template<uint Size> auto M68K::instructionNEGX(EffectiveAddress with) -> void {
auto source = read<Size>(with);
auto source = read<Size, Hold>(with);
auto result = SUB<Size, Extend>(0, source);
write<Size>(with, result);
}
@ -788,7 +787,7 @@ auto M68K::instructionNOP() -> void {
}
template<uint Size> auto M68K::instructionNOT(EffectiveAddress with) -> void {
auto result = ~read<Size>(with);
auto result = ~read<Size, Hold>(with);
write<Size>(with, result);
r.c = 0;
@ -817,14 +816,14 @@ template<uint Size> auto M68K::instructionOR(EffectiveAddress from, DataRegister
template<uint Size> auto M68K::instructionOR(DataRegister from, EffectiveAddress with) -> void {
auto source = read<Size>(from);
auto target = read<Size>(with);
auto target = read<Size, Hold>(with);
auto result = OR<Size>(source, target);
write<Size>(with, result);
}
template<uint Size> auto M68K::instructionORI(EffectiveAddress with) -> void {
auto source = readPC<Size>();
auto target = read<Size, NoUpdate>(with);
auto target = read<Size, Hold>(with);
auto result = OR<Size>(source, target);
write<Size>(with, result);
}
@ -879,7 +878,7 @@ template<uint Size> auto M68K::instructionROL(DataRegister shift, DataRegister m
}
auto M68K::instructionROL(EffectiveAddress modify) -> void {
auto result = ROL<Word>(read<Word, NoUpdate>(modify), 1);
auto result = ROL<Word>(read<Word, Hold>(modify), 1);
write<Word>(modify, result);
}
@ -911,7 +910,7 @@ template<uint Size> auto M68K::instructionROR(DataRegister shift, DataRegister m
}
auto M68K::instructionROR(EffectiveAddress modify) -> void {
auto result = ROR<Word>(read<Word, NoUpdate>(modify), 1);
auto result = ROR<Word>(read<Word, Hold>(modify), 1);
write<Word>(modify, result);
}
@ -944,7 +943,7 @@ template<uint Size> auto M68K::instructionROXL(DataRegister shift, DataRegister
}
auto M68K::instructionROXL(EffectiveAddress modify) -> void {
auto result = ROXL<Word>(read<Word, NoUpdate>(modify), 1);
auto result = ROXL<Word>(read<Word, Hold>(modify), 1);
write<Word>(modify, result);
}
@ -978,7 +977,7 @@ template<uint Size> auto M68K::instructionROXR(DataRegister shift, DataRegister
}
auto M68K::instructionROXR(EffectiveAddress modify) -> void {
auto result = ROXR<Word>(read<Word, NoUpdate>(modify), 1);
auto result = ROXR<Word>(read<Word, Hold>(modify), 1);
write<Word>(modify, result);
}
@ -1001,8 +1000,8 @@ auto M68K::instructionRTS() -> void {
auto M68K::instructionSBCD(EffectiveAddress with, EffectiveAddress from) -> void {
auto source = read<Byte>(from);
auto target = read<Byte, NoUpdate>(with);
auto result = target - source - r.x;
auto target = read<Byte, Hold>(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<Byte>(result >> 1) < 0;
r.v = v;
r.z = clip<Byte>(result) == 0 ? 0 : r.z;
r.z = clip<Byte>(result) ? 0 : r.z;
r.n = sign<Byte>(result) < 0;
}
@ -1042,13 +1041,12 @@ auto M68K::instructionSTOP() -> void {
}
template<uint Size, bool Extend> 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<Size>(result >> 1) < 0;
r.v = sign<Size>((target ^ source) & (target ^ result)) < 0;
if(Extend == 0) r.z = clip<Size>(result == 0);
if(Extend == 1) if(clip<Size>(result)) r.z = 0;
r.z = clip<Size>(result) ? 0 : (Extend ? r.z : 1);
r.n = sign<Size>(result) < 0;
r.x = r.c;
@ -1064,34 +1062,34 @@ template<uint Size> auto M68K::instructionSUB(EffectiveAddress source_, DataRegi
template<uint Size> auto M68K::instructionSUB(DataRegister source_, EffectiveAddress target_) -> void {
auto source = read<Size>(source_);
auto target = read<Size>(target_);
auto target = read<Size, Hold>(target_);
auto result = SUB<Size>(source, target);
write<Size>(target_, result);
}
template<uint Size> auto M68K::instructionSUBA(AddressRegister to, EffectiveAddress from) -> void {
auto source = read<Size>(from);
auto source = sign<Size>(read<Size>(from));
auto target = read<Size>(to);
write<Long>(to, target - source);
}
template<uint Size> auto M68K::instructionSUBI(EffectiveAddress with) -> void {
auto source = readPC<Size>();
auto target = read<Size>(with);
auto target = read<Size, Hold>(with);
auto result = SUB<Size>(source, target);
write<Size>(with, result);
}
template<uint Size> auto M68K::instructionSUBQ(uint4 immediate, EffectiveAddress ea) -> void {
auto source = immediate;
auto target = read<Size, NoUpdate>(ea);
auto target = read<Size, Hold>(ea);
auto result = SUB<Size>(source, target);
write<Size>(ea, result);
}
template<uint Size> auto M68K::instructionSUBX(EffectiveAddress with, EffectiveAddress from) -> void {
auto source = read<Size>(from);
auto target = read<Size>(with);
auto target = read<Size, Hold>(with);
auto result = SUB<Size, Extend>(source, target);
write<Size>(with, result);
}
@ -1108,7 +1106,7 @@ auto M68K::instructionSWAP(DataRegister with) -> void {
}
auto M68K::instructionTAS(EffectiveAddress with) -> void {
auto data = read<Byte, NoUpdate>(with);
auto data = read<Byte, Hold>(with);
write<Byte>(with, data | 0x80);
r.c = 0;

View File

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

View File

@ -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<uint Size> auto fetch(EffectiveAddress& ea) -> uint32;
template<uint Size, bool Update = 1> auto read(EffectiveAddress& ea) -> uint32;
template<uint Size, bool Update = 1> auto write(EffectiveAddress& ea, uint32 data) -> void;
template<uint Size, bool Hold = 0> auto read(EffectiveAddress& ea) -> uint32;
template<uint Size, bool Hold = 0> auto write(EffectiveAddress& ea, uint32 data) -> void;
template<uint Size> auto flush(EffectiveAddress& ea, uint32 data) -> void;
//instruction.cpp
@ -126,11 +126,11 @@ struct M68K {
template<uint Size> auto instructionADDA(AddressRegister ar, EffectiveAddress ea) -> void;
template<uint Size> auto instructionADDI(EffectiveAddress modify) -> void;
template<uint Size> auto instructionADDQ(uint4 immediate, EffectiveAddress modify) -> void;
template<uint Size> auto instructionADDX(EffectiveAddress target, EffectiveAddress source) -> void;
template<uint Size> auto instructionADDX(EffectiveAddress with, EffectiveAddress from) -> void;
template<uint Size> auto AND(uint32 source, uint32 target) -> uint32;
template<uint Size> auto instructionAND(EffectiveAddress from, DataRegister with) -> void;
template<uint Size> auto instructionAND(DataRegister from, EffectiveAddress with) -> void;
template<uint Size> auto instructionANDI(EffectiveAddress ea) -> void;
template<uint Size> auto instructionANDI(EffectiveAddress with) -> void;
auto instructionANDI_TO_CCR() -> void;
auto instructionANDI_TO_SR() -> void;
template<uint Size> auto ASL(uint32 result, uint shift) -> uint32;
@ -282,10 +282,10 @@ private:
template<uint Size> auto disassembleADDA(AddressRegister ar, EffectiveAddress ea) -> string;
template<uint Size> auto disassembleADDI(EffectiveAddress modify) -> string;
template<uint Size> auto disassembleADDQ(uint4 immediate, EffectiveAddress modify) -> string;
template<uint Size> auto disassembleADDX(EffectiveAddress target, EffectiveAddress source) -> string;
template<uint Size> auto disassembleADDX(EffectiveAddress with, EffectiveAddress from) -> string;
template<uint Size> auto disassembleAND(EffectiveAddress from, DataRegister with) -> string;
template<uint Size> auto disassembleAND(DataRegister from, EffectiveAddress with) -> string;
template<uint Size> auto disassembleANDI(EffectiveAddress ea) -> string;
template<uint Size> auto disassembleANDI(EffectiveAddress with) -> string;
auto disassembleANDI_TO_CCR() -> string;
auto disassembleANDI_TO_SR() -> string;
template<uint Size> auto disassembleASL(uint4 shift, DataRegister modify) -> string;

View File

@ -0,0 +1 @@
system name:Game Gear

View File

@ -0,0 +1 @@
system name:Master System

View File

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

View File

@ -1,6 +1,7 @@
#include "../tomoko.hpp"
#include <fc/interface/interface.hpp>
#include <sfc/interface/interface.hpp>
#include <ms/interface/interface.hpp>
#include <md/interface/interface.hpp>
#include <gb/interface/interface.hpp>
#include <gba/interface/interface.hpp>
@ -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);

View File

@ -86,8 +86,8 @@ template<uint Bits> 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<uint Bits> 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); }