Compare commits

...

22 commits
1 ... master

Author SHA1 Message Date
Sharpy
8b547f1c5d necdsp: improve OV1/S1 flag calculations
necdsp: improve OV1/S1 flag calculations
2017-09-05 21:07:58 +01:00
Alex W. Jackson
e93c847785 necdsp: improve OV1/S1 flag calculations 2017-09-05 12:42:58 -04:00
Sharpy
57d813f20e AwJackson SMP improvements
Smp improvements
2017-08-06 12:26:32 +01:00
Sharpy
b795baab6d nall: let's not do a switch() on every. single. call to keyboard(), mouse(), and joypad()
nall: let's not do a switch() on every. single. call to keyboard(), mouse(), and joypad()
2017-07-12 16:03:51 +01:00
Sharpy
3adabb8bf3 Revert "Revert "awjackson"" 2017-07-12 16:01:59 +01:00
Sharpy
ff735792d7 ppu: improve BGnHOFS latching, fixes Super Pac-Man (PD)
ppu: improve BGnHOFS latching, fixes Super Pac-Man (PD)
2017-07-12 15:59:44 +01:00
Alex W. Jackson
4b143b74e3 ppu: improve BGnHOFS latching, fixes Super Pac-Man (PD) 2017-07-11 23:15:25 -04:00
Alex W. Jackson
a47e32ce96 smp: don't need a lookup table for 1 << n, either 2017-07-01 15:40:28 -04:00
Alex W. Jackson
994b35cd30 smp: no need to multiply these by 3 anymore 2017-07-01 13:39:09 -04:00
Alex W. Jackson
04c29e5279 smp: apply recent TEST findings 2017-07-01 11:59:26 -04:00
Sharpy
22e2e245c5 Merge pull request #3 from sharknnth/revert-2-master
Revert "awjackson"
2017-06-27 22:41:19 +01:00
Sharpy
7463b0294f Revert "awjackson" 2017-06-27 22:40:51 +01:00
Sharpy
4d70efe386 nall: let's not do a switch() on every. single. call to keyboard(), m… … …ouse(), and joypad() 11888c6 @awjackson awjackson dsp: change initial ENDX register state to match current higan; fixes… … … Magical Drop
nall: let's not do a switch() on every. single. call to keyboard(), m…  …
…ouse(), and joypad()
11888c6
 @awjackson	awjackson	dsp: change initial ENDX register state to match current higan; fixes…  …
… Magical Drop
2017-06-27 22:36:03 +01:00
Alex W. Jackson
c583f8eebf dsp: change initial ENDX register state to match current higan; fixes Magical Drop 2017-06-26 21:28:30 -04:00
Alex W. Jackson
11888c6b6e nall: let's not do a switch() on every. single. call to keyboard(), mouse(), and joypad() 2017-06-26 20:01:23 -04:00
Sharpy
de984287c0 Added Windows (x64) building instructions 2016-11-07 20:53:21 +00:00
Sharpy
2292635fa1 Added Windows (x64) building instructions 2016-11-07 20:49:08 +00:00
Sharpy
35376200d4 Added Windows (x64) builiding instructions 2016-11-07 20:32:43 +00:00
Sharpy
cc1c0e387b Makefile Windows distribution fixes 2016-09-09 21:56:42 +01:00
Sharpy
c80eea5392 Create README.md 2016-08-24 21:11:33 +01:00
Sharpy
546c443a9a Delete README.md 2016-08-24 21:07:37 +01:00
Sharpy
9919878654 Create README.md 2016-08-24 21:06:25 +01:00
27 changed files with 227 additions and 199 deletions

52
README.md Normal file
View file

@ -0,0 +1,52 @@
# bsnes-classic
This fork of bsnes-classic also includes perfect emulation of Super FX and Super FX 2 games as well as an experimental upscaling 6xBRZ filter for OpenGL. All courtesy of Zenju, CarterLi and awjackson.
## Building on Windows (64-bit)
- Get mingw-w64 with 64-bit Qt 4.8.6 and do a full installation of the exe (https://sourceforge.net/projects/qt64ng/files/qt/x86-64/4.8.6/mingw-4.9/seh/)
- Set following environment variables (right click on My Computer, then Properties, Advanced, Environment variables): 
QTDIR to C:\Qt\4.X.X (or whatever path you installed QT)
QMAKESPEC to win32-g++
and adjust PATH, add C:\Qt\4.X.X\bin and C:\MinGW\bin (or whatever path you installed MinGW)
- Logout/login or restart after changing environment variables, otherwise it won't work
- Run the terminal from minGW in the start menu and navigate to the Makefiles
- Run `mingw32-make`
Building with the original MinGW used to be the preferred way to do it, but made building "out of the box" annoying for various reasons (including requiring outdated DirectX headers/libs and problems with some native Windows code) and is no longer supported.
## Building on OS X
- Install a C++ toolchain ([Xcode](https://developer.apple.com) is probably the easiest route)
- Install Qt 4.8 (get [Brew](http://brew.sh) and run `brew install qt`)
- Make sure the `qtpath` environment variable points to your Qt installation, ie. add `export qtpath=/usr/local/Cellar/qt/4.8.7_2` to .bash_profile.
- Run `make`from the bsnes directory.
If you're running macOS 10.12 Sierra you will (probably not) be able to install Qt4 using brew. If so, try installing this unofficial branch:
```
brew install cartr/qt4/qt
brew linkapps qt
```
## Building on Linux / other *nix
As there is no ``configure`` step, make sure necessary Qt4/X11 packages are installed. On a Debian/Ubuntu system, it would require a command like:
```
apt-get install libqt4-dev libqt4-dev-bin libxv-dev libsdl1.2-dev libao-dev
libopenal-dev g++
```
Afterwards, run ``make`` and if everything works out correctly you will find the output binary in the ``out/`` directory.
The snesfilter, snesreader, and supergameboy plugins can all be built by running make (or mingw32-make) after you've configured your environment to build bsnes itself.
After building, just copy the .dll, .so, or .dylib files into the same directory as bsnes itself.
This fork of bsnes doesn't include the alternate UI based on byuu's `phoenix` library. The purpose of this fork is primarily to add additional UI functionality and I have no intention of implementing every new feature twice using completely different libraries just to keep both versions of the UI at parity.
bsnes v073 and its derivatives are licensed under the GPL v2; see *Help > License ...* for more information.
## Contributors
See *Help > Documentation ...* for a list of authors.

View file

@ -11,7 +11,7 @@
namespace nall {
struct Keyboard;
Keyboard& keyboard(unsigned = 0);
Keyboard keyboard(unsigned = 0);
static const char KeyboardScancodeName[][64] = {
"Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
@ -122,12 +122,9 @@ struct Keyboard {
Keyboard(unsigned ID_) : ID(ID_) {}
};
inline Keyboard& keyboard(unsigned id) {
static Keyboard kb0(0), kb1(1), kb2(2), kb3(3), kb4(4), kb5(5), kb6(6), kb7(7);
switch(id) { default:
case 0: return kb0; case 1: return kb1; case 2: return kb2; case 3: return kb3;
case 4: return kb4; case 5: return kb5; case 6: return kb6; case 7: return kb7;
}
inline Keyboard keyboard(unsigned id) {
assert(id < Keyboard::Count);
return Keyboard(id);
}
static const char MouseScancodeName[][64] = {
@ -136,7 +133,7 @@ static const char MouseScancodeName[][64] = {
};
struct Mouse;
Mouse& mouse(unsigned = 0);
Mouse mouse(unsigned = 0);
struct Mouse {
const unsigned ID;
@ -220,12 +217,9 @@ struct Mouse {
Mouse(unsigned ID_) : ID(ID_) {}
};
inline Mouse& mouse(unsigned id) {
static Mouse ms0(0), ms1(1), ms2(2), ms3(3), ms4(4), ms5(5), ms6(6), ms7(7);
switch(id) { default:
case 0: return ms0; case 1: return ms1; case 2: return ms2; case 3: return ms3;
case 4: return ms4; case 5: return ms5; case 6: return ms6; case 7: return ms7;
}
inline Mouse mouse(unsigned id) {
assert(id < Mouse::Count);
return Mouse(id);
}
static const char JoypadScancodeName[][64] = {
@ -239,7 +233,7 @@ static const char JoypadScancodeName[][64] = {
};
struct Joypad;
Joypad& joypad(unsigned = 0);
Joypad joypad(unsigned = 0);
struct Joypad {
const unsigned ID;
@ -345,12 +339,9 @@ struct Joypad {
Joypad(unsigned ID_) : ID(ID_) {}
};
inline Joypad& joypad(unsigned id) {
static Joypad jp0(0), jp1(1), jp2(2), jp3(3), jp4(4), jp5(5), jp6(6), jp7(7);
switch(id) { default:
case 0: return jp0; case 1: return jp1; case 2: return jp2; case 3: return jp3;
case 4: return jp4; case 5: return jp5; case 6: return jp6; case 7: return jp7;
}
inline Joypad joypad(unsigned id) {
assert(id < Joypad::Count);
return Joypad(id);
}
struct Scancode {

View file

@ -40,7 +40,7 @@ static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] =
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,
// 0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80,
// 0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF,
@ -856,6 +856,7 @@ void SPC_DSP::soft_reset_common()
void SPC_DSP::soft_reset()
{
REG(flg) = 0xE0;
REG(endx) = 0xFF;
soft_reset_common();
}

View file

@ -111,8 +111,9 @@ void PPU::mmio_w210d(uint8 value) {
regs.m7_hofs = (value << 8) | regs.m7_latch;
regs.m7_latch = value;
regs.bg_hofs[BG1] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG1] >> 8) & 7);
regs.bg_ofslatch = value;
regs.bg_hofs[BG1] = (value << 8) | (regs.bg_ppu1ofslatch & ~7) | (regs.bg_ppu2ofslatch & 7);
regs.bg_ppu1ofslatch = value;
regs.bg_ppu2ofslatch = value;
}
//BG1VOFS
@ -120,44 +121,47 @@ void PPU::mmio_w210e(uint8 value) {
regs.m7_vofs = (value << 8) | regs.m7_latch;
regs.m7_latch = value;
regs.bg_vofs[BG1] = (value << 8) | (regs.bg_ofslatch);
regs.bg_ofslatch = value;
regs.bg_vofs[BG1] = (value << 8) | (regs.bg_ppu1ofslatch);
regs.bg_ppu1ofslatch = value;
}
//BG2HOFS
void PPU::mmio_w210f(uint8 value) {
regs.bg_hofs[BG2] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG2] >> 8) & 7);
regs.bg_ofslatch = value;
regs.bg_hofs[BG2] = (value << 8) | (regs.bg_ppu1ofslatch & ~7) | (regs.bg_ppu2ofslatch & 7);
regs.bg_ppu1ofslatch = value;
regs.bg_ppu2ofslatch = value;
}
//BG2VOFS
void PPU::mmio_w2110(uint8 value) {
regs.bg_vofs[BG2] = (value << 8) | (regs.bg_ofslatch);
regs.bg_ofslatch = value;
regs.bg_vofs[BG2] = (value << 8) | (regs.bg_ppu1ofslatch);
regs.bg_ppu1ofslatch = value;
}
//BG3HOFS
void PPU::mmio_w2111(uint8 value) {
regs.bg_hofs[BG3] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG3] >> 8) & 7);
regs.bg_ofslatch = value;
regs.bg_hofs[BG3] = (value << 8) | (regs.bg_ppu1ofslatch & ~7) | (regs.bg_ppu2ofslatch & 7);
regs.bg_ppu1ofslatch = value;
regs.bg_ppu2ofslatch = value;
}
//BG3VOFS
void PPU::mmio_w2112(uint8 value) {
regs.bg_vofs[BG3] = (value << 8) | (regs.bg_ofslatch);
regs.bg_ofslatch = value;
regs.bg_vofs[BG3] = (value << 8) | (regs.bg_ppu1ofslatch);
regs.bg_ppu1ofslatch = value;
}
//BG4HOFS
void PPU::mmio_w2113(uint8 value) {
regs.bg_hofs[BG4] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG4] >> 8) & 7);
regs.bg_ofslatch = value;
regs.bg_hofs[BG4] = (value << 8) | (regs.bg_ppu1ofslatch & ~7) | (regs.bg_ppu2ofslatch & 7);
regs.bg_ppu1ofslatch = value;
regs.bg_ppu2ofslatch = value;
}
//BG4VOFS
void PPU::mmio_w2114(uint8 value) {
regs.bg_vofs[BG4] = (value << 8) | (regs.bg_ofslatch);
regs.bg_ofslatch = value;
regs.bg_vofs[BG4] = (value << 8) | (regs.bg_ppu1ofslatch);
regs.bg_ppu1ofslatch = value;
}
//VMAIN

View file

@ -45,7 +45,8 @@ struct {
uint16 bg_tdaddr[4];
//$210d-$2114
uint8 bg_ofslatch;
uint8 bg_ppu1ofslatch;
uint8 bg_ppu2ofslatch;
uint16 m7_hofs, m7_vofs;
uint16 bg_hofs[4];
uint16 bg_vofs[4];

View file

@ -191,7 +191,8 @@ void PPU::power() {
regs.bg_tdaddr[BG4] = 0x0000;
//$210d-$2114
regs.bg_ofslatch = 0x00;
regs.bg_ppu1ofslatch = 0x00;
regs.bg_ppu2ofslatch = 0x00;
regs.m7_hofs = regs.m7_vofs = 0x0000;
regs.bg_hofs[BG1] = regs.bg_vofs[BG1] = 0x0000;
regs.bg_hofs[BG2] = regs.bg_vofs[BG2] = 0x0000;

View file

@ -53,7 +53,8 @@ void PPU::serialize(serializer &s) {
for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_tdaddr[n]);
s.integer(regs.bg_ofslatch);
s.integer(regs.bg_ppu1ofslatch);
s.integer(regs.bg_ppu2ofslatch);
s.integer(regs.m7_hofs);
s.integer(regs.m7_vofs);
for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_hofs[n]);

View file

@ -383,8 +383,9 @@ void PPU::mmio_write(unsigned addr, uint8 data) {
regs.mode7_hoffset = (data << 8) | regs.mode7_latchdata;
regs.mode7_latchdata = data;
bg1.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg1.regs.hoffset >> 8) & 7);
regs.bgofs_latchdata = data;
bg1.regs.hoffset = (data << 8) | (regs.bgofs_ppu1latchdata & ~7) | (regs.bgofs_ppu2latchdata & 7);
regs.bgofs_ppu1latchdata = data;
regs.bgofs_ppu2latchdata = data;
return;
}
@ -392,44 +393,47 @@ void PPU::mmio_write(unsigned addr, uint8 data) {
regs.mode7_voffset = (data << 8) | regs.mode7_latchdata;
regs.mode7_latchdata = data;
bg1.regs.voffset = (data << 8) | regs.bgofs_latchdata;
regs.bgofs_latchdata = data;
bg1.regs.voffset = (data << 8) | regs.bgofs_ppu1latchdata;
regs.bgofs_ppu1latchdata = data;
return;
}
case 0x0f: { //BG2HOFS
bg2.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg2.regs.hoffset >> 8) & 7);
regs.bgofs_latchdata = data;
bg2.regs.hoffset = (data << 8) | (regs.bgofs_ppu1latchdata & ~7) | (regs.bgofs_ppu2latchdata & 7);
regs.bgofs_ppu1latchdata = data;
regs.bgofs_ppu2latchdata = data;
return;
}
case 0x10: { //BG2VOFS
bg2.regs.voffset = (data << 8) | regs.bgofs_latchdata;
regs.bgofs_latchdata = data;
bg2.regs.voffset = (data << 8) | regs.bgofs_ppu1latchdata;
regs.bgofs_ppu1latchdata = data;
return;
}
case 0x11: { //BG3HOFS
bg3.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg3.regs.hoffset >> 8) & 7);
regs.bgofs_latchdata = data;
return;
bg3.regs.hoffset = (data << 8) | (regs.bgofs_ppu1latchdata & ~7) | (regs.bgofs_ppu2latchdata & 7);
regs.bgofs_ppu1latchdata = data;
regs.bgofs_ppu2latchdata = data;
return;
}
case 0x12: { //BG3VOFS
bg3.regs.voffset = (data << 8) | regs.bgofs_latchdata;
regs.bgofs_latchdata = data;
bg3.regs.voffset = (data << 8) | regs.bgofs_ppu1latchdata;
regs.bgofs_ppu1latchdata = data;
return;
}
case 0x13: { //BG4HOFS
bg4.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg4.regs.hoffset >> 8) & 7);
regs.bgofs_latchdata = data;
return;
bg4.regs.hoffset = (data << 8) | (regs.bgofs_ppu1latchdata & ~7) | (regs.bgofs_ppu2latchdata & 7);
regs.bgofs_ppu1latchdata = data;
regs.bgofs_ppu2latchdata = data;
return;
}
case 0x14: { //BG4VOFS
bg4.regs.voffset = (data << 8) | regs.bgofs_latchdata;
regs.bgofs_latchdata = data;
bg4.regs.voffset = (data << 8) | regs.bgofs_ppu1latchdata;
regs.bgofs_ppu1latchdata = data;
return;
}
@ -688,7 +692,8 @@ void PPU::mmio_reset() {
regs.vram_readbuffer = 0;
regs.oam_latchdata = 0;
regs.cgram_latchdata = 0;
regs.bgofs_latchdata = 0;
regs.bgofs_ppu1latchdata = 0;
regs.bgofs_ppu2latchdata = 0;
regs.mode7_latchdata = 0;
regs.counters_latched = 0;

View file

@ -6,7 +6,8 @@ struct Regs {
uint16 vram_readbuffer;
uint8 oam_latchdata;
uint8 cgram_latchdata;
uint8 bgofs_latchdata;
uint8 bgofs_ppu1latchdata;
uint8 bgofs_ppu2latchdata;
uint8 mode7_latchdata;
bool counters_latched;

View file

@ -25,7 +25,8 @@ void PPU::serialize(serializer &s) {
s.integer(regs.vram_readbuffer);
s.integer(regs.oam_latchdata);
s.integer(regs.cgram_latchdata);
s.integer(regs.bgofs_latchdata);
s.integer(regs.bgofs_ppu1latchdata);
s.integer(regs.bgofs_ppu2latchdata);
s.integer(regs.mode7_latchdata);
s.integer(regs.counters_latched);

View file

@ -100,6 +100,7 @@ void NECDSP::exec_op(uint24 opcode) {
flag.s0 = (r & 0x8000);
flag.z = (r == 0);
if (!flag.ov1) flag.s1 = flag.s0;
switch(alu) {
case 1: case 2: case 3: case 10: case 13: case 14: case 15: {
@ -111,17 +112,14 @@ void NECDSP::exec_op(uint24 opcode) {
case 4: case 5: case 6: case 7: case 8: case 9: {
if(alu & 1) {
//addition
flag.ov0 = (q ^ r) & ~(q ^ p) & 0x8000;
flag.ov0 = (q ^ r) & (p ^ r) & 0x8000;
flag.c = (r < q);
} else {
//subtraction
flag.ov0 = (q ^ r) & (q ^ p) & 0x8000;
flag.ov0 = (q ^ r) & (q ^ p) & 0x8000;
flag.c = (r > q);
}
if(flag.ov0) {
flag.s1 = flag.ov1 ^ !(r & 0x8000);
flag.ov1 = !flag.ov1;
}
flag.ov1 = (flag.ov0 & flag.ov1) ? (flag.s1 == flag.s0) : (flag.ov0 | flag.ov1);
break;
}
case 11: {
@ -146,15 +144,16 @@ void NECDSP::exec_op(uint24 opcode) {
exec_ld((idb << 6) + dst);
switch(dpl) {
case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC
case 2: regs.dp = (regs.dp & 0xf0) + ((regs.dp - 1) & 0x0f); break; //DPDEC
case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR
if (dst != 4) {
switch(dpl) {
case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC
case 2: regs.dp = (regs.dp & 0xf0) + ((regs.dp - 1) & 0x0f); break; //DPDEC
case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR
}
regs.dp ^= dphm << 4;
}
regs.dp ^= dphm << 4;
if(rpdcr) regs.rp--;
if(rpdcr && dst != 5) regs.rp--;
}
void NECDSP::exec_rt(uint24 opcode) {

View file

@ -337,6 +337,7 @@ void DSP::reset() {
#endif
REG(flg) = 0xe0;
REG(endx) = 0xff;
state.noise = 0x4000;
state.echo_hist_pos = 0;

View file

@ -246,8 +246,9 @@ void PPU::mmio_w210d(uint8 data) {
regs.mode7_hoffset = (data << 8) | regs.mode7_latchdata;
regs.mode7_latchdata = data;
bg1.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg1.regs.hoffset >> 8) & 7);
regs.bgofs_latchdata = data;
bg1.regs.hoffset = (data << 8) | (regs.bgofs_ppu1latchdata & ~7) | (regs.bgofs_ppu2latchdata);
regs.bgofs_ppu1latchdata = data;
regs.bgofs_ppu2latchdata = data;
}
//BG1VOFS
@ -255,44 +256,47 @@ void PPU::mmio_w210e(uint8 data) {
regs.mode7_voffset = (data << 8) | regs.mode7_latchdata;
regs.mode7_latchdata = data;
bg1.regs.voffset = (data << 8) | regs.bgofs_latchdata;
regs.bgofs_latchdata = data;
bg1.regs.voffset = (data << 8) | regs.bgofs_ppu1latchdata;
regs.bgofs_ppu1latchdata = data;
}
//BG2HOFS
void PPU::mmio_w210f(uint8 data) {
bg2.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg2.regs.hoffset >> 8) & 7);
regs.bgofs_latchdata = data;
bg2.regs.hoffset = (data << 8) | (regs.bgofs_ppu1latchdata & ~7) | (regs.bgofs_ppu2latchdata);
regs.bgofs_ppu1latchdata = data;
regs.bgofs_ppu2latchdata = data;
}
//BG2VOFS
void PPU::mmio_w2110(uint8 data) {
bg2.regs.voffset = (data << 8) | regs.bgofs_latchdata;
regs.bgofs_latchdata = data;
bg2.regs.voffset = (data << 8) | regs.bgofs_ppu1latchdata;
regs.bgofs_ppu1latchdata = data;
}
//BG3HOFS
void PPU::mmio_w2111(uint8 data) {
bg3.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg3.regs.hoffset >> 8) & 7);
regs.bgofs_latchdata = data;
bg3.regs.hoffset = (data << 8) | (regs.bgofs_ppu1latchdata & ~7) | (regs.bgofs_ppu2latchdata);
regs.bgofs_ppu1latchdata = data;
regs.bgofs_ppu2latchdata = data;
}
//BG3VOFS
void PPU::mmio_w2112(uint8 data) {
bg3.regs.voffset = (data << 8) | regs.bgofs_latchdata;
regs.bgofs_latchdata = data;
bg3.regs.voffset = (data << 8) | regs.bgofs_ppu1latchdata;
regs.bgofs_ppu1latchdata = data;
}
//BG4HOFS
void PPU::mmio_w2113(uint8 data) {
bg4.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg4.regs.hoffset >> 8) & 7);
regs.bgofs_latchdata = data;
bg4.regs.hoffset = (data << 8) | (regs.bgofs_ppu1latchdata & ~7) | (regs.bgofs_ppu2latchdata);
regs.bgofs_ppu1latchdata = data;
regs.bgofs_ppu2latchdata = data;
}
//BG4VOFS
void PPU::mmio_w2114(uint8 data) {
bg4.regs.voffset = (data << 8) | regs.bgofs_latchdata;
regs.bgofs_latchdata = data;
bg4.regs.voffset = (data << 8) | regs.bgofs_ppu1latchdata;
regs.bgofs_ppu1latchdata = data;
}
//VMAIN
@ -690,7 +694,8 @@ void PPU::mmio_reset() {
regs.vram_readbuffer = 0x0000;
regs.oam_latchdata = 0x00;
regs.cgram_latchdata = 0x00;
regs.bgofs_latchdata = 0x00;
regs.bgofs_ppu1latchdata = 0x00;
regs.bgofs_ppu2latchdata = 0x00;
regs.mode7_latchdata = 0x00;
regs.counters_latched = false;
regs.latch_hcounter = 0;

View file

@ -5,7 +5,8 @@ struct {
uint16 vram_readbuffer;
uint8 oam_latchdata;
uint8 cgram_latchdata;
uint8 bgofs_latchdata;
uint8 bgofs_ppu1latchdata;
uint3 bgofs_ppu2latchdata;
uint8 mode7_latchdata;
bool counters_latched;
bool latch_hcounter;

View file

@ -18,7 +18,8 @@ void PPU::serialize(serializer &s) {
s.integer(regs.vram_readbuffer);
s.integer(regs.oam_latchdata);
s.integer(regs.cgram_latchdata);
s.integer(regs.bgofs_latchdata);
s.integer(regs.bgofs_ppu1latchdata);
s.integer(regs.bgofs_ppu2latchdata);
s.integer(regs.mode7_latchdata);
s.integer(regs.counters_latched);
s.integer(regs.latch_hcounter);

View file

@ -80,14 +80,12 @@ alwaysinline void SMP::op_buswrite(uint16 addr, uint8 data) {
if(regs.p.p) break; //writes only valid when P flag is clear
status.clock_speed = (data >> 6) & 3;
status.timer_speed = (data >> 4) & 3;
status.ram_speed = (data >> 4) & 3;
status.timers_enabled = data & 0x08;
status.ram_disabled = data & 0x04;
status.ram_writable = data & 0x02;
status.timers_disabled = data & 0x01;
status.timer_step = (1 << status.clock_speed) + (2 << status.timer_speed);
t0.sync_stage1();
t1.sync_stage1();
t2.sync_stage1();
@ -176,23 +174,29 @@ alwaysinline void SMP::op_buswrite(uint16 addr, uint8 data) {
ram_write(addr, data);
}
unsigned SMP::speed(uint16 addr) const {
if((addr & 0xfff0) == 0x00f0) return status.clock_speed;
if(addr >= 0xffc0 && status.iplrom_enabled) return status.clock_speed;
return status.ram_speed;
}
void SMP::op_io() {
add_clocks(24);
cycle_edge();
cycle_edge(status.clock_speed);
}
uint8 SMP::op_read(uint16 addr) {
add_clocks(12);
uint8 r = op_busread(addr);
add_clocks(12);
cycle_edge();
cycle_edge(speed(addr));
return r;
}
void SMP::op_write(uint16 addr, uint8 data) {
add_clocks(24);
op_buswrite(addr, data);
cycle_edge();
cycle_edge(speed(addr));
}
#endif

View file

@ -4,6 +4,8 @@ void ram_write(uint16 addr, uint8 data);
uint8 op_busread(uint16 addr);
void op_buswrite(uint16 addr, uint8 data);
alwaysinline unsigned speed(uint16 addr) const;
void op_io();
debugvirtual uint8 op_read(uint16 addr);
debugvirtual void op_write(uint16 addr, uint8 data);

View file

@ -4,12 +4,8 @@ void SMP::serialize(serializer &s) {
Processor::serialize(s);
SMPcore::core_serialize(s);
s.integer(status.clock_counter);
s.integer(status.dsp_counter);
s.integer(status.timer_step);
s.integer(status.clock_speed);
s.integer(status.timer_speed);
s.integer(status.ram_speed);
s.integer(status.timers_enabled);
s.integer(status.ram_disabled);
s.integer(status.ram_writable);

View file

@ -76,13 +76,9 @@ void SMP::reset() {
memory::apuram.write(i, 0x00);
}
status.clock_counter = 0;
status.dsp_counter = 0;
status.timer_step = 3;
//$00f0
status.clock_speed = 0;
status.timer_speed = 0;
status.ram_speed = 0;
status.timers_enabled = true;
status.ram_disabled = false;
status.ram_writable = true;

View file

@ -21,14 +21,9 @@ private:
#include "timing/timing.hpp"
struct {
//timing
unsigned clock_counter;
unsigned dsp_counter;
unsigned timer_step;
//$00f0
uint8 clock_speed;
uint8 timer_speed;
uint8 ram_speed;
bool timers_enabled;
bool ram_disabled;
bool ram_writable;

View file

@ -9,25 +9,22 @@ void SMP::add_clocks(unsigned clocks) {
if(clock > +(768 * 24 * (int64)24000000)) synchronize_cpu();
}
void SMP::cycle_edge() {
t0.tick();
t1.tick();
t2.tick();
void SMP::cycle_edge(unsigned speed) {
static const uint8 wait_states[] = {0, 24*1, 24*4, 24*9};
unsigned ticks = 1 << speed;
t0.tick(ticks);
t1.tick(ticks);
t2.tick(ticks);
//TEST register S-SMP speed control
//24 clocks have already been added for this cycle at this point
switch(status.clock_speed) {
case 0: break; //100% speed
case 1: add_clocks(24); break; // 50% speed
case 2: while(true) add_clocks(24); // 0% speed -- locks S-SMP
case 3: add_clocks(24 * 9); break; // 10% speed
}
if(speed) add_clocks(wait_states[speed]);
}
template<unsigned timer_frequency>
void SMP::sSMPTimer<timer_frequency>::tick() {
void SMP::sSMPTimer<timer_frequency>::tick(unsigned step) {
//stage 0 increment
stage0_ticks += smp.status.timer_step;
stage0_ticks += step;
if(stage0_ticks < timer_frequency) return;
stage0_ticks -= timer_frequency;

View file

@ -9,13 +9,13 @@ public:
bool enabled;
uint8 target;
void tick();
void tick(unsigned step);
void sync_stage1();
};
sSMPTimer<192> t0;
sSMPTimer<192> t1;
sSMPTimer< 24> t2;
sSMPTimer<64> t0;
sSMPTimer<64> t1;
sSMPTimer< 8> t2;
alwaysinline void add_clocks(unsigned clocks);
alwaysinline void cycle_edge();
alwaysinline void cycle_edge(unsigned speed);

View file

@ -3,7 +3,7 @@ namespace SNES {
static const char Name[] = "bsnes-classic";
static const char Version[] = "073u1";
static const unsigned SerializerSignature = 0x43545342; //'BSTC'
static const unsigned SerializerVersion = 6;
static const unsigned SerializerVersion = 7;
}
}

View file

@ -11,7 +11,7 @@ link :=
ifeq ($(DEBUG), 1)
flags += -O0 -g -DDEBUG
else
flags += -O3 -fomit-frame-pointer -DNDEBUG -march=native
flags += -O3 -fomit-frame-pointer -DNDEBUG
endif
# silence warnings

View file

@ -11,7 +11,7 @@
namespace nall {
struct Keyboard;
Keyboard& keyboard(unsigned = 0);
Keyboard keyboard(unsigned = 0);
static const char KeyboardScancodeName[][64] = {
"Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
@ -122,12 +122,9 @@ struct Keyboard {
Keyboard(unsigned ID_) : ID(ID_) {}
};
inline Keyboard& keyboard(unsigned id) {
static Keyboard kb0(0), kb1(1), kb2(2), kb3(3), kb4(4), kb5(5), kb6(6), kb7(7);
switch(id) { default:
case 0: return kb0; case 1: return kb1; case 2: return kb2; case 3: return kb3;
case 4: return kb4; case 5: return kb5; case 6: return kb6; case 7: return kb7;
}
inline Keyboard keyboard(unsigned id) {
assert(id < Keyboard::Count);
return Keyboard(id);
}
static const char MouseScancodeName[][64] = {
@ -136,7 +133,7 @@ static const char MouseScancodeName[][64] = {
};
struct Mouse;
Mouse& mouse(unsigned = 0);
Mouse mouse(unsigned = 0);
struct Mouse {
const unsigned ID;
@ -220,12 +217,9 @@ struct Mouse {
Mouse(unsigned ID_) : ID(ID_) {}
};
inline Mouse& mouse(unsigned id) {
static Mouse ms0(0), ms1(1), ms2(2), ms3(3), ms4(4), ms5(5), ms6(6), ms7(7);
switch(id) { default:
case 0: return ms0; case 1: return ms1; case 2: return ms2; case 3: return ms3;
case 4: return ms4; case 5: return ms5; case 6: return ms6; case 7: return ms7;
}
inline Mouse mouse(unsigned id) {
assert(id < Mouse::Count);
return Mouse(id);
}
static const char JoypadScancodeName[][64] = {
@ -239,7 +233,7 @@ static const char JoypadScancodeName[][64] = {
};
struct Joypad;
Joypad& joypad(unsigned = 0);
Joypad joypad(unsigned = 0);
struct Joypad {
const unsigned ID;
@ -345,12 +339,9 @@ struct Joypad {
Joypad(unsigned ID_) : ID(ID_) {}
};
inline Joypad& joypad(unsigned id) {
static Joypad jp0(0), jp1(1), jp2(2), jp3(3), jp4(4), jp5(5), jp6(6), jp7(7);
switch(id) { default:
case 0: return jp0; case 1: return jp1; case 2: return jp2; case 3: return jp3;
case 4: return jp4; case 5: return jp5; case 6: return jp6; case 7: return jp7;
}
inline Joypad joypad(unsigned id) {
assert(id < Joypad::Count);
return Joypad(id);
}
struct Scancode {

View file

@ -11,7 +11,7 @@
namespace nall {
struct Keyboard;
Keyboard& keyboard(unsigned = 0);
Keyboard keyboard(unsigned = 0);
static const char KeyboardScancodeName[][64] = {
"Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
@ -122,12 +122,9 @@ struct Keyboard {
Keyboard(unsigned ID_) : ID(ID_) {}
};
inline Keyboard& keyboard(unsigned id) {
static Keyboard kb0(0), kb1(1), kb2(2), kb3(3), kb4(4), kb5(5), kb6(6), kb7(7);
switch(id) { default:
case 0: return kb0; case 1: return kb1; case 2: return kb2; case 3: return kb3;
case 4: return kb4; case 5: return kb5; case 6: return kb6; case 7: return kb7;
}
inline Keyboard keyboard(unsigned id) {
assert(id < Keyboard::Count);
return Keyboard(id);
}
static const char MouseScancodeName[][64] = {
@ -136,7 +133,7 @@ static const char MouseScancodeName[][64] = {
};
struct Mouse;
Mouse& mouse(unsigned = 0);
Mouse mouse(unsigned = 0);
struct Mouse {
const unsigned ID;
@ -220,12 +217,9 @@ struct Mouse {
Mouse(unsigned ID_) : ID(ID_) {}
};
inline Mouse& mouse(unsigned id) {
static Mouse ms0(0), ms1(1), ms2(2), ms3(3), ms4(4), ms5(5), ms6(6), ms7(7);
switch(id) { default:
case 0: return ms0; case 1: return ms1; case 2: return ms2; case 3: return ms3;
case 4: return ms4; case 5: return ms5; case 6: return ms6; case 7: return ms7;
}
inline Mouse mouse(unsigned id) {
assert(id < Mouse::Count);
return Mouse(id);
}
static const char JoypadScancodeName[][64] = {
@ -239,7 +233,7 @@ static const char JoypadScancodeName[][64] = {
};
struct Joypad;
Joypad& joypad(unsigned = 0);
Joypad joypad(unsigned = 0);
struct Joypad {
const unsigned ID;
@ -345,12 +339,9 @@ struct Joypad {
Joypad(unsigned ID_) : ID(ID_) {}
};
inline Joypad& joypad(unsigned id) {
static Joypad jp0(0), jp1(1), jp2(2), jp3(3), jp4(4), jp5(5), jp6(6), jp7(7);
switch(id) { default:
case 0: return jp0; case 1: return jp1; case 2: return jp2; case 3: return jp3;
case 4: return jp4; case 5: return jp5; case 6: return jp6; case 7: return jp7;
}
inline Joypad joypad(unsigned id) {
assert(id < Joypad::Count);
return Joypad(id);
}
struct Scancode {

View file

@ -11,7 +11,7 @@
namespace nall {
struct Keyboard;
Keyboard& keyboard(unsigned = 0);
Keyboard keyboard(unsigned = 0);
static const char KeyboardScancodeName[][64] = {
"Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
@ -122,12 +122,9 @@ struct Keyboard {
Keyboard(unsigned ID_) : ID(ID_) {}
};
inline Keyboard& keyboard(unsigned id) {
static Keyboard kb0(0), kb1(1), kb2(2), kb3(3), kb4(4), kb5(5), kb6(6), kb7(7);
switch(id) { default:
case 0: return kb0; case 1: return kb1; case 2: return kb2; case 3: return kb3;
case 4: return kb4; case 5: return kb5; case 6: return kb6; case 7: return kb7;
}
inline Keyboard keyboard(unsigned id) {
assert(id < Keyboard::Count);
return Keyboard(id);
}
static const char MouseScancodeName[][64] = {
@ -136,7 +133,7 @@ static const char MouseScancodeName[][64] = {
};
struct Mouse;
Mouse& mouse(unsigned = 0);
Mouse mouse(unsigned = 0);
struct Mouse {
const unsigned ID;
@ -220,12 +217,9 @@ struct Mouse {
Mouse(unsigned ID_) : ID(ID_) {}
};
inline Mouse& mouse(unsigned id) {
static Mouse ms0(0), ms1(1), ms2(2), ms3(3), ms4(4), ms5(5), ms6(6), ms7(7);
switch(id) { default:
case 0: return ms0; case 1: return ms1; case 2: return ms2; case 3: return ms3;
case 4: return ms4; case 5: return ms5; case 6: return ms6; case 7: return ms7;
}
inline Mouse mouse(unsigned id) {
assert(id < Mouse::Count);
return Mouse(id);
}
static const char JoypadScancodeName[][64] = {
@ -239,7 +233,7 @@ static const char JoypadScancodeName[][64] = {
};
struct Joypad;
Joypad& joypad(unsigned = 0);
Joypad joypad(unsigned = 0);
struct Joypad {
const unsigned ID;
@ -345,12 +339,9 @@ struct Joypad {
Joypad(unsigned ID_) : ID(ID_) {}
};
inline Joypad& joypad(unsigned id) {
static Joypad jp0(0), jp1(1), jp2(2), jp3(3), jp4(4), jp5(5), jp6(6), jp7(7);
switch(id) { default:
case 0: return jp0; case 1: return jp1; case 2: return jp2; case 3: return jp3;
case 4: return jp4; case 5: return jp5; case 6: return jp6; case 7: return jp7;
}
inline Joypad joypad(unsigned id) {
assert(id < Joypad::Count);
return Joypad(id);
}
struct Scancode {