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:
byuu 2006-04-25 15:51:10 +00:00
parent 6b6233b3af
commit a3945e5772
28 changed files with 219 additions and 197 deletions

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

33
src/lib/libwin32_misc.cpp Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -103,7 +103,7 @@ MSG msg;
}
_end:
cartridge.unload();
if(cartridge.loaded() == true)cartridge.unload();
term_ui();
term_snes();

View File

@ -62,6 +62,7 @@ MENU_SETTINGS,
MENU_MISC,
MENU_MISC_SCREENSHOT,
MENU_MISC_LOGAUDIO,
MENU_MISC_CHEATEDITOR,
//---
MENU_MISC_ABOUT,
};

View File

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