From fc7d5991cee9e488527385ede94fcaf0190081fc Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Thu, 25 Feb 2016 21:38:03 +1100 Subject: [PATCH] Update to v097r18 release. byuu says: Changelog: - fixed SNES sprite priority regression from r17 - added nall/windows/guard.hpp to guard against global namespace pollution (similar to nall/xorg/guard.hpp) - almost fixed Windows compilation (still accuracy profile only, sorry) - finished porting all of gba/ppu's registers over to the new .bit,.bits format ... all GBA registers.cpp files gone now - the "processors :=" line in the target-$(ui)/GNUmakefile is no longer required - processors += added to each emulator core - duplicates are removed using the new nall/GNUmakefile's $(unique) function - SFC core can be compiled without the GB core now - "-DSFC_SUPERGAMEBOY" is required to build in SGB support now (it's set in target-tomoko/GNUmakefile) - started once again on loki (higan/target-loki/) [as before, loki is Linux/BSD only on account of needing hiro::Console] loki shouldn't be too horrendous ... I hope. I just have the base skeleton ready for now. But the code from v094r08 should be mostly copyable over to it. It's just that it's about 50KiB of incredibly tricky code that has to be just perfect, so it's not going to be quick. But at least with the skeleton, it'll be a lot easier to pick away at it as I want. Windows compilation fix: move hiro/windows/header.hpp line 18 (header guard) to line 16 instead. --- higan/GNUmakefile | 1 + higan/emulator/emulator.hpp | 2 +- higan/fc/GNUmakefile | 2 + higan/gb/GNUmakefile | 2 + higan/gba/GNUmakefile | 2 + higan/gba/apu/mmio.cpp | 44 +-- higan/gba/ppu/mmio.cpp | 332 +++++++++++------- higan/gba/ppu/ppu.cpp | 35 +- higan/gba/ppu/registers.cpp | 140 -------- higan/gba/ppu/registers.hpp | 62 +--- higan/gba/ppu/screen.cpp | 21 +- higan/sfc/GNUmakefile | 2 + higan/sfc/cartridge/cartridge.cpp | 2 + higan/sfc/coprocessor/icd2/icd2.cpp | 7 +- higan/sfc/coprocessor/icd2/icd2.hpp | 21 ++ higan/sfc/interface/interface.cpp | 8 +- higan/sfc/ppu/sprite/list.cpp | 4 +- higan/sfc/ppu/sprite/sprite.hpp | 24 +- higan/sfc/sfc.hpp | 5 +- higan/target-loki/GNUmakefile | 73 ++++ higan/target-loki/loki.cpp | 23 ++ higan/target-loki/loki.hpp | 21 ++ .../target-loki/presentation/presentation.cpp | 28 ++ .../target-loki/presentation/presentation.hpp | 9 + higan/target-loki/program/program.cpp | 45 +++ higan/target-loki/program/program.hpp | 21 ++ higan/target-loki/terminal/about-window.cpp | 18 + higan/target-loki/terminal/terminal.cpp | 26 ++ higan/target-loki/terminal/terminal.hpp | 22 ++ higan/target-tomoko/GNUmakefile | 9 +- higan/ws/GNUmakefile | 2 + hiro/windows/header.hpp | 2 + nall/string/platform.hpp | 2 +- nall/windows/guard.hpp | 13 + nall/windows/utf8.hpp | 5 +- ruby/video/wgl.cpp | 2 +- 36 files changed, 656 insertions(+), 381 deletions(-) delete mode 100644 higan/gba/ppu/registers.cpp create mode 100644 higan/target-loki/GNUmakefile create mode 100644 higan/target-loki/loki.cpp create mode 100644 higan/target-loki/loki.hpp create mode 100644 higan/target-loki/presentation/presentation.cpp create mode 100644 higan/target-loki/presentation/presentation.hpp create mode 100644 higan/target-loki/program/program.cpp create mode 100644 higan/target-loki/program/program.hpp create mode 100644 higan/target-loki/terminal/about-window.cpp create mode 100644 higan/target-loki/terminal/terminal.cpp create mode 100644 higan/target-loki/terminal/terminal.hpp create mode 100644 nall/windows/guard.hpp diff --git a/higan/GNUmakefile b/higan/GNUmakefile index 1daac6cf..f195426e 100644 --- a/higan/GNUmakefile +++ b/higan/GNUmakefile @@ -8,6 +8,7 @@ ws := ws profile := accuracy target := tomoko +# target := loki # console := true flags += -I. -I.. -O3 diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 69d32806..56f07a27 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -6,7 +6,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "097.17"; + static const string Version = "097.18"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/fc/GNUmakefile b/higan/fc/GNUmakefile index 265fce38..d9ad3864 100644 --- a/higan/fc/GNUmakefile +++ b/higan/fc/GNUmakefile @@ -1,3 +1,5 @@ +processors += r6502 + fc_objects := fc-interface fc-system fc-scheduler fc-input fc_objects += fc-memory fc-cartridge fc-cpu fc-apu fc-ppu fc_objects += fc-cheat diff --git a/higan/gb/GNUmakefile b/higan/gb/GNUmakefile index ff89d69c..34110715 100644 --- a/higan/gb/GNUmakefile +++ b/higan/gb/GNUmakefile @@ -1,3 +1,5 @@ +processors += lr35902 + gb_objects := gb-interface gb-system gb-scheduler gb_objects += gb-memory gb-cartridge gb_objects += gb-cpu gb-ppu gb-apu diff --git a/higan/gba/GNUmakefile b/higan/gba/GNUmakefile index 03418988..16b0e0e7 100644 --- a/higan/gba/GNUmakefile +++ b/higan/gba/GNUmakefile @@ -1,3 +1,5 @@ +processors += arm + gba_objects := gba-memory gba-interface gba-scheduler gba-system gba_objects += gba-cartridge gba-player gba_objects += gba-cpu gba-ppu gba-apu diff --git a/higan/gba/apu/mmio.cpp b/higan/gba/apu/mmio.cpp index 16dadb77..847504f7 100644 --- a/higan/gba/apu/mmio.cpp +++ b/higan/gba/apu/mmio.cpp @@ -5,19 +5,19 @@ auto APU::read(uint32 addr) -> uint8 { case 0x0400'0060: return square1.read(0); case 0x0400'0061: return 0; - //NR11 + NR12 + //NR11, NR12 case 0x0400'0062: return square1.read(1); case 0x0400'0063: return square1.read(2); - //NR13 + NR14 + //NR13, NR14 case 0x0400'0064: return square1.read(3); case 0x0400'0065: return square1.read(4); - //NR21 + NR22 + //NR21, NR22 case 0x0400'0068: return square2.read(1); case 0x0400'0069: return square2.read(2); - //NR23 + NR24 + //NR23, NR24 case 0x0400'006c: return square2.read(3); case 0x0400'006d: return square2.read(4); @@ -25,23 +25,23 @@ auto APU::read(uint32 addr) -> uint8 { case 0x0400'0070: return wave.read(0); case 0x0400'0071: return 0; - //NR31 + NR32 + //NR31, NR32 case 0x0400'0072: return wave.read(1); case 0x0400'0073: return wave.read(2); - //NR33 + NR34 + //NR33, NR34 case 0x0400'0074: return wave.read(3); case 0x0400'0075: return wave.read(4); - //NR41 + NR42 + //NR41, NR42 case 0x0400'0078: return noise.read(1); case 0x0400'0079: return noise.read(2); - //NR43 + NR44 + //NR43, NR44 case 0x0400'007c: return noise.read(3); case 0x0400'007d: return noise.read(4); - //NR50 + NR51 + //NR50, NR51 case 0x0400'0080: return sequencer.read(0); case 0x0400'0081: return sequencer.read(1); @@ -70,8 +70,8 @@ auto APU::read(uint32 addr) -> uint8 { regs.bias.level.bits(0,7) ); case 0x0400'0089: return ( - regs.bias.level.bits(8,9) - | regs.bias.amplitude << 6 + regs.bias.level.bits(8,9) << 0 + | regs.bias.amplitude << 6 ); //WAVE_RAM0_L @@ -108,7 +108,7 @@ auto APU::read(uint32 addr) -> uint8 { } - return 0u; + return 0; } auto APU::write(uint32 addr, uint8 data) -> void { @@ -118,19 +118,19 @@ auto APU::write(uint32 addr, uint8 data) -> void { case 0x0400'0060: return square1.write(0, data); case 0x0400'0061: return; - //NR11 + NR12 + //NR11, NR12 case 0x0400'0062: return square1.write(1, data); case 0x0400'0063: return square1.write(2, data); - //NR13 + NR14 + //NR13, NR14 case 0x0400'0064: return square1.write(3, data); case 0x0400'0065: return square1.write(4, data); - //NR21 + NR22 + //NR21, NR22 case 0x0400'0068: return square2.write(1, data); case 0x0400'0069: return square2.write(2, data); - //NR23 + NR24 + //NR23, NR24 case 0x0400'006c: return square2.write(3, data); case 0x0400'006d: return square2.write(4, data); @@ -138,23 +138,23 @@ auto APU::write(uint32 addr, uint8 data) -> void { case 0x0400'0070: return wave.write(0, data); case 0x0400'0071: return; - //NR31 + NR32 + //NR31, NR32 case 0x0400'0072: return wave.write(1, data); case 0x0400'0073: return wave.write(2, data); - //NR33 + NR34 + //NR33, NR34 case 0x0400'0074: return wave.write(3, data); case 0x0400'0075: return wave.write(4, data); - //NR41 + NR42 + //NR41, NR42 case 0x0400'0078: return noise.write(1, data); case 0x0400'0079: return noise.write(2, data); - //NR43 + NR44 + //NR43, NR44 case 0x0400'007c: return noise.write(3, data); case 0x0400'007d: return noise.write(4, data); - //NR50 + NR51 + //NR50, NR51 case 0x0400'0080: return sequencer.write(0, data); case 0x0400'0081: return sequencer.write(1, data); @@ -185,7 +185,7 @@ auto APU::write(uint32 addr, uint8 data) -> void { return; case 0x0400'0089: regs.bias.level.bits(8,9) = data.bits(0,1); - regs.bias.amplitude = data.bits(6,7); + regs.bias.amplitude = data.bits(6,7); return; //WAVE_RAM0_L diff --git a/higan/gba/ppu/mmio.cpp b/higan/gba/ppu/mmio.cpp index 698b0b48..5c55d5ae 100644 --- a/higan/gba/ppu/mmio.cpp +++ b/higan/gba/ppu/mmio.cpp @@ -1,41 +1,95 @@ auto PPU::read(uint32 addr) -> uint8 { + auto bgcnt = [&]() -> Registers::Background::Control& { return regs.bg[addr.bits(1,2)].control; }; + auto wf = [&]() -> Registers::WindowFlags& { + static uint id[] = {In0, In1, Out, Obj}; + return regs.windowflags[id[addr.bits(0,1)]]; + }; + switch(addr) { //DISPCNT - case 0x0400'0000: return regs.control >> 0; - case 0x0400'0001: return regs.control >> 8; + case 0x0400'0000: return ( + regs.control.bgmode << 0 + | regs.control.cgbmode << 3 + | regs.control.frame << 4 + | regs.control.hblank << 5 + | regs.control.objmapping << 6 + | regs.control.forceblank << 7 + ); + case 0x0400'0001: return ( + regs.control.enable[BG0] << 0 + | regs.control.enable[BG1] << 1 + | regs.control.enable[BG2] << 2 + | regs.control.enable[BG3] << 3 + | regs.control.enable[OBJ] << 4 + | regs.control.enablewindow[In0] << 5 + | regs.control.enablewindow[In1] << 6 + | regs.control.enablewindow[Obj] << 7 + ); //GRSWP case 0x0400'0002: return regs.greenswap; - case 0x0400'0003: return 0u; + case 0x0400'0003: return 0; //DISPSTAT - case 0x0400'0004: return regs.status >> 0; - case 0x0400'0005: return regs.status >> 8; + case 0x0400'0004: return ( + regs.status.vblank << 0 + | regs.status.hblank << 1 + | regs.status.vcoincidence << 2 + | regs.status.irqvblank << 3 + | regs.status.irqhblank << 4 + | regs.status.irqvcoincidence << 5 + ); + case 0x0400'0005: return ( + regs.status.vcompare + ); //VCOUNT - case 0x0400'0006: return regs.vcounter >> 0; - case 0x0400'0007: return regs.vcounter >> 8; + case 0x0400'0006: return regs.vcounter.byte(0); + case 0x0400'0007: return regs.vcounter.byte(1); - //BG0CNT,BG1CNT,BG2CNT,BG3CNT - case 0x0400'0008: case 0x0400'0009: - case 0x0400'000a: case 0x0400'000b: - case 0x0400'000c: case 0x0400'000d: - case 0x0400'000e: case 0x0400'000f: { - auto& bg = regs.bg[(addr >> 1) & 3]; - unsigned shift = (addr & 1) * 8; - return bg.control >> shift; - } + //BG0CNT, BG1CNT, BG2CNT, BG3CNT + case 0x0400'0008: case 0x0400'000a: case 0x0400'000c: case 0x0400'000e: return ( + bgcnt().priority << 0 + | bgcnt().characterbaseblock << 2 + | bgcnt().unused << 4 + | bgcnt().mosaic << 6 + | bgcnt().colormode << 7 + ); + case 0x0400'0009: case 0x0400'000b: case 0x0400'000d: case 0x0400'000f: return ( + bgcnt().screenbaseblock << 0 + | bgcnt().affinewrap << 5 + | bgcnt().screensize << 6 + ); - //WININ - case 0x0400'0048: return regs.windowflags[In0]; - case 0x0400'0049: return regs.windowflags[In1]; - case 0x0400'004a: return regs.windowflags[Out]; - case 0x0400'004b: return regs.windowflags[Obj]; + //WININ, WINOUT + case 0x0400'0048: case 0x0400'0049: case 0x0400'004a: case 0x0400'004b: return ( + wf().enable[BG0] << 0 + | wf().enable[BG1] << 1 + | wf().enable[BG2] << 2 + | wf().enable[BG3] << 3 + | wf().enable[OBJ] << 4 + | wf().enable[SFX] << 4 + ); //BLTCNT - case 0x0400'0050: return regs.blend.control >> 0; - case 0x0400'0051: return regs.blend.control >> 8; + case 0x0400'0050: return ( + regs.blend.control.above[BG0] << 0 + | regs.blend.control.above[BG1] << 1 + | regs.blend.control.above[BG2] << 2 + | regs.blend.control.above[BG3] << 3 + | regs.blend.control.above[OBJ] << 4 + | regs.blend.control.above[SFX] << 5 + | regs.blend.control.mode << 6 + ); + case 0x0400'0051: return ( + regs.blend.control.below[BG0] << 0 + | regs.blend.control.below[BG1] << 1 + | regs.blend.control.below[BG2] << 2 + | regs.blend.control.below[BG3] << 3 + | regs.blend.control.below[OBJ] << 4 + | regs.blend.control.below[SFX] << 5 + ); //BLDALPHA case 0x0400'0052: return regs.blend.eva; @@ -45,162 +99,176 @@ auto PPU::read(uint32 addr) -> uint8 { } - return 0u; + return 0; } -auto PPU::write(uint32 addr, uint8 byte) -> void { +auto PPU::write(uint32 addr, uint8 data) -> void { + auto bgcnt = [&]() -> Registers::Background::Control& { return regs.bg[addr.bits(1,2)].control; }; + auto bgofs = [&]() -> Registers::Background& { return regs.bg[addr.bits(2,3)]; }; + auto bg = [&]() -> Registers::Background& { return regs.bg[addr.bits(4,5)]; }; + auto wf = [&]() -> Registers::WindowFlags& { + static uint id[] = {In0, In1, Out, Obj}; + return regs.windowflags[id[addr.bits(0,1)]]; + }; + switch(addr) { //DISPCNT - case 0x0400'0000: regs.control = (regs.control & 0xff00) | (byte << 0); return; - case 0x0400'0001: regs.control = (regs.control & 0x00ff) | (byte << 8); return; + case 0x0400'0000: + regs.control.bgmode = data.bits(0,2); + regs.control.cgbmode = data.bit (3); + regs.control.frame = data.bit (4); + regs.control.hblank = data.bit (5); + regs.control.objmapping = data.bit (6); + regs.control.forceblank = data.bit (7); + return; + case 0x0400'0001: + regs.control.enable[BG0] = data.bit(0); + regs.control.enable[BG1] = data.bit(1); + regs.control.enable[BG2] = data.bit(2); + regs.control.enable[BG3] = data.bit(3); + regs.control.enable[OBJ] = data.bit(4); + regs.control.enablewindow[In0] = data.bit(5); + regs.control.enablewindow[In1] = data.bit(6); + regs.control.enablewindow[Obj] = data.bit(7); + return; //GRSWP - case 0x0400'0002: regs.greenswap = byte >> 0; return; + case 0x0400'0002: + regs.greenswap = data.bit(0); + return; case 0x0400'0003: return; //DISPSTAT case 0x0400'0004: - regs.status.irqvblank = byte >> 3; - regs.status.irqhblank = byte >> 4; - regs.status.irqvcoincidence = byte >> 5; + regs.status.irqvblank = data.bit(3); + regs.status.irqhblank = data.bit(4); + regs.status.irqvcoincidence = data.bit(5); return; case 0x0400'0005: - regs.status.vcompare = byte; + regs.status.vcompare = data; return; - //BG0CNT,BG1CNT,BG2CNT,BG3CNT - case 0x0400'0008: case 0x0400'0009: - case 0x0400'000a: case 0x0400'000b: - case 0x0400'000c: case 0x0400'000d: - case 0x0400'000e: case 0x0400'000f: { - auto& bg = regs.bg[(addr >> 1) & 3]; - unsigned shift = (addr & 1) * 8; - if(addr == 0x04000009 || addr == 0x0400000b) byte &= 0xdf; //clear affine wrap for BG0,1 - bg.control = (bg.control & ~(255 << shift)) | (byte << shift); + //BG0CNT, BG1CNT, BG2CNT, BG3CNT + case 0x0400'0008: case 0x0400'000a: case 0x0400'000c: case 0x0400'000e: + bgcnt().priority = data.bits(0,1); + bgcnt().characterbaseblock = data.bits(2,3); + bgcnt().unused = data.bits(4,5); + bgcnt().mosaic = data.bit (6); + bgcnt().colormode = data.bit (7); + return; + case 0x0400'0009: case 0x0400'000b: case 0x0400'000d: case 0x0400'000f: + if(addr.bits(1,2) <= 1) data.bit(5) = 0; //clear affine wrap for BG0, BG1 + bgcnt().screenbaseblock = data.bits(0,4); + bgcnt().affinewrap = data.bit (5); + bgcnt().screensize = data.bits(6,7); return; - } - //BG0HOFS,BG1HOFS,BG2BOFS,BG3HOFS - case 0x0400'0010: case 0x0400'0011: - case 0x0400'0014: case 0x0400'0015: - case 0x0400'0018: case 0x0400'0019: - case 0x0400'001c: case 0x0400'001d: { - auto& bg = regs.bg[(addr >> 2) & 3]; - unsigned shift = (addr & 1) * 8; - bg.hoffset = (bg.hoffset & ~(255 << shift)) | (byte << shift); + //BG0HOFS, BG1HOFS, BG2BOFS, BG3HOFS + case 0x0400'0010: case 0x0400'0014: case 0x0400'0018: case 0x0400'001c: + bgofs().hoffset.bits(0,7) = data; + return; + case 0x0400'0011: case 0x0400'0015: case 0x0400'0019: case 0x0400'001d: + bgofs().hoffset.bit(8) = data.bit(0); return; - } - //BG0VOFS,BG1VOFS,BG2VOFS,BG3VOFS - case 0x0400'0012: case 0x0400'0013: - case 0x0400'0016: case 0x0400'0017: - case 0x0400'001a: case 0x0400'001b: - case 0x0400'001e: case 0x0400'001f: { - auto& bg = regs.bg[(addr >> 2) & 3]; - unsigned shift = (addr & 1) * 8; - bg.voffset = (bg.voffset & ~(255 << shift)) | (byte << shift); + //BG0VOFS, BG1VOFS, BG2VOFS, BG3VOFS + case 0x0400'0012: case 0x0400'0016: case 0x0400'001a: case 0x0400'001e: + bgofs().voffset.bits(0,7) = data; + return; + case 0x0400'0013: case 0x0400'0017: case 0x0400'001b: case 0x0400'001f: + bgofs().voffset.bit(8) = data.bit(0); return; - } - //BG2PA,BG3PA - case 0x0400'0020: case 0x0400'0021: - case 0x0400'0030: case 0x0400'0031: { - auto& bg = regs.bg[(addr >> 4) & 3]; - unsigned shift = (addr & 1) * 8; - bg.pa = (bg.pa & ~(255 << shift)) | (byte << shift); - return; - } + //BG2PA, BG3PA + case 0x0400'0020: case 0x0400'0030: bg().pa.byte(0) = data; return; + case 0x0400'0021: case 0x0400'0031: bg().pa.byte(1) = data; return; - //BG2PB,BG3PB - case 0x0400'0022: case 0x0400'0023: - case 0x0400'0032: case 0x0400'0033: { - auto& bg = regs.bg[(addr >> 4) & 3]; - unsigned shift = (addr & 1) * 8; - bg.pb = (bg.pb & ~(255 << shift)) | (byte << shift); - return; - } + //BG2PB, BG3PB + case 0x0400'0022: case 0x0400'0032: bg().pb.byte(0) = data; return; + case 0x0400'0023: case 0x0400'0033: bg().pb.byte(1) = data; return; - //BG2PC,BG3PC - case 0x0400'0024: case 0x0400'0025: - case 0x0400'0034: case 0x0400'0035: { - auto& bg = regs.bg[(addr >> 4) & 3]; - unsigned shift = (addr & 1) * 8; - bg.pc = (bg.pc & ~(255 << shift)) | (byte << shift); - return; - } + //BG2PC, BG3PC + case 0x0400'0024: case 0x0400'0034: bg().pc.byte(0) = data; return; + case 0x0400'0025: case 0x0400'0035: bg().pc.byte(1) = data; return; - //BG2PD,BG3PD - case 0x0400'0026: case 0x0400'0027: - case 0x0400'0036: case 0x0400'0037: { - auto& bg = regs.bg[(addr >> 4) & 3]; - unsigned shift = (addr & 1) * 8; - bg.pd = (bg.pd & ~(255 << shift)) | (byte << shift); - return; - } + //BG2PD, BG3PD + case 0x0400'0026: case 0x0400'0036: bg().pd.byte(0) = data; return; + case 0x0400'0027: case 0x0400'0037: bg().pd.byte(1) = data; return; - //BG2X_L,BG2X_H,BG3X_L,BG3X_H - case 0x0400'0028: case 0x0400'0029: case 0x0400'002a: case 0x0400'002b: - case 0x0400'0038: case 0x0400'0039: case 0x0400'003a: case 0x0400'003b: { - auto& bg = regs.bg[(addr >> 4) & 3]; - unsigned shift = (addr & 3) * 8; - bg.lx = bg.x = (bg.x & ~(255 << shift)) | (byte << shift); - return; - } + //BG2X_L, BG2X_H, BG3X_L, BG3X_H + case 0x0400'0028: case 0x0400'0038: bg().x.bits( 0, 7) = data.bits(0,7); bg().lx = bg().x; return; + case 0x0400'0029: case 0x0400'0039: bg().x.bits( 8,15) = data.bits(0,7); bg().lx = bg().x; return; + case 0x0400'002a: case 0x0400'003a: bg().x.bits(16,23) = data.bits(0,7); bg().lx = bg().x; return; + case 0x0400'002b: case 0x0400'003b: bg().x.bits(24,27) = data.bits(0,3); bg().lx = bg().x; return; - //BG2Y_L,BG2Y_H,BG3Y_L,BG3Y_H - case 0x0400'002c: case 0x0400'002d: case 0x0400'002e: case 0x0400'002f: - case 0x0400'003c: case 0x0400'003d: case 0x0400'003e: case 0x0400'003f: { - auto& bg = regs.bg[(addr >> 4) & 3]; - unsigned shift = (addr & 3) * 8; - bg.ly = bg.y = (bg.y & ~(255 << shift)) | (byte << shift); - return; - } + //BG2Y_L, BG2Y_H, BG3Y_L, BG3Y_H + case 0x0400'002c: case 0x0400'003c: bg().y.bits( 0, 7) = data.bits(0,7); bg().ly = bg().y; return; + case 0x0400'002d: case 0x0400'003d: bg().y.bits( 8,15) = data.bits(0,7); bg().ly = bg().y; return; + case 0x0400'002e: case 0x0400'003e: bg().y.bits(16,23) = data.bits(0,7); bg().ly = bg().y; return; + case 0x0400'002f: case 0x0400'003f: bg().y.bits(24,27) = data.bits(0,3); bg().ly = bg().y; return; //WIN0H - case 0x0400'0040: regs.window[0].x2 = byte; return; - case 0x0400'0041: regs.window[0].x1 = byte; return; + case 0x0400'0040: regs.window[0].x2 = data; return; + case 0x0400'0041: regs.window[0].x1 = data; return; //WIN1H - case 0x0400'0042: regs.window[1].x2 = byte; return; - case 0x0400'0043: regs.window[1].x1 = byte; return; + case 0x0400'0042: regs.window[1].x2 = data; return; + case 0x0400'0043: regs.window[1].x1 = data; return; //WIN0V - case 0x0400'0044: regs.window[0].y2 = byte; return; - case 0x0400'0045: regs.window[0].y1 = byte; return; + case 0x0400'0044: regs.window[0].y2 = data; return; + case 0x0400'0045: regs.window[0].y1 = data; return; //WIN1V - case 0x0400'0046: regs.window[1].y2 = byte; return; - case 0x0400'0047: regs.window[1].y1 = byte; return; + case 0x0400'0046: regs.window[1].y2 = data; return; + case 0x0400'0047: regs.window[1].y1 = data; return; - //WININ - case 0x0400'0048: regs.windowflags[In0] = byte; return; - case 0x0400'0049: regs.windowflags[In1] = byte; return; - - //WINOUT - case 0x0400'004a: regs.windowflags[Out] = byte; return; - case 0x0400'004b: regs.windowflags[Obj] = byte; return; + //WININ, WINOUT + case 0x0400'0048: case 0x0400'0049: case 0x0400'004a: case 0x0400'004b: + wf().enable[BG0] = data.bit(0); + wf().enable[BG1] = data.bit(1); + wf().enable[BG2] = data.bit(2); + wf().enable[BG3] = data.bit(3); + wf().enable[OBJ] = data.bit(4); + wf().enable[SFX] = data.bit(5); + return; //MOSAIC case 0x0400'004c: - regs.mosaic.bghsize = byte >> 0; - regs.mosaic.bgvsize = byte >> 4; + regs.mosaic.bghsize = data.bits(0,3); + regs.mosaic.bgvsize = data.bits(4,7); return; case 0x0400'004d: - regs.mosaic.objhsize = byte >> 0; - regs.mosaic.objvsize = byte >> 4; + regs.mosaic.objhsize = data.bits(0,3); + regs.mosaic.objvsize = data.bits(4,7); return; //BLDCNT - case 0x0400'0050: regs.blend.control = (regs.blend.control & 0xff00) | (byte << 0); return; - case 0x0400'0051: regs.blend.control = (regs.blend.control & 0x00ff) | (byte << 8); return; + case 0x0400'0050: + regs.blend.control.above[BG0] = data.bit (0); + regs.blend.control.above[BG1] = data.bit (1); + regs.blend.control.above[BG2] = data.bit (2); + regs.blend.control.above[BG3] = data.bit (3); + regs.blend.control.above[OBJ] = data.bit (4); + regs.blend.control.above[SFX] = data.bit (5); + regs.blend.control.mode = data.bits(6,7); + return; + case 0x0400'0051: + regs.blend.control.below[BG0] = data.bit(0); + regs.blend.control.below[BG1] = data.bit(1); + regs.blend.control.below[BG2] = data.bit(2); + regs.blend.control.below[BG3] = data.bit(3); + regs.blend.control.below[OBJ] = data.bit(4); + regs.blend.control.below[SFX] = data.bit(5); + return; //BLDALPHA - case 0x0400'0052: regs.blend.eva = byte & 0x1f; return; - case 0x0400'0053: regs.blend.evb = byte & 0x1f; return; + case 0x0400'0052: regs.blend.eva = data.bits(0,4); return; + case 0x0400'0053: regs.blend.evb = data.bits(0,4); return; //BLDY - case 0x0400'0054: regs.blend.evy = byte & 0x1f; return; + case 0x0400'0054: regs.blend.evy = data.bits(0,4); return; case 0x0400'0055: return; } diff --git a/higan/gba/ppu/ppu.cpp b/higan/gba/ppu/ppu.cpp index d6ec98b8..bff0a7b3 100644 --- a/higan/gba/ppu/ppu.cpp +++ b/higan/gba/ppu/ppu.cpp @@ -15,7 +15,6 @@ namespace GameBoyAdvance { PPU ppu; #include "video.cpp" -#include "registers.cpp" #include "background.cpp" #include "object.cpp" #include "mosaic.cpp" @@ -58,12 +57,32 @@ auto PPU::power() -> void { for(uint n = 0; n < 1024; n += 2) pram_write(n, Half, 0x0000); for(uint n = 0; n < 1024; n += 2) oam_write(n, Half, 0x0000); - regs.control = 0; + regs.control.bgmode = 0; + regs.control.cgbmode = 0; + regs.control.frame = 0; + regs.control.hblank = 0; + regs.control.objmapping = 0; + regs.control.forceblank = 0; + for(auto& enable : regs.control.enable) enable = 0; + for(auto& enablewindow : regs.control.enablewindow) enablewindow = 0; regs.greenswap = 0; - regs.status = 0; + regs.status.vblank = 0; + regs.status.hblank = 0; + regs.status.vcoincidence = 0; + regs.status.irqvblank = 0; + regs.status.irqhblank = 0; + regs.status.irqvcoincidence = 0; + regs.status.vcompare = 0; regs.vcounter = 0; for(auto& bg : regs.bg) { - bg.control = 0; + bg.control.priority = 0; + bg.control.characterbaseblock = 0; + bg.control.unused = 0; + bg.control.mosaic = 0; + bg.control.colormode = 0; + bg.control.screenbaseblock = 0; + bg.control.affinewrap = 0; + bg.control.screensize = 0; bg.hoffset = 0; bg.voffset = 0; bg.pa = 0; @@ -81,14 +100,16 @@ auto PPU::power() -> void { w.y1 = 0; w.y2 = 0; } - for(auto& f : regs.windowflags) { - f = 0; + for(auto& flags : regs.windowflags) { + for(auto& enable : flags.enable) enable = 0; } regs.mosaic.bghsize = 0; regs.mosaic.bgvsize = 0; regs.mosaic.objhsize = 0; regs.mosaic.objvsize = 0; - regs.blend.control = 0; + for(auto& above : regs.blend.control.above) above = 0; + regs.blend.control.mode = 0; + for(auto& below : regs.blend.control.below) below = 0; regs.blend.eva = 0; regs.blend.evb = 0; regs.blend.evy = 0; diff --git a/higan/gba/ppu/registers.cpp b/higan/gba/ppu/registers.cpp deleted file mode 100644 index e23b4c7c..00000000 --- a/higan/gba/ppu/registers.cpp +++ /dev/null @@ -1,140 +0,0 @@ -PPU::Registers::Control::operator uint16_t() const { - return ( - (bgmode << 0) - | (cgbmode << 3) - | (frame << 4) - | (hblank << 5) - | (objmapping << 6) - | (forceblank << 7) - | (enable[BG0] << 8) - | (enable[BG1] << 9) - | (enable[BG2] << 10) - | (enable[BG3] << 11) - | (enable[OBJ] << 12) - | (enablewindow[In0] << 13) - | (enablewindow[In1] << 14) - | (enablewindow[Obj] << 15) - ); -} - -auto PPU::Registers::Control::operator=(uint16 source) -> uint16 { - bgmode = source >> 0; - cgbmode = source >> 3; - frame = source >> 4; - hblank = source >> 5; - objmapping = source >> 6; - forceblank = source >> 7; - enable[BG0] = source >> 8; - enable[BG1] = source >> 9; - enable[BG2] = source >> 10; - enable[BG3] = source >> 11; - enable[OBJ] = source >> 12; - enablewindow[In0] = source >> 13; - enablewindow[In1] = source >> 14; - enablewindow[Obj] = source >> 15; - return operator uint16_t(); -} - -PPU::Registers::Status::operator uint16_t() const { - return ( - (vblank << 0) - | (hblank << 1) - | (vcoincidence << 2) - | (irqvblank << 3) - | (irqhblank << 4) - | (irqvcoincidence << 5) - | (vcompare << 8) - ); -} - -auto PPU::Registers::Status::operator=(uint16 source) -> uint16 { - vblank = source >> 0; - hblank = source >> 1; - vcoincidence = source >> 2; - irqvblank = source >> 3; - irqhblank = source >> 4; - irqvcoincidence = source >> 5; - vcompare = source >> 8; - return operator uint16_t(); -} - -PPU::Registers::BackgroundControl::operator uint16_t() const { - return ( - (priority << 0) - | (characterbaseblock << 2) - | (unused << 4) - | (mosaic << 6) - | (colormode << 7) - | (screenbaseblock << 8) - | (affinewrap << 13) - | (screensize << 14) - ); -} - -auto PPU::Registers::BackgroundControl::operator=(uint16 source) -> uint16 { - priority = source >> 0; - characterbaseblock = source >> 2; - unused = source >> 4; - mosaic = source >> 6; - colormode = source >> 7; - screenbaseblock = source >> 8; - affinewrap = source >> 13; - screensize = source >> 14; - return operator uint16_t(); -} - -PPU::Registers::WindowFlags::operator uint8_t() const { - return ( - (enable[BG0] << 0) - | (enable[BG1] << 1) - | (enable[BG2] << 2) - | (enable[BG3] << 3) - | (enable[OBJ] << 4) - | (enable[SFX] << 5) - ); -} - -auto PPU::Registers::WindowFlags::operator=(uint8 source) -> uint8 { - enable[BG0] = source >> 0; - enable[BG1] = source >> 1; - enable[BG2] = source >> 2; - enable[BG3] = source >> 3; - enable[OBJ] = source >> 4; - enable[SFX] = source >> 5; - return operator uint8_t(); -} - -PPU::Registers::BlendControl::operator uint16_t() const { - return ( - (above[BG0] << 0) - | (above[BG1] << 1) - | (above[BG2] << 2) - | (above[BG3] << 3) - | (above[OBJ] << 4) - | (above[SFX] << 5) - | (mode << 6) - | (below[BG0] << 8) - | (below[BG1] << 9) - | (below[BG2] << 10) - | (below[BG3] << 11) - | (below[OBJ] << 12) - | (below[SFX] << 13) - ); -} - -auto PPU::Registers::BlendControl::operator=(uint16 source) -> uint16 { - above[BG0] = source >> 0; - above[BG1] = source >> 1; - above[BG2] = source >> 2; - above[BG3] = source >> 3; - above[OBJ] = source >> 4; - above[SFX] = source >> 5; - mode = source >> 6; - below[BG0] = source >> 8; - below[BG1] = source >> 9; - below[BG2] = source >> 10; - below[BG3] = source >> 11; - below[OBJ] = source >> 12; - below[SFX] = source >> 13; - return operator uint16_t(); -} diff --git a/higan/gba/ppu/registers.hpp b/higan/gba/ppu/registers.hpp index 19b43b58..3aabf5c2 100644 --- a/higan/gba/ppu/registers.hpp +++ b/higan/gba/ppu/registers.hpp @@ -11,10 +11,6 @@ struct Registers { uint1 forceblank; uint1 enable[5]; uint1 enablewindow[3]; - - operator uint16_t() const; - auto operator=(uint16 source) -> uint16; - auto operator=(const Control&) -> Control& = delete; } control; uint1 greenswap; @@ -27,31 +23,21 @@ struct Registers { uint1 irqhblank; uint1 irqvcoincidence; uint8 vcompare; - - operator uint16_t() const; - auto operator=(uint16 source) -> uint16; - auto operator=(const Status&) -> Status& = delete; } status; uint16 vcounter; - struct BackgroundControl { - uint2 priority; - uint2 characterbaseblock; - uint2 unused; - uint1 mosaic; - uint1 colormode; - uint5 screenbaseblock; - uint1 affinewrap; //BG2,3 only - uint2 screensize; - - operator uint16_t() const; - auto operator=(uint16 source) -> uint16; - auto operator=(const BackgroundControl&) -> BackgroundControl& = delete; - }; - struct Background { - BackgroundControl control; + struct Control { + uint2 priority; + uint2 characterbaseblock; + uint2 unused; + uint1 mosaic; + uint1 colormode; + uint5 screenbaseblock; + uint1 affinewrap; //BG2,3 only + uint2 screensize; + } control; uint9 hoffset; uint9 voffset; @@ -66,20 +52,14 @@ struct Registers { uint id; } bg[4]; - struct WindowFlags { - uint1 enable[6]; - - operator uint8_t() const; - auto operator=(uint8 source) -> uint8; - auto operator=(const WindowFlags&) -> WindowFlags& = delete; - }; - struct Window { uint8 x1, x2; uint8 y1, y2; } window[2]; - WindowFlags windowflags[4]; + struct WindowFlags { + uint1 enable[6]; + } windowflags[4]; struct Mosaic { uint4 bghsize; @@ -88,18 +68,12 @@ struct Registers { uint4 objvsize; } mosaic; - struct BlendControl { - uint1 above[6]; - uint1 below[6]; - uint2 mode; - - operator uint16_t() const; - auto operator=(uint16 source) -> uint16; - auto operator=(const BlendControl&) -> BlendControl& = delete; - }; - struct Blend { - BlendControl control; + struct Control { + uint1 above[6]; + uint2 mode; + uint1 below[6]; + } control; uint5 eva; uint5 evb; uint5 evy; diff --git a/higan/gba/ppu/screen.cpp b/higan/gba/ppu/screen.cpp index ca08079c..d5438896 100644 --- a/higan/gba/ppu/screen.cpp +++ b/higan/gba/ppu/screen.cpp @@ -14,14 +14,19 @@ auto PPU::render_screen() -> void { for(auto x : range(240)) { Registers::WindowFlags flags; - flags = ~0; //enable all layers if no windows are enabled + flags.enable[BG0] = true; //enable all layers if no windows are enabled + flags.enable[BG1] = true; + flags.enable[BG2] = true; + flags.enable[BG3] = true; + flags.enable[OBJ] = true; + flags.enable[SFX] = true; //determine active window if(regs.control.enablewindow[In0] || regs.control.enablewindow[In1] || regs.control.enablewindow[Obj]) { - flags = (uint8)regs.windowflags[Out]; - if(regs.control.enablewindow[Obj] && windowmask[Obj][x]) flags = (uint8)regs.windowflags[Obj]; - if(regs.control.enablewindow[In1] && windowmask[In1][x]) flags = (uint8)regs.windowflags[In1]; - if(regs.control.enablewindow[In0] && windowmask[In0][x]) flags = (uint8)regs.windowflags[In0]; + flags = regs.windowflags[Out]; + if(regs.control.enablewindow[Obj] && windowmask[Obj][x]) flags = regs.windowflags[Obj]; + if(regs.control.enablewindow[In1] && windowmask[In1][x]) flags = regs.windowflags[In1]; + if(regs.control.enablewindow[In0] && windowmask[In0][x]) flags = regs.windowflags[In0]; } //priority sorting: find topmost two pixels @@ -40,9 +45,9 @@ auto PPU::render_screen() -> void { bool blendabove = regs.blend.control.above[a]; bool blendbelow = regs.blend.control.below[b]; uint color = above[x].color; - auto eva = min(16u, (unsigned)regs.blend.eva); - auto evb = min(16u, (unsigned)regs.blend.evb); - auto evy = min(16u, (unsigned)regs.blend.evy); + auto eva = min(16u, (uint)regs.blend.eva); + auto evb = min(16u, (uint)regs.blend.evb); + auto evy = min(16u, (uint)regs.blend.evy); //perform blending, if needed if(flags.enable[SFX] == false) { diff --git a/higan/sfc/GNUmakefile b/higan/sfc/GNUmakefile index 82421e64..b5c4488d 100644 --- a/higan/sfc/GNUmakefile +++ b/higan/sfc/GNUmakefile @@ -1,3 +1,5 @@ +processors += r65816 spc700 arm gsu hg51b upd96050 + sfc_objects := sfc-interface sfc-system sfc-scheduler sfc-controller sfc_objects += sfc-cartridge sfc-cheat sfc_objects += sfc-memory sfc-cpu sfc-smp sfc-dsp sfc-ppu diff --git a/higan/sfc/cartridge/cartridge.cpp b/higan/sfc/cartridge/cartridge.cpp index b557c25f..d424aa4e 100644 --- a/higan/sfc/cartridge/cartridge.cpp +++ b/higan/sfc/cartridge/cartridge.cpp @@ -139,10 +139,12 @@ auto Cartridge::load() -> void { } auto Cartridge::loadGameBoy() -> void { + #if defined(SFC_SUPERGAMEBOY) //invoked from ICD2::load() _sha256 = GameBoy::interface->sha256(); information.markup.gameBoy = GameBoy::interface->manifest(); information.title.gameBoy = GameBoy::interface->title(); + #endif } auto Cartridge::loadBSMemory() -> void { diff --git a/higan/sfc/coprocessor/icd2/icd2.cpp b/higan/sfc/coprocessor/icd2/icd2.cpp index 6456221f..7eb3fe93 100644 --- a/higan/sfc/coprocessor/icd2/icd2.cpp +++ b/higan/sfc/coprocessor/icd2/icd2.cpp @@ -2,10 +2,13 @@ namespace SuperFamicom { +ICD2 icd2; + +#if defined(SFC_SUPERGAMEBOY) + #include "interface/interface.cpp" #include "mmio/mmio.cpp" #include "serialization.cpp" -ICD2 icd2; auto ICD2::Enter() -> void { while(true) { @@ -78,4 +81,6 @@ auto ICD2::reset() -> void { GameBoy::system.power(); } +#endif + } diff --git a/higan/sfc/coprocessor/icd2/icd2.hpp b/higan/sfc/coprocessor/icd2/icd2.hpp index d8e2e6b0..14831815 100644 --- a/higan/sfc/coprocessor/icd2/icd2.hpp +++ b/higan/sfc/coprocessor/icd2/icd2.hpp @@ -1,3 +1,5 @@ +#if defined(SFC_SUPERGAMEBOY) + struct ICD2 : Emulator::Interface::Bind, GameBoy::Interface::Hook, Coprocessor { static auto Enter() -> void; auto main() -> void; @@ -23,4 +25,23 @@ private: GameBoy::Interface::Hook* hook = nullptr; }; +#else + +struct ICD2 : Coprocessor { + auto init() -> void {} + auto load() -> void {} + auto unload() -> void {} + auto power() -> void {} + auto reset() -> void {} + + auto read(uint24, uint8) -> uint8 { return 0; } + auto write(uint24, uint8) -> void { return; } + + auto serialize(serializer&) -> void {} + + uint revision; +}; + +#endif + extern ICD2 icd2; diff --git a/higan/sfc/interface/interface.cpp b/higan/sfc/interface/interface.cpp index 7b55a06e..4c1a6014 100644 --- a/higan/sfc/interface/interface.cpp +++ b/higan/sfc/interface/interface.cpp @@ -330,6 +330,7 @@ auto Interface::load(uint id, const stream& stream) -> void { if(id == ID::MCCROM) mcc.rom.read(stream); if(id == ID::MCCRAM) mcc.ram.read(stream); + #if defined(SFC_SUPERGAMEBOY) if(id == ID::SuperGameBoyManifest) { GameBoy::interface->load(GameBoy::ID::SystemManifest, stream); } @@ -349,6 +350,7 @@ auto Interface::load(uint id, const stream& stream) -> void { if(id == ID::GameBoyRAM) { GameBoy::interface->load(GameBoy::ID::RAM, stream); } + #endif if(id == ID::BSMemoryManifest) cartridge.information.markup.bsMemory = stream.text(); if(id == ID::BSMemoryROM) bsmemory.memory.read(stream); @@ -401,9 +403,11 @@ auto Interface::save(uint id, const stream& stream) -> void { if(id == ID::SDD1RAM) stream.write((uint8_t*)sdd1.ram.data(), sdd1.ram.size()); if(id == ID::OBC1RAM) stream.write((uint8_t*)obc1.ram.data(), obc1.ram.size()); + #if defined(SFC_SUPERGAMEBOY) if(id == ID::GameBoyRAM) { GameBoy::interface->save(GameBoy::ID::RAM, stream); } + #endif if(id == ID::MCCRAM) stream.write((uint8_t*)mcc.ram.data(), mcc.ram.size()); @@ -455,7 +459,7 @@ auto Interface::unserialize(serializer& s) -> bool { auto Interface::cheatSet(const lstring& list) -> void { cheat.reset(); - //Super Game Boy + #if defined(SFC_SUPERGAMEBOY) if(cartridge.hasICD2()) { GameBoy::cheat.reset(); for(auto& codeset : list) { @@ -468,8 +472,8 @@ auto Interface::cheatSet(const lstring& list) -> void { } return; } + #endif - //Super Famicom, Broadcast Satellaview, Sufami Turbo for(auto& codeset : list) { lstring codes = codeset.split("+"); for(auto& code : codes) { diff --git a/higan/sfc/ppu/sprite/list.cpp b/higan/sfc/ppu/sprite/list.cpp index aff53120..f4451e5e 100644 --- a/higan/sfc/ppu/sprite/list.cpp +++ b/higan/sfc/ppu/sprite/list.cpp @@ -1,5 +1,5 @@ -auto PPU::Sprite::update(uint addr, uint8 data) -> void { - if(addr < 0x0200) { +auto PPU::Sprite::update(uint10 addr, uint8 data) -> void { + if(!addr.bit(9)) { uint n = addr >> 2; //sprite# addr &= 3; if(addr == 0) { diff --git a/higan/sfc/ppu/sprite/sprite.hpp b/higan/sfc/ppu/sprite/sprite.hpp index 29d55cd1..f60c6327 100644 --- a/higan/sfc/ppu/sprite/sprite.hpp +++ b/higan/sfc/ppu/sprite/sprite.hpp @@ -3,27 +3,27 @@ struct Sprite { uint9 x; uint8 y; uint8 character; - bool nameselect; - bool vflip; - bool hflip; + uint1 nameselect; + uint1 vflip; + uint1 hflip; uint2 priority; uint3 palette; - bool size; + uint1 size; alwaysinline auto width() const -> uint; alwaysinline auto height() const -> uint; } list[128]; struct Item { - bool valid; + bool valid; uint7 index; }; struct Tile { - bool valid; + bool valid; uint9 x; uint2 priority; uint8 palette; - bool hflip; + uint1 hflip; uint8 d0, d1, d2, d3; }; @@ -44,10 +44,10 @@ struct Sprite { bool sub_enable; bool interlace; - uint3 base_size; - uint2 nameselect; + uint3 base_size; + uint2 nameselect; uint16 tiledata_addr; - uint7 first_sprite; + uint7 first_sprite; uint priority0; uint priority1; @@ -60,7 +60,7 @@ struct Sprite { struct Output { struct Pixel { - uint2 priority; //0 = none (transparent) + uint priority; //0 = none (transparent) uint8 palette; } main, sub; } output; @@ -68,7 +68,7 @@ struct Sprite { Sprite(PPU& self); //list.cpp - auto update(uint addr, uint8 data) -> void; + auto update(uint10 addr, uint8 data) -> void; auto synchronize() -> void; //sprite.cpp diff --git a/higan/sfc/sfc.hpp b/higan/sfc/sfc.hpp index d26b8cbc..b100df3d 100644 --- a/higan/sfc/sfc.hpp +++ b/higan/sfc/sfc.hpp @@ -23,7 +23,10 @@ namespace SuperFamicom { */ #include -#include + +#if defined(SFC_SUPERGAMEBOY) + #include +#endif #if defined(PROFILE_PERFORMANCE) #include diff --git a/higan/target-loki/GNUmakefile b/higan/target-loki/GNUmakefile new file mode 100644 index 00000000..72c94d56 --- /dev/null +++ b/higan/target-loki/GNUmakefile @@ -0,0 +1,73 @@ +name := loki + +include sfc/GNUmakefile +include processor/GNUmakefile +include emulator/GNUmakefile + +ui_objects := ui-loki ui-program +ui_objects += ui-terminal ui-presentation +ui_objects += ruby hiro +ui_objects += $(if $(call streq,$(platform),windows),ui-resource) + +# platform +ifeq ($(platform),windows) + ruby += video.gdi audio.directsound input.windows +else ifeq ($(platform),macosx) + ruby += video.cgl audio.openal input.quartz +else ifeq ($(platform),linux) + ruby += video.xshm audio.openal input.sdl +else ifeq ($(platform),bsd) + ruby += video.xshm audio.oss input.sdl +endif + +# ruby +include ../ruby/GNUmakefile +link += $(rubylink) + +# hiro +include ../hiro/GNUmakefile +link += $(hirolink) + +# rules +objects := $(ui_objects) $(objects) +objects := $(patsubst %,obj/%.o,$(objects)) + +obj/libco.o: ../libco/libco.c $(call rwildcard,../libco/) + +obj/ruby.o: ../ruby/ruby.cpp $(call rwildcard,../ruby/) + $(compiler) $(rubyflags) -c $< -o $@ + +obj/hiro.o: ../hiro/hiro.cpp $(call rwildcard,../hiro/) + $(compiler) $(hiroflags) -c $< -o $@ + +obj/ui-loki.o: $(ui)/loki.cpp $(call rwildcard,$(ui)/) +obj/ui-program.o: $(ui)/program/program.cpp $(call rwildcard,$(ui)/) +obj/ui-terminal.o: $(ui)/terminal/terminal.cpp $(call rwildcard,$(ui)/) +obj/ui-presentation.o: $(ui)/presentation/presentation.cpp $(call rwildcard,$(ui)/) + +obj/ui-resource.o: + windres data/resource.rc obj/ui-resource.o + +# targets +build: $(objects) + $(call unique,$(compiler) -o out/$(name) $(objects) $(link)) + +install: +ifeq ($(shell id -un),root) + $(error "make install should not be run as root") +else ifneq ($(filter $(platform),linux bsd),) + mkdir -p $(prefix)/bin/ + mkdir -p $(prefix)/share/icons/ + mkdir -p $(prefix)/share/$(name)/ + cp out/$(name) $(prefix)/bin/$(name) + cp data/higan.png $(prefix)/share/icons/$(name).png + cp -R profile/* $(prefix)/share/$(name)/ +endif + +uninstall: +ifeq ($(shell id -un),root) + $(error "make uninstall should not be run as root") +else ifneq ($(filter $(platform),linux bsd),) + if [ -f $(prefix)/bin/$(name) ]; then rm $(prefix)/bin/$(name); fi + if [ -f $(prefix)/share/icons/$(name).png ]; then rm $(prefix)/share/icons/$(name).png; fi +endif diff --git a/higan/target-loki/loki.cpp b/higan/target-loki/loki.cpp new file mode 100644 index 00000000..06c2502f --- /dev/null +++ b/higan/target-loki/loki.cpp @@ -0,0 +1,23 @@ +#include "loki.hpp" +unique_pointer