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.
This commit is contained in:
Tim Allen 2016-02-25 21:38:03 +11:00
parent 29be18ce0c
commit fc7d5991ce
36 changed files with 656 additions and 381 deletions

View File

@ -8,6 +8,7 @@ ws := ws
profile := accuracy
target := tomoko
# target := loki
# console := true
flags += -I. -I.. -O3

View File

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

View File

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

View File

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

View File

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

View File

@ -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,7 +70,7 @@ auto APU::read(uint32 addr) -> uint8 {
regs.bias.level.bits(0,7)
);
case 0x0400'0089: return (
regs.bias.level.bits(8,9)
regs.bias.level.bits(8,9) << 0
| regs.bias.amplitude << 6
);
@ -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);

View File

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

View File

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

View File

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

View File

@ -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,15 +23,12 @@ 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 {
struct Background {
struct Control {
uint2 priority;
uint2 characterbaseblock;
uint2 unused;
@ -44,14 +37,7 @@ struct Registers {
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;
} 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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,12 +3,12 @@ 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];
@ -23,7 +23,7 @@ struct Sprite {
uint9 x;
uint2 priority;
uint8 palette;
bool hflip;
uint1 hflip;
uint8 d0, d1, d2, d3;
};
@ -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

View File

@ -23,7 +23,10 @@ namespace SuperFamicom {
*/
#include <libco/libco.h>
#include <gb/gb.hpp>
#if defined(SFC_SUPERGAMEBOY)
#include <gb/gb.hpp>
#endif
#if defined(PROFILE_PERFORMANCE)
#include <nall/priority-queue.hpp>

View File

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

View File

@ -0,0 +1,23 @@
#include "loki.hpp"
unique_pointer<Video> video;
unique_pointer<Audio> audio;
unique_pointer<Input> input;
Emulator::Interface* emulator = nullptr;
auto locate(string name) -> string {
string location = {programpath(), name};
if(inode::exists(location)) return location;
location = {configpath(), "loki/", name};
if(inode::exists(location)) return location;
directory::create({localpath(), "loki/"});
return {localpath(), "loki/", name};
}
#include <nall/main.hpp>
auto nall::main(lstring args) -> void {
Application::setName("loki");
new Program(args);
Application::run();
}

View File

@ -0,0 +1,21 @@
#include <nall/nall.hpp>
#include <ruby/ruby.hpp>
#include <hiro/hiro.hpp>
using namespace nall;
using namespace ruby;
using namespace hiro;
extern unique_pointer<Video> video;
extern unique_pointer<Audio> audio;
extern unique_pointer<Input> input;
#include <emulator/emulator.hpp>
extern Emulator::Interface* emulator;
#include <sfc/sfc.hpp>
namespace SFC = SuperFamicom;
auto locate(string name) -> string;
#include "program/program.hpp"
#include "terminal/terminal.hpp"
#include "presentation/presentation.hpp"

View File

@ -0,0 +1,28 @@
#include "../loki.hpp"
unique_pointer<Presentation> presentation;
Presentation::Presentation() {
presentation = this;
onClose([&] { program->quit(); });
setTitle({"loki v", Emulator::Version});
setResizable(false);
setBackgroundColor({0, 0, 0});
setSize({512, 480});
setCentered();
setVisible();
}
auto Presentation::drawSplashScreen() -> void {
uint32_t* output;
uint length;
if(video->lock(output, length, 512, 480)) {
for(auto y : range(480)) {
auto dp = output + y * (length >> 2);
for(auto x : range(512)) *dp++ = 0xff'00'00'00;
}
video->unlock();
video->refresh();
}
}

View File

@ -0,0 +1,9 @@
struct Presentation : Window {
Presentation();
auto drawSplashScreen() -> void;
VerticalLayout layout{this};
Viewport viewport{&layout, Size{~0, ~0}};
};
extern unique_pointer<Presentation> presentation;

View File

@ -0,0 +1,45 @@
#include "../loki.hpp"
unique_pointer<Program> program;
Program::Program(lstring args) {
program = this;
Application::onMain({&Program::main, this});
emulator = new SuperFamicom::Interface;
emulator->bind = this;
new Terminal;
new Presentation;
terminal->setFocused();
video = Video::create();
video->set(Video::Handle, presentation->viewport.handle());
video->set(Video::Synchronize, false);
if(!video->init()) video = Video::create("None");
audio = Audio::create();
audio->set(Audio::Handle, presentation->viewport.handle());
audio->set(Audio::Synchronize, true);
audio->set(Audio::Frequency, 96000u);
audio->set(Audio::Latency, 80u);
if(!audio->init()) audio = Audio::create("None");
input = Input::create();
input->set(Input::Handle, presentation->viewport.handle());
if(!input->init()) input = Input::create("None");
presentation->drawSplashScreen();
}
auto Program::load(string location) -> void {
}
auto Program::main() -> void {
}
auto Program::quit() -> void {
video.reset();
audio.reset();
input.reset();
Application::quit();
}

View File

@ -0,0 +1,21 @@
struct Program : Emulator::Interface::Bind {
//program.cpp
Program(lstring args);
auto load(string) -> void;
auto main() -> void;
auto quit() -> void;
//interface.cpp
auto loadRequest(uint id, string name, string type, bool required) -> void override {}
auto loadRequest(uint id, string path, bool required) -> void override {}
auto saveRequest(uint id, string path) -> void override {}
auto videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void override {}
auto audioSample(int16 lsample, int16 rsample) -> void override {}
auto inputPoll(uint port, uint device, uint input) -> int16 override { return 0; }
auto inputRumble(uint port, uint device, uint input, bool enable) -> void override {}
auto dipSettings(const Markup::Node& node) -> uint override { return 0; }
auto path(uint group) -> string override { return ""; }
auto notify(string text) -> void override {}
};
extern unique_pointer<Program> program;

View File

@ -0,0 +1,18 @@
unique_pointer<AboutWindow> aboutWindow;
AboutWindow::AboutWindow() {
aboutWindow = this;
layout.setMargin(5);
canvas.setIcon({locate("loki.png")});
information.setFont(Font().setFamily(Font::Sans).setBold()).setAlignment(0.5).setText({
"loki v", Emulator::Version, "\n\n"
"Author: ", Emulator::Author, "\n",
"License: ", Emulator::License, "\n",
"Website: ", Emulator::Website
});
setTitle("About loki ...");
setSize(layout.minimumSize());
setCentered();
}

View File

@ -0,0 +1,26 @@
#include "../loki.hpp"
#include "about-window.cpp"
unique_pointer<Terminal> terminal;
Terminal::Terminal() {
terminal = this;
new AboutWindow;
onClose([&] { program->quit(); });
helpMenu.setText("Help");
aboutAction.setText("About ...").onActivate([&] { aboutWindow->setFocused(); });
console.setBackgroundColor({ 56, 56, 56});
console.setForegroundColor({255, 255, 255});
console.setFont(Font().setFamily(Font::Mono).setSize(8));
console.setPrompt("$ ");
setTitle({"loki v", Emulator::Version});
setSize({800, 480});
setAlignment({0.0, 1.0});
setVisible();
}
auto Terminal::showAboutWindow() -> void {
}

View File

@ -0,0 +1,22 @@
struct Terminal : Window {
Terminal();
auto showAboutWindow() -> void;
MenuBar menuBar{this};
Menu helpMenu{&menuBar};
MenuItem aboutAction{&helpMenu};
VerticalLayout layout{this};
Console console{&layout, Size{~0, ~0}};
};
struct AboutWindow : Window {
AboutWindow();
VerticalLayout layout{this};
Canvas canvas{&layout, Size{288, 360}, 15};
Label information{&layout, Size{~0, 0}};
};
extern unique_pointer<Terminal> terminal;
extern unique_pointer<AboutWindow> aboutWindow;

View File

@ -1,15 +1,16 @@
name := higan
flags += -DSFC_SUPERGAMEBOY
processors := arm gsu hg51b lr35902 r6502 r65816 spc700 upd96050 v30mz
include processor/GNUmakefile
include emulator/GNUmakefile
include fc/GNUmakefile
include sfc/GNUmakefile
include gb/GNUmakefile
include gba/GNUmakefile
include ws/GNUmakefile
processors := $(call unique,$(processors))
include processor/GNUmakefile
include emulator/GNUmakefile
ui_objects := ui-tomoko ui-program ui-configuration ui-input
ui_objects += ui-settings ui-tools ui-presentation
ui_objects += ruby hiro

View File

@ -1,3 +1,5 @@
processors += v30mz
ws_objects := ws-interface ws-system ws-scheduler
ws_objects += ws-memory ws-eeprom ws-cartridge
ws_objects += ws-cpu ws-ppu ws-apu

View File

@ -5,6 +5,7 @@
#define __MSVCRT_VERSION__ WINVER
#define NOMINMAX
#include <nall/windows/guard.hpp>
#include <winsock2.h>
#include <windows.h>
#include <windowsx.h>
@ -14,6 +15,7 @@
#include <shlobj.h>
#include <nall/windows/registry.hpp>
#include <nall/windows/utf8.hpp>
#include <nall/windows/guard.hpp>
//MinGW/32-bit has painfully outdated platform headers ...

View File

@ -44,7 +44,7 @@ auto rootpath() -> string {
SHGetFolderPathW(nullptr, CSIDL_WINDOWS | CSIDL_FLAG_CREATE, nullptr, 0, path);
string result = (const char*)utf8_t(path);
result.transform("\\", "/");
return result.slice(0, 3);
return slice(result, 0, 3);
#else
return "/";
#endif

13
nall/windows/guard.hpp Normal file
View File

@ -0,0 +1,13 @@
#ifndef NALL_WINDOWS_GUARD_HPP
#define NALL_WINDOWS_GUARD_HPP
#define boolean WindowsBoolean
#define interface WindowsBoolean
#else
#undef NALL_WINDOWS_GUARD_HPP
#undef boolean
#undef interface
#endif

View File

@ -10,11 +10,10 @@
#undef NOMINMAX
#define NOMINMAX
#define boolean WindowsBoolean
#include <nall/windows/guard.hpp>
#include <winsock2.h>
#include <windows.h>
#undef boolean
#undef interface
#include <nall/windows/guard.hpp>
#if !defined(PATH_MAX)
#define PATH_MAX 260

View File

@ -69,7 +69,7 @@ struct VideoWGL : Video, OpenGL {
return false;
}
auto lock(uint32*& data, uint& pitch, uint width, uint height) -> bool {
auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool {
OpenGL::size(width, height);
return OpenGL::lock(data, pitch);
}