mirror of https://github.com/bsnes-emu/bsnes.git
Update to bsnes v016 release.
- Added Direct3D renderer with options for disabling hardware filtering and scanlines - Screenshots can now be captured in BMP, JPEG, or PNG format - Added config file option to specify default ROM and SRAM paths - Config file is always loaded from path to bsnes executable - Added support for analog mode joypad input - Up to 32 joypads can be used at once now - Fixed bug regarding enabling interlace mid-frame - Moved PPU rendering to V=240, from V=0 - Started on new debugger. So far only debug messages and memory editor added - Added joypad axis resistance option for analog input mode - Added config file option to set window style attributes - Added color adjustment settings for brightness, contrast, gamma, and scanline intensity - Added grayscale, sepia, and invert color settings - Added NTSC filter by blargg, HQ2x filter by MaxSt, and Scale2x filter - PPU now renders scanline 224 - Revampled about box - Added Game Genie / PAR cheat code support + editor, saves codes to .cht files - HDMA channels are no longer disabled when starting DMA, fixes Dracula X [DMV27] - Fixes to OAM priority mode (not perfect), fixes Final Fantasy: Mystic Quest [DMV27] - Fixed ENDX sound bug, fixes voices in Earthworm Jim 2 [DMV27] - bsnes should now compile with MinGW [DMV27] - Added DSP-2 support - Added OBC-1 support - Major rewrite of SNES address bus mirroring and MMIO handlers - Many address mirroring corrections, fixes Dezaemon, etc - Blocked invalid (H)DMA transfers, fixes Kirby's Super Funhouse - Wrote Win32 API wrapper and ported all GUI code to use it, should help to create Linux GUI later on - Revampled input system, should lead to customizable GUI shortcut keys later on - Fixed numerous bugs with input registers. Fixes many games that previous had their intro cut off (Super Conflict, etc), and many that never accepted input (Super Double Dragon, etc) - Moved auto joypad strobing from V=225 to V=227 - Killed OAM table caching and window range caching, as they were actually hindering speed - Rewrote input configuration screen to show currently mapped keys - Greatly enhanced configuration options for each video profile - Modified fullscreen mode to exit to windowed mode when menu is activated, use F11 to toggle fullscreen mode - Fixed bugs in txs, wai, brk, cop, and rti opcodes [DMV27] - Fixed bug with emulation-mode IRQs [DMV27] - Initializing DMA registers to $ff [DMV27] - Memory writes now update CPU MDR register (open bus) [DMV27] - Improved ROM header detection, fixes Chou Jikuu Yousai Macross [DMV27] - Reading OAM no longer updates OAM latch - Writing to OAM high table no longer updates OAM latch - Writing CGRAM now updates CGRAM latch - Improved pseudo-hires rendering [blargg] - Much, much more
This commit is contained in:
parent
6b6233b3af
commit
a3945e5772
Binary file not shown.
|
@ -1,4 +1,4 @@
|
|||
#define BSNES_VERSION "0.015 rc3" //wip47
|
||||
#define BSNES_VERSION "0.016"
|
||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||
|
||||
#define MEMCORE bMemBus
|
||||
|
@ -7,9 +7,6 @@
|
|||
#define DSPCORE bDSP
|
||||
#define PPUCORE bPPU
|
||||
|
||||
//debugging extensions (~10% speed hit)
|
||||
#define DEBUGGER
|
||||
|
||||
//game genie + pro action replay code support (~1-3% speed hit)
|
||||
#define CHEAT_SYSTEM
|
||||
|
||||
|
@ -19,6 +16,9 @@
|
|||
//enable JMA support
|
||||
//#define JMA_SUPPORT
|
||||
|
||||
//debugging extensions (~10% speed hit)
|
||||
#define DEBUGGER
|
||||
|
||||
//snes core polymorphism
|
||||
//(allow mem/cpu/apu/ppu overriding, ~10% speed hit)
|
||||
//#define POLYMORPHISM
|
||||
|
|
|
@ -93,10 +93,15 @@ int32 score_lo = 0,
|
|||
uint16 cksum, icksum;
|
||||
cksum = rom[0x7fc0 + CKSUM] | (rom[0x7fc0 + CKSUM + 1] << 8);
|
||||
icksum = rom[0x7fc0 + ICKSUM] | (rom[0x7fc0 + ICKSUM + 1] << 8);
|
||||
if((cksum + icksum) == 0xffff)score_lo += 8;
|
||||
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
|
||||
score_lo += 8;
|
||||
}
|
||||
|
||||
cksum = rom[0xffc0 + CKSUM] | (rom[0xffc0 + CKSUM + 1] << 8);
|
||||
icksum = rom[0xffc0 + ICKSUM] | (rom[0xffc0 + ICKSUM + 1] << 8);
|
||||
if((cksum + icksum) == 0xffff)score_hi += 8;
|
||||
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
|
||||
score_hi += 8;
|
||||
}
|
||||
|
||||
if(rom_size < 0x401000) {
|
||||
score_ex = 0;
|
||||
|
|
|
@ -57,6 +57,7 @@ struct {
|
|||
void save_sram();
|
||||
void find_header();
|
||||
void read_header();
|
||||
bool loaded() { return cart_loaded; }
|
||||
bool load(const char *fn);
|
||||
bool unload();
|
||||
|
||||
|
|
|
@ -79,7 +79,9 @@ void bCPU::power() {
|
|||
|
||||
void bCPU::reset() {
|
||||
//reset vector location
|
||||
regs.pc = r_mem->read(0xfffc) | (r_mem->read(0xfffd) << 8);
|
||||
regs.pc.d = 0;
|
||||
regs.pc.l = r_mem->read(0xfffc);
|
||||
regs.pc.h = r_mem->read(0xfffd);
|
||||
|
||||
//registers are not fully reset by SNES
|
||||
regs.x.h = 0x00;
|
||||
|
@ -91,6 +93,9 @@ void bCPU::reset() {
|
|||
regs.e = 1;
|
||||
regs.mdr = 0x00;
|
||||
|
||||
//simulate pbr:pc push during reset irq vector
|
||||
regs.s.l -= 3;
|
||||
|
||||
time_reset();
|
||||
mmio_reset();
|
||||
dma_reset();
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
void bCPU::last_cycle() {
|
||||
time.nmi_pending = nmi_test();
|
||||
//DMV27: keep previous nmi value,
|
||||
//to allow wai and irq to work properly
|
||||
time.nmi_pending = nmi_test() || time.nmi_pending;
|
||||
time.irq_pending = irq_test();
|
||||
}
|
||||
|
||||
|
|
|
@ -13,18 +13,37 @@ void bCPU::irq_run() {
|
|||
//WDC documentation is incorrect, first cycle
|
||||
//is a memory read fetch from PBR:PC
|
||||
switch(status.cycle_pos++) {
|
||||
case 0: add_cycles(r_mem->speed(regs.pc.d)); break;
|
||||
case 1: add_cycles(6); break;
|
||||
case 2: stack_write(regs.pc.b); break;
|
||||
case 3: stack_write(regs.pc.h); break;
|
||||
case 4: stack_write(regs.pc.l); break;
|
||||
case 5: stack_write(regs.p); break;
|
||||
case 6: rd.l = op_read(OPMODE_ADDR, aa.w); break;
|
||||
case 7: rd.h = op_read(OPMODE_ADDR, aa.w + 1);
|
||||
case 0:
|
||||
//read from PBR:PC, but do not increment PC counter
|
||||
mem_read(regs.pc.d);
|
||||
break;
|
||||
case 1:
|
||||
cpu_io();
|
||||
if(regs.e)status.cycle_pos++;
|
||||
break;
|
||||
case 2:
|
||||
stack_write(regs.pc.b);
|
||||
break;
|
||||
case 3:
|
||||
stack_write(regs.pc.h);
|
||||
break;
|
||||
case 4:
|
||||
stack_write(regs.pc.l);
|
||||
break;
|
||||
case 5:
|
||||
//emulation-mode irqs clear brk bit 0x10
|
||||
stack_write((regs.e) ? (regs.p & ~0x10) : regs.p);
|
||||
break;
|
||||
case 6:
|
||||
//todo: test if NMI can override IRQ here...
|
||||
rd.l = op_read(OPMODE_ADDR, aa.w);
|
||||
regs.pc.b = 0x00;
|
||||
regs.pc.w = rd.w;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
break;
|
||||
case 7:
|
||||
rd.h = op_read(OPMODE_ADDR, aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
#ifdef DEBUGGER
|
||||
//let debugger know the new IRQ opcode address
|
||||
snes->notify(SNES::CPU_EXEC_OPCODE_END);
|
||||
|
|
|
@ -17,16 +17,16 @@ void bCPU::mmio_reset() {
|
|||
status.pio = 0xff;
|
||||
|
||||
//$4202-$4203
|
||||
status.mul_a = 0x00;
|
||||
status.mul_b = 0x00;
|
||||
status.mul_a = 0xff;
|
||||
status.mul_b = 0xff;
|
||||
|
||||
//$4204-$4206
|
||||
status.div_a = 0x0000;
|
||||
status.div_b = 0x00;
|
||||
status.div_a = 0xffff;
|
||||
status.div_b = 0xff;
|
||||
|
||||
//$4207-$420a
|
||||
status.hirq_pos = 0;
|
||||
status.virq_pos = 0;
|
||||
status.hirq_pos = 0x01ff;
|
||||
status.virq_pos = 0x01ff;
|
||||
|
||||
//$4214-$4217
|
||||
status.r4214 = 0x0000;
|
||||
|
@ -505,7 +505,6 @@ void bCPU::mmio_w420a(uint8 value) {
|
|||
|
||||
//DMAEN
|
||||
void bCPU::mmio_w420b(uint8 value) {
|
||||
int len;
|
||||
if(value != 0x00) {
|
||||
run_state.dma = true;
|
||||
status.dma_state = DMASTATE_DMASYNC;
|
||||
|
|
Binary file not shown.
|
@ -42,13 +42,13 @@ cop(0x02, 0xfff4, 0xfff5, 0xffe4, 0xffe5) {
|
|||
3:stack_write(regs.pc.h);
|
||||
4:stack_write(regs.pc.l);
|
||||
5:stack_write(regs.p);
|
||||
6:rd.l = op_read(OPMODE_LONG, (regs.e)?$1:$3);
|
||||
7:last_cycle();
|
||||
rd.h = op_read(OPMODE_LONG, (regs.e)?$2:$4);
|
||||
6:rd.l = op_read(OPMODE_LONG, (regs.e) ? $1 : $3);
|
||||
regs.pc.b = 0x00;
|
||||
regs.pc.w = rd.w;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
7:last_cycle();
|
||||
rd.h = op_read(OPMODE_LONG, (regs.e) ? $2 : $4);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
stp(0xdb) {
|
||||
|
@ -64,10 +64,16 @@ wai(0xcb) {
|
|||
run_state.wai = true;
|
||||
2:last_cycle();
|
||||
cpu_io();
|
||||
if(run_state.wai) {
|
||||
//this can be cleared within last_cycle()
|
||||
regs.pc.w--;
|
||||
}
|
||||
//no wakeup delay if last_cycle() cancelled wai
|
||||
if(run_state.wai == false)end;
|
||||
3:last_cycle();
|
||||
cpu_io();
|
||||
//sleep another i/o cycle
|
||||
//note: this should alert the debugger that wai is continuing...
|
||||
if(run_state.wai == true)status.cycle_pos--;
|
||||
//wai wakeup delay (one i/o cycle)
|
||||
4:last_cycle();
|
||||
cpu_io();
|
||||
}
|
||||
|
||||
xce(0xfb) {
|
||||
|
@ -183,12 +189,8 @@ txs(0x9a) {
|
|||
cpu_io();
|
||||
if(regs.e) {
|
||||
regs.s.l = regs.x.l;
|
||||
regs.p.n = !!(regs.s.l & 0x80);
|
||||
regs.p.z = (regs.s.l == 0);
|
||||
} else {
|
||||
regs.s.w = regs.x.w;
|
||||
regs.p.n = !!(regs.s.w & 0x8000);
|
||||
regs.p.z = (regs.s.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -113,15 +113,15 @@ void bCPU::op_brk() {
|
|||
stack_write(regs.p);
|
||||
} break;
|
||||
case 6: {
|
||||
rd.l = op_read(OPMODE_LONG, (regs.e)?0xfffe:0xffe6);
|
||||
rd.l = op_read(OPMODE_LONG, (regs.e) ? 0xfffe : 0xffe6);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
rd.h = op_read(OPMODE_LONG, (regs.e)?0xffff:0xffe7);
|
||||
regs.pc.b = 0x00;
|
||||
rd.h = op_read(OPMODE_LONG, (regs.e) ? 0xffff : 0xffe7);
|
||||
regs.pc.w = rd.w;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
|
@ -146,15 +146,15 @@ void bCPU::op_cop() {
|
|||
stack_write(regs.p);
|
||||
} break;
|
||||
case 6: {
|
||||
rd.l = op_read(OPMODE_LONG, (regs.e)?0xfff4:0xffe4);
|
||||
rd.l = op_read(OPMODE_LONG, (regs.e) ? 0xfff4 : 0xffe4);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
rd.h = op_read(OPMODE_LONG, (regs.e)?0xfff5:0xffe5);
|
||||
regs.pc.b = 0x00;
|
||||
rd.h = op_read(OPMODE_LONG, (regs.e) ? 0xfff5 : 0xffe5);
|
||||
regs.pc.w = rd.w;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
|
@ -184,10 +184,20 @@ void bCPU::op_wai() {
|
|||
case 2: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(run_state.wai) {
|
||||
//this can be cleared within last_cycle()
|
||||
regs.pc.w--;
|
||||
}
|
||||
//no wakeup delay if last_cycle() cancelled wai
|
||||
if(run_state.wai == false)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
//sleep another i/o cycle
|
||||
//note: this should alert the debugger that wai is continuing...
|
||||
if(run_state.wai == true)status.cycle_pos--;
|
||||
//wai wakeup delay (one i/o cycle)
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
|
@ -523,12 +533,8 @@ void bCPU::op_txs() {
|
|||
cpu_io();
|
||||
if(regs.e) {
|
||||
regs.s.l = regs.x.l;
|
||||
regs.p.n = !!(regs.s.l & 0x80);
|
||||
regs.p.z = (regs.s.l == 0);
|
||||
} else {
|
||||
regs.s.w = regs.x.w;
|
||||
regs.p.n = !!(regs.s.w & 0x8000);
|
||||
regs.p.z = (regs.s.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
|
|
|
@ -126,7 +126,8 @@ rti(0x40) {
|
|||
regs.y.h = 0x00;
|
||||
}
|
||||
4:rd.l = stack_read();
|
||||
5:rd.h = stack_read();
|
||||
5:if(regs.e)last_cycle();
|
||||
rd.h = stack_read();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
end;
|
||||
|
|
|
@ -417,6 +417,7 @@ void bCPU::op_rti() {
|
|||
rd.l = stack_read();
|
||||
} break;
|
||||
case 5: {
|
||||
if(regs.e)last_cycle();
|
||||
rd.h = stack_read();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
|
|
|
@ -233,25 +233,31 @@ void bCPU::hdma_activate() {
|
|||
}
|
||||
|
||||
void bCPU::dma_reset() {
|
||||
status.dma_state = DMASTATE_CPUSYNC;
|
||||
status.hdma_state = HDMASTATE_CPUSYNC;
|
||||
status.dma_cycle_count = 0;
|
||||
status.hdma_cycle_count = 0;
|
||||
|
||||
for(int i = 0; i < 8; i++) {
|
||||
channel[i].read_index = 0;
|
||||
channel[i].active = false;
|
||||
channel[i].hdma_enabled = false;
|
||||
channel[i].dmap = 0x00;
|
||||
channel[i].direction = 0;
|
||||
channel[i].hdma_indirect = false;
|
||||
channel[i].incmode = 1;
|
||||
channel[i].fixedxfer = false;
|
||||
channel[i].xfermode = 0;
|
||||
channel[i].destaddr = 0;
|
||||
channel[i].srcaddr = 0;
|
||||
channel[i].xfersize = 0x0000;
|
||||
channel[i].dmap = 0xff;
|
||||
channel[i].direction = 1;
|
||||
channel[i].hdma_indirect = 1;
|
||||
channel[i].incmode = -1;
|
||||
channel[i].fixedxfer = 1;
|
||||
channel[i].xfermode = 7;
|
||||
channel[i].destaddr = 0xff;
|
||||
channel[i].srcaddr = 0xffff;
|
||||
channel[i].srcbank = 0xff;
|
||||
channel[i].xfersize = 0xffff;
|
||||
//xfersize and hdma_iaddr are of union { uint16 };
|
||||
//channel[i].hdma_iaddr = 0x0000;
|
||||
channel[i].hdma_ibank = 0;
|
||||
channel[i].hdma_addr = 0x0000;
|
||||
channel[i].hdma_line_counter = 0x00;
|
||||
channel[i].hdma_unknown = 0x00;
|
||||
//channel[i].hdma_iaddr = 0xffff;
|
||||
channel[i].hdma_ibank = 0xff;
|
||||
channel[i].hdma_addr = 0xffff;
|
||||
channel[i].hdma_line_counter = 0xff;
|
||||
channel[i].hdma_unknown = 0xff;
|
||||
|
||||
channel[i].hdma_active = false;
|
||||
channel[i].hdma_do_transfer = false;
|
||||
|
|
|
@ -34,6 +34,7 @@ void bCPU::mem_write(uint32 addr, uint8 value) {
|
|||
status.cycle_count = r_mem->speed(addr);
|
||||
pre_exec_cycle();
|
||||
add_cycles(status.cycle_count);
|
||||
regs.mdr = value;
|
||||
r_mem->write(addr, value);
|
||||
cycle_edge();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "libbase.h"
|
||||
#include "libwin32.h"
|
||||
|
||||
#include "libwin32_misc.cpp"
|
||||
#include "libwin32_file.cpp"
|
||||
#include "libwin32_window.cpp"
|
||||
#include "libwin32_control.cpp"
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
#include "libstring.h"
|
||||
|
||||
#define WINVER 0x0501
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#define WINVER 0x0400
|
||||
#define _WIN32_WINNT 0x0400
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <direct.h>
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef WS_EX_LAYERED
|
||||
#define WS_EX_LAYERED 0x00080000
|
||||
#endif
|
||||
|
||||
typedef BOOL (WINAPI *SLWAProc)(HWND hwnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags);
|
||||
|
||||
#ifndef LWA_COLORKEY
|
||||
#define LWA_COLORKEY 0x00000001
|
||||
#endif
|
||||
|
||||
#ifndef LWA_ALPHA
|
||||
#define LWA_ALPHA 0x0000002
|
||||
#endif
|
||||
|
||||
BOOL SetWindowAlphaLevel(HWND hwnd, uint level) {
|
||||
SLWAProc pSLWA;
|
||||
HMODULE handle = GetModuleHandle("USER32.DLL");
|
||||
BOOL result;
|
||||
if(!handle)return FALSE;
|
||||
pSLWA = (SLWAProc)GetProcAddress(handle, (char*)"SetLayeredWindowAttributes");
|
||||
if(pSLWA == 0)return FALSE;
|
||||
|
||||
level &= 255;
|
||||
if(level != 255) {
|
||||
SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
|
||||
result = pSLWA(hwnd, 0, level, LWA_ALPHA);
|
||||
} else {
|
||||
SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED);
|
||||
result = pSLWA(hwnd, 0, 0, 0);
|
||||
}
|
||||
InvalidateRect(hwnd, 0, TRUE);
|
||||
return result;
|
||||
}
|
|
@ -291,15 +291,11 @@ string part;
|
|||
void Window::SetAlphaLevel(uint level) {
|
||||
level &= 255;
|
||||
if(level == 255) {
|
||||
//no reason to use layered attribute for completely opaque window
|
||||
state.es &= ~WS_EX_LAYERED;
|
||||
SetWindowLong(hwnd, GWL_EXSTYLE, state.es);
|
||||
SetLayeredWindowAttributes(hwnd, 0, 0, 0);
|
||||
} else {
|
||||
state.es |= WS_EX_LAYERED;
|
||||
SetWindowLong(hwnd, GWL_EXSTYLE, state.es);
|
||||
SetLayeredWindowAttributes(hwnd, 0, level, LWA_ALPHA);
|
||||
}
|
||||
SetWindowAlphaLevel(hwnd, level);
|
||||
}
|
||||
|
||||
void Window::SetBackgroundColor(uint r, uint g, uint b) {
|
||||
|
|
|
@ -123,10 +123,12 @@ void bPPU::reset() {
|
|||
//$2102-$2103
|
||||
regs.oam_baseaddr = 0x0000;
|
||||
regs.oam_addr = 0x0000;
|
||||
regs.oam_latchdata = 0x00;
|
||||
regs.oam_priority = false;
|
||||
regs.oam_firstsprite = 0x00;
|
||||
|
||||
//$2104
|
||||
regs.oam_latchdata = 0x00;
|
||||
|
||||
//$2105
|
||||
regs.bg_tilesize[BG1] = 0;
|
||||
regs.bg_tilesize[BG2] = 0;
|
||||
|
@ -193,6 +195,9 @@ void bPPU::reset() {
|
|||
//$2121
|
||||
regs.cgram_addr = 0x0000;
|
||||
|
||||
//$2122
|
||||
regs.cgram_latchdata = 0x00;
|
||||
|
||||
//$2123-$2125
|
||||
regs.window1_enabled[BG1] = false;
|
||||
regs.window1_enabled[BG2] = false;
|
||||
|
|
|
@ -33,10 +33,12 @@ struct {
|
|||
//$2102-$2103
|
||||
uint16 oam_baseaddr;
|
||||
uint16 oam_addr;
|
||||
uint8 oam_latchdata;
|
||||
bool oam_priority;
|
||||
uint8 oam_firstsprite;
|
||||
|
||||
//$2104
|
||||
uint8 oam_latchdata;
|
||||
|
||||
//$2105
|
||||
bool bg_tilesize[4];
|
||||
bool bg3_priority;
|
||||
|
@ -81,6 +83,9 @@ struct {
|
|||
//$2121
|
||||
uint16 cgram_addr;
|
||||
|
||||
//$2122
|
||||
uint8 cgram_latchdata;
|
||||
|
||||
//$2123-$2125
|
||||
bool window1_enabled[6];
|
||||
bool window1_invert [6];
|
||||
|
|
|
@ -94,15 +94,16 @@ void bPPU::mmio_w2103(uint8 value) {
|
|||
//OAMDATA
|
||||
void bPPU::mmio_w2104(uint8 value) {
|
||||
if(regs.oam_addr >= 0x0200) {
|
||||
if(!(regs.oam_addr & 1)) {
|
||||
regs.oam_latchdata = value;
|
||||
}
|
||||
//does this happen?
|
||||
//if(!(regs.oam_addr & 1)) {
|
||||
// regs.oam_latchdata = value;
|
||||
//}
|
||||
oam_write(regs.oam_addr, value);
|
||||
} else if(!(regs.oam_addr & 1)) {
|
||||
regs.oam_latchdata = value;
|
||||
} else {
|
||||
oam_write((regs.oam_addr & 0x03fe), regs.oam_latchdata);
|
||||
oam_write((regs.oam_addr & 0x03fe) + 1, value);
|
||||
oam_write((regs.oam_addr & 0x01fe), regs.oam_latchdata);
|
||||
oam_write((regs.oam_addr & 0x01fe) + 1, value);
|
||||
}
|
||||
regs.oam_addr++;
|
||||
regs.oam_addr &= 0x03ff;
|
||||
|
@ -336,11 +337,17 @@ void bPPU::mmio_w2121(uint8 value) {
|
|||
//note: CGRAM palette data format is 15-bits
|
||||
//(0,bbbbb,ggggg,rrrrr). Highest bit is ignored,
|
||||
//as evidenced by $213b CGRAM data reads.
|
||||
//
|
||||
//anomie indicates writes to CGDATA work the same
|
||||
//as writes to OAMDATA's low table. need to verify
|
||||
//this on hardware.
|
||||
void bPPU::mmio_w2122(uint8 value) {
|
||||
if(regs.cgram_addr & 1) {
|
||||
value &= 0x7f;
|
||||
if(!(regs.cgram_addr & 1)) {
|
||||
regs.cgram_latchdata = value;
|
||||
} else {
|
||||
cgram_write((regs.cgram_addr & 0x01fe), regs.cgram_latchdata);
|
||||
cgram_write((regs.cgram_addr & 0x01fe) + 1, value & 0x7f);
|
||||
}
|
||||
cgram_write(regs.cgram_addr, value);
|
||||
regs.cgram_addr++;
|
||||
regs.cgram_addr &= 0x01ff;
|
||||
}
|
||||
|
@ -526,9 +533,12 @@ uint8 bPPU::mmio_r2137() {
|
|||
//OAMDATAREAD
|
||||
uint8 bPPU::mmio_r2138() {
|
||||
regs.ppu1_mdr = oam_read(regs.oam_addr);
|
||||
if(!(regs.oam_addr & 1)) {
|
||||
regs.oam_latchdata = regs.ppu1_mdr;
|
||||
}
|
||||
//DMV27: OAM writes do not affect latch data
|
||||
//byuu: Even if they do, this should only affect the low table
|
||||
//byuu: Disable for now, see what happens... test on hardware
|
||||
//if(!(regs.oam_addr & 1)) {
|
||||
// regs.oam_latchdata = regs.ppu1_mdr;
|
||||
//}
|
||||
regs.oam_addr++;
|
||||
regs.oam_addr &= 0x03ff;
|
||||
return regs.ppu1_mdr;
|
||||
|
|
|
@ -4,14 +4,14 @@ CFLAGS = -O3 -fomit-frame-pointer -ffast-math
|
|||
CXXFLAGS = $(CFLAGS) -fno-rtti
|
||||
OBJS = sdlmain.o \
|
||||
libstring.o libconfig.o libbpf.o \
|
||||
reader.o cart.o \
|
||||
reader.o cart.o cheat.o \
|
||||
memory.o bmemory.o \
|
||||
cpu.o bcpu.o \
|
||||
apu.o bapu.o \
|
||||
bdsp.o \
|
||||
ppu.o bppu.o \
|
||||
snes.o \
|
||||
srtc.o sdd1.o c4.o \
|
||||
srtc.o sdd1.o c4.o dsp2.o obc1.o \
|
||||
adler32.o compress.o crc32.o deflate.o gzio.o inffast.o \
|
||||
inflate.o inftrees.o ioapi.o trees.o unzip.o zip.o zutil.o \
|
||||
jma.o jcrc32.o lzmadec.o 7zlzma.o iiostrm.o inbyte.o lzma.o winout.o
|
||||
|
@ -89,6 +89,9 @@ reader.o: ../reader/*.cpp ../reader/*.h
|
|||
cart.o: ../cart/*.cpp ../cart/*.h
|
||||
$(CXX) $(CXXFLAGS) -c ../cart/cart.cpp
|
||||
|
||||
cheat.o: ../cheat/*.cpp ../cheat/*.h
|
||||
$(CXX) $(CXXFLAGS) -c ../cheat/cheat.cpp
|
||||
|
||||
############
|
||||
### snes ###
|
||||
############
|
||||
|
@ -107,6 +110,12 @@ sdd1.o: ../chip/sdd1/*.cpp ../chip/sdd1/*.h
|
|||
c4.o: ../chip/c4/*.cpp ../chip/c4/*.h
|
||||
$(CXX) $(CXXFLAGS) -c ../chip/c4/c4.cpp
|
||||
|
||||
dsp2.o: ../chip/dsp2/*.cpp ../chip/dsp2/*.h
|
||||
$(CXX) $(CXXFLAGS) -c ../chip/dsp2/dsp2.cpp
|
||||
|
||||
obc1.o: ../chip/obc1/*.cpp ../chip/obc1/*.h
|
||||
$(CXX) $(CXXFLAGS) -c ../chip/obc1/obc1.cpp
|
||||
|
||||
############
|
||||
### zlib ###
|
||||
############
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
# Default path to look for ROM files in ("" = use default directory)
|
||||
# (default = "")
|
||||
fs.rom_path = ""
|
||||
|
||||
# Default path for all save RAM files ("" = use current directory)
|
||||
# (default = "")
|
||||
fs.sram_path = ""
|
||||
|
||||
# Extension to be used for all save RAM files
|
||||
# (default = "srm")
|
||||
fs.sram_ext = "srm"
|
||||
|
||||
# Applies contrast adjust filter to video output when enabled
|
||||
# Works by lowering the brightness of darker colors,
|
||||
# while leaving brighter colors alone; thus reducing saturation
|
||||
# (default = true)
|
||||
snes.video_color_curve = true
|
||||
|
||||
# Selects color adjustment filter for video output
|
||||
# 0 = Normal (no filter, rgb555)
|
||||
# 1 = Grayscale mode (l5)
|
||||
# 2 = VGA mode (rgb332)
|
||||
# 3 = Genesis mode (rgb333)
|
||||
# (default = 0)
|
||||
snes.video_color_adjust_mode = 0
|
||||
|
||||
# Mutes SNES audio output when enabled
|
||||
# (default = false)
|
||||
snes.mute = true
|
||||
|
||||
# Enable fullscreen mode at startup
|
||||
# (default = false)
|
||||
video.fullscreen = false
|
||||
|
||||
# Window / Fullscreen width
|
||||
# (default = 320)
|
||||
video.display_width = 320
|
||||
|
||||
# Window / Fullscreen height
|
||||
# (default = 240)
|
||||
video.display_height = 240
|
||||
|
||||
# SNES video output width
|
||||
# (default = 256)
|
||||
video.output_width = 256
|
||||
|
||||
# SNES video output height
|
||||
# (default = 223)
|
||||
video.output_height = 223
|
||||
|
||||
# Joypad1 up
|
||||
# (default = 0x111)
|
||||
input.joypad1.up = 0x111
|
||||
|
||||
# Joypad1 down
|
||||
# (default = 0x112)
|
||||
input.joypad1.down = 0x112
|
||||
|
||||
# Joypad1 left
|
||||
# (default = 0x114)
|
||||
input.joypad1.left = 0x114
|
||||
|
||||
# Joypad1 right
|
||||
# (default = 0x113)
|
||||
input.joypad1.right = 0x113
|
||||
|
||||
# Joypad1 A
|
||||
# (default = 0x78)
|
||||
input.joypad1.a = 0x78
|
||||
|
||||
# Joypad1 B
|
||||
# (default = 0x7a)
|
||||
input.joypad1.b = 0x7a
|
||||
|
||||
# Joypad1 X
|
||||
# (default = 0x73)
|
||||
input.joypad1.x = 0x73
|
||||
|
||||
# Joypad1 Y
|
||||
# (default = 0x61)
|
||||
input.joypad1.y = 0x61
|
||||
|
||||
# Joypad1 L
|
||||
# (default = 0x64)
|
||||
input.joypad1.l = 0x64
|
||||
|
||||
# Joypad1 R
|
||||
# (default = 0x63)
|
||||
input.joypad1.r = 0x63
|
||||
|
||||
# Joypad1 select
|
||||
# (default = 0x12f)
|
||||
input.joypad1.select = 0x12f
|
||||
|
||||
# Joypad1 start
|
||||
# (default = 0xd)
|
||||
input.joypad1.start = 0xd
|
||||
|
|
@ -97,7 +97,7 @@ string dir;
|
|||
|
||||
if(!GetOpenFileName(&ofn))return;
|
||||
|
||||
cartridge.unload();
|
||||
if(cartridge.loaded() == true)cartridge.unload();
|
||||
wDebug.Clear();
|
||||
|
||||
cartridge.load(t);
|
||||
|
@ -107,6 +107,8 @@ string dir;
|
|||
}
|
||||
|
||||
void unload_rom() {
|
||||
if(cartridge.loaded() == false)return;
|
||||
|
||||
cartridge.unload();
|
||||
uiVideo->clear_video();
|
||||
uiAudio->clear_audio();
|
||||
|
|
|
@ -103,7 +103,7 @@ MSG msg;
|
|||
}
|
||||
|
||||
_end:
|
||||
cartridge.unload();
|
||||
if(cartridge.loaded() == true)cartridge.unload();
|
||||
|
||||
term_ui();
|
||||
term_snes();
|
||||
|
|
|
@ -62,6 +62,7 @@ MENU_SETTINGS,
|
|||
MENU_MISC,
|
||||
MENU_MISC_SCREENSHOT,
|
||||
MENU_MISC_LOGAUDIO,
|
||||
MENU_MISC_CHEATEDITOR,
|
||||
//---
|
||||
MENU_MISC_ABOUT,
|
||||
};
|
||||
|
|
|
@ -132,13 +132,17 @@ bool MainWindow::Event(EventInfo &info) {
|
|||
} break;
|
||||
|
||||
case MENU_FILE_RESET: {
|
||||
bsnes->reset();
|
||||
dprintf("* Reset");
|
||||
if(cartridge.loaded() == true) {
|
||||
bsnes->reset();
|
||||
dprintf("* Reset");
|
||||
}
|
||||
} break;
|
||||
|
||||
case MENU_FILE_POWER: {
|
||||
bsnes->power();
|
||||
dprintf("* Power");
|
||||
if(cartridge.loaded() == true) {
|
||||
bsnes->power();
|
||||
dprintf("* Power");
|
||||
}
|
||||
} break;
|
||||
|
||||
case MENU_FILE_EXIT: {
|
||||
|
@ -217,6 +221,11 @@ bool MainWindow::Event(EventInfo &info) {
|
|||
}
|
||||
} break;
|
||||
|
||||
case MENU_MISC_CHEATEDITOR: {
|
||||
settings.set_active_panel(&wCheatEditor);
|
||||
wSettings.Show();
|
||||
} break;
|
||||
|
||||
case MENU_MISC_ABOUT: {
|
||||
wAbout.Show();
|
||||
} break;
|
||||
|
@ -303,8 +312,9 @@ char t[128];
|
|||
EndMenuGroup();
|
||||
|
||||
AddMenuGroup("&Misc");
|
||||
AddMenuItem(MENU_MISC_SCREENSHOT, "&Capture Screenshot");
|
||||
AddMenuItem(MENU_MISC_LOGAUDIO, "&Log Audio Data");
|
||||
AddMenuItem(MENU_MISC_SCREENSHOT, "Capture &Screenshot");
|
||||
AddMenuItem(MENU_MISC_LOGAUDIO, "&Log Audio Data");
|
||||
AddMenuItem(MENU_MISC_CHEATEDITOR, "&Cheat Code Editor");
|
||||
AddMenuSeparator();
|
||||
AddMenuItem(MENU_MISC_ABOUT, "&About");
|
||||
EndMenuGroup();
|
||||
|
|
Loading…
Reference in New Issue