Update to bsnes v025 release.

bsnes is exactly three years old today. I've posted a new version which adds DSP-3 and DSP-4 special chip support. The DSP-3 is used by SD Gundam GX, and the DSP-4 is used by Top Gear 3000. Please note that the DSP-3 is not fully emulated, thusly SD Gundam GX is not fully playable. Also, due to lack of timing emulation with the DSP-4, the Top Gear 3000 track sometimes flickers in split screen mode. However, it is believed that Top Gear 3000 is fully playable.
I should also note that I have started on SuperFX emulation, as some will inevitably see said code in my source releases. What I have now is nothing more than a skeleton implementation, and absolutely nothing using it is playable yet. I am making absolutely no promises that I will ever be able to emulate this chip. It will take at least several months of work, and even then, the speed will probably be too slow to reach 60fps on any system, but ... I'm working on it. While I have no way to run tests on the actual SuperFX hardware, I will do the best I can to emulate the chip accurately. I will be emulating the caching and cycle delays as best I can, but the information I have on this chip is extremely limited, so don't expect miracles.
Lastly, as promised, I have released the special chips I have personally emulated to the public domain. See license.txt for more information if interested. I cannot release the special chips whose code I did not write to the public domain, but all of that is already available under the GPLv2 (from ZSNES) or the SNES9x license.
Changelog:
    - Added DSP-3 support, thanks to John Weidman, Kris Bleakley, Lancer, z80 gaiden
    - Added DSP-4 support, thanks to Dreamer Nom, John Weidman, Kris Bleakley, Nach, z80 gaiden
    - Started on support for SuperFX, no games playable as chip emulation is less than 1% complete
    - Unsupported special chips will now display an alert
    - Missing stbios.bin file when loading Sufami Turbo cartridges will now display an alert
    - Video settings now saved separately for windowed and fullscreen mode
    - Advanced option video<.mode>.synchronize can be enabled for vsync, but will cause sound crackling
    - Added menu option to toggle FPS counter
    - Minor source code cleanup
This commit is contained in:
byuu 2007-10-15 10:03:36 +00:00
parent d1fcddee9c
commit 85fa3cc968
68 changed files with 4425 additions and 307 deletions

BIN
cart.db

Binary file not shown.

View File

@ -52,12 +52,35 @@ Further, respective source code files are labeled with their correct licensing
information in the header. The lack of such a header indicates said file falls
under the bsnes license.
HQ2x Filter, author: MaxST, license: LGPL
JMA, author: NSRT Team, license: GPL (*)
libco, author: byuu, license: public domain
libui, author: byuu, license: public domain
NTSC Filter, author: blargg, license: LGPL
S-DD1, author: Andreas Naive, license: public domain
zlib, license: zlib license
HQ2x filter, author: MaxST, license: LGPL
JMA decompressor, author: NSRT Team, license: GPL (*)
NTSC filter, author: blargg, license: LGPL
zlib decompressor, license: zlib license
(*) bsnes has received an exemption from the copyright holder to use this work.
The software also includes works which have been released to the public domain,
which are not bound to any licensing agreements. Below is a complete list of all
such software.
libco, author: byuu
libui, author: byuu
OBC-1 emu, author: byuu
S-DD1 emu, author: Andreas Naive
S-RTC emu, author: byuu
Any software listed above as exemptions may be relicensed individually from
bsnes under their respective terms. However, no bsnes licensed portions can be
combined with such a derivative work.
The software also includes the work of other copyright holders, which is
licensed under the terms of the bsnes license, with permission to do so from the
respective authors. Below is a complete list of all such software.
Cx4 emu, authors: anomie, Overload, zsKnight, Nach
DSP-1 emu, authors: Overload, John Weidman, Neviksti, Andreas Naive
DSP-2 emu, author: Overload
DSP-3 emu, authors: John Weidman, Kris Bleakley, Lancer, z80 gaiden
DSP-4 emu, authors: Dreamer Nom, John Weidman, Kris Bleakley, Nach, z80 gaiden
S-DSP emu, author: blargg
ST-010 emu, authors: John Weidman, Matthew Kendora, Overload, Feather

View File

@ -1,5 +1,5 @@
bsnes
Version 0.024
Version 0.025
Author: byuu
--------
@ -17,7 +17,7 @@ Please see license.txt for important licensing information.
Shortcut Keys:
--------------
Esc - Toggle menubar visibility
F11 - Toggle fullscreen
F11 - Toggle fullscreen mode
------------------
Known Limitations:
@ -66,16 +66,10 @@ Coprocessor used only by the following games:
- Momotarou Densetsu Happy
- Super Power League 4
DSP-3
Coprocessor used only by SD Gundam GX
DSP-4
Coprocessor used only by Top Gear 3000
ST011
ST-011
SETA DSP used only by Quick-move Shogi Match with Nidan Rank-holder Morita
ST018
ST-018
SETA RISC CPU used only by Quick-move Shogi Match with Nidan Rank-holder Morita 2
BS-X (Broadcast Satellite)

View File

@ -81,7 +81,7 @@ endif
ifeq ($(PLATFORM),win-mingw4-lui)
OS = win
CC = mingw32-gcc-sjlj
CFLAGS = -mwindows -O3 -fomit-frame-pointer -DPLATFORM_WIN -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI
CFLAGS = -mconsole -O3 -fomit-frame-pointer -DPLATFORM_WIN -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI
AS = nasm
ASFLAGS = -f win32 -DWIN32
LIBS = -ld3d9 -lddraw -ldsound -ldinput8 -ldxguid -luuid -lkernel32 -luser32 -lgdi32 -lshell32 -lwinmm -lcomdlg32 -lcomctl32
@ -154,8 +154,8 @@ OBJECTS = main.$(OBJ) $(LIBCO).$(OBJ) $(LIBUI).$(OBJ) \
libstring.$(OBJ) \
reader.$(OBJ) cart.$(OBJ) cheat.$(OBJ) memory.$(OBJ) bmemory.$(OBJ) \
cpu.$(OBJ) scpu.$(OBJ) smp.$(OBJ) ssmp.$(OBJ) bdsp.$(OBJ) ppu.$(OBJ) \
bppu.$(OBJ) snes.$(OBJ) srtc.$(OBJ) sdd1.$(OBJ) c4.$(OBJ) dsp1.$(OBJ) \
dsp2.$(OBJ) obc1.$(OBJ) st010.$(OBJ)
bppu.$(OBJ) snes.$(OBJ) superfx.$(OBJ) srtc.$(OBJ) sdd1.$(OBJ) c4.$(OBJ) \
dsp1.$(OBJ) dsp2.$(OBJ) dsp3.$(OBJ) dsp4.$(OBJ) obc1.$(OBJ) st010.$(OBJ)
ifeq ($(GZIP_SUPPORT),true)
OBJECTS += adler32.$(OBJ) compress.$(OBJ) crc32.$(OBJ) deflate.$(OBJ) \
@ -259,13 +259,16 @@ snes.$(OBJ): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* sne
#####################
### special chips ###
#####################
srtc.$(OBJ) : chip/srtc/srtc.cpp chip/srtc/*
sdd1.$(OBJ) : chip/sdd1/sdd1.cpp chip/sdd1/*
c4.$(OBJ) : chip/c4/c4.cpp chip/c4/*
dsp1.$(OBJ) : chip/dsp1/dsp1.cpp chip/dsp1/*
dsp2.$(OBJ) : chip/dsp2/dsp2.cpp chip/dsp2/*
obc1.$(OBJ) : chip/obc1/obc1.cpp chip/obc1/*
st010.$(OBJ): chip/st010/st010.cpp chip/st010/*
superfx.$(OBJ): chip/superfx/superfx.cpp chip/superfx/* chip/superfx/core/* chip/superfx/memory/*
srtc.$(OBJ) : chip/srtc/srtc.cpp chip/srtc/*
sdd1.$(OBJ) : chip/sdd1/sdd1.cpp chip/sdd1/*
c4.$(OBJ) : chip/c4/c4.cpp chip/c4/*
dsp1.$(OBJ) : chip/dsp1/dsp1.cpp chip/dsp1/*
dsp2.$(OBJ) : chip/dsp2/dsp2.cpp chip/dsp2/*
dsp3.$(OBJ) : chip/dsp3/dsp3.cpp chip/dsp3/*
dsp4.$(OBJ) : chip/dsp4/dsp4.cpp chip/dsp4/*
obc1.$(OBJ) : chip/obc1/obc1.cpp chip/obc1/*
st010.$(OBJ) : chip/st010/st010.cpp chip/st010/*
############
### zlib ###

View File

@ -1,4 +1,4 @@
#define BSNES_VERSION "0.024"
#define BSNES_VERSION "0.025"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
#define MEMCORE bMemBus

View File

@ -10,18 +10,24 @@
Cartridge cartridge;
void Cartridge::load_begin(uint cart_type) {
void Cartridge::load_begin(CartridgeType cart_type) {
if(loaded() == true)return;
info.type = cart_type;
info.srtc = false;
info.sdd1 = false;
info.c4 = false;
info.dsp1 = false;
info.dsp2 = false;
info.obc1 = false;
info.st010 = false;
info.superfx = false;
info.sa1 = false;
info.srtc = false;
info.sdd1 = false;
info.c4 = false;
info.dsp1 = false;
info.dsp2 = false;
info.dsp3 = false;
info.dsp4 = false;
info.obc1 = false;
info.st010 = false;
info.st011 = false;
info.st018 = false;
info.dsp1_mapper = 0;
@ -30,7 +36,6 @@ void Cartridge::load_begin(uint cart_type) {
strcpy(info.name, "");
strcpy(info.pcb, "");
info.region = NTSC;
info.cart_mmio = false;
info.rom_size = 0;
info.ram_size = 0;
@ -93,15 +98,15 @@ bool Cartridge::load_end() {
}
switch(info.type) {
case CART_NORMAL: {
case CartridgeNormal: {
load_rom_normal();
load_ram_normal();
} break;
case CART_ST: {
case CartridgeSufamiTurbo: {
load_rom_st();
load_ram_st();
} break;
case CART_STDUAL: {
case CartridgeSufamiTurboDual: {
load_rom_stdual();
load_ram_stdual();
} break;
@ -118,13 +123,13 @@ bool Cartridge::unload() {
r_mem->unload_cart();
switch(info.type) {
case CART_NORMAL: {
case CartridgeNormal: {
save_ram_normal();
} break;
case CART_ST: {
case CartridgeSufamiTurbo: {
save_ram_st();
} break;
case CART_STDUAL: {
case CartridgeSufamiTurboDual: {
save_ram_stdual();
} break;
}

View File

@ -15,10 +15,10 @@ db_item dbi;
//
enum {
CART_NORMAL,
CART_ST,
CART_STDUAL,
enum CartridgeType {
CartridgeNormal,
CartridgeSufamiTurbo,
CartridgeSufamiTurboDual,
};
bool cart_loaded;
@ -33,7 +33,7 @@ enum {
ROM_SIZE = 0x17,
RAM_SIZE = 0x18,
REGION = 0x19,
LICENSE = 0x1a,
COMPANY = 0x1a,
VERSION = 0x1b,
ICKSUM = 0x1c,
CKSUM = 0x1e,
@ -78,16 +78,19 @@ struct {
uint rom_size;
uint ram_size;
//set to true for games that need cart MMIO mapping (c4, dsp-n, ...),
//for games that map outside the standard MMIO range of $2000-$5fff
bool cart_mmio;
bool superfx;
bool sa1;
bool srtc;
bool sdd1;
bool c4;
bool dsp1;
bool dsp2;
bool dsp3;
bool dsp4;
bool obc1;
bool st010;
bool st011;
bool st018;
uint dsp1_mapper;
@ -114,7 +117,7 @@ struct {
void read_header();
bool loaded() { return cart_loaded; }
void load_begin(uint cart_type);
void load_begin(CartridgeType cart_type);
void load(const char *rom_fn);
bool load_end();
bool unload();

View File

@ -13,6 +13,7 @@ bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) {
dprintf("* Loading \"%s\"...", fn);
if(fexists(fn) == false) {
alert("Error: file '%s' not found!", fn);
return false;
}

View File

@ -1,13 +1,4 @@
void Cartridge::read_header() {
info.srtc = false;
info.sdd1 = false;
info.c4 = false;
info.dsp1 = false;
info.dsp2 = false;
info.obc1 = false;
info.dsp1_mapper = 0;
if(info.header_index == 0x7fc0 && info.rom_size >= 0x401000) {
info.mapper = EXLOROM;
strcpy(info.pcb, "UNL-EXLOROM");
@ -27,6 +18,16 @@ void Cartridge::read_header() {
uint8 mapper = rom[info.header_index + MAPPER];
uint8 rom_type = rom[info.header_index + ROM_TYPE];
uint8 company = rom[info.header_index + COMPANY];
if(mapper == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) {
info.superfx = true;
}
if(mapper == 0x23 && (rom_type == 0x34 || rom_type == 0x35)) {
info.sa1 = true;
}
if(mapper == 0x35 && rom_type == 0x55) {
info.srtc = true;
}
@ -43,7 +44,7 @@ uint8 rom_type = rom[info.header_index + ROM_TYPE];
info.dsp1 = true;
}
if(mapper == 0x30 && rom_type == 0x05) {
if(mapper == 0x30 && rom_type == 0x05 && company != 0xb2) {
info.dsp1 = true;
}
@ -65,15 +66,28 @@ uint8 rom_type = rom[info.header_index + ROM_TYPE];
info.dsp2 = true;
}
if(mapper == 0x30 && rom_type == 0x05 && company == 0xb2) {
info.dsp3 = true;
}
if(mapper == 0x30 && rom_type == 0x03) {
info.dsp4 = true;
}
if(mapper == 0x30 && rom_type == 0x25) {
info.obc1 = true;
}
if(mapper == 0x30 && rom_type == 0xf6) {
//TODO: both ST010 and ST011 share the same mapper + rom_type
//need way to determine which is which
//for now, default to supported ST010
info.st010 = true;
}
info.cart_mmio = info.c4 | info.dsp1 | info.dsp2 | info.obc1;
if(mapper == 0x30 && rom_type == 0xf5) {
info.st018 = true;
}
if(rom[info.header_index + RAM_SIZE] & 7) {
info.ram_size = 1024 << (rom[info.header_index + RAM_SIZE] & 7);
@ -117,8 +131,8 @@ int32 score_lo = 0,
if(rom[0x7fc0 + REGION] < 14)score_lo++;
if(rom[0xffc0 + REGION] < 14)score_hi++;
if(rom[0x7fc0 + LICENSE] < 3)score_lo++;
if(rom[0xffc0 + LICENSE] < 3)score_hi++;
if(rom[0x7fc0 + COMPANY] < 3)score_lo++;
if(rom[0xffc0 + COMPANY] < 3)score_hi++;
if(rom[0x7fc0 + RESH] & 0x80)score_lo += 2;
if(rom[0xffc0 + RESH] & 0x80)score_hi += 2;

View File

@ -20,21 +20,11 @@ uint offset = 0;
info.crc32 = crc32_calculate(rom, info.rom_size);
if(read_database() == true) {
info.srtc = false;
info.sdd1 = false;
info.c4 = false;
info.dsp1 = false;
info.dsp2 = false;
info.obc1 = false;
info.dsp1_mapper = 0;
info.header_index = 0xffc0;
info.mapper = PCB;
strcpy(info.name, dbi.name);
strcpy(info.pcb, dbi.pcb);
info.region = NTSC;
info.cart_mmio = false;
info.rom_size = dbi.rom;
info.ram_size = dbi.ram;

Binary file not shown.

View File

@ -106,6 +106,12 @@ pcb = "BSC-1A7M-10"
rom = 24mbit
ram = 512kbit
[0xcf98ddaa]
name = "Super Mario World 2: Yoshi's Island (USA)"
pcb = "SHVC-1CB5B-01"
rom = 16mbit
ram = 256kbit
[0x64a91e64]
name = "Wanderers from Ys (USA) [!]"
pcb = "SHVC-1A3B-12"

View File

@ -53,9 +53,9 @@ db_item dbi;
dbi.ram = 0;
for(int i = 1; i < count(line); i++) {
uint pos;
if(strpos(line[i], ";", pos) == true) {
strset(line[i], pos, 0);
int pos = strpos(line[i], ";");
if(pos >= 0) {
strptr(line[i])[pos] = 0;
}
if(line[i] == "")continue;

View File

@ -1,3 +1,4 @@
::@make -r PLATFORM=win-mingw4-lui
::@make -r PLATFORM=win-visualc-lui
@make -r PLATFORM=win-visualc-lui GZIP_SUPPORT=true JMA_SUPPORT=true
@move bsnes.exe ../bsnes.exe>nul

View File

@ -7,8 +7,6 @@
#include "../../base.h"
C4 *c4;
#include "c4data.cpp"
#include "c4fn.cpp"
#include "c4oam.cpp"

View File

@ -93,4 +93,4 @@ public:
C4();
};
extern C4 *c4;
extern C4 c4;

View File

@ -1,7 +1,5 @@
#include "../../base.h"
DSP1 *dsp1;
#include "dsp1emu.cpp"
void DSP1::init() {}

View File

@ -15,4 +15,4 @@ public:
void write(uint16 addr, uint8 data);
};
extern DSP1 *dsp1;
extern DSP1 dsp1;

View File

@ -1,7 +1,5 @@
#include "../../base.h"
DSP2 *dsp2;
#include "dsp2_op.cpp"
void DSP2::init() {}

View File

@ -1,5 +1,4 @@
class DSP2 {
public:
class DSP2 { public:
struct {
bool waiting_for_command;
uint command;
@ -40,4 +39,4 @@ struct {
~DSP2();
};
extern DSP2 *dsp2;
extern DSP2 dsp2;

33
src/chip/dsp3/dsp3.cpp Normal file
View File

@ -0,0 +1,33 @@
#include "../../base.h"
namespace DSP3i {
#define bool8 bool
#include "dsp3emu.c"
#undef bool8
};
void DSP3::init() {
}
void DSP3::enable() {
}
void DSP3::power() {
reset();
}
void DSP3::reset() {
DSP3i::DSP3_Reset();
}
uint8 DSP3::read(uint16 addr) {
DSP3i::dsp3_address = addr;
DSP3i::DSP3GetByte();
return DSP3i::dsp3_byte;
}
void DSP3::write(uint16 addr, uint8 data) {
DSP3i::dsp3_address = addr;
DSP3i::dsp3_byte = data;
DSP3i::DSP3SetByte();
}

11
src/chip/dsp3/dsp3.h Normal file
View File

@ -0,0 +1,11 @@
class DSP3 { public:
void init();
void enable();
void power();
void reset();
uint8 read (uint16 addr);
void write(uint16 addr, uint8 data);
};
extern DSP3 dsp3;

1142
src/chip/dsp3/dsp3emu.c Normal file

File diff suppressed because it is too large Load Diff

51
src/chip/dsp4/dsp4.cpp Normal file
View File

@ -0,0 +1,51 @@
#include "../../base.h"
namespace DSP4i {
inline uint16 READ_WORD(uint8 *addr) {
return (addr[0]) + (addr[1] << 8);
}
inline uint32 READ_DWORD(uint8 *addr) {
return (addr[0]) + (addr[1] << 8) + (addr[2] << 16) + (addr[3] << 24);
}
inline void WRITE_WORD(uint8 *addr, uint16 data) {
addr[0] = data;
addr[1] = data >> 8;
}
#define bool8 bool
#include "dsp4emu.c"
#undef bool8
};
void DSP4::init() {
}
void DSP4::enable() {
}
void DSP4::power() {
reset();
}
void DSP4::reset() {
DSP4i::InitDSP4();
}
uint8 DSP4::read(uint16 addr) {
if(addr < 0xc000) {
DSP4i::dsp4_address = addr;
DSP4i::DSP4GetByte();
return DSP4i::dsp4_byte;
}
return 0x80;
}
void DSP4::write(uint16 addr, uint8 data) {
if(addr < 0xc000) {
DSP4i::dsp4_address = addr;
DSP4i::dsp4_byte = data;
DSP4i::DSP4SetByte();
}
}

11
src/chip/dsp4/dsp4.h Normal file
View File

@ -0,0 +1,11 @@
class DSP4 { public:
void init();
void enable();
void power();
void reset();
uint8 read (uint16 addr);
void write(uint16 addr, uint8 data);
};
extern DSP4 dsp4;

2146
src/chip/dsp4/dsp4emu.c Normal file

File diff suppressed because it is too large Load Diff

108
src/chip/dsp4/dsp4emu.h Normal file
View File

@ -0,0 +1,108 @@
//DSP-4 emulator code
//Copyright (c) 2004-2006 Dreamer Nom, John Weidman, Kris Bleakley, Nach, z80 gaiden
#ifndef DSP4EMU_H
#define DSP4EMU_H
#undef TRUE
#undef FALSE
#define TRUE true
#define FALSE false
struct DSP4_t
{
bool8 waiting4command;
bool8 half_command;
uint16 command;
uint32 in_count;
uint32 in_index;
uint32 out_count;
uint32 out_index;
uint8 parameters[512];
uint8 output[512];
};
extern struct DSP4_t DSP4;
struct DSP4_vars_t
{
// op control
int8 DSP4_Logic; // controls op flow
// projection format
int16 lcv; // loop-control variable
int16 distance; // z-position into virtual world
int16 raster; // current raster line
int16 segments; // number of raster lines drawn
// 1.15.16 or 1.15.0 [sign, integer, fraction]
int32 world_x; // line of x-projection in world
int32 world_y; // line of y-projection in world
int32 world_dx; // projection line x-delta
int32 world_dy; // projection line y-delta
int16 world_ddx; // x-delta increment
int16 world_ddy; // y-delta increment
int32 world_xenv; // world x-shaping factor
int16 world_yofs; // world y-vertical scroll
int16 view_x1; // current viewer-x
int16 view_y1; // current viewer-y
int16 view_x2; // future viewer-x
int16 view_y2; // future viewer-y
int16 view_dx; // view x-delta factor
int16 view_dy; // view y-delta factor
int16 view_xofs1; // current viewer x-vertical scroll
int16 view_yofs1; // current viewer y-vertical scroll
int16 view_xofs2; // future viewer x-vertical scroll
int16 view_yofs2; // future viewer y-vertical scroll
int16 view_yofsenv; // y-scroll shaping factor
int16 view_turnoff_x; // road turnoff data
int16 view_turnoff_dx; // road turnoff delta factor
// drawing area
int16 viewport_cx; // x-center of viewport window
int16 viewport_cy; // y-center of render window
int16 viewport_left; // x-left of viewport
int16 viewport_right; // x-right of viewport
int16 viewport_top; // y-top of viewport
int16 viewport_bottom; // y-bottom of viewport
// sprite structure
int16 sprite_x; // projected x-pos of sprite
int16 sprite_y; // projected y-pos of sprite
int16 sprite_attr; // obj attributes
bool8 sprite_size; // sprite size: 8x8 or 16x16
int16 sprite_clipy; // visible line to clip pixels off
int16 sprite_count;
// generic projection variables designed for
// two solid polygons + two polygon sides
int16 poly_clipLf[2][2]; // left clip boundary
int16 poly_clipRt[2][2]; // right clip boundary
int16 poly_ptr[2][2]; // HDMA structure pointers
int16 poly_raster[2][2]; // current raster line below horizon
int16 poly_top[2][2]; // top clip boundary
int16 poly_bottom[2][2]; // bottom clip boundary
int16 poly_cx[2][2]; // center for left/right points
int16 poly_start[2]; // current projection points
int16 poly_plane[2]; // previous z-plane distance
// OAM
int16 OAM_attr[16]; // OAM (size,MSB) data
int16 OAM_index; // index into OAM table
int16 OAM_bits; // offset into OAM table
int16 OAM_RowMax; // maximum number of tiles per 8 aligned pixels (row)
int16 OAM_Row[32]; // current number of tiles per row
};
extern struct DSP4_vars_t DSP4_vars;
#endif

View File

@ -1,7 +1,5 @@
#include "../../base.h"
OBC1 *obc1;
void OBC1::init() {}
void OBC1::enable() {}

View File

@ -17,4 +17,4 @@ struct {
~OBC1();
};
extern OBC1 *obc1;
extern OBC1 obc1;

View File

@ -1,7 +1,5 @@
#include "../../base.h"
SDD1 *sdd1;
#include "sdd1emu.cpp"
void SDD1::init() {}

View File

@ -29,4 +29,4 @@ struct {
SDD1();
};
extern SDD1 *sdd1;
extern SDD1 sdd1;

View File

@ -52,8 +52,6 @@
#include "../../base.h"
SRTC *srtc;
void SRTC::set_time() {
time_t rawtime;
tm *t;

View File

@ -49,4 +49,4 @@ struct {
SRTC();
};
extern SRTC *srtc;
extern SRTC srtc;

View File

@ -2,8 +2,6 @@
#include "st010_data.h"
#include "st010_op.cpp"
ST010 *st010;
int16 ST010::sin(int16 theta) {
return sin_table[(theta >> 8) & 0xff];
}

View File

@ -37,4 +37,4 @@ static const uint8 arctan[32][32];
void write(uint16 addr, uint8 data);
};
extern ST010 *st010;
extern ST010 st010;

View File

@ -0,0 +1,3 @@
void op_unknown() {}
void op_00();

View File

@ -0,0 +1,7 @@
//STOP
void SuperFX::op_00() {
regs.sfr.g = 0;
regs.sfr.b = 0;
regs.sfr.alt1 = 0;
regs.sfr.alt2 = 0;
}

View File

@ -0,0 +1,64 @@
uint8 SuperFX::mmio_read(uint16 addr) {
switch(addr) {
case 0x3000: return regs.r0.l;
case 0x3001: return regs.r0.h;
case 0x3002: return regs.r1.l;
case 0x3003: return regs.r1.h;
case 0x3004: return regs.r2.l;
case 0x3005: return regs.r2.h;
case 0x3006: return regs.r3.l;
case 0x3007: return regs.r3.h;
case 0x3008: return regs.r4.l;
case 0x3009: return regs.r4.h;
case 0x300a: return regs.r5.l;
case 0x300b: return regs.r5.h;
case 0x300c: return regs.r6.l;
case 0x300d: return regs.r6.h;
case 0x300e: return regs.r7.l;
case 0x300f: return regs.r7.h;
case 0x3010: return regs.r8.l;
case 0x3011: return regs.r8.h;
case 0x3012: return regs.r9.l;
case 0x3013: return regs.r9.h;
case 0x3014: return regs.r10.l;
case 0x3015: return regs.r10.h;
case 0x3016: return regs.r11.l;
case 0x3017: return regs.r11.h;
case 0x3018: return regs.r12.l;
case 0x3019: return regs.r12.h;
case 0x301a: return regs.r13.l;
case 0x301b: return regs.r13.h;
case 0x301c: return regs.r14.l;
case 0x301d: return regs.r14.h;
case 0x301e: return regs.r15.l;
case 0x301f: return regs.r15.h;
//0x3020 - 0x302f unused
case 0x3030: return regs.sfr;
case 0x3031: return regs.sfr >> 8;
case 0x3032: return 0x00; //unused
case 0x3033: return 0x00; //BRAMR (write only)
case 0x3034: return regs.pbr;
case 0x3035: return 0x00; //unused
case 0x3036: return regs.rombr;
case 0x3037: return 0x00; //CFGR (write only)
case 0x3038: return 0x00; //SCBR (write only)
case 0x3039: return 0x00; //CLSR (write only)
case 0x303a: return 0x00; //SCMR (write only)
case 0x303b: return regs.vcr;
case 0x303c: return regs.rambr;
case 0x303d: return 0x00; //unused
case 0x303e: return regs.cbr;
case 0x303f: return regs.cbr >> 8;
//0x3040 - 0x30ff unused
}
if(addr >= 0x3100 && addr <= 0x32ff) {
return cache[addr - 0x3100];
}
return 0x00;
}

View File

@ -0,0 +1,63 @@
void SuperFX::mmio_write(uint16 addr, uint8 data) {
switch(addr) {
case 0x3000: regs.r0.l = data; return;
case 0x3001: regs.r0.h = data; return;
case 0x3002: regs.r1.l = data; return;
case 0x3003: regs.r1.h = data; return;
case 0x3004: regs.r2.l = data; return;
case 0x3005: regs.r2.h = data; return;
case 0x3006: regs.r3.l = data; return;
case 0x3007: regs.r3.h = data; return;
case 0x3008: regs.r4.l = data; return;
case 0x3009: regs.r4.h = data; return;
case 0x300a: regs.r5.l = data; return;
case 0x300b: regs.r5.h = data; return;
case 0x300c: regs.r6.l = data; return;
case 0x300d: regs.r6.h = data; return;
case 0x300e: regs.r7.l = data; return;
case 0x300f: regs.r7.h = data; return;
case 0x3010: regs.r8.l = data; return;
case 0x3011: regs.r8.h = data; return;
case 0x3012: regs.r9.l = data; return;
case 0x3013: regs.r9.h = data; return;
case 0x3014: regs.r10.l = data; return;
case 0x3015: regs.r10.h = data; return;
case 0x3016: regs.r11.l = data; return;
case 0x3017: regs.r11.h = data; return;
case 0x3018: regs.r12.l = data; return;
case 0x3019: regs.r12.h = data; return;
case 0x301a: regs.r13.l = data; return;
case 0x301b: regs.r13.h = data; return;
case 0x301c: regs.r14.l = data; return;
case 0x301d: regs.r14.h = data; return;
case 0x301e: regs.r15.l = data; return;
case 0x301f: regs.r15.h = data; return;
//0x3020 - 0x302f unused
case 0x3030: regs.sfr.l = data & 0x7e; return; //mask invalid bits
case 0x3031: regs.sfr.h = data & 0x9f; return; //mask invalid bits
case 0x3032: return; //unused
case 0x3033: regs.bramr = data; return;
case 0x3034: regs.pbr = data; return;
case 0x3035: return; //unused
case 0x3036: return; //ROMBR (read only)
case 0x3037: regs.cfgr = data; return;
case 0x3038: regs.scbr = data; return;
case 0x3039: regs.clsr = data; return;
case 0x303a: regs.scmr = data; return;
case 0x303b: return; //VCR (read only)
case 0x303c: return; //RAMBR (read only)
case 0x303d: return; //unused
case 0x303e: return; //CBR low (read only)
case 0x303f: return; //CBR high (read only)
//0x3040 - 0x30ff unused
}
if(addr >= 0x3100 && addr <= 0x32ff) {
cache[addr - 0x3100] = data;
return;
}
}

174
src/chip/superfx/regs.h Normal file
View File

@ -0,0 +1,174 @@
struct Reg16 {
union {
uint16 w;
struct { uint8 order_lsb2(l, h); };
};
inline operator unsigned() const { return w; }
inline unsigned operator=(const unsigned i) { return w = i; }
Reg16() : w(0) {}
};
template<int bit> struct RegFlag8 {
uint8 data;
inline operator bool() const { return data & bit; }
inline bool operator=(const bool i) { i ? data |= bit : data &= ~bit; return i; }
};
template<int bit> struct RegFlag16 {
uint16 data;
inline operator bool() const { return data & bit; }
inline bool operator=(const bool i) { i ? data |= bit : data &= ~bit; return i; }
};
struct SFR {
union {
uint16 w;
struct { uint8 order_lsb2(l, h); };
RegFlag16<0x0002> z; //zero flag
RegFlag16<0x0004> c; //carry flag
RegFlag16<0x0008> s; //sign flag
RegFlag16<0x0010> v; //overflow flag
RegFlag16<0x0020> g; //go flag
RegFlag16<0x0040> r; //ROM read using r14 flag
RegFlag16<0x0100> alt1; //alternate instruction 1 flag
RegFlag16<0x0200> alt2; //alternate instruction 2 flag
RegFlag16<0x0400> il; //immediate lower 8-bit flag
RegFlag16<0x0800> ih; //immediate upper 8-bit flag
RegFlag16<0x1000> b; //WITH instruction flag
RegFlag16<0x8000> irq; //interrupt flag
};
inline operator unsigned() const { return w & 0x9f7e; } //invalid flag bits always return 0 when read
inline unsigned operator=(const unsigned i) { return w = i & 0x9f7e; }
SFR() : w(0) {}
};
struct RAMBR {
union {
uint8 b;
RegFlag8<0x01> bank;
};
inline operator unsigned() const { return b & 0x01; }
inline unsigned operator=(const unsigned i) { return b = i & 0x01; }
RAMBR() : b(0) {}
};
struct CBR {
uint16 w;
inline operator unsigned() const { return w & 0xfff0; }
inline unsigned operator=(const unsigned i) { return w = i & 0xfff0; }
CBR() : w(0) {}
};
struct SCMR {
union {
uint8 b;
RegFlag8<0x01> md0; //color mode low
RegFlag8<0x02> md1; //color mode high
RegFlag8<0x04> ht0; //height low
RegFlag8<0x08> ran; //ram enable
RegFlag8<0x10> ron; //rom enable
RegFlag8<0x20> ht1; //height high
};
inline operator unsigned() const { return b; }
inline unsigned operator=(const unsigned i) { return b = i; }
SCMR() : b(0) {}
};
struct BRAMR {
union {
uint8 b;
RegFlag8<0x01> flag;
};
inline operator unsigned() const { return b; }
inline unsigned operator=(const unsigned i) { return b = i; }
BRAMR() : b(0) {}
};
struct CFGR {
union {
uint8 b;
RegFlag8<0x20> ms0; //multiplier speed selection
RegFlag8<0x80> irq; //irq mask flag
};
inline operator unsigned() const { return b; }
inline unsigned operator=(const unsigned i) { return b = i; }
CFGR() : b(0) {}
};
struct CLSR {
union {
uint8 b;
RegFlag8<0x01> flag;
};
inline operator unsigned() const { return b; }
inline unsigned operator=(const unsigned i) { return b = i; }
CLSR() : b(0) {}
};
struct POR {
union {
uint8 b;
RegFlag8<0x01> transparent; //transparent flag
RegFlag8<0x02> dither; //dither flag
RegFlag8<0x04> highnibble; //high nibble flag
RegFlag8<0x08> freezehigh; //freeze high flag
RegFlag8<0x10> obj; //OBJ flag
};
inline operator unsigned() const { return b; }
inline unsigned operator=(const unsigned i) { return b = i; }
POR() : b(0) {}
};
struct Regs {
Reg16 r0; //default source/destination register
Reg16 r1; //pixel plot X position register
Reg16 r2; //pixel plot Y position register
Reg16 r3;
Reg16 r4; //lower 16-bit result of lmult
Reg16 r5;
Reg16 r6; //multiplier for fmult and lmult
Reg16 r7; //fixed point texel X position for merge
Reg16 r8; //fixed point texel Y position for merge
Reg16 r9;
Reg16 r10;
Reg16 r11; //return address set by link
Reg16 r12; //loop counter
Reg16 r13; //loop point address
Reg16 r14; //rom address for getb, getbh, getbl, getbs
Reg16 r15; //program counter
SFR sfr; //status/flag register
uint8 pbr; //program bank register
uint8 rombr; //rom bank register
RAMBR rambr; //ram bank register
CBR cbr; //cache base register
uint8 scbr; //screen base register
SCMR scmr; //screen mode register
BRAMR bramr; //backup ram register
uint8 vcr; //version code register
CFGR cfgr; //config register
CLSR clsr; //clock select register
uint8 colr; //color register
POR por; //plot option register
} regs;

View File

@ -0,0 +1,42 @@
#include "../../base.h"
#include "core/op0x.cpp"
#include "memory/read.cpp"
#include "memory/write.cpp"
void SuperFX::init() {
}
void SuperFX::enable() {
for(uint i = 0x3000; i <= 0x32ff; i++) {
r_mem->set_mmio_mapper(i, this);
}
}
void SuperFX::power() {
reset();
}
void SuperFX::reset() {
regs.r0 = 0;
regs.r1 = 0;
regs.r2 = 0;
regs.r3 = 0;
regs.r4 = 0;
regs.r5 = 0;
regs.r6 = 0;
regs.r7 = 0;
regs.r8 = 0;
regs.r9 = 0;
regs.r10 = 0;
regs.r11 = 0;
regs.r12 = 0;
regs.r13 = 0;
regs.r14 = 0;
regs.r15 = 0;
regs.sfr = 0;
memset(cache, 0, sizeof cache);
}

View File

@ -0,0 +1,17 @@
class SuperFX : public MMIO { public:
#include "core/core.h"
void init();
void enable();
void power();
void reset();
uint8 mmio_read (uint16 addr);
void mmio_write(uint16 addr, uint8 data);
private:
#include "regs.h"
uint8 cache[512]; //cache RAM
};
extern SuperFX superfx;

View File

@ -1 +1,2 @@
::@make PLATFORM=win-mingw4-lui clean
@make PLATFORM=win-visualc-lui clean

View File

@ -83,8 +83,8 @@ inline uint32 sCPU::hdma_iaddr(uint8 i) {
*****/
void sCPU::dma_transfertobusb(uint8 i, uint8 bbus) {
if(cartridge.info.sdd1 == true && sdd1->dma_active() == true) {
r_mem->write(0x2100 | bbus, sdd1->dma_read());
if(cartridge.info.sdd1 == true && sdd1.dma_active() == true) {
r_mem->write(0x2100 | bbus, sdd1.dma_read());
} else {
dma_transfer(0, bbus, dma_addr(i));
}
@ -111,8 +111,7 @@ void sCPU::dma_run() {
dma_add_clocks(8);
if(cartridge.info.sdd1 == true) {
sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr),
channel[i].xfersize);
sdd1.dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr), channel[i].xfersize);
}
if(tracer.enabled() == true && tracer.cpudma_enabled() == true) {

View File

@ -1,8 +1,6 @@
class sCPU : public CPU {
public:
class sCPU : public CPU { public:
void enter();
public:
#include "core/core.h"
#include "dma/dma.h"
#include "memory/memory.h"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -33,11 +33,14 @@
#include "snes/snes.h"
#include "chip/superfx/superfx.h"
#include "chip/srtc/srtc.h"
#include "chip/sdd1/sdd1.h"
#include "chip/c4/c4.h"
#include "chip/dsp1/dsp1.h"
#include "chip/dsp2/dsp2.h"
#include "chip/dsp3/dsp3.h"
#include "chip/dsp4/dsp4.h"
#include "chip/obc1/obc1.h"
#include "chip/st010/st010.h"

View File

@ -31,6 +31,8 @@ void bMemBus::load_cart() {
if(cartridge.info.c4) cart_map_c4();
if(cartridge.info.dsp1) cart_map_dsp1();
if(cartridge.info.dsp2) cart_map_dsp2();
if(cartridge.info.dsp3) cart_map_dsp3();
if(cartridge.info.dsp4) cart_map_dsp4();
if(cartridge.info.obc1) cart_map_obc1();
if(cartridge.info.st010)cart_map_st010();
@ -58,13 +60,19 @@ char t[256];
dprintf("* Region : %s", (cartridge.info.region == Cartridge::NTSC) ? "NTSC" : "PAL");
strcpy(t, "");
if(cartridge.info.srtc) strcat(t, "S-RTC, ");
if(cartridge.info.sdd1) strcat(t, "S-DD1, ");
if(cartridge.info.c4) strcat(t, "Cx4, ");
if(cartridge.info.dsp1) strcat(t, "DSP-1, ");
if(cartridge.info.dsp2) strcat(t, "DSP-2, ");
if(cartridge.info.obc1) strcat(t, "OBC-1, ");
if(cartridge.info.st010)strcat(t, "ST010, ");
if(cartridge.info.superfx)strcat(t, "SuperFX, ");
if(cartridge.info.sa1) strcat(t, "SA-1, ");
if(cartridge.info.srtc) strcat(t, "S-RTC, ");
if(cartridge.info.sdd1) strcat(t, "S-DD1, ");
if(cartridge.info.c4) strcat(t, "Cx4, ");
if(cartridge.info.dsp1) strcat(t, "DSP-1, ");
if(cartridge.info.dsp2) strcat(t, "DSP-2, ");
if(cartridge.info.dsp3) strcat(t, "DSP-3, ");
if(cartridge.info.dsp4) strcat(t, "DSP-4, ");
if(cartridge.info.obc1) strcat(t, "OBC-1, ");
if(cartridge.info.st010) strcat(t, "ST010, ");
if(cartridge.info.st011) strcat(t, "ST011, ");
if(cartridge.info.st018) strcat(t, "ST018, ");
strrtrim(t, ", ");
dprintf("* Coprocessor(s) : %s", (strlen(t) == 0) ? "None" : t);
dprintf("* Reset:%0.4x NMI[n]:%0.4x IRQ[n]:%0.4x BRK[n]:%0.4x COP[n]:%0.4x",

View File

@ -39,6 +39,10 @@ enum { TYPE_WRAM, TYPE_MMIO, TYPE_CART };
void write_dsp1 (uint32 addr, uint8 data);
uint8 read_dsp2 (uint32 addr);
void write_dsp2 (uint32 addr, uint8 data);
uint8 read_dsp3 (uint32 addr);
void write_dsp3 (uint32 addr, uint8 data);
uint8 read_dsp4 (uint32 addr);
void write_dsp4 (uint32 addr, uint8 data);
uint8 read_obc1 (uint32 addr);
void write_obc1 (uint32 addr, uint8 data);
uint8 read_st010 (uint32 addr);
@ -52,6 +56,8 @@ enum { TYPE_WRAM, TYPE_MMIO, TYPE_CART };
void cart_map_c4();
void cart_map_dsp1();
void cart_map_dsp2();
void cart_map_dsp3();
void cart_map_dsp4();
void cart_map_obc1();
void cart_map_st010();

View File

@ -167,6 +167,30 @@ void bMemBus::cart_map_dsp2() {
}
}
void bMemBus::cart_map_dsp3() {
//$[20-3f|a0-bf]:[8000-ffff]
for(uint bank = 0x20; bank <= 0x3f; bank++) {
for(uint page = 0x80; page <= 0xff; page++) {
page_read [0x0000 + (bank << 8) + page] = &bMemBus::read_dsp3;
page_read [0x8000 + (bank << 8) + page] = &bMemBus::read_dsp3;
page_write[0x0000 + (bank << 8) + page] = &bMemBus::write_dsp3;
page_write[0x8000 + (bank << 8) + page] = &bMemBus::write_dsp3;
}
}
}
void bMemBus::cart_map_dsp4() {
//$[30-3f|b0-bf]:[8000-ffff]
for(uint bank = 0x30; bank <= 0x3f; bank++) {
for(uint page = 0x80; page <= 0xff; page++) {
page_read [0x0000 + (bank << 8) + page] = &bMemBus::read_dsp4;
page_read [0x8000 + (bank << 8) + page] = &bMemBus::read_dsp4;
page_write[0x0000 + (bank << 8) + page] = &bMemBus::write_dsp4;
page_write[0x8000 + (bank << 8) + page] = &bMemBus::write_dsp4;
}
}
}
void bMemBus::cart_map_obc1() {
//$[00-3f|80-bf]:[6000-7fff]
for(uint bank = 0x00; bank <= 0x3f; bank++) {

View File

@ -39,29 +39,35 @@ void bMemBus::write_ram(uint32 addr, uint8 data) {
//
uint8 bMemBus::read_sdd1(uint32 addr) {
addr = sdd1->offset(addr) % cartridge.info.rom_size;
addr = sdd1.offset(addr) % cartridge.info.rom_size;
return cartridge.rom[addr];
}
void bMemBus::write_sdd1(uint32 addr, uint8 data) {
if(cart_write_protect_enabled == true)return;
addr = sdd1->offset(addr) % cartridge.info.rom_size;
addr = sdd1.offset(addr) % cartridge.info.rom_size;
cartridge.rom[addr] = data;
}
//
uint8 bMemBus::read_c4 (uint32 addr) { return c4->read(addr); }
void bMemBus::write_c4(uint32 addr, uint8 data) { c4->write(addr, data); }
uint8 bMemBus::read_c4 (uint32 addr) { return c4.read(addr); }
void bMemBus::write_c4(uint32 addr, uint8 data) { c4.write(addr, data); }
uint8 bMemBus::read_dsp1 (uint32 addr) { return dsp1->read(addr); }
void bMemBus::write_dsp1(uint32 addr, uint8 data) { dsp1->write(addr, data); }
uint8 bMemBus::read_dsp1 (uint32 addr) { return dsp1.read(addr); }
void bMemBus::write_dsp1(uint32 addr, uint8 data) { dsp1.write(addr, data); }
uint8 bMemBus::read_dsp2 (uint32 addr) { return dsp2->read(addr); }
void bMemBus::write_dsp2(uint32 addr, uint8 data) { dsp2->write(addr, data); }
uint8 bMemBus::read_dsp2 (uint32 addr) { return dsp2.read(addr); }
void bMemBus::write_dsp2(uint32 addr, uint8 data) { dsp2.write(addr, data); }
uint8 bMemBus::read_obc1 (uint32 addr) { return obc1->read(addr); }
void bMemBus::write_obc1(uint32 addr, uint8 data) { obc1->write(addr, data); }
uint8 bMemBus::read_dsp3 (uint32 addr) { return dsp3.read(addr); }
void bMemBus::write_dsp3(uint32 addr, uint8 data) { dsp3.write(addr, data); }
uint8 bMemBus::read_st010 (uint32 addr) { return st010->read(addr); }
void bMemBus::write_st010(uint32 addr, uint8 data) { st010->write(addr, data); }
uint8 bMemBus::read_dsp4 (uint32 addr) { return dsp4.read(addr); }
void bMemBus::write_dsp4(uint32 addr, uint8 data) { dsp4.write(addr, data); }
uint8 bMemBus::read_obc1 (uint32 addr) { return obc1.read(addr); }
void bMemBus::write_obc1(uint32 addr, uint8 data) { obc1.write(addr, data); }
uint8 bMemBus::read_st010 (uint32 addr) { return st010.read(addr); }
void bMemBus::write_st010(uint32 addr, uint8 data) { st010.write(addr, data); }

View File

@ -1,30 +1,33 @@
bool bMemBus::cart_map_pcb(const char *pcb) {
if(!strcmp(pcb, "SHVC-1A3B-01")) { cart_map_shvc_1a3b_13(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-11")) { cart_map_shvc_1a3b_13(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-12")) { cart_map_shvc_1a3b_13(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-13")) { cart_map_shvc_1a3b_13(); return true; }
if(!strcmp(pcb, "SHVC-1CB5B-01")) { cart_map_shvc_1cb5b_20(); return true; }
if(!strcmp(pcb, "SHVC-1CB5B-20")) { cart_map_shvc_1cb5b_20(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-20")) { cart_map_shvc_1a3b_20(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-01")) { cart_map_shvc_1a3b_13(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-11")) { cart_map_shvc_1a3b_13(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-12")) { cart_map_shvc_1a3b_13(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-13")) { cart_map_shvc_1a3b_13(); return true; }
if(!strcmp(pcb, "SHVC-1A3M-10")) { cart_map_shvc_1a3m_30(); return true; }
if(!strcmp(pcb, "SHVC-1A3M-20")) { cart_map_shvc_1a3m_30(); return true; }
if(!strcmp(pcb, "SHVC-1A3M-21")) { cart_map_shvc_1a3m_30(); return true; }
if(!strcmp(pcb, "SHVC-1A3M-30")) { cart_map_shvc_1a3m_30(); return true; }
if(!strcmp(pcb, "SHVC-1A3B-20")) { cart_map_shvc_1a3b_20(); return true; }
if(!strcmp(pcb, "SHVC-1J3M-01")) { cart_map_shvc_1j3m_20(); return true; }
if(!strcmp(pcb, "SHVC-1J3M-10")) { cart_map_shvc_1j3m_20(); return true; }
if(!strcmp(pcb, "SHVC-1J3M-11")) { cart_map_shvc_1j3m_20(); return true; }
if(!strcmp(pcb, "SHVC-1J3M-20")) { cart_map_shvc_1j3m_20(); return true; }
if(!strcmp(pcb, "SHVC-1A3M-10")) { cart_map_shvc_1a3m_30(); return true; }
if(!strcmp(pcb, "SHVC-1A3M-20")) { cart_map_shvc_1a3m_30(); return true; }
if(!strcmp(pcb, "SHVC-1A3M-21")) { cart_map_shvc_1a3m_30(); return true; }
if(!strcmp(pcb, "SHVC-1A3M-30")) { cart_map_shvc_1a3m_30(); return true; }
if(!strcmp(pcb, "BSC-1A5M-01")) { cart_map_bsc_1a5m_01(); return true; }
if(!strcmp(pcb, "SHVC-1J3M-01")) { cart_map_shvc_1j3m_20(); return true; }
if(!strcmp(pcb, "SHVC-1J3M-10")) { cart_map_shvc_1j3m_20(); return true; }
if(!strcmp(pcb, "SHVC-1J3M-11")) { cart_map_shvc_1j3m_20(); return true; }
if(!strcmp(pcb, "SHVC-1J3M-20")) { cart_map_shvc_1j3m_20(); return true; }
if(!strcmp(pcb, "BSC-1A7M-01")) { cart_map_bsc_1a7m_01(); return true; }
if(!strcmp(pcb, "BSC-1A5M-01")) { cart_map_bsc_1a5m_01(); return true; }
if(!strcmp(pcb, "BSC-1A7M-10")) { cart_map_bsc_1a7m_10(); return true; }
if(!strcmp(pcb, "BSC-1A7M-01")) { cart_map_bsc_1a7m_01(); return true; }
if(!strcmp(pcb, "STC-SOLO")) { cart_map_stc_solo(); return true; }
if(!strcmp(pcb, "BSC-1A7M-10")) { cart_map_bsc_1a7m_10(); return true; }
if(!strcmp(pcb, "STC-DUAL")) { cart_map_stc_dual(); return true; }
if(!strcmp(pcb, "STC-SOLO")) { cart_map_stc_solo(); return true; }
if(!strcmp(pcb, "STC-DUAL")) { cart_map_stc_dual(); return true; }
return false;
}

View File

@ -19,6 +19,7 @@ enum {
void cart_map_range(uint mode, uint8 bank_lo, uint8 bank_hi, uint16 addr_lo, uint16 addr_hi, uint type, uint offset = 0);
#define mapper(name) void cart_map_##name()
mapper(shvc_1cb5b_20);
mapper(shvc_1a3b_13);
mapper(shvc_1a3b_20);
mapper(shvc_1a3m_30);

View File

@ -1,3 +1,15 @@
//SHVC-1CB5B-01
//SHVC-1CB5B-20
mapper(shvc_1cb5b_20) {
cartridge.info.superfx = true; //TODO: make this more elegant
map(LINEAR, 0x00, 0x3f, 0x6000, 0x7fff, MAP_RAM);
map(LINEAR, 0x00, 0x3f, 0x8000, 0xffff, MAP_ROM);
map(LINEAR, 0x40, 0x5f, 0x0000, 0xffff, MAP_ROM);
map(LINEAR, 0x70, 0x71, 0x0000, 0xffff, MAP_RAM);
map(LINEAR, 0x80, 0xbf, 0x6000, 0x7fff, MAP_RAM);
}
//SHVC-1A3B-01
//SHVC-1A3B-11
//SHVC-1A3B-12

View File

@ -1,6 +1,16 @@
#include "../base.h"
SNES snes;
SuperFX superfx;
SRTC srtc;
SDD1 sdd1;
C4 c4;
DSP1 dsp1;
DSP2 dsp2;
DSP3 dsp3;
DSP4 dsp4;
OBC1 obc1;
ST010 st010;
#include "scheduler/scheduler.cpp"
#include "tracer/tracer.cpp"
@ -16,21 +26,16 @@ void SNES::runtoframe() {
}
void SNES::init() {
srtc = new SRTC();
sdd1 = new SDD1();
c4 = new C4();
dsp1 = new DSP1();
dsp2 = new DSP2();
obc1 = new OBC1();
st010 = new ST010();
srtc->init();
sdd1->init();
c4->init();
dsp1->init();
dsp2->init();
obc1->init();
st010->init();
superfx.init();
srtc.init();
sdd1.init();
c4.init();
dsp1.init();
dsp2.init();
dsp3.init();
dsp4.init();
obc1.init();
st010.init();
video_init();
audio_init();
@ -52,13 +57,16 @@ void SNES::power() {
r_ppu->power();
r_mem->power();
if(cartridge.info.srtc) srtc->power();
if(cartridge.info.sdd1) sdd1->power();
if(cartridge.info.c4) c4->power();
if(cartridge.info.dsp1) dsp1->power();
if(cartridge.info.dsp2) dsp2->power();
if(cartridge.info.obc1) obc1->power();
if(cartridge.info.st010)st010->power();
if(cartridge.info.superfx)superfx.power();
if(cartridge.info.srtc) srtc.power();
if(cartridge.info.sdd1) sdd1.power();
if(cartridge.info.c4) c4.power();
if(cartridge.info.dsp1) dsp1.power();
if(cartridge.info.dsp2) dsp2.power();
if(cartridge.info.dsp3) dsp3.power();
if(cartridge.info.dsp4) dsp4.power();
if(cartridge.info.obc1) obc1.power();
if(cartridge.info.st010) st010.power();
r_mem->flush_mmio_mappers();
for(int i = 0x2100; i <= 0x213f; i++)r_mem->set_mmio_mapper(i, r_ppu);
@ -68,13 +76,16 @@ void SNES::power() {
for(int i = 0x4200; i <= 0x421f; i++)r_mem->set_mmio_mapper(i, r_cpu);
for(int i = 0x4300; i <= 0x437f; i++)r_mem->set_mmio_mapper(i, r_cpu);
if(cartridge.info.srtc) srtc->enable();
if(cartridge.info.sdd1) sdd1->enable();
if(cartridge.info.c4) c4->enable();
if(cartridge.info.dsp1) dsp1->enable();
if(cartridge.info.dsp2) dsp2->enable();
if(cartridge.info.obc1) obc1->enable();
if(cartridge.info.st010)st010->enable();
if(cartridge.info.superfx)superfx.enable();
if(cartridge.info.srtc) srtc.enable();
if(cartridge.info.sdd1) sdd1.enable();
if(cartridge.info.c4) c4.enable();
if(cartridge.info.dsp1) dsp1.enable();
if(cartridge.info.dsp2) dsp2.enable();
if(cartridge.info.dsp3) dsp3.enable();
if(cartridge.info.dsp4) dsp4.enable();
if(cartridge.info.obc1) obc1.enable();
if(cartridge.info.st010) st010.enable();
video_update();
}
@ -88,13 +99,16 @@ void SNES::reset() {
r_ppu->reset();
r_mem->reset();
if(cartridge.info.srtc) srtc->reset();
if(cartridge.info.sdd1) sdd1->reset();
if(cartridge.info.c4) c4->reset();
if(cartridge.info.dsp1) dsp1->reset();
if(cartridge.info.dsp2) dsp2->reset();
if(cartridge.info.obc1) obc1->reset();
if(cartridge.info.st010)st010->reset();
if(cartridge.info.superfx)superfx.reset();
if(cartridge.info.srtc) srtc.reset();
if(cartridge.info.sdd1) sdd1.reset();
if(cartridge.info.c4) c4.reset();
if(cartridge.info.dsp1) dsp1.reset();
if(cartridge.info.dsp2) dsp2.reset();
if(cartridge.info.dsp3) dsp3.reset();
if(cartridge.info.dsp4) dsp4.reset();
if(cartridge.info.obc1) obc1.reset();
if(cartridge.info.st010) st010.reset();
video_update();
}

View File

@ -1,5 +1,3 @@
#define IDI_APP_ICON 100
#define IDI_CONTROLLER 101
#define IDI_APP_ICON 100
IDI_APP_ICON ICON DISCARDABLE "../data/bsnes.ico"
IDI_CONTROLLER BITMAP DISCARDABLE "../data/snes_controller.bmp"
IDI_APP_ICON ICON DISCARDABLE "../data/bsnes.ico"

View File

@ -26,46 +26,62 @@ IntegerSetting System::speed_fast (&config(), "system.speed_fast", "Fast
IntegerSetting System::speed_fastest (&config(), "system.speed_fastest", "Fastest speed setting", IntegerSetting::Decimal, 200);
struct Video {
static IntegerSetting synchronize;
static IntegerSetting fullscreen;
static IntegerSetting multiplier, aspect_correction, region;
static IntegerSetting mode;
struct Windowed {
static IntegerSetting synchronize, aspect_correction;
static IntegerSetting region, multiplier, hardware_filter, software_filter;
} windowed;
struct Fullscreen {
static IntegerSetting synchronize, aspect_correction;
static IntegerSetting region, multiplier, hardware_filter, software_filter;
} fullscreen;
static IntegerSetting aspect_ntsc_x, aspect_ntsc_y, aspect_pal_x, aspect_pal_y;
static IntegerSetting hardware_filter, software_filter;
static IntegerSetting frameskip;
static IntegerSetting use_vram;
} video;
IntegerSetting Video::synchronize(&config(), "video.synchronize", "Synchronize to video refresh rate.", IntegerSetting::Boolean, false);
IntegerSetting Video::fullscreen(0, "video.fullscreen", "", IntegerSetting::Boolean, false);
IntegerSetting Video::multiplier(&config(), "video.multiplier", "Video output size multiplier (1-5x)\n"
"1 = 1x (~256x224)\n"
"2 = 2x (~512x448)\n"
"etc.",
IntegerSetting::Decimal, 2);
IntegerSetting Video::aspect_correction(&config(), "video.aspect_correction",
//0 = windowed, 1 = fullscreen, 2 = exclusive
IntegerSetting Video::mode(0, "video.mode", "Active video mode", IntegerSetting::Decimal, 0);
IntegerSetting Video::Windowed::synchronize(&config(), "video.windowed.synchronize", "Synchronize to video refresh rate", IntegerSetting::Boolean, false);
IntegerSetting Video::Windowed::aspect_correction(&config(), "video.windowed.aspect_correction",
"Correct video aspect ratio\n"
"Formula: width = width * video.aspect_<region>_x / video.aspect_<region>_y",
"Defaults assume display pixels are perfectly square\n"
"Formula: width = width * video.aspect_<region>_x / video.aspect_<region>_y\n",
IntegerSetting::Boolean, true);
IntegerSetting Video::region(&config(), "video.region", "Video output region\n"
IntegerSetting Video::Windowed::region(&config(), "video.windowed.region", "Video output region\n"
"0 = NTSC, 1 = PAL",
IntegerSetting::Decimal, 0);
IntegerSetting Video::Windowed::multiplier(&config(), "video.windowed.multiplier", "Video output size multiplier (1-5x)\n"
"1 = 1x (<= 320x240)\n"
"2 = 2x (<= 640x480)\n"
"etc.",
IntegerSetting::Decimal, 2);
IntegerSetting Video::Windowed::hardware_filter(&config(), "video.windowed.hardware_filter", "Video hardware filter\n"
"0 = Point\n"
"1 = Linear\n",
IntegerSetting::Decimal, 1);
IntegerSetting Video::Windowed::software_filter(&config(), "video.windowed.software_filter", "Video software filter\n"
"0 = None\n"
"1 = NTSC\n"
"2 = HQ2x\n"
"3 = Scale2x\n",
IntegerSetting::Decimal, 0);
IntegerSetting Video::Fullscreen::synchronize (&config(), "video.fullscreen.synchronize", "", IntegerSetting::Boolean, false);
IntegerSetting Video::Fullscreen::aspect_correction(&config(), "video.fullscreen.aspect_correction", "", IntegerSetting::Boolean, true);
IntegerSetting Video::Fullscreen::region (&config(), "video.fullscreen.region", "", IntegerSetting::Decimal, 0);
IntegerSetting Video::Fullscreen::multiplier (&config(), "video.fullscreen.multiplier", "", IntegerSetting::Decimal, 2);
IntegerSetting Video::Fullscreen::hardware_filter (&config(), "video.fullscreen.hardware_filter", "", IntegerSetting::Decimal, 1);
IntegerSetting Video::Fullscreen::software_filter (&config(), "video.fullscreen.software_filter", "", IntegerSetting::Decimal, 0);
IntegerSetting Video::aspect_ntsc_x(&config(), "video.aspect_ntsc_x", "", IntegerSetting::Decimal, 54);
IntegerSetting Video::aspect_ntsc_y(&config(), "video.aspect_ntsc_y", "", IntegerSetting::Decimal, 47);
IntegerSetting Video::aspect_pal_x (&config(), "video.aspect_pal_x", "", IntegerSetting::Decimal, 32);
IntegerSetting Video::aspect_pal_y (&config(), "video.aspect_pal_y", "", IntegerSetting::Decimal, 23);
IntegerSetting Video::hardware_filter(&config(), "video.hardware_filter", "Video hardware filter\n"
"0 = Point\n"
"1 = Linear\n",
IntegerSetting::Decimal, 1);
IntegerSetting Video::software_filter(&config(), "video.software_filter", "Video software filter\n"
"0 = None\n"
"1 = NTSC\n"
"2 = HQ2x\n"
"3 = Scale2x\n",
IntegerSetting::Decimal, 0);
IntegerSetting Video::frameskip(0, "video.frameskip", "Video frameskip", IntegerSetting::Decimal, 0);
IntegerSetting Video::use_vram(&config(), "video.use_vram", "Use Video RAM instead of System RAM", IntegerSetting::Boolean, true);
IntegerSetting Video::use_vram(&config(), "video.use_vram", "Use Video RAM instead of System RAM when possible", IntegerSetting::Boolean, true);
struct Audio {
static IntegerSetting synchronize;

View File

@ -1,5 +1,67 @@
namespace event {
void load_video_settings() {
video_settings.mode = config::video.mode;
switch(video_settings.mode) { default:
case 0: //windowed
video_settings.aspect_correction = config::video.windowed.aspect_correction;
video_settings.synchronize = config::video.windowed.synchronize;
video_settings.region = config::video.windowed.region;
video_settings.multiplier = config::video.windowed.multiplier;
video_settings.hardware_filter = config::video.windowed.hardware_filter;
video_settings.software_filter = config::video.windowed.software_filter;
break;
case 1: //fullscreen
video_settings.aspect_correction = config::video.fullscreen.aspect_correction;
video_settings.synchronize = config::video.fullscreen.synchronize;
video_settings.region = config::video.fullscreen.region;
video_settings.multiplier = config::video.fullscreen.multiplier;
video_settings.hardware_filter = config::video.fullscreen.hardware_filter;
video_settings.software_filter = config::video.fullscreen.software_filter;
break;
}
}
void update_aspect_correction(bool aspect_correction) {
switch(config::video.mode) { default:
case 0: config::video.windowed.aspect_correction = aspect_correction; break;
case 1: config::video.fullscreen.aspect_correction = aspect_correction; break;
}
update_video_settings();
}
void update_multiplier(uint multiplier) {
switch(config::video.mode) { default:
case 0: config::video.windowed.multiplier = multiplier; break;
case 1: config::video.fullscreen.multiplier = multiplier; break;
}
update_video_settings();
}
void update_region(uint region) {
switch(config::video.mode) { default:
case 0: config::video.windowed.region = region; break;
case 1: config::video.fullscreen.region = region; break;
}
update_video_settings();
}
void update_hardware_filter(uint hardware_filter) {
switch(config::video.mode) { default:
case 0: config::video.windowed.hardware_filter = hardware_filter; break;
case 1: config::video.fullscreen.hardware_filter = hardware_filter; break;
}
update_video_settings();
}
void update_software_filter(uint software_filter) {
switch(config::video.mode) { default:
case 0: config::video.windowed.software_filter = software_filter; break;
case 1: config::video.fullscreen.software_filter = software_filter; break;
}
update_video_settings();
}
void update_frame_counter() {
if(r_ppu->status.frames_updated) {
r_ppu->status.frames_updated = false;
@ -10,49 +72,59 @@ void update_frame_counter() {
}
void update_video_settings() {
load_video_settings();
uint width = 256;
uint height = config::video.region == 0 ? 224 : 239;
uint multiplier = minmax<1, 5>(uint(config::video.multiplier));
uint height = video_settings.region == 0 ? 224 : 239;
uint multiplier = minmax<1, 5>(video_settings.multiplier);
width *= multiplier;
height *= multiplier;
if(config::video.aspect_correction == true) {
if(config::video.region == 0) { //NTSC
if(video_settings.aspect_correction == true) {
if(video_settings.region == 0) { //NTSC
width = uint( double(width) * double(config::video.aspect_ntsc_x) / double(config::video.aspect_ntsc_y) );
} else { //PAL
width = uint( double(width) * double(config::video.aspect_pal_x) / double(config::video.aspect_pal_y) );
}
}
if(config::video.fullscreen) {
//window_main.menu.hide();
window_main.fullscreen();
window_main.view.move((ui::get_screen_width() - width) / 2, (ui::get_screen_height() - height) / 2);
window_main.view.resize(width, height);
} else {
//window_main.menu.show();
switch(video_settings.mode) { default:
case 0: //windowed
window_main.unfullscreen();
window_main.resize(width, height);
window_main.view.move(0, 0);
window_main.view.resize(width, height);
break;
case 1: //fullscreen
window_main.fullscreen();
window_main.view.move((ui::get_screen_width() - width) / 2, (ui::get_screen_height() - height) / 2);
window_main.view.resize(width, height);
break;
}
}
void update_raster_settings() {
uint filter, standard;
switch(uint(config::video.software_filter)) { default:
switch(video_settings.software_filter) { default:
case 0: filter = VIDEOFILTER_DIRECT; break;
case 1: filter = VIDEOFILTER_NTSC; break;
case 2: filter = VIDEOFILTER_HQ2X; break;
case 3: filter = VIDEOFILTER_SCALE2X; break;
}
switch(uint(config::video.region)) { default:
switch(video_settings.region) { default:
case 0: standard = SNES::VIDEOSTANDARD_NTSC; break;
case 1: standard = SNES::VIDEOSTANDARD_PAL; break;
}
snes.set_video_filter(filter);
snes.set_video_standard(standard);
if(uiVideo) {
uiVideo->settings.synchronize = video_settings.synchronize;
uiVideo->settings.filter = video_settings.hardware_filter;
uiVideo->update_settings();
}
//update main window video mode checkbox settings
window_main.update_menu_settings();
}
void toggle_menu() {
@ -61,7 +133,11 @@ void toggle_menu() {
}
void toggle_fullscreen() {
config::video.fullscreen = !config::video.fullscreen;
if(config::video.mode != 1) { //switch to fullscreen mode if not already in it
config::video.mode = 1;
} else { //switch to windowed mode if already in fullscreen mode
config::video.mode = 0;
}
update_video_settings();
}
@ -99,9 +175,16 @@ char fn[PATH_MAX];
if(load_rom(fn) == false)return;
if(cartridge.loaded() == true)cartridge.unload();
cartridge.load_begin(Cartridge::CART_NORMAL);
cartridge.load_begin(Cartridge::CartridgeNormal);
cartridge.load(fn);
cartridge.load_end();
//warn if unsupported hardware detected
if(cartridge.info.superfx)alert("Warning: unsupported SuperFX chip detected.");
if(cartridge.info.sa1) alert("Warning: unsupported SA-1 chip detected.");
if(cartridge.info.st011) alert("Warning: unsupported ST011 chip detected.");
if(cartridge.info.st018) alert("Warning: unsupported ST018 chip detected.");
snes.power();
window_cheat_editor.refresh();
}
@ -111,7 +194,7 @@ char fn[PATH_MAX];
if(load_rom(fn) == false)return;
if(cartridge.loaded() == true)cartridge.unload();
cartridge.load_begin(Cartridge::CART_ST);
cartridge.load_begin(Cartridge::CartridgeSufamiTurbo);
cartridge.load(fn);
cartridge.load_end();
snes.power();
@ -124,7 +207,7 @@ char fn_a[PATH_MAX], fn_b[PATH_MAX];
if(load_rom(fn_b) == false)return;
if(cartridge.loaded() == true)cartridge.unload();
cartridge.load_begin(Cartridge::CART_STDUAL);
cartridge.load_begin(Cartridge::CartridgeSufamiTurboDual);
cartridge.load(fn_a);
cartridge.load(fn_b);
cartridge.load_end();

View File

@ -1,12 +1,29 @@
namespace event {
struct VideoSettings {
uint mode;
bool synchronize;
bool aspect_correction;
uint region;
uint multiplier;
uint hardware_filter;
uint software_filter;
} video_settings;
void load_video_settings();
//change video settings for active video mode
void update_aspect_correction(bool);
void update_multiplier(uint);
void update_region(uint);
void update_hardware_filter(uint);
void update_software_filter(uint);
void update_frame_counter();
void update_video_settings();
void update_raster_settings();
void toggle_menu();
void toggle_fullscreen();
bool load_rom(char *fn);
bool load_rom(char*);
void load_rom();
void load_rom_st();
void load_rom_stdual();

View File

@ -24,7 +24,11 @@ va_list args;
va_start(args, s);
vsprintf(str, s, args);
va_end(args);
#if defined(PLATFORM_WIN)
MessageBox(0, str, "bsnes", MB_OK);
#else
fprintf(stdout, "%s\r\n", str);
#endif
}
void dprintf(const char *s, ...) {
@ -104,12 +108,16 @@ int main(int argc, char *argv[]) {
ui::init();
config::config().load(config::filename);
config::config().save(config::filename); //in case program crashes on first run, config file settings can be modified
if(fexists(config::filename) == false) {
//in case program crashes on first run, save config file
//settings, so that they can be modified by hand ...
config::config().save(config::filename);
}
init_snes();
ui_init();
if(argc >= 2) {
cartridge.load_begin(Cartridge::CART_NORMAL);
cartridge.load_begin(Cartridge::CartridgeNormal);
cartridge.load(argv[1]);
cartridge.load_end();
snes.power();

View File

@ -35,7 +35,7 @@ void ui_init() {
window_advanced.setup();
window_settings.setup();
event::update_video_settings();
event::update_video_settings(); //call first time to resize main window and update menubar
window_main.show();
while(ui::events_pending()) { ui::run(); }
@ -68,7 +68,7 @@ void ui_init() {
uiAudio->init();
uiInput->init();
window_main.setup_menu();
event::update_video_settings(); //call second time to update uiVideo->settings
}
void ui_term() {

View File

@ -56,59 +56,68 @@ ui::Control *control = (ui::Control*)param;
message(ui::Message::Close);
}
if(control == &menu_settings_videomode_1x) { config::video.multiplier = 1; event::update_video_settings(); }
if(control == &menu_settings_videomode_2x) { config::video.multiplier = 2; event::update_video_settings(); }
if(control == &menu_settings_videomode_3x) { config::video.multiplier = 3; event::update_video_settings(); }
if(control == &menu_settings_videomode_4x) { config::video.multiplier = 4; event::update_video_settings(); }
if(control == &menu_settings_videomode_5x) { config::video.multiplier = 5; event::update_video_settings(); }
if(locked == false) {
//set locked to true to update below menu item check statuses without triggering events
if(control == &menu_settings_videomode_1x) { event::update_multiplier(1); }
if(control == &menu_settings_videomode_2x) { event::update_multiplier(2); }
if(control == &menu_settings_videomode_3x) { event::update_multiplier(3); }
if(control == &menu_settings_videomode_4x) { event::update_multiplier(4); }
if(control == &menu_settings_videomode_5x) { event::update_multiplier(5); }
if(control == &menu_settings_videomode_aspect_correction) {
config::video.aspect_correction = menu_settings_videomode_aspect_correction.checked();
event::update_video_settings();
if(control == &menu_settings_videomode_aspect_correction) {
event::update_aspect_correction(menu_settings_videomode_aspect_correction.checked());
}
if(control == &menu_settings_videomode_ntsc) { event::update_region(0); }
if(control == &menu_settings_videomode_pal) { event::update_region(1); }
if(control == &menu_settings_videofilter_hwpoint) { event::update_hardware_filter(0); }
if(control == &menu_settings_videofilter_hwlinear) { event::update_hardware_filter(1); }
if(control == &menu_settings_videofilter_swnone) { event::update_software_filter(0); }
if(control == &menu_settings_videofilter_swntsc) { event::update_software_filter(1); }
if(control == &menu_settings_videofilter_swhq2x) { event::update_software_filter(2); }
if(control == &menu_settings_videofilter_swscale2x) { event::update_software_filter(3); }
if(control == &menu_settings_videoframeskip_0) { config::video.frameskip = 0; }
if(control == &menu_settings_videoframeskip_1) { config::video.frameskip = 1; }
if(control == &menu_settings_videoframeskip_2) { config::video.frameskip = 2; }
if(control == &menu_settings_videoframeskip_3) { config::video.frameskip = 3; }
if(control == &menu_settings_videoframeskip_4) { config::video.frameskip = 4; }
if(control == &menu_settings_videoframeskip_5) { config::video.frameskip = 5; }
if(control == &menu_settings_videoframeskip_6) { config::video.frameskip = 6; }
if(control == &menu_settings_videoframeskip_7) { config::video.frameskip = 7; }
if(control == &menu_settings_videoframeskip_8) { config::video.frameskip = 8; }
if(control == &menu_settings_videoframeskip_9) { config::video.frameskip = 9; }
if(control == &menu_settings_mute) {
config::snes.mute = menu_settings_mute.checked();
}
if(control == &menu_settings_speedreg_enable) {
config::system.regulate_speed = menu_settings_speedreg_enable.checked();
}
if(control == &menu_settings_speedreg_slowest) { config::system.speed = 1; uiAudio->update_frequency(); }
if(control == &menu_settings_speedreg_slow) { config::system.speed = 2; uiAudio->update_frequency(); }
if(control == &menu_settings_speedreg_normal) { config::system.speed = 3; uiAudio->update_frequency(); }
if(control == &menu_settings_speedreg_fast) { config::system.speed = 4; uiAudio->update_frequency(); }
if(control == &menu_settings_speedreg_fastest) { config::system.speed = 5; uiAudio->update_frequency(); }
}
if(control == &menu_settings_videomode_ntsc) { config::video.region = 0; event::update_raster_settings(); event::update_video_settings(); }
if(control == &menu_settings_videomode_pal) { config::video.region = 1; event::update_raster_settings(); event::update_video_settings(); }
if(control == &menu_settings_videofilter_hwpoint) { config::video.hardware_filter = 0; uiVideo->update_hardware_filter(); }
if(control == &menu_settings_videofilter_hwlinear) { config::video.hardware_filter = 1; uiVideo->update_hardware_filter(); }
if(control == &menu_settings_videofilter_swnone) { config::video.software_filter = 0; event::update_raster_settings(); }
if(control == &menu_settings_videofilter_swntsc) { config::video.software_filter = 1; event::update_raster_settings(); }
if(control == &menu_settings_videofilter_swhq2x) { config::video.software_filter = 2; event::update_raster_settings(); }
if(control == &menu_settings_videofilter_swscale2x) { config::video.software_filter = 3; event::update_raster_settings(); }
if(control == &menu_settings_videoframeskip_0) { config::video.frameskip = 0; }
if(control == &menu_settings_videoframeskip_1) { config::video.frameskip = 1; }
if(control == &menu_settings_videoframeskip_2) { config::video.frameskip = 2; }
if(control == &menu_settings_videoframeskip_3) { config::video.frameskip = 3; }
if(control == &menu_settings_videoframeskip_4) { config::video.frameskip = 4; }
if(control == &menu_settings_videoframeskip_5) { config::video.frameskip = 5; }
if(control == &menu_settings_videoframeskip_6) { config::video.frameskip = 6; }
if(control == &menu_settings_videoframeskip_7) { config::video.frameskip = 7; }
if(control == &menu_settings_videoframeskip_8) { config::video.frameskip = 8; }
if(control == &menu_settings_videoframeskip_9) { config::video.frameskip = 9; }
if(control == &menu_settings_mute) {
config::snes.mute = menu_settings_mute.checked();
}
if(control == &menu_settings_speedreg_enable) {
config::system.regulate_speed = menu_settings_speedreg_enable.checked();
}
if(control == &menu_settings_speedreg_slowest) { config::system.speed = 1; uiAudio->update_frequency(); }
if(control == &menu_settings_speedreg_slow) { config::system.speed = 2; uiAudio->update_frequency(); }
if(control == &menu_settings_speedreg_normal) { config::system.speed = 3; uiAudio->update_frequency(); }
if(control == &menu_settings_speedreg_fast) { config::system.speed = 4; uiAudio->update_frequency(); }
if(control == &menu_settings_speedreg_fastest) { config::system.speed = 5; uiAudio->update_frequency(); }
if(control == &menu_settings_config) { window_settings.show(); }
if(control == &menu_misc_logaudio) {
(menu_misc_logaudio.checked() == true) ? snes.log_audio_enable() : snes.log_audio_disable();
}
if(control == &menu_misc_showfps) {
config::misc.show_frame_counter = menu_misc_showfps.checked();
if(config::misc.show_frame_counter == false) {
set_text(string() << BSNES_TITLE);
}
}
if(control == &menu_misc_about) {
window_about.focus();
}
@ -122,6 +131,8 @@ ui::Control *control = (ui::Control*)param;
void MainWindow::setup() {
snesinterface.input_ready = bind(&MainWindow::input_ready, this);
locked = true;
ui::ControlGroup group;
create(ui::Window::Center, 256, 224, BSNES_TITLE);
set_background_color(0, 0, 0);
@ -233,6 +244,7 @@ ui::ControlGroup group;
menu_misc.create(menu, "Misc");
menu_misc_logaudio.create(menu_misc, "Log Audio Data");
menu_misc_showfps.create(menu_misc, "Show FPS");
menu_misc_sep1.create(menu_misc);
menu_misc_about.create(menu_misc, "About ...");
menu_misc.finish();
@ -242,9 +254,12 @@ ui::ControlGroup group;
view.set_background_color(0, 0, 0);
}
void MainWindow::setup_menu() {
config::video.multiplier = minmax<1, 5>(uint(config::video.multiplier));
switch(uint(config::video.multiplier)) {
void MainWindow::update_menu_settings() {
locked = true;
event::load_video_settings();
switch(event::video_settings.multiplier) { default:
case 1: menu_settings_videomode_1x.check(); break;
case 2: menu_settings_videomode_2x.check(); break;
case 3: menu_settings_videomode_3x.check(); break;
@ -252,22 +267,19 @@ void MainWindow::setup_menu() {
case 5: menu_settings_videomode_5x.check(); break;
}
menu_settings_videomode_aspect_correction.check(config::video.aspect_correction);
menu_settings_videomode_aspect_correction.check(event::video_settings.aspect_correction);
config::video.region = minmax<0, 1>(uint(config::video.region));
switch(uint(config::video.region)) {
switch(event::video_settings.region) { default:
case 0: menu_settings_videomode_ntsc.check(); break;
case 1: menu_settings_videomode_pal.check(); break;
}
config::video.hardware_filter = minmax<0, 1>(uint(config::video.hardware_filter));
switch(uint(config::video.hardware_filter)) {
switch(event::video_settings.hardware_filter) { default:
case 0: menu_settings_videofilter_hwpoint.check(); break;
case 1: menu_settings_videofilter_hwlinear.check(); break;
}
config::video.software_filter = minmax<0, 3>(uint(config::video.software_filter));
switch(uint(config::video.software_filter)) {
switch(event::video_settings.software_filter) { default:
case 0: menu_settings_videofilter_swnone.check(); break;
case 1: menu_settings_videofilter_swntsc.check(); break;
case 2: menu_settings_videofilter_swhq2x.check(); break;
@ -278,4 +290,8 @@ void MainWindow::setup_menu() {
menu_settings_speedreg_enable.check(config::system.regulate_speed);
menu_settings_speedreg_normal.check();
menu_misc_showfps.check(config::misc.show_frame_counter);
locked = false;
}

View File

@ -57,6 +57,7 @@ ui::MenuGroup menu_settings;
ui::MenuItem menu_settings_config;
ui::MenuGroup menu_misc;
ui::MenuCheckItem menu_misc_logaudio;
ui::MenuCheckItem menu_misc_showfps;
ui::MenuSeparator menu_misc_sep1;
ui::MenuItem menu_misc_about;
@ -65,7 +66,8 @@ ui::Container view;
bool input_ready();
bool locked;
bool message(uint id, uintptr_t param = 0);
void setup();
void setup_menu();
void update_menu_settings();
} window_main;

View File

@ -87,7 +87,7 @@ HRESULT hr;
device->SetVertexShader(NULL);
device->SetFVF(D3DVERTEX);
update_hardware_filter();
update_settings();
if(caps.stretchrect == true) {
device->CreateOffscreenPlainSurface(1024, 1024, D3DFMT_R5G6B5,
@ -104,10 +104,10 @@ HRESULT hr;
return true;
}
void VideoD3D::update_hardware_filter() {
void VideoD3D::update_settings() {
if(!device)return;
switch(uint(config::video.hardware_filter)) {
switch(settings.filter) {
case Video::FilterPoint:
flags.filter = D3DTEXF_POINT;
break;
@ -230,7 +230,7 @@ void VideoD3D::refresh(uint r_width, uint r_height) {
device->EndScene();
if(config::video.synchronize == true) {
if(settings.synchronize == true) {
D3DRASTER_STATUS status;
for(;;) {
device->GetRasterStatus(0, &status);

View File

@ -43,7 +43,7 @@ struct {
uint screen_height() { return GetSystemMetrics(SM_CYSCREEN); }
bool update_video_mode();
void update_hardware_filter();
void update_settings();
bool capture_screenshot();

View File

@ -18,7 +18,7 @@ void VideoDD::unlock() {
}
void VideoDD::refresh(uint r_width, uint r_height) {
if(config::video.synchronize == true) {
if(settings.synchronize) {
for(;;) {
BOOL in_vblank;
lpdd7->GetVerticalBlankStatus(&in_vblank);

View File

@ -1,12 +1,18 @@
#ifndef VIDEO_H
#define VIDEO_H
class Video { public:
enum Filter {
FilterPoint,
#ifndef VIDEO_H
#define VIDEO_H
class Video { public:
struct Settings {
bool synchronize;
uint filter;
Settings() : synchronize(false), filter(0) {}
} settings;
enum Filter {
FilterPoint,
FilterLinear,
};
};
virtual bool lock(uint16 *&data, uint &pitch) { return false; }
virtual void unlock() {}
@ -16,10 +22,10 @@ enum Filter {
virtual void init() {}
virtual void term() {}
virtual void update_hardware_filter() {}
virtual void update_settings() {}
Video() {}
virtual ~Video() {}
} *uiVideo;
#endif
#endif