2018-05-26 23:04:43 +00:00
|
|
|
//performance-focused, scanline-based, parallelized implementation of PPU
|
|
|
|
|
|
|
|
//limitations:
|
|
|
|
//* mid-scanline effects not support
|
|
|
|
//* mid-frame OAM changes not supported
|
Update to v106r33 release.
byuu says:
Changelog:
- nall/GNUmakefile: added `openmp=(true,false)` option; can be toggled
when building higan/bsnes
- defaults to disabled on macOS, because Xcode doesn't stupidly
doesn't ship with support for it
- higan/GNUmakefile: forgot to switch target,profile back from
bsnes,fast to higan,accurate
- this is just gonna happen from time to time, sorry
- sfc/dsp: when using the fast profile, the DSP syncs per sample
instead of per clock
- should only negatively impact Koushien 2, but is a fairly
significant speedup otherwise
- sfc/ppc,ppu-fast: optimized the code a bit (ppu 130fps to 133fps)
- sfc/ppu-fast: basic vertical mosaic support (not accurate, but
should look okay hopefully)
- sfc/ppu-fast: added missing mode7 hflip support
- sfc/ppu-fast: added support to render at 256-width and/or 240-height
- gives a decent speed boost, and also allows all of the older
quark shaders to work nicely again
- it does violate the contract of Emulator::Interface, but oh
well, it works fine in the bsnes GUI
- sfc/ppu-fast: use cached CGRAM values for mode7 and sprites
- sfc/ppu-fast: use global range/time over flags in object rendering
- may not actually work as we intended since it's a race condition
even if it's only ORing the flags
- really don't want to have to make those variables atomic if I
don't have to
- sfc/ppu-fast: should fully support interlace and overscan modes now
- hiro/cocoa: updated macOS Gatekeeper disable support to work on
10.13+
- ruby: forgot to fix macOS input driver, sorry
- nall/GNUmakefile: if uname is present, then just default to rm
instead of del (fixes Msys)
Note: blur emulation option will break pretty badly in 256x240 output
mode. I'll fix it later.
2018-05-31 07:06:55 +00:00
|
|
|
//* range-time over flags not reported in real-time
|
2018-05-26 23:04:43 +00:00
|
|
|
|
2018-05-26 03:29:14 +00:00
|
|
|
struct PPU : Thread, PPUcounter {
|
Update to v106r33 release.
byuu says:
Changelog:
- nall/GNUmakefile: added `openmp=(true,false)` option; can be toggled
when building higan/bsnes
- defaults to disabled on macOS, because Xcode doesn't stupidly
doesn't ship with support for it
- higan/GNUmakefile: forgot to switch target,profile back from
bsnes,fast to higan,accurate
- this is just gonna happen from time to time, sorry
- sfc/dsp: when using the fast profile, the DSP syncs per sample
instead of per clock
- should only negatively impact Koushien 2, but is a fairly
significant speedup otherwise
- sfc/ppc,ppu-fast: optimized the code a bit (ppu 130fps to 133fps)
- sfc/ppu-fast: basic vertical mosaic support (not accurate, but
should look okay hopefully)
- sfc/ppu-fast: added missing mode7 hflip support
- sfc/ppu-fast: added support to render at 256-width and/or 240-height
- gives a decent speed boost, and also allows all of the older
quark shaders to work nicely again
- it does violate the contract of Emulator::Interface, but oh
well, it works fine in the bsnes GUI
- sfc/ppu-fast: use cached CGRAM values for mode7 and sprites
- sfc/ppu-fast: use global range/time over flags in object rendering
- may not actually work as we intended since it's a race condition
even if it's only ORing the flags
- really don't want to have to make those variables atomic if I
don't have to
- sfc/ppu-fast: should fully support interlace and overscan modes now
- hiro/cocoa: updated macOS Gatekeeper disable support to work on
10.13+
- ruby: forgot to fix macOS input driver, sorry
- nall/GNUmakefile: if uname is present, then just default to rm
instead of del (fixes Msys)
Note: blur emulation option will break pretty badly in 256x240 output
mode. I'll fix it later.
2018-05-31 07:06:55 +00:00
|
|
|
alwaysinline auto interlace() const -> bool { return frame.interlace; }
|
|
|
|
alwaysinline auto overscan() const -> bool { return frame.overscan; }
|
|
|
|
alwaysinline auto hires() const -> bool { return frame.hires; }
|
2018-05-26 23:04:43 +00:00
|
|
|
alwaysinline auto vdisp() const -> uint { return !io.overscan ? 225 : 240; }
|
2018-05-26 03:29:14 +00:00
|
|
|
|
|
|
|
//ppu.cpp
|
|
|
|
PPU();
|
|
|
|
~PPU();
|
|
|
|
|
|
|
|
static auto Enter() -> void;
|
|
|
|
alwaysinline auto step(uint clocks) -> void;
|
|
|
|
auto main() -> void;
|
|
|
|
auto scanline() -> void;
|
|
|
|
auto refresh() -> void;
|
|
|
|
auto load(Markup::Node) -> bool;
|
|
|
|
auto power(bool reset) -> void;
|
|
|
|
|
|
|
|
//serialization.cpp
|
|
|
|
auto serialize(serializer&) -> void;
|
|
|
|
|
|
|
|
public:
|
|
|
|
uint32* output = nullptr;
|
2018-05-28 01:51:38 +00:00
|
|
|
uint8* tilecache[3] = {}; //bitplane -> bitmap tiledata
|
2018-05-26 03:29:14 +00:00
|
|
|
uint16 vram[32 * 1024];
|
|
|
|
uint16 cgram[256];
|
|
|
|
|
|
|
|
struct {
|
|
|
|
uint4 version;
|
|
|
|
uint8 mdr;
|
|
|
|
} ppu1, ppu2;
|
|
|
|
|
|
|
|
struct Latch {
|
2018-05-26 23:04:43 +00:00
|
|
|
uint16 vram;
|
|
|
|
uint8 oam;
|
|
|
|
uint8 cgram;
|
|
|
|
uint8 bgofsPPU1;
|
|
|
|
uint8 bgofsPPU2;
|
|
|
|
uint8 mode7;
|
|
|
|
uint1 counters;
|
|
|
|
uint1 hcounter; //hdot
|
|
|
|
uint1 vcounter;
|
|
|
|
|
|
|
|
uint10 oamAddress;
|
|
|
|
uint8 cgramAddress;
|
2018-05-26 03:29:14 +00:00
|
|
|
} latch;
|
|
|
|
|
|
|
|
//io.cpp
|
2018-05-26 23:04:43 +00:00
|
|
|
auto latchCounters() -> void;
|
|
|
|
alwaysinline auto vramAddress() const -> uint15;
|
|
|
|
alwaysinline auto readVRAM() -> uint16;
|
|
|
|
alwaysinline auto writeVRAM(uint1 byte, uint8 data) -> void;
|
|
|
|
alwaysinline auto readOAM(uint10 address) -> uint8;
|
|
|
|
alwaysinline auto writeOAM(uint10 address, uint8 data) -> void;
|
|
|
|
alwaysinline auto readCGRAM(uint1 byte, uint8 address) -> uint8;
|
|
|
|
alwaysinline auto writeCGRAM(uint8 address, uint15 data) -> void;
|
2018-05-26 03:29:14 +00:00
|
|
|
auto readIO(uint24 address, uint8 data) -> uint8;
|
|
|
|
auto writeIO(uint24 address, uint8 data) -> void;
|
2018-05-26 23:04:43 +00:00
|
|
|
auto updateVideoMode() -> void;
|
|
|
|
|
2018-05-28 01:51:38 +00:00
|
|
|
struct Source { enum : uint { BG1, BG2, BG3, BG4, OBJ1, OBJ2, COL }; };
|
2018-05-26 23:04:43 +00:00
|
|
|
struct TileMode { enum : uint { BPP2, BPP4, BPP8, Mode7, Inactive }; };
|
|
|
|
struct ScreenMode { enum : uint { Above, Below }; };
|
2018-05-26 03:29:14 +00:00
|
|
|
|
|
|
|
struct IO {
|
2018-05-26 23:04:43 +00:00
|
|
|
uint1 displayDisable;
|
|
|
|
uint4 displayBrightness;
|
|
|
|
uint10 oamBaseAddress;
|
|
|
|
uint10 oamAddress;
|
|
|
|
uint1 oamPriority;
|
|
|
|
uint1 bgPriority;
|
|
|
|
uint3 bgMode;
|
|
|
|
uint4 mosaicSize;
|
|
|
|
uint1 vramIncrementMode;
|
|
|
|
uint2 vramMapping;
|
|
|
|
uint8 vramIncrementSize;
|
|
|
|
uint16 vramAddress;
|
|
|
|
uint8 cgramAddress;
|
|
|
|
uint1 cgramAddressLatch;
|
|
|
|
uint9 hcounter; //hdot
|
|
|
|
uint9 vcounter;
|
|
|
|
uint1 interlace;
|
|
|
|
uint1 overscan;
|
|
|
|
uint1 pseudoHires;
|
|
|
|
uint1 extbg;
|
|
|
|
|
|
|
|
struct WindowLayer {
|
|
|
|
uint1 oneEnable;
|
|
|
|
uint1 oneInvert;
|
|
|
|
uint1 twoEnable;
|
|
|
|
uint1 twoInvert;
|
|
|
|
uint2 mask;
|
|
|
|
uint1 aboveEnable;
|
|
|
|
uint1 belowEnable;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct WindowColor {
|
|
|
|
uint1 oneEnable;
|
|
|
|
uint1 oneInvert;
|
|
|
|
uint1 twoEnable;
|
|
|
|
uint1 twoInvert;
|
|
|
|
uint2 mask;
|
|
|
|
uint2 aboveMask;
|
|
|
|
uint2 belowMask;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Window {
|
|
|
|
uint8 oneLeft;
|
|
|
|
uint8 oneRight;
|
|
|
|
uint8 twoLeft;
|
|
|
|
uint8 twoRight;
|
|
|
|
} window;
|
|
|
|
|
|
|
|
struct Mode7 {
|
2018-05-29 11:26:48 +00:00
|
|
|
uint1 hflip;
|
|
|
|
uint1 vflip;
|
|
|
|
uint2 repeat;
|
2018-05-26 23:04:43 +00:00
|
|
|
uint16 a;
|
|
|
|
uint16 b;
|
|
|
|
uint16 c;
|
|
|
|
uint16 d;
|
|
|
|
uint16 x;
|
|
|
|
uint16 y;
|
|
|
|
uint16 hoffset;
|
|
|
|
uint16 voffset;
|
|
|
|
} mode7;
|
|
|
|
|
|
|
|
struct Background {
|
|
|
|
WindowLayer window;
|
|
|
|
uint1 aboveEnable;
|
|
|
|
uint1 belowEnable;
|
|
|
|
uint1 mosaicEnable;
|
|
|
|
uint15 tiledataAddress;
|
|
|
|
uint15 screenAddress;
|
|
|
|
uint2 screenSize;
|
|
|
|
uint1 tileSize;
|
|
|
|
uint16 hoffset;
|
|
|
|
uint16 voffset;
|
|
|
|
uint3 tileMode;
|
|
|
|
uint4 priority[2];
|
|
|
|
} bg1, bg2, bg3, bg4;
|
|
|
|
|
|
|
|
struct Object {
|
|
|
|
WindowLayer window;
|
|
|
|
uint1 aboveEnable;
|
|
|
|
uint1 belowEnable;
|
|
|
|
uint1 interlace;
|
|
|
|
uint3 baseSize;
|
|
|
|
uint2 nameselect;
|
|
|
|
uint15 tiledataAddress;
|
2018-05-29 11:26:48 +00:00
|
|
|
uint7 first;
|
2018-05-26 23:04:43 +00:00
|
|
|
uint1 rangeOver;
|
|
|
|
uint1 timeOver;
|
|
|
|
uint4 priority[4];
|
|
|
|
} obj;
|
|
|
|
|
|
|
|
struct Color {
|
|
|
|
WindowColor window;
|
2018-05-29 11:26:48 +00:00
|
|
|
uint1 enable[7];
|
|
|
|
uint1 directColor;
|
|
|
|
uint1 blendMode; //0 = fixed; 1 = pixel
|
|
|
|
uint1 halve;
|
|
|
|
uint1 mathMode; //0 = add; 1 = sub
|
|
|
|
uint15 fixedColor;
|
2018-05-26 23:04:43 +00:00
|
|
|
} col;
|
2018-05-26 03:29:14 +00:00
|
|
|
} io;
|
|
|
|
|
Update to v106r33 release.
byuu says:
Changelog:
- nall/GNUmakefile: added `openmp=(true,false)` option; can be toggled
when building higan/bsnes
- defaults to disabled on macOS, because Xcode doesn't stupidly
doesn't ship with support for it
- higan/GNUmakefile: forgot to switch target,profile back from
bsnes,fast to higan,accurate
- this is just gonna happen from time to time, sorry
- sfc/dsp: when using the fast profile, the DSP syncs per sample
instead of per clock
- should only negatively impact Koushien 2, but is a fairly
significant speedup otherwise
- sfc/ppc,ppu-fast: optimized the code a bit (ppu 130fps to 133fps)
- sfc/ppu-fast: basic vertical mosaic support (not accurate, but
should look okay hopefully)
- sfc/ppu-fast: added missing mode7 hflip support
- sfc/ppu-fast: added support to render at 256-width and/or 240-height
- gives a decent speed boost, and also allows all of the older
quark shaders to work nicely again
- it does violate the contract of Emulator::Interface, but oh
well, it works fine in the bsnes GUI
- sfc/ppu-fast: use cached CGRAM values for mode7 and sprites
- sfc/ppu-fast: use global range/time over flags in object rendering
- may not actually work as we intended since it's a race condition
even if it's only ORing the flags
- really don't want to have to make those variables atomic if I
don't have to
- sfc/ppu-fast: should fully support interlace and overscan modes now
- hiro/cocoa: updated macOS Gatekeeper disable support to work on
10.13+
- ruby: forgot to fix macOS input driver, sorry
- nall/GNUmakefile: if uname is present, then just default to rm
instead of del (fixes Msys)
Note: blur emulation option will break pretty badly in 256x240 output
mode. I'll fix it later.
2018-05-31 07:06:55 +00:00
|
|
|
struct Frame {
|
|
|
|
uint1 interlace;
|
|
|
|
uint1 overscan;
|
|
|
|
uint1 hires;
|
|
|
|
} frame;
|
|
|
|
|
2018-05-26 03:29:14 +00:00
|
|
|
//object.cpp
|
2018-05-26 23:04:43 +00:00
|
|
|
auto oamAddressReset() -> void;
|
|
|
|
auto oamSetFirstObject() -> void;
|
|
|
|
auto readObject(uint10 address) -> uint8;
|
|
|
|
auto writeObject(uint10 address, uint8 data) -> void;
|
2018-05-26 03:29:14 +00:00
|
|
|
|
|
|
|
struct Object {
|
|
|
|
uint9 x;
|
|
|
|
uint8 y;
|
|
|
|
uint8 character;
|
|
|
|
uint1 nameselect;
|
|
|
|
uint1 vflip;
|
|
|
|
uint1 hflip;
|
|
|
|
uint2 priority;
|
|
|
|
uint3 palette;
|
|
|
|
uint1 size;
|
2018-05-29 11:26:48 +00:00
|
|
|
} objects[128];
|
2018-05-26 03:29:14 +00:00
|
|
|
|
|
|
|
struct Line {
|
2018-05-29 11:26:48 +00:00
|
|
|
struct Pixel;
|
|
|
|
|
2018-05-26 03:29:14 +00:00
|
|
|
//line.cpp
|
|
|
|
auto render() -> void;
|
2018-05-29 11:26:48 +00:00
|
|
|
auto pixel(uint x, Pixel above, Pixel below) const -> uint15;
|
|
|
|
auto blend(uint x, uint y, bool halve) const -> uint15;
|
|
|
|
alwaysinline auto directColor(uint palette, uint tile) const -> uint15;
|
2018-05-28 01:51:38 +00:00
|
|
|
alwaysinline auto plotAbove(uint x, uint source, uint priority, uint color) -> void;
|
|
|
|
alwaysinline auto plotBelow(uint x, uint source, uint priority, uint color) -> void;
|
2018-05-26 03:29:14 +00:00
|
|
|
|
2018-05-26 23:04:43 +00:00
|
|
|
//background.cpp
|
2018-05-28 01:51:38 +00:00
|
|
|
auto renderBackground(PPU::IO::Background&, uint source) -> void;
|
2018-05-29 11:26:48 +00:00
|
|
|
auto getTile(PPU::IO::Background&, uint hoffset, uint voffset) -> uint;
|
|
|
|
|
|
|
|
//mode7.cpp
|
|
|
|
auto renderMode7(PPU::IO::Background&, uint source) -> void;
|
2018-05-26 23:04:43 +00:00
|
|
|
|
|
|
|
//object.cpp
|
|
|
|
auto renderObject(PPU::IO::Object&) -> void;
|
|
|
|
|
|
|
|
//window.cpp
|
2018-05-29 11:26:48 +00:00
|
|
|
auto renderWindow(PPU::IO::WindowLayer&, bool, bool*) -> void;
|
|
|
|
auto renderWindow(PPU::IO::WindowColor&, uint, bool*) -> void;
|
2018-05-26 23:04:43 +00:00
|
|
|
|
|
|
|
uint9 y;
|
2018-05-26 03:29:14 +00:00
|
|
|
uint32* outputLo = nullptr;
|
|
|
|
uint32* outputHi = nullptr;
|
|
|
|
|
|
|
|
uint15 cgram[256];
|
|
|
|
IO io;
|
2018-05-28 01:51:38 +00:00
|
|
|
|
2018-05-29 11:26:48 +00:00
|
|
|
struct ObjectItem {
|
|
|
|
uint1 valid;
|
|
|
|
uint7 index;
|
|
|
|
uint8 width;
|
|
|
|
uint8 height;
|
|
|
|
} items[32];
|
|
|
|
|
|
|
|
struct ObjectTile {
|
|
|
|
uint1 valid;
|
|
|
|
uint9 x;
|
|
|
|
uint8 y;
|
|
|
|
uint2 priority;
|
|
|
|
uint8 palette;
|
|
|
|
uint1 hflip;
|
|
|
|
uint11 number;
|
|
|
|
} tiles[34];
|
|
|
|
|
|
|
|
struct Pixel {
|
2018-05-28 01:51:38 +00:00
|
|
|
uint source;
|
|
|
|
uint priority;
|
|
|
|
uint color;
|
|
|
|
} above[256], below[256];
|
2018-05-29 11:26:48 +00:00
|
|
|
|
|
|
|
bool windowAbove[256];
|
|
|
|
bool windowBelow[256];
|
2018-05-26 03:29:14 +00:00
|
|
|
} lines[240];
|
|
|
|
};
|
|
|
|
|
|
|
|
extern PPU ppu;
|